Presented at Confoo (Montreal, Cananda)
Let's spend some time seeing how easy it can be to set up Mocha and Chai, a testing framework for JavaScript/CoffeeScript, in your application. We'll learn how to test that our jQuery or Backbone code is doing what it supposed to. It's really not as hard as you think it might be.
Testing JavaScript/CoffeeScript with Mocha and ChaiMark
Presented at the Burlington Ruby Conference on July 28th.
Learn just how easy it is to test your JavaScript and CoffeeScript code. Don't be scared by events, DOM interactions, or AJAX requests any more!
Testing your JavaScript and/or CofffeeScript applications is not nearly as difficult as you think. Learn how to quickly setup Jasmine in your Rails application and start testing your *script applications now!
Tom Lazar Using Zope3 Views And Viewlets For Plone 3.0 Product DevelopmentVincenzo Barone
A hands-on workshop on how to use Zope3 Views and Viewlets in Products targeted for Plone 3.0 (and why you would want to do so). Special emphasis will be on best practices in general, handling and validation of forms and how Zope3's shiny new toys make it easier to write reusable code and cleaner markup. Finally, the talk will deal with how Views and Viewlets can help you make your product better cacheable. Although the talk is targeted at Plone integrators who already have experience using the older CMF-based approach it will also try to address people new to Plone who want to customize it in a future-proof manner.
Implementing CQRS and Event Sourcing with RavenDBOren Eini
CQRS stands for Command Query Responsibility Segregation. That is, that command stack and query stack are designed separately. This leads to a dramatic simplification of design and potential enhancement of scalability.
Events are a new trend in software industry. In real-world, we perform actions and these actions generate a reaction. Event Sourcing is about persisting events and rebuilding the state of the aggregates from recorded events.
In this talk I will share a lot of examples about how to effective implementing CQRS and Event Sourcing with RavenDB
Testing JavaScript/CoffeeScript with Mocha and ChaiMark
Presented at the Burlington Ruby Conference on July 28th.
Learn just how easy it is to test your JavaScript and CoffeeScript code. Don't be scared by events, DOM interactions, or AJAX requests any more!
Testing your JavaScript and/or CofffeeScript applications is not nearly as difficult as you think. Learn how to quickly setup Jasmine in your Rails application and start testing your *script applications now!
Tom Lazar Using Zope3 Views And Viewlets For Plone 3.0 Product DevelopmentVincenzo Barone
A hands-on workshop on how to use Zope3 Views and Viewlets in Products targeted for Plone 3.0 (and why you would want to do so). Special emphasis will be on best practices in general, handling and validation of forms and how Zope3's shiny new toys make it easier to write reusable code and cleaner markup. Finally, the talk will deal with how Views and Viewlets can help you make your product better cacheable. Although the talk is targeted at Plone integrators who already have experience using the older CMF-based approach it will also try to address people new to Plone who want to customize it in a future-proof manner.
Implementing CQRS and Event Sourcing with RavenDBOren Eini
CQRS stands for Command Query Responsibility Segregation. That is, that command stack and query stack are designed separately. This leads to a dramatic simplification of design and potential enhancement of scalability.
Events are a new trend in software industry. In real-world, we perform actions and these actions generate a reaction. Event Sourcing is about persisting events and rebuilding the state of the aggregates from recorded events.
In this talk I will share a lot of examples about how to effective implementing CQRS and Event Sourcing with RavenDB
Using Kotlin coroutines it’s really easy to execute a task in a background thread and update the UI based on the result. Just enter the coroutine world using the launch method and then change thread using withContext. It’s even simpler if the task is an http call (thanks to coroutines support in retrofit) or a database query (thanks to Room). The final code is the same we’d use to execute synchronous code. But coroutines are more than just a tool to switch thread, we can use them to execute tasks in parallel. The code is still really easy to read but sometimes it can be difficult to write: we need to pay attention to many aspects (like nested scopes, exceptions and dispatchers). In this talk we’ll see how to leverage the coroutines library to manage parallelism, from the basic concepts to some advanced example.
Compose is stable, it's time to integrate it into our apps! But it can be harder than expected and there are some questions to answer. Can the same architecture of a View-based app be reused or should we change it? Should the Compose code be aware of the architecture at all? And should the non UI code be changed to start using Compose? What can be replaced with a Composable, only the layouts or also something else?
Probably the best answer to all these questions is “it depends”, in this talk we’ll see some reasons and how to leverage Compose and the other tools to create a good architecture. Compose is more than just a UI framework and it can seem appealing to use it in a big portion of an app, a good architecture can be useful to limit this portion and use it only when necessary.
Using Kotlin coroutines it’s really easy to execute a task in a background thread and update the UI based on the result. Just enter the coroutine world using the launch method and then change thread using withContext. It’s even simpler if the task is an http call (thanks to coroutines support in retrofit) or a database query (thanks to Room). The final code is the same we’d use to execute synchronous code. But coroutines are more than just a tool to switch thread, we can use them to execute tasks in parallel. The code is still really easy to read but sometimes it can be difficult to write: we need to pay attention to many aspects (like nested scopes, exceptions and dispatchers). In this talk we’ll see how to leverage the coroutines library to manage parallelism, from the basic concepts to some advanced example.
Compose is stable, it's time to integrate it into our apps! But it can be harder than expected and there are some questions to answer. Can the same architecture of a View-based app be reused or should we change it? Should the Compose code be aware of the architecture at all? And should the non UI code be changed to start using Compose? What can be replaced with a Composable, only the layouts or also something else?
Probably the best answer to all these questions is “it depends”, in this talk we’ll see some reasons and how to leverage Compose and the other tools to create a good architecture. Compose is more than just a UI framework and it can seem appealing to use it in a big portion of an app, a good architecture can be useful to limit this portion and use it only when necessary.
Is your web app drowning in a sea of JavaScript? Has your client-side codebase grown from "a snippet here and there" to "more JavaScript than HTML"? Do you find yourself writing one-off snippets instead of generalized components? You're not the only one. Learn about a handful of strategies you can use to keep your JavaScript codebase lean, modular, and flexible. We'll cover all the major pain points — MVC, templates, persisting state, namespacing, graceful error handling, client/server communication, and separation of concerns. And we'll cover how to do all this incrementally so that you don't have to redo everything from scratch.
Slides from talk given at Ithaca Web Group and GORGES on CoffeeScript.
The focus is on explaining to people who haven't tried it yet that it's more than syntactic sugar. There are several real life code examples but they were explained verbally so they may not be super helpful if you don't know CoffeeScript yet.
It's an overview, not a tutorial.
2013-06-15 - Software Craftsmanship mit JavaScriptJohannes Hoppe
Entwickeln Sie Clean Code mit JavaScript. Den “Software Craftsman” zeichnen dabei Wissen, Werkzeuge und Wiederholung aus. Diese drei Grundfeste werden speziell für JavaScript beleuchtet. Lernen Sie die wichtigsten Patterns für eine stabile und wartbare Website kennen. Überprüfen Sie Ihre persönliche Werkzeugkiste für Entwicklung, Testing und Deployment. Schließen Sie Bekanntschaft mit Code Katas für JavaScript.
2013-06-24 - Software Craftsmanship with JavaScriptJohannes Hoppe
Entwickeln Sie Clean Code mit JavaScript. Den “Software Craftsman” zeichnen dabei Wissen, Werkzeuge und Wiederholung aus. Diese drei Grundfeste werden speziell für JavaScript beleuchtet. Lernen Sie die wichtigsten Patterns für eine stabile und wartbare Website kennen. Überprüfen Sie Ihre persönliche Werkzeugkiste für Entwicklung, Testing und Deployment. Schließen Sie Bekanntschaft mit Code Katas für JavaScript.
As present at FluentConf 2014 on March 11th, 2014.
AngularJS is one of the most popular, and powerful, JavaScript frameworks for building rich client-side applications. AngularJS is both simultaneously both simple to use and extremely full featured. With AngularJS a little goes a long way, but to make the most of it, you need to know what you’re doing.
In this workshop we will build a complex application to help exercise all of the salient points of the AngularJS framework.
Topics covered include, ngResource, directives, fitlers, routing, templates, controllers, testing, and more.
Code can be found at: https://github.com/markbates/fluent-2014
Presented at LA Ruby Conf on February 8th, 2014. A high level overview of Go, golang, and how it relates to Ruby. Packages such as Martini, Lineman.js, sqlx, Ginkgo, and more are covered.
Presented at RubyConf 11/10/2013
Introduced in Ruby 2.0, TracePoint is meant to help developers better instrument their code for debugging and performance reasons, but there's more to TracePoint than that!
In this talk we'll learn about TracePoint while building several example projects. Once we know the basics we'll use TracePoint to do things to Ruby that we couldn't have done otherwise.
By the end of this talk you'll be able to frighten and amaze your friends when you show them things like true abstract classes and interfaces in Ruby, just like Java! Yikes!
The world of JavaScript client-side frameworks is overflowing with contenders vying for the crown, but which one do you choose for your next project? Which one has what it takes?
In this talk we’ll look at the “Big 3”, AngularJS, Ember.js, and Backbone.js. We’ll compare them head to head, toe to toe. We’ll look at the pros and cons of each one. How do they handle form bindings? Talking to APIs? Code organization? Routing? Etc?
Who’ll come out victorious in this battle of the JavaScript frameworks, or will we all just come out bloodied and bruised on the other side? Guess we’ll find out!
Presented at Confoo (Montreal, Canada) on 3/1/2013
In this talk I’ll show you how to build your application and get a working, well tested, and useable API in the process, with almost no extra overhead. I’ll also show you how to do it without making your controllers a mess of respond_to blocks. If anything, you’re controllers will become cleaner and leaner.
Presented on 8/14/2012 at BostonRb. This talk provides a nice intro and overview of what RubyMotion is and whether or not it's worth incorporating into your development toolkit.
A fun filled tour through distributed programming with the Ruby standard library.
Presented on February 2nd, 2012 at RubyFuza in Cape Town, South Africa.
Distributed Programming with Ruby/Rubyconf 2010Mark
This talk will guide you through the various different aspects of building distributed applications with Ruby. While this talk will not do a deep dive into any technology we will look at libraries that ship with Ruby, such as DRb and Rinda, as well as other 3rd party libraries that are available, during the discussion and examples. We'll talk about remote method invocation (RMI), message queues, asynchronous tasks, map reduce, and background jobs, just to name a few. The discussion will include what those terms all mean and when and where you may want to use a particular technology.
Neuro-symbolic is not enough, we need neuro-*semantic*Frank van Harmelen
Neuro-symbolic (NeSy) AI is on the rise. However, simply machine learning on just any symbolic structure is not sufficient to really harvest the gains of NeSy. These will only be gained when the symbolic structures have an actual semantics. I give an operational definition of semantics as “predictable inference”.
All of this illustrated with link prediction over knowledge graphs, but the argument is general.
UiPath Test Automation using UiPath Test Suite series, part 3DianaGray10
Welcome to UiPath Test Automation using UiPath Test Suite series part 3. In this session, we will cover desktop automation along with UI automation.
Topics covered:
UI automation Introduction,
UI automation Sample
Desktop automation flow
Pradeep Chinnala, Senior Consultant Automation Developer @WonderBotz and UiPath MVP
Deepak Rai, Automation Practice Lead, Boundaryless Group and UiPath MVP
Epistemic Interaction - tuning interfaces to provide information for AI supportAlan Dix
Paper presented at SYNERGY workshop at AVI 2024, Genoa, Italy. 3rd June 2024
https://alandix.com/academic/papers/synergy2024-epistemic/
As machine learning integrates deeper into human-computer interactions, the concept of epistemic interaction emerges, aiming to refine these interactions to enhance system adaptability. This approach encourages minor, intentional adjustments in user behaviour to enrich the data available for system learning. This paper introduces epistemic interaction within the context of human-system communication, illustrating how deliberate interaction design can improve system understanding and adaptation. Through concrete examples, we demonstrate the potential of epistemic interaction to significantly advance human-computer interaction by leveraging intuitive human communication strategies to inform system design and functionality, offering a novel pathway for enriching user-system engagements.
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualityInflectra
In this insightful webinar, Inflectra explores how artificial intelligence (AI) is transforming software development and testing. Discover how AI-powered tools are revolutionizing every stage of the software development lifecycle (SDLC), from design and prototyping to testing, deployment, and monitoring.
Learn about:
• The Future of Testing: How AI is shifting testing towards verification, analysis, and higher-level skills, while reducing repetitive tasks.
• Test Automation: How AI-powered test case generation, optimization, and self-healing tests are making testing more efficient and effective.
• Visual Testing: Explore the emerging capabilities of AI in visual testing and how it's set to revolutionize UI verification.
• Inflectra's AI Solutions: See demonstrations of Inflectra's cutting-edge AI tools like the ChatGPT plugin and Azure Open AI platform, designed to streamline your testing process.
Whether you're a developer, tester, or QA professional, this webinar will give you valuable insights into how AI is shaping the future of software delivery.
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Tobias Schneck
As AI technology is pushing into IT I was wondering myself, as an “infrastructure container kubernetes guy”, how get this fancy AI technology get managed from an infrastructure operational view? Is it possible to apply our lovely cloud native principals as well? What benefit’s both technologies could bring to each other?
Let me take this questions and provide you a short journey through existing deployment models and use cases for AI software. On practical examples, we discuss what cloud/on-premise strategy we may need for applying it to our own infrastructure to get it to work from an enterprise perspective. I want to give an overview about infrastructure requirements and technologies, what could be beneficial or limiting your AI use cases in an enterprise environment. An interactive Demo will give you some insides, what approaches I got already working for real.
UiPath Test Automation using UiPath Test Suite series, part 4DianaGray10
Welcome to UiPath Test Automation using UiPath Test Suite series part 4. In this session, we will cover Test Manager overview along with SAP heatmap.
The UiPath Test Manager overview with SAP heatmap webinar offers a concise yet comprehensive exploration of the role of a Test Manager within SAP environments, coupled with the utilization of heatmaps for effective testing strategies.
Participants will gain insights into the responsibilities, challenges, and best practices associated with test management in SAP projects. Additionally, the webinar delves into the significance of heatmaps as a visual aid for identifying testing priorities, areas of risk, and resource allocation within SAP landscapes. Through this session, attendees can expect to enhance their understanding of test management principles while learning practical approaches to optimize testing processes in SAP environments using heatmap visualization techniques
What will you get from this session?
1. Insights into SAP testing best practices
2. Heatmap utilization for testing
3. Optimization of testing processes
4. Demo
Topics covered:
Execution from the test manager
Orchestrator execution result
Defect reporting
SAP heatmap example with demo
Speaker:
Deepak Rai, Automation Practice Lead, Boundaryless Group and UiPath MVP
Connector Corner: Automate dynamic content and events by pushing a buttonDianaGray10
Here is something new! In our next Connector Corner webinar, we will demonstrate how you can use a single workflow to:
Create a campaign using Mailchimp with merge tags/fields
Send an interactive Slack channel message (using buttons)
Have the message received by managers and peers along with a test email for review
But there’s more:
In a second workflow supporting the same use case, you’ll see:
Your campaign sent to target colleagues for approval
If the “Approve” button is clicked, a Jira/Zendesk ticket is created for the marketing design team
But—if the “Reject” button is pushed, colleagues will be alerted via Slack message
Join us to learn more about this new, human-in-the-loop capability, brought to you by Integration Service connectors.
And...
Speakers:
Akshay Agnihotri, Product Manager
Charlie Greenberg, Host
Securing your Kubernetes cluster_ a step-by-step guide to success !KatiaHIMEUR1
Today, after several years of existence, an extremely active community and an ultra-dynamic ecosystem, Kubernetes has established itself as the de facto standard in container orchestration. Thanks to a wide range of managed services, it has never been so easy to set up a ready-to-use Kubernetes cluster.
However, this ease of use means that the subject of security in Kubernetes is often left for later, or even neglected. This exposes companies to significant risks.
In this talk, I'll show you step-by-step how to secure your Kubernetes cluster for greater peace of mind and reliability.
Key Trends Shaping the Future of Infrastructure.pdfCheryl Hung
Keynote at DIGIT West Expo, Glasgow on 29 May 2024.
Cheryl Hung, ochery.com
Sr Director, Infrastructure Ecosystem, Arm.
The key trends across hardware, cloud and open-source; exploring how these areas are likely to mature and develop over the short and long-term, and then considering how organisations can position themselves to adapt and thrive.
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Jeffrey Haguewood
Sidekick Solutions uses Bonterra Impact Management (fka Social Solutions Apricot) and automation solutions to integrate data for business workflows.
We believe integration and automation are essential to user experience and the promise of efficient work through technology. Automation is the critical ingredient to realizing that full vision. We develop integration products and services for Bonterra Case Management software to support the deployment of automations for a variety of use cases.
This video focuses on the notifications, alerts, and approval requests using Slack for Bonterra Impact Management. The solutions covered in this webinar can also be deployed for Microsoft Teams.
Interested in deploying notification automations for Bonterra Impact Management? Contact us at sales@sidekicksolutionsllc.com to discuss next steps.
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf91mobiles
91mobiles recently conducted a Smart TV Buyer Insights Survey in which we asked over 3,000 respondents about the TV they own, aspects they look at on a new TV, and their TV buying preferences.
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Ramesh Iyer
In today's fast-changing business world, Companies that adapt and embrace new ideas often need help to keep up with the competition. However, fostering a culture of innovation takes much work. It takes vision, leadership and willingness to take risks in the right proportion. Sachin Dev Duggal, co-founder of Builder.ai, has perfected the art of this balance, creating a company culture where creativity and growth are nurtured at each stage.
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...UiPathCommunity
💥 Speed, accuracy, and scaling – discover the superpowers of GenAI in action with UiPath Document Understanding and Communications Mining™:
See how to accelerate model training and optimize model performance with active learning
Learn about the latest enhancements to out-of-the-box document processing – with little to no training required
Get an exclusive demo of the new family of UiPath LLMs – GenAI models specialized for processing different types of documents and messages
This is a hands-on session specifically designed for automation developers and AI enthusiasts seeking to enhance their knowledge in leveraging the latest intelligent document processing capabilities offered by UiPath.
Speakers:
👨🏫 Andras Palfi, Senior Product Manager, UiPath
👩🏫 Lenka Dulovicova, Product Program Manager, UiPath
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Albert Hoitingh
In this session I delve into the encryption technology used in Microsoft 365 and Microsoft Purview. Including the concepts of Customer Key and Double Key Encryption.
12. app/models/todo.rb
class Todo < ActiveRecord::Base
validates :body, presence: true
attr_accessible :body, :completed
end
Monday, February 25, 13
13. spec/models/todo_spec.rb
require 'spec_helper'
describe Todo do
it "requires a body" do
todo = Todo.new
todo.should_not be_valid
todo.errors[:body].should include("can't be blank")
todo.body = "Do something"
todo.should be_valid
end
end
Monday, February 25, 13
14. app/controllers/todos_controller.rb
class TodosController < ApplicationController
respond_to :html, :json
def index
respond_to do |format|
format.html {}
format.json do
@todos = Todo.order("created_at asc")
respond_with @todos
end
end
end
def show
@todo = Todo.find(params[:id])
respond_with @todo
end
def create
@todo = Todo.create(params[:todo])
respond_with @todo
end
def update
@todo = Todo.find(params[:id])
@todo.update_attributes(params[:todo])
respond_with @todo
end
def destroy
@todo = Todo.find(params[:id])
@todo.destroy
respond_with @todo
end
end
Monday, February 25, 13
15. spec/controllers/todos_controller_spec.rb
require 'spec_helper'
it "responds with errors" do
expect {
describe TodosController do
post :create, todo: {}, format: 'json'
let(:todo) { Factory(:todo) }
response.should_not be_successful
json = decode_json(response.body)
describe 'index' do
json.errors.should have(1).error
json.errors.body.should include("can't be blank")
context "HTML" do
}.to_not change(Todo, :count)
end
it "renders the HTML page" do
get :index
end
response.should render_template(:index)
end
assigns(:todos).should be_nil
end
describe 'update' do
end
context "JSON" do
context "JSON" do
it "updates a todo" do
put :update, id: todo.id, todo: {body: "do something else"}, format: 'json'
it "returns JSON for the todos" do
get :index, format: "json"
response.should be_successful
todo.reload
response.should_not render_template(:index)
todo.body.should eql "do something else"
assigns(:todos).should_not be_nil
end
end
it "responds with errors" do
end
put :update, id: todo.id, todo: {body: ""}, format: 'json'
end
response.should_not be_successful
json = decode_json(response.body)
describe 'show' do
json.errors.should have(1).error
json.errors.body.should include("can't be blank")
context "JSON" do
end
it "returns the todo" do
end
get :show, id: todo.id, format: 'json'
end
response.should be_successful
response.body.should eql todo.to_json
describe 'destroy' do
end
context "JSON" do
end
it "destroys the todo" do
end
todo.should_not be_nil
expect {
describe 'create' do
delete :destroy, id: todo.id, format: 'JSON'
}.to change(Todo, :count).by(-1)
context "JSON" do
end
it "creates a new todo" do
end
expect {
post :create, todo: {body: "do something"}, format: 'json'
end
response.should be_successful
end
}.to change(Todo, :count).by(1)
end
Monday, February 25, 13
16. app/views/todos/index.html.erb
<form class='form-horizontal' id='todo_form'></form>
<ul id='todos' class="unstyled"></ul>
<script>
$(function() {
new OMG.Views.TodosApp();
})
</script>
Monday, February 25, 13
30. ASSERTIONS/MATCHERS
• to (should) • .ok • .instanceof(constructor)
• be • .true • .property(name, [value])
• been • .false • .ownProperty(name)
• is • .null • .length(value)
• that • .undefined • .match(regexp)
• and • .exist • .string(string)
• have • .empty • .keys(key1, [key2], [...])
• with • .equal (.eql) • .throw(constructor)
• .deep • .above(value) • .respondTo(method)
• .a(type) • .below(value) • .satisfy(method)
• .include(value) • .within(start, finish) • .closeTo(expected, delta)
Monday, February 25, 13
31. MOCHA/CHAI WITH RAILS
• gem 'konacha'
• gem 'poltergiest' (brew install phantomjs)
Monday, February 25, 13
32. config/initializers/konacha.rb
if defined?(Konacha)
require 'capybara/poltergeist'
Konacha.configure do |config|
config.spec_dir = "spec/javascripts"
config.driver = :poltergeist
end
end
Monday, February 25, 13
37. spec/javascripts/spec_helper.coffee
# Require the appropriate asset-pipeline files:
#= require application
# Any other testing specific code here...
# Custom matchers, etc....
# Needed for stubbing out "window" properties
# like the confirm dialog
Konacha.mochaOptions.ignoreLeaks = true
beforeEach ->
@page = $("#konacha")
Monday, February 25, 13
38. app/assets/javascript/greeter.js.coffee
class @Greeter
constructor: (@name) ->
unless @name?
throw new Error("You need a name!")
greet: ->
"Hi #{@name}"
Monday, February 25, 13
39. spec/javascripts/greeter_spec.coffee
#= require spec_helper
describe "Greeter", ->
describe "initialize", ->
it "raises an error if no name", ->
expect(-> new Greeter()).to.throw("You need a name!")
describe "greet", ->
it "greets someone", ->
greeter = new Greeter("Mark")
greeter.greet().should.eql("Hi Mark")
Monday, February 25, 13
45. spec/javascripts/spec_helper.coffee
# Require the appropriate asset-pipeline files:
#= require application
#= require_tree ./support
# Any other testing specific code here...
# Custom matchers, etc....
# Needed for stubbing out "window" properties
# like the confirm dialog
Konacha.mochaOptions.ignoreLeaks = true
beforeEach ->
@page = $("#konacha")
Monday, February 25, 13
46. app/assets/javascripts/views/todo_view.js.coffee
class OMG.Views.TodoView extends OMG.Views.BaseView
tagName: 'li'
template: JST['todos/_todo']
events:
'change [name=completed]': 'completedChecked'
'click .delete': 'deleteClicked'
initialize: ->
@model.on "change", @render
@render()
render: =>
$(@el).html(@template(todo: @model))
if @model.get("completed") is true
@$(".todo-body").addClass("completed")
@$("[name=completed]").attr("checked", true)
return @
completedChecked: (e) =>
@model.save(completed: $(e.target).attr("checked")?)
deleteClicked: (e) =>
e?.preventDefault()
if confirm("Are you sure?")
@model.destroy()
$(@el).remove()
Monday, February 25, 13
47. spec/javascripts/views/todos/todo_view_spec.coffee
#= require spec_helper
describe "OMG.Views.TodoView", ->
beforeEach ->
@collection = new OMG.Collections.Todos()
@model = new OMG.Models.Todo(id: 1, body: "Do something!", completed: false)
@view = new OMG.Views.TodoView(model: @model, collection: @collection)
@page.html(@view.el)
Monday, February 25, 13
48. spec/javascripts/views/todos/todo_view_spec.coffee
describe "model bindings", ->
it "re-renders on change", ->
$('.todo-body').should.have.text("Do something!")
@model.set(body: "Do something else!")
$('.todo-body').should.have.text("Do something else!")
Monday, February 25, 13
49. spec/javascripts/views/todos/todo_view_spec.coffee
describe "displaying of todos", ->
it "contains the body of the todo", ->
$('.todo-body').should.have.text("Do something!")
it "is not marked as completed", ->
$('[name=completed]').should.not.be.checked
$('.todo-body').should.not.have.class("completed")
describe "completed todos", ->
beforeEach ->
@model.set(completed: true)
it "is marked as completed", ->
$('[name=completed]').should.be.checked
$('.todo-body').should.have.class("completed")
Monday, February 25, 13
50. spec/javascripts/views/todos/todo_view_spec.coffee
describe "checking the completed checkbox", ->
beforeEach ->
$('[name=completed]').should.not.be.checked
$('[name=completed]').click()
it "marks it as completed", ->
$('[name=completed]').should.be.checked
$('.todo-body').should.have.class("completed")
describe "unchecking the completed checkbox", ->
beforeEach ->
@model.set(completed: true)
$('[name=completed]').should.be.checked
$('[name=completed]').click()
it "marks it as not completed", ->
$('[name=completed]').should.not.be.checked
$('.todo-body').should.not.have.class("completed")
Monday, February 25, 13
51. app/assets/javascripts/todos/todo_view.coffee
class OMG.Views.TodoView extends OMG.Views.BaseView
# ...
deleteClicked: (e) =>
e?.preventDefault()
if confirm("Are you sure?")
@model.destroy()
$(@el).remove()
Monday, February 25, 13
52. spec/javascripts/views/todos/todo_view_spec.coffee
describe "clicking the delete button", ->
describe "if confirmed", ->
it "will remove the todo from the @page", ->
@page.html().should.contain($(@view.el).html())
$(".delete").click()
@page.html().should.not.contain($(@view.el).html())
describe "if not confirmed", ->
it "will not remove the todo from the @page", ->
@page.html().should.contain($(@view.el).html())
$(".delete").click()
@page.html().should.contain($(@view.el).html())
Monday, February 25, 13
57. spec/javascripts/spec_helper.coffee
# Require the appropriate asset-pipeline files:
#= require application
#= require support/sinon
#= require_tree ./support
# Any other testing specific code here...
# Custom matchers, etc....
# Needed for stubbing out "window" properties
# like the confirm dialog
Konacha.mochaOptions.ignoreLeaks = true
beforeEach ->
@page = $("#konacha")
@sandbox = sinon.sandbox.create()
afterEach ->
@sandbox.restore()
Monday, February 25, 13
58. spec/javascripts/views/todos/todo_view_spec.coffee
describe "clicking the delete button", ->
describe "if confirmed", ->
beforeEach ->
@sandbox.stub(window, "confirm").returns(true)
it "will remove the todo from the @page", ->
@page.html().should.contain($(@view.el).html())
$(".delete").click()
@page.html().should.not.contain($(@view.el).html())
describe "if not confirmed", ->
beforeEach ->
@sandbox.stub(window, "confirm").returns(false)
it "will not remove the todo from the @page", ->
@page.html().should.contain($(@view.el).html())
$(".delete").click()
@page.html().should.contain($(@view.el).html())
Monday, February 25, 13
60. app/assets/javascripts/views/todos/todo_list_view.js.coffee
class OMG.Views.TodosListView extends OMG.Views.BaseView
el: "#todos"
initialize: ->
@collection.on "reset", @render
@collection.on "add", @renderTodo
@collection.fetch()
render: =>
$(@el).html("")
@collection.forEach (todo) =>
@renderTodo(todo)
renderTodo: (todo) =>
view = new OMG.Views.TodoView(model: todo, collection: @collection)
$(@el).prepend(view.el)
Monday, February 25, 13
61. spec/javascripts/views/todos/todo_list_view_spec.coffee
#= require spec_helper
describe "OMG.Views.TodosListView", ->
beforeEach ->
@page.html("<ul id='todos'></ul>")
@collection = new OMG.Collections.Todos()
@view = new OMG.Views.TodosListView(collection: @collection)
it "fetches the collection", ->
@collection.should.have.length(2)
it "renders the todos from the collection", ->
el = $(@view.el).html()
el.should.match(/Do something!/)
el.should.match(/Do something else!/)
it "renders new todos added to the collection", ->
@collection.add(new OMG.Models.Todo(body: "Do another thing!"))
el = $(@view.el).html()
el.should.match(/Do another thing!/)
Monday, February 25, 13
67. spec/javascripts/views/todos/todo_list_view_spec.coffee
#= require spec_helper
describe "OMG.Views.TodosListView", ->
beforeEach ->
@page.html("<ul id='todos'></ul>")
@collection = new OMG.Collections.Todos()
@view = new OMG.Views.TodosListView(collection: @collection)
it "fetches the collection", ->
@collection.should.have.length(2)
it "renders the todos from the collection", ->
el = $(@view.el).html()
el.should.match(/Do something!/)
el.should.match(/Do something else!/)
it "renders new todos added to the collection", ->
@collection.add(new OMG.Models.Todo(body: "Do another thing!"))
el = $(@view.el).html()
el.should.match(/Do another thing!/)
Monday, February 25, 13
68. spec/javascripts/views/todos/todo_list_view_spec.coffee
#= require spec_helper
describe "OMG.Views.TodosListView", ->
beforeEach ->
@page.html("<ul id='todos'></ul>")
@collection = new OMG.Collections.Todos()
@view = new OMG.Views.TodosListView(collection: @collection)
MockServer.respond()
it "fetches the collection", ->
@collection.should.have.length(2)
it "renders the todos from the collection", ->
el = $(@view.el).html()
el.should.match(/Do something!/)
el.should.match(/Do something else!/)
it "renders new todos added to the collection", ->
@collection.add(new OMG.Models.Todo(body: "Do another thing!"))
el = $(@view.el).html()
el.should.match(/Do another thing!/)
Monday, February 25, 13