SlideShare una empresa de Scribd logo
1 de 107
How do I test my Sproutcore Application?
               Greg Moeck
@gregmoeck
Quick
 Poll
Question
   1
Full Time
Sproutcore?
Full Time
JavaScript?
Other?
Question
   2
Practice
TDD/BDD?
Practice
Test Last
  Unit
Testing?
No
Automated
  Tests?
Question
   3
Practice
 TDD/BDD
In JS / SC?
What We
 Want In
Our Tests
Ensure
Application
 Behavior
All Objects
   Work
 Together
All Objects
   Work
Individually
All Objects Work
    Together


  Acceptance/
Integration Tests
All Objects Work
   Individually


  Unit Tests
“
     Unit Tests Tell You That
    You Built The System Right.

     Acceptance / Integration
    Tests Tell You That You’ve
      Built The Right System

                       Gojko Adzic,
           Specification by Example
Integration
   Tests
Ensures
Value For
The User
Use The
System As
 The User
  Would
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Scenario('Searching For An Item', function() {
 Given('an auction item that is available for sale', function() {
  var itemTitle = 'item';
  beforeEach(function() {
    Fictum.addResource('Item', {title: itemTitle});
  });
  When('I search for that auction item', function() {
    beforeEach(function() {
        Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle);
        Simulo.clickOn('#mainSearchWidget .submit-search');
      });

        Then('I should see the auction item within the search results', function(page) {
          page.within('.search-results', function(page) {
            expect(page).toHaveContent(itemTitle);
          });
        });
      });
    });
  });
});
Unit
Tests
Ensures
Value Of The
Architecture
Use Object
   Like A
Collaborator
  Would
Isolate
  The
Object
Example:
Testing A
  View
Test
Through
View API
Total
Flow
Example
sc-init todos --template
install jasmine-sproutcore
https://github.com/gmoeck/jasmine-
             sproutcore
install simulo
https://github.com/gmoeck/simulo
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
describe('Scenario: Adding a todo', function() {
  Given('I have loaded the todo application', function() {
    afterEach(function() {
      Todos.mainPane.remove();
    });
    When('I add a new todo item', function() {
      var description;
      beforeEach(function() {
        description = 'Do Something';
        Simulo.fillIn('#new-todo', description).pressEnter();
      });
      Then('I should see the item in the list of available items', function(page) {
        page.within('#incomplete-todos', function(page) {
          expect(page).toHaveContent(description);
        });
      });
    });
  });
});
resources/templates/todos.handlebars

<h1>Todos</h1>
{{#view Todos.CreateTodoView}}
  <input id="new-todo" type="text" placeholder="What needs to be done?" >
{{/view}}
Error
Error
views/create_todo_view.js


Todos.CreateTodoView = SC.TemplateView.extend({
});
resources/templates/todos.handlebars
<h1>Todos</h1>
{{#view Todos.CreateTodoView}}
  <input id="new-todo" type="text" placeholder="What needs to be done?" >
{{/view}}

{{#collection Todos.TodoListView id="incomplete-todos"}}
  {{content.title}}
{{/collection}}
views/todo_list_view.js


Todos.TodoListView = SC.TemplateCollectionView.extend({
});
tests/unit/views/create_todo_view_spec.js
 describe('Todos.CreateTodoView', function() {
  describe('#insertNewline', function() {
   var createTodoSpy, value;
   beforeEach(function() {
     value = 'Do Something';
     view = Todos.CreateTodoView.create({value: value});
     createTodoSpy = spyOn(Todos.todoListController, 'createTodo');
     view.insertNewline();
   });

       it('delegates to create a new todo with it's current value', function() {
         expect(createTodoSpy).toHaveBeenCalledWith(value);
       });
 });
tests/unit/views/create_todo_view_spec.js
 describe('Todos.CreateTodoView', function() {
  describe('#insertNewline', function() {
   var createTodoSpy, value;
   beforeEach(function() {
     value = 'Do Something';
     view = Todos.CreateTodoView.create({value: value});
     createTodoSpy = spyOn(Todos.todoListController, 'createTodo');
     view.insertNewline();
   });

       it('delegates to create a new todo with it's current value', function() {
         expect(createTodoSpy).toHaveBeenCalledWith(value);
       });
 });
tests/unit/views/create_todo_view_spec.js
 describe('Todos.CreateTodoView', function() {
  describe('#insertNewline', function() {
   var createTodoSpy, value;
   beforeEach(function() {
     value = 'Do Something';
     view = Todos.CreateTodoView.create({value: value});
     createTodoSpy = spyOn(Todos.todoListController, 'createTodo');
     view.insertNewline();
   });

       it('delegates to create a new todo with it's current value', function() {
         expect(createTodoSpy).toHaveBeenCalledWith(value);
       });
 });
tests/unit/views/create_todo_view_spec.js
 describe('Todos.CreateTodoView', function() {
  describe('#insertNewline', function() {
   var createTodoSpy, value;
   beforeEach(function() {
     value = 'Do Something';
     view = Todos.CreateTodoView.create({value: value});
     createTodoSpy = spyOn(Todos.todoListController, 'createTodo');
     view.insertNewline();
   });

       it('delegates to create a new todo with it's current value', function() {
         expect(createTodoSpy).toHaveBeenCalledWith(value);
       });
 });
tests/unit/views/create_todo_view_spec.js
 describe('Todos.CreateTodoView', function() {
  describe('#insertNewline', function() {
   var createTodoSpy, value;
   beforeEach(function() {
     value = 'Do Something';
     view = Todos.CreateTodoView.create({value: value});
     createTodoSpy = spyOn(Todos.todoListController, 'createTodo');
     view.insertNewline();
   });

       it('delegates to create a new todo with it's current value', function() {
         expect(createTodoSpy).toHaveBeenCalledWith(value);
       });
 });
tests/unit/views/create_todo_view_spec.js
 describe('Todos.CreateTodoView', function() {
  describe('#insertNewline', function() {
   var createTodoSpy, value;
   beforeEach(function() {
     value = 'Do Something';
     view = Todos.CreateTodoView.create({value: value});
     createTodoSpy = spyOn(Todos.todoListController, 'createTodo');
     view.insertNewline();
   });

       it('delegates to create a new todo with it's current value', function() {
         expect(createTodoSpy).toHaveBeenCalledWith(value);
       });
 });
tests/unit/views/create_todo_view_spec.js
 describe('Todos.CreateTodoView', function() {
  describe('#insertNewline', function() {
   var createTodoSpy, value;
   beforeEach(function() {
     value = 'Do Something';
     view = Todos.CreateTodoView.create({value: value});
     createTodoSpy = spyOn(Todos.todoListController, 'createTodo');
     view.insertNewline();
   });

       it('delegates to create a new todo with it's current value', function() {
         expect(createTodoSpy).toHaveBeenCalledWith(value);
       });
 });
Todos.todoListController.createTodo
controllers/todo_list_controller.js
Todos.todoListController = SC.ArrayController.create({
  createTodo: function(title) {
  }
});
views/create_todo_view.js
Todos.CreateTodoView = SC.TemplateView.extend(SC.TextFieldSupport, {
  insertNewline: function() {
  }
});
views/create_todo_view.js
Todos.CreateTodoView = SC.TemplateView.extend(SC.TextFieldSupport, {
  insertNewline: function() {
    Todos.todoListController.createTodo(this.get('value'));
  }
});
Should be different, but we already defined
Todos.todoListController.
tests/unit/controllers/todo_list_controller_spec.js

describe('Todos.todoListController', function() {
 describe('#createTodo', function() {
  var createTodoSpy, title;

  beforeEach(function() {
   title = 'title';
   createTodoSpy = spyOn(Todos.Todo, 'create');

   Todos.todoListController.createTodo(title);
  });

    it('creates a todo with the passed in title', function() {
      expect(createTodoSpy).toHaveBeenCalledWith({title: title});
    });
  });
});
tests/unit/controllers/todo_list_controller_spec.js

describe('Todos.todoListController', function() {
 describe('#createTodo', function() {
  var createTodoSpy, title;

  beforeEach(function() {
   title = 'title';
   createTodoSpy = spyOn(Todos.Todo, 'create');

   Todos.todoListController.createTodo(title);
  });

    it('creates a todo with the passed in title', function() {
      expect(createTodoSpy).toHaveBeenCalledWith({title: title});
    });
  });
});
tests/unit/controllers/todo_list_controller_spec.js

describe('Todos.todoListController', function() {
 describe('#createTodo', function() {
  var createTodoSpy, title;

  beforeEach(function() {
   title = 'title';
   createTodoSpy = spyOn(Todos.Todo, 'create');

   Todos.todoListController.createTodo(title);
  });

    it('creates a todo with the passed in title', function() {
      expect(createTodoSpy).toHaveBeenCalledWith({title: title});
    });
  });
});
tests/unit/controllers/todo_list_controller_spec.js

describe('Todos.todoListController', function() {
 describe('#createTodo', function() {
  var createTodoSpy, title;

  beforeEach(function() {
   title = 'title';
   createTodoSpy = spyOn(Todos.Todo, 'create');

   Todos.todoListController.createTodo(title);
  });

    it('creates a todo with the passed in title', function() {
      expect(createTodoSpy).toHaveBeenCalledWith({title: title});
    });
  });
});
tests/unit/controllers/todo_list_controller_spec.js

describe('Todos.todoListController', function() {
 describe('#createTodo', function() {
  var createTodoSpy, title;

  beforeEach(function() {
   title = 'title';
   createTodoSpy = spyOn(Todos.Todo, 'create');

   Todos.todoListController.createTodo(title);
  });

    it('creates a todo with the passed in title', function() {
      expect(createTodoSpy).toHaveBeenCalledWith({title: title});
    });
  });
});
tests/unit/controllers/todo_list_controller_spec.js

describe('Todos.todoListController', function() {
 describe('#createTodo', function() {
  var createTodoSpy, title;

  beforeEach(function() {
   title = 'title';
   createTodoSpy = spyOn(Todos.Todo, 'create');

   Todos.todoListController.createTodo(title);
  });

    it('creates a todo with the passed in title', function() {
      expect(createTodoSpy).toHaveBeenCalledWith({title: title});
    });
  });
});
Todos.Todo.create
models/todo.js
Todos.Todo = SC.Object.extend({
});
controllers/todo_list_controller.js
Todos.todoListController = SC.ArrayController.create({
  createTodo: function(title) {
    Todos.Todo.create({title: title});
  }
});
tests/unit/controllers/todo_list_controller_spec.js
describe('Todos.todoListController', function() {
 describe('#createTodo', function() {
  var createTodoSpy, title, todo;

  beforeEach(function() {
   title = 'title';
   todo = {title: title};
   createTodoSpy = spyOn(Todos.Todo, 'create').andReturn(todo);

      Todos.todoListController.createTodo(title);
    });
    ...
    it('adds that todo to it's content', function() {
       expect(Todos.todoListController.get('content')).toContain(todo);
    });
  });
});
controllers/todo_list_controller.js

Todos.todoListController = SC.ArrayController.create({
 content: [],

  createTodo: function(title) {
    Todos.Todo.create({title: title});
  }
});
controllers/todo_list_controller.js
Todos.todoListController = SC.ArrayController.create({
 content: [],

  createTodo: function(title) {
    var todo = Todos.Todo.create({title: title});
    this.pushObject(todo);
  }
});
Questions?
gmoeck@gmail.com
   @gregmoeck

Más contenido relacionado

La actualidad más candente

Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
Rubyc Slides
 

La actualidad más candente (13)

Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with Jasmine
 
ngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency InjectionngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency Injection
 
Postgre sql index
Postgre sql indexPostgre sql index
Postgre sql index
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
 
Akka tips
Akka tipsAkka tips
Akka tips
 
Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo
 
06 jQuery #burningkeyboards
06 jQuery  #burningkeyboards06 jQuery  #burningkeyboards
06 jQuery #burningkeyboards
 
Javascript Primer
Javascript PrimerJavascript Primer
Javascript Primer
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wild
 
Your Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsYour Second iPhone App - Code Listings
Your Second iPhone App - Code Listings
 
04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascript
 

Destacado

Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
Yehuda Katz
 
Presentation islam
Presentation islamPresentation islam
Presentation islam
Zinat Tamami
 
Derechos de autor entrega
Derechos de autor entregaDerechos de autor entrega
Derechos de autor entrega
Camilo Diaz
 
Google chrome chromebooks
Google chrome   chromebooksGoogle chrome   chromebooks
Google chrome chromebooks
Brandon Raymo
 
2.1.2 contoh pendekatan scientific pai pb sd
2.1.2 contoh pendekatan scientific pai pb sd2.1.2 contoh pendekatan scientific pai pb sd
2.1.2 contoh pendekatan scientific pai pb sd
Julak Laraw
 
Presentation biologi
Presentation biologiPresentation biologi
Presentation biologi
Zinat Tamami
 
From GNETS to Home School
From GNETS to Home SchoolFrom GNETS to Home School
From GNETS to Home School
eeniarrol
 

Destacado (20)

Дума и администрация о дорогах
Дума и администрация о дорогахДума и администрация о дорогах
Дума и администрация о дорогах
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Presentation islam
Presentation islamPresentation islam
Presentation islam
 
Ke arah kesatuan gerakan islam fathi yakan
Ke arah kesatuan gerakan islam   fathi yakanKe arah kesatuan gerakan islam   fathi yakan
Ke arah kesatuan gerakan islam fathi yakan
 
Unknown Unicast Storm Control in Internet Exchange
Unknown Unicast Storm Control in Internet ExchangeUnknown Unicast Storm Control in Internet Exchange
Unknown Unicast Storm Control in Internet Exchange
 
Derechos de autor entrega
Derechos de autor entregaDerechos de autor entrega
Derechos de autor entrega
 
Tugas 1
Tugas 1Tugas 1
Tugas 1
 
Facebook Feature (Like,Unlike,Comment)
Facebook Feature (Like,Unlike,Comment)  Facebook Feature (Like,Unlike,Comment)
Facebook Feature (Like,Unlike,Comment)
 
Google chrome chromebooks
Google chrome   chromebooksGoogle chrome   chromebooks
Google chrome chromebooks
 
2.1.2 contoh pendekatan scientific pai pb sd
2.1.2 contoh pendekatan scientific pai pb sd2.1.2 contoh pendekatan scientific pai pb sd
2.1.2 contoh pendekatan scientific pai pb sd
 
Sistemas visuais do cotidiano - Etec
Sistemas visuais do cotidiano - EtecSistemas visuais do cotidiano - Etec
Sistemas visuais do cotidiano - Etec
 
President's List Honors
President's List Honors President's List Honors
President's List Honors
 
Presentation biologi
Presentation biologiPresentation biologi
Presentation biologi
 
From GNETS to Home School
From GNETS to Home SchoolFrom GNETS to Home School
From GNETS to Home School
 
Chris Woolard, Ofcom, Preparing for change – what will drive future growth?
Chris Woolard, Ofcom, Preparing for change – what will drive future growth?Chris Woolard, Ofcom, Preparing for change – what will drive future growth?
Chris Woolard, Ofcom, Preparing for change – what will drive future growth?
 
Wc no
Wc noWc no
Wc no
 
La perdurabilidad en las empresas familiares maria perez
La perdurabilidad en las empresas familiares maria perezLa perdurabilidad en las empresas familiares maria perez
La perdurabilidad en las empresas familiares maria perez
 
Olahragasr
OlahragasrOlahragasr
Olahragasr
 
jQuery For Developers Stack Overflow Dev Days Toronto
jQuery For Developers Stack Overflow Dev Days TorontojQuery For Developers Stack Overflow Dev Days Toronto
jQuery For Developers Stack Overflow Dev Days Toronto
 
Dba i 9i
Dba i 9iDba i 9i
Dba i 9i
 

Similar a Testing Your Sproutcore Presentation

Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
Miao Siyu
 
Edit the script in to disable code which adds demonstration entries to.pdf
Edit the script in to disable code which adds demonstration entries to.pdfEdit the script in to disable code which adds demonstration entries to.pdf
Edit the script in to disable code which adds demonstration entries to.pdf
PeterM9sWhitej
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
SHIVA101531
 
This is the main file include itemh include itemList.pdf
This is the main file include itemh include itemList.pdfThis is the main file include itemh include itemList.pdf
This is the main file include itemh include itemList.pdf
info334223
 

Similar a Testing Your Sproutcore Presentation (20)

Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScript
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
JavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScriptJavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScript
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 
Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScript
 
J Query
J QueryJ Query
J Query
 
Write a program to find the number of comparisons using the binary se.docx
 Write a program to find the number of comparisons using the binary se.docx Write a program to find the number of comparisons using the binary se.docx
Write a program to find the number of comparisons using the binary se.docx
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
 
Edit the script in to disable code which adds demonstration entries to.pdf
Edit the script in to disable code which adds demonstration entries to.pdfEdit the script in to disable code which adds demonstration entries to.pdf
Edit the script in to disable code which adds demonstration entries to.pdf
 
Say It With Javascript
Say It With JavascriptSay It With Javascript
Say It With Javascript
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
 
BVJS
BVJSBVJS
BVJS
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code Organization
 
Creating a Facebook Clone - Part XXXI - Transcript.pdf
Creating a Facebook Clone - Part XXXI - Transcript.pdfCreating a Facebook Clone - Part XXXI - Transcript.pdf
Creating a Facebook Clone - Part XXXI - Transcript.pdf
 
JSConf: All You Can Leet
JSConf: All You Can LeetJSConf: All You Can Leet
JSConf: All You Can Leet
 
Object-oriented Javascript
Object-oriented JavascriptObject-oriented Javascript
Object-oriented Javascript
 
This is the main file include itemh include itemList.pdf
This is the main file include itemh include itemList.pdfThis is the main file include itemh include itemList.pdf
This is the main file include itemh include itemList.pdf
 

Último

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Último (20)

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 

Testing Your Sproutcore Presentation

  • 1. How do I test my Sproutcore Application? Greg Moeck
  • 10. Practice Test Last Unit Testing?
  • 12. Question 3
  • 14. What We Want In Our Tests
  • 16. All Objects Work Together
  • 17. All Objects Work Individually
  • 18. All Objects Work Together Acceptance/ Integration Tests
  • 19. All Objects Work Individually Unit Tests
  • 20. Unit Tests Tell You That You Built The System Right. Acceptance / Integration Tests Tell You That You’ve Built The Right System Gojko Adzic, Specification by Example
  • 21. Integration Tests
  • 23. Use The System As The User Would
  • 24. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 25. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 26. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 27. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 28. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 29. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 30. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 31. Scenario('Searching For An Item', function() { Given('an auction item that is available for sale', function() { var itemTitle = 'item'; beforeEach(function() { Fictum.addResource('Item', {title: itemTitle}); }); When('I search for that auction item', function() { beforeEach(function() { Simulo.fillIn('#mainSearchWidget input[type="text"]', itemTitle); Simulo.clickOn('#mainSearchWidget .submit-search'); }); Then('I should see the auction item within the search results', function(page) { page.within('.search-results', function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); }); });
  • 34. Use Object Like A Collaborator Would
  • 39.
  • 41.
  • 45. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 46. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 47. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 48. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 49. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 50. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 51. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 52. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 53. describe('Scenario: Adding a todo', function() { Given('I have loaded the todo application', function() { afterEach(function() { Todos.mainPane.remove(); }); When('I add a new todo item', function() { var description; beforeEach(function() { description = 'Do Something'; Simulo.fillIn('#new-todo', description).pressEnter(); }); Then('I should see the item in the list of available items', function(page) { page.within('#incomplete-todos', function(page) { expect(page).toHaveContent(description); }); }); }); }); });
  • 54.
  • 55. resources/templates/todos.handlebars <h1>Todos</h1> {{#view Todos.CreateTodoView}} <input id="new-todo" type="text" placeholder="What needs to be done?" > {{/view}}
  • 56.
  • 57.
  • 58. Error
  • 59. Error
  • 61.
  • 62. resources/templates/todos.handlebars <h1>Todos</h1> {{#view Todos.CreateTodoView}} <input id="new-todo" type="text" placeholder="What needs to be done?" > {{/view}} {{#collection Todos.TodoListView id="incomplete-todos"}} {{content.title}} {{/collection}}
  • 63.
  • 64.
  • 65.
  • 67.
  • 68. tests/unit/views/create_todo_view_spec.js describe('Todos.CreateTodoView', function() { describe('#insertNewline', function() { var createTodoSpy, value; beforeEach(function() { value = 'Do Something'; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, 'createTodo'); view.insertNewline(); }); it('delegates to create a new todo with it's current value', function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • 69. tests/unit/views/create_todo_view_spec.js describe('Todos.CreateTodoView', function() { describe('#insertNewline', function() { var createTodoSpy, value; beforeEach(function() { value = 'Do Something'; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, 'createTodo'); view.insertNewline(); }); it('delegates to create a new todo with it's current value', function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • 70. tests/unit/views/create_todo_view_spec.js describe('Todos.CreateTodoView', function() { describe('#insertNewline', function() { var createTodoSpy, value; beforeEach(function() { value = 'Do Something'; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, 'createTodo'); view.insertNewline(); }); it('delegates to create a new todo with it's current value', function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • 71. tests/unit/views/create_todo_view_spec.js describe('Todos.CreateTodoView', function() { describe('#insertNewline', function() { var createTodoSpy, value; beforeEach(function() { value = 'Do Something'; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, 'createTodo'); view.insertNewline(); }); it('delegates to create a new todo with it's current value', function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • 72. tests/unit/views/create_todo_view_spec.js describe('Todos.CreateTodoView', function() { describe('#insertNewline', function() { var createTodoSpy, value; beforeEach(function() { value = 'Do Something'; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, 'createTodo'); view.insertNewline(); }); it('delegates to create a new todo with it's current value', function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • 73. tests/unit/views/create_todo_view_spec.js describe('Todos.CreateTodoView', function() { describe('#insertNewline', function() { var createTodoSpy, value; beforeEach(function() { value = 'Do Something'; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, 'createTodo'); view.insertNewline(); }); it('delegates to create a new todo with it's current value', function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • 74. tests/unit/views/create_todo_view_spec.js describe('Todos.CreateTodoView', function() { describe('#insertNewline', function() { var createTodoSpy, value; beforeEach(function() { value = 'Do Something'; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, 'createTodo'); view.insertNewline(); }); it('delegates to create a new todo with it's current value', function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • 75.
  • 76.
  • 79.
  • 81.
  • 82. views/create_todo_view.js Todos.CreateTodoView = SC.TemplateView.extend(SC.TextFieldSupport, { insertNewline: function() { Todos.todoListController.createTodo(this.get('value')); } });
  • 83.
  • 84.
  • 85.
  • 86. Should be different, but we already defined Todos.todoListController.
  • 87. tests/unit/controllers/todo_list_controller_spec.js describe('Todos.todoListController', function() { describe('#createTodo', function() { var createTodoSpy, title; beforeEach(function() { title = 'title'; createTodoSpy = spyOn(Todos.Todo, 'create'); Todos.todoListController.createTodo(title); }); it('creates a todo with the passed in title', function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); }); });
  • 88. tests/unit/controllers/todo_list_controller_spec.js describe('Todos.todoListController', function() { describe('#createTodo', function() { var createTodoSpy, title; beforeEach(function() { title = 'title'; createTodoSpy = spyOn(Todos.Todo, 'create'); Todos.todoListController.createTodo(title); }); it('creates a todo with the passed in title', function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); }); });
  • 89. tests/unit/controllers/todo_list_controller_spec.js describe('Todos.todoListController', function() { describe('#createTodo', function() { var createTodoSpy, title; beforeEach(function() { title = 'title'; createTodoSpy = spyOn(Todos.Todo, 'create'); Todos.todoListController.createTodo(title); }); it('creates a todo with the passed in title', function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); }); });
  • 90. tests/unit/controllers/todo_list_controller_spec.js describe('Todos.todoListController', function() { describe('#createTodo', function() { var createTodoSpy, title; beforeEach(function() { title = 'title'; createTodoSpy = spyOn(Todos.Todo, 'create'); Todos.todoListController.createTodo(title); }); it('creates a todo with the passed in title', function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); }); });
  • 91. tests/unit/controllers/todo_list_controller_spec.js describe('Todos.todoListController', function() { describe('#createTodo', function() { var createTodoSpy, title; beforeEach(function() { title = 'title'; createTodoSpy = spyOn(Todos.Todo, 'create'); Todos.todoListController.createTodo(title); }); it('creates a todo with the passed in title', function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); }); });
  • 92. tests/unit/controllers/todo_list_controller_spec.js describe('Todos.todoListController', function() { describe('#createTodo', function() { var createTodoSpy, title; beforeEach(function() { title = 'title'; createTodoSpy = spyOn(Todos.Todo, 'create'); Todos.todoListController.createTodo(title); }); it('creates a todo with the passed in title', function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); }); });
  • 93.
  • 94.
  • 97.
  • 98. controllers/todo_list_controller.js Todos.todoListController = SC.ArrayController.create({ createTodo: function(title) { Todos.Todo.create({title: title}); } });
  • 99.
  • 100. tests/unit/controllers/todo_list_controller_spec.js describe('Todos.todoListController', function() { describe('#createTodo', function() { var createTodoSpy, title, todo; beforeEach(function() { title = 'title'; todo = {title: title}; createTodoSpy = spyOn(Todos.Todo, 'create').andReturn(todo); Todos.todoListController.createTodo(title); }); ... it('adds that todo to it's content', function() { expect(Todos.todoListController.get('content')).toContain(todo); }); }); });
  • 101.
  • 102. controllers/todo_list_controller.js Todos.todoListController = SC.ArrayController.create({ content: [], createTodo: function(title) { Todos.Todo.create({title: title}); } });
  • 103.
  • 104. controllers/todo_list_controller.js Todos.todoListController = SC.ArrayController.create({ content: [], createTodo: function(title) { var todo = Todos.Todo.create({title: title}); this.pushObject(todo); } });
  • 105.
  • 106.

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n