SlideShare uma empresa 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

Mais conteúdo relacionado

Mais procurados

Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018Joke Puts
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineRaimonds Simanovskis
 
ngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency InjectionngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency InjectionDzmitry Ivashutsin
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmineRubyc Slides
 
Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo Evans Hauser
 
06 jQuery #burningkeyboards
06 jQuery  #burningkeyboards06 jQuery  #burningkeyboards
06 jQuery #burningkeyboardsDenis Ristic
 
Javascript Primer
Javascript PrimerJavascript Primer
Javascript PrimerAdam Hepton
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboardsDenis Ristic
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wildJoe Morgan
 
Your Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsYour Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsVu Tran Lam
 
04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascriptcrgwbr
 

Mais procurados (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
 

Destaque

Дума и администрация о дорогах
Дума и администрация о дорогахДума и администрация о дорогах
Дума и администрация о дорогахОльга Бердецкая
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Presentation islam
Presentation islamPresentation islam
Presentation islamZinat Tamami
 
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 yakanKammi Daerah Serang
 
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 ExchangeJimmy Lim
 
Derechos de autor entrega
Derechos de autor entregaDerechos de autor entrega
Derechos de autor entregaCamilo Diaz
 
Facebook Feature (Like,Unlike,Comment)
Facebook Feature (Like,Unlike,Comment)  Facebook Feature (Like,Unlike,Comment)
Facebook Feature (Like,Unlike,Comment) Kaml Sah
 
Google chrome chromebooks
Google chrome   chromebooksGoogle chrome   chromebooks
Google chrome chromebooksBrandon 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 sdJulak Laraw
 
Presentation biologi
Presentation biologiPresentation biologi
Presentation biologiZinat Tamami
 
From GNETS to Home School
From GNETS to Home SchoolFrom GNETS to Home School
From GNETS to Home Schooleeniarrol
 
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?dcmsdigital
 
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 perezmariaperezgamboa
 
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 TorontoRalph Whitbeck
 

Destaque (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
 

Semelhante a Testing Your Sproutcore Presentation

Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScriptkvangork
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascriptkvangork
 
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 JavaScriptLaurence Svekis ✔
 
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 journeyHuiyi Yan
 
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 JavaScriptRyan Anklam
 
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.docxajoy21
 
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 AppsRebecca Murphey
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascriptMiao 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.pdfPeterM9sWhitej
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript FunctionsColin DeCarlo
 
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 .docxSHIVA101531
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code OrganizationRebecca Murphey
 
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.pdfShaiAlmog1
 
JSConf: All You Can Leet
JSConf: All You Can LeetJSConf: All You Can Leet
JSConf: All You Can Leetjohndaviddalton
 
Object-oriented Javascript
Object-oriented JavascriptObject-oriented Javascript
Object-oriented JavascriptDaniel Ku
 
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.pdfinfo334223
 

Semelhante 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

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
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...Martijn de Jong
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
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 2024The Digital Insurer
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 

Último (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
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...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
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
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 

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 do 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