Commit afd0bc24 authored by Pascal Hartig's avatar Pascal Hartig

flight: add first set of unit tests

parent 26da0784
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"depot": "~0.1.4", "depot": "~0.1.4",
"es5-shim": "git://github.com/kriskowal/es5-shim.git#2.0.0",
"flight": "~1.1.0", "flight": "~1.1.0",
"jquery": "1.8.3", "jquery": "1.8.3",
"requirejs": "~2.1.5", "requirejs": "~2.1.5",
......
...@@ -17,3 +17,17 @@ Here are some links you may find helpful: ...@@ -17,3 +17,17 @@ Here are some links you may find helpful:
* [Flight on Twitter](http://twitter.com/flight) * [Flight on Twitter](http://twitter.com/flight)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ _If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Running the Tests
To run the tests, you need to install additional helpers via bower and npm and
run `npm test` afterwards:
```bash
bower install & npm install
npm test
```
You can also run `karma start` after the dependencies are installed to
automatically watch for changes and re-run the test suite.
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 4,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"white": true,
"jquery": true,
"globals": {
"requirejs": false,
"describe": false,
"describeComponent": false,
"setupComponent": false,
"it": false,
"expect": false,
"beforeEach": false,
"afterEach": false,
"spyOnEvent": false,
"mocks": false,
"readFixtures": false,
"spyOn": false
}
}
<input id="new-todo" placeholder="What needs to be done?" autofocus>
(function () {
'use strict';
function FakeDataStore(data) {
this.data = data || [
{title: 'buy some unicorns', completed: false, id: '108e8c51-bb3f-608d-15e2-611cfc7e5838'},
{title: 'get a baguette mustache', completed: false, id: '6cdd0a1f-b6f8-21e1-f35b-aa18af99ad91'},
{title: 'shave yaks', completed: true, id: 'abe678dd-3087-198c-eefa-180248cb3d8b'}
];
}
FakeDataStore.prototype.all = function all() {
return this.data;
};
FakeDataStore.prototype.save = function save(data) {
this.data.push(data);
};
FakeDataStore.prototype.destroyAll = function destroyAll() {
// Stub
};
window.mocks.DataStore = FakeDataStore;
}());
describeComponent('app/js/data/stats', function () {
'use strict';
describe('recount without datastore', function () {
beforeEach(function () {
setupComponent({
dataStore: new mocks.DataStore([])
});
});
afterEach(function () {
localStorage.clear();
});
it('should trigger a dataStatsCounted event', function () {
spyOnEvent(document, 'dataStatsCounted');
this.component.recount();
expect('dataStatsCounted').toHaveBeenTriggeredOn(document);
});
it('should trigger dataStatsCounted when todos are loaded', function () {
spyOnEvent(document, 'dataStatsCounted');
$(document).trigger('dataTodosLoaded');
expect('dataStatsCounted').toHaveBeenTriggeredOn(document);
});
it('should provide empty stats', function () {
spyOnEvent(document, 'dataStatsCounted');
this.component.recount();
expect('dataStatsCounted').toHaveBeenTriggeredOnAndWith(document, {
all: 0,
remaining: 0,
completed: 0,
filter: ''
});
});
});
describe('recount with datastore', function () {
beforeEach(function () {
setupComponent({
dataStore: new mocks.DataStore()
});
});
it('should provide full stats', function () {
spyOnEvent(document, 'dataStatsCounted');
this.component.recount();
expect('dataStatsCounted').toHaveBeenTriggeredOnAndWith(document, {
all: 3,
remaining: 2,
completed: 1,
filter: ''
});
});
});
});
describeComponent('app/js/data/todos', function () {
'use strict';
describe('without datastore', function () {
beforeEach(function () {
this.dataStore = new mocks.DataStore([]);
setupComponent({
dataStore: this.dataStore
});
});
it('should add a new entry', function () {
var title = 'buy some unicorns';
spyOnEvent(document, 'dataTodoAdded');
this.component.trigger('uiAddRequested', {
title: title
});
expect('dataTodoAdded').toHaveBeenTriggeredOn(document);
expect(this.dataStore.data.length).toBe(1);
expect(this.dataStore.all()[0].title).toBe(title);
});
});
describe('with datastore', function () {
beforeEach(function () {
this.dataStore = new mocks.DataStore();
setupComponent({
dataStore: this.dataStore
});
});
it('removes completed', function () {
spyOn(this.dataStore, 'destroyAll');
this.component.trigger('uiClearRequested');
expect(this.dataStore.destroyAll).toHaveBeenCalledWith({ completed: true });
});
});
});
describeComponent('app/js/ui/new_item', function () {
'use strict';
var ENTER_KEY = 13;
beforeEach(function () {
setupComponent(readFixtures('new_todo.html'));
});
it('triggers uiAddRequested on enter', function () {
var event = $.Event('keydown');
event.which = ENTER_KEY;
spyOnEvent(document, 'uiAddRequested');
this.component.$node.val('shave moar yaks');
this.component.trigger(event);
expect('uiAddRequested').toHaveBeenTriggeredOnAndWith(document, {
title: 'shave moar yaks'
});
});
it('trims values', function () {
var event = $.Event('keydown');
event.which = ENTER_KEY;
spyOnEvent(document, 'uiAddRequested');
this.component.$node.val(' trim inputs ');
this.component.trigger(event);
expect('uiAddRequested').toHaveBeenTriggeredOnAndWith(document, {
title: 'trim inputs'
});
});
it('ignore empty values', function () {
var event = $.Event('keydown');
event.which = ENTER_KEY;
spyOnEvent(document, 'uiAddRequested');
this.component.trigger(event);
expect('uiAddRequested').not.toHaveBeenTriggeredOn(document);
});
});
describeComponent('app/js/ui/stats', function () {
'use strict';
beforeEach(function () {
setupComponent(readFixtures('footer.html'));
});
it('renders when stats change', function () {
var data = {
all: 3,
remaining: 2,
completed: 1,
filter: ''
};
expect(this.component.$node).toBeEmpty();
$(document).trigger('dataStatsCounted', data);
expect(this.component.$node).not.toBeEmpty();
expect(this.component.$node).toBeVisible();
});
it('is hidden when data is empty', function () {
var data = {
all: 0,
remaining: 0,
completed: 0,
filter: ''
};
$(document).trigger('dataStatsCounted', data);
expect(this.component.$node).toBeHidden();
});
it('hides clear-completed with no completed items', function () {
var data = {
all: 2,
remaining: 2,
completed: 0,
filter: ''
};
this.component.render(null, data);
expect(this.component.select('clearCompletedSelector').length).toBe(0);
});
it('shows clear-completed with completed items', function () {
var data = {
all: 2,
remaining: 1,
completed: 1,
filter: ''
};
this.component.render(null, data);
expect(this.component.select('clearCompletedSelector').length).toBe(1);
});
it('triggers uiClearRequested on click', function () {
var data = {
all: 2,
remaining: 1,
completed: 1,
filter: ''
};
spyOnEvent(document, 'uiClearRequested');
this.component.render(null, data);
this.component.trigger(this.component.attr.clearCompletedSelector, 'click');
expect('uiClearRequested').toHaveBeenTriggeredOn(this.component);
});
});
/*jshint camelcase:false*/
/*global jasmine*/
'use strict';
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return (/_spec\.js$/.test(file));
});
window.mocks = {};
requirejs.config({
// Karma serves files from '/base'
baseUrl: '/base',
paths: {
flight: 'bower_components/flight',
depot: 'bower_components/depot/depot',
text: 'bower_components/requirejs-text/text'
},
// ask Require.js to load these files (all our tests)
deps: tests,
// start test run, once Require.js is done
callback: window.__karma__.start
});
jasmine.getFixtures().fixturesPath = '/base/test/fixture';
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment