Skip to content
This repository has been archived by the owner on Nov 11, 2019. It is now read-only.

Commit

Permalink
#9 ui change
Browse files Browse the repository at this point in the history
  • Loading branch information
tomvej committed May 21, 2017
1 parent 1ba5714 commit 337d52c
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"max-len": ["error", 120],
"object-curly-spacing": ["error", "never"],
"import/no-extraneous-dependencies": ["error", {
"devDependencies": ["src/test.js"]
"devDependencies": ["src/test.js", "**/*.spec.js"]
}],
"import/prefer-default-export": "off",
"no-else-return": "off",
Expand Down
28 changes: 14 additions & 14 deletions example/redux.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ feature('Character Search Module', reducer, NAME, () => {
const INITIALIZED_SEARCH = 'initialized search';
scenario('first query', () => {
given();
when('search is initialized', setQuery('Bonehunters'));
when('search is initialized', setQuery, 'Bonehunters');
then('there are no characters', getCharacterIds, (result) => result.should.be.empty());
then('it is loading', isLoading, (result) => result.should.be.true());
then('it can load more', isLoading, (result) => result.should.be.true());
result(INITIALIZED_SEARCH);
});
scenario('first empty query', () => {
given();
when('search is initialized with empty query', setQuery(''));
when('search is initialized with empty query', setQuery, '');
then('there are no characters', getCharacterIds, (result) => result.should.be.empty());
then('it is not loading', isLoading, (result) => result.should.be.false());
then('it cannot load more', canLoadMore, (result) => result.should.be.false());
Expand All @@ -79,7 +79,7 @@ feature('Character Search Module', reducer, NAME, () => {
const LOADED_FIRST_CHARACTERS = 'store with first batch of characters';
scenario('adding less than total characters before limit', () => {
given(INITIALIZED_SEARCH);
when('characters are added', addCharacters(firstBatch, bonehunters.length));
when('characters are added', addCharacters, firstBatch, bonehunters.length);
then('their ids are in the list', getCharacterIds,
(result) => firstBatch.forEach(({id}) => result.should.include(id)));
then('they can be displayed', getCharacter, [0], (result) => result.should.equal(fromJS(bonehunters[0])));
Expand All @@ -91,7 +91,7 @@ feature('Character Search Module', reducer, NAME, () => {
const LOADED_SECOND_CHARACTERS = 'store with second batch of characters';
scenario('adding another characters before limit', () => {
given(LOADED_FIRST_CHARACTERS);
when('another characters are added', addCharacters(secondBatch, bonehunters.length));
when('another characters are added', addCharacters, secondBatch, bonehunters.length);
then('their ids are in the list', getCharacterIds,
(result) => secondBatch.forEach(({id}) => result.should.include(id)));
then('original ids are in the list', getCharacterIds,
Expand All @@ -107,7 +107,7 @@ feature('Character Search Module', reducer, NAME, () => {
const OVER_LIMIT = 'store with characters over limit';
scenario('adding characters over limit', () => {
given(LOADED_SECOND_CHARACTERS);
when('another characters are added', addCharacters(thirdBatch, bonehunters.length));
when('another characters are added', addCharacters, thirdBatch, bonehunters.length);
then('their ids are in the list', getCharacterIds,
(result) => thirdBatch.forEach(({id}) => result.should.include(id)));
then('it is not loading', isLoading, (result) => result.should.be.false());
Expand All @@ -116,15 +116,15 @@ feature('Character Search Module', reducer, NAME, () => {
});
scenario('extending limit', () => {
given(OVER_LIMIT);
when('limit is extended', loadMore());
when('limit is extended', loadMore);
then('it is loading', isLoading, (result) => result.should.be.true());
then('it can load more', isLoading, (result) => result.should.be.true());
});
const ALL_LOADED = 'all characters are loaded';
const fourthSquad = bonehunters.filter(({squad}) => squad === 4);
scenario('getting all characters before limit', () => {
given(INITIALIZED_SEARCH);
when('all characters are loaded', addCharacters(fourthSquad, fourthSquad.length));
when('all characters are loaded', addCharacters, fourthSquad, fourthSquad.length);
then('all characters are in the list', getCharacterIds,
(result) => fourthSquad.forEach(({id}) => result.should.include(id)));
then('it is not loading', isLoading, (result) => result.should.be.false());
Expand All @@ -133,34 +133,34 @@ feature('Character Search Module', reducer, NAME, () => {
});
scenario('extending limit on full store', () => {
given(ALL_LOADED);
when('limit is extended', loadMore());
when('limit is extended', loadMore);
then('it is not loading', isLoading, (result) => result.should.be.false());
then('it cannot load more', isLoading, (result) => result.should.be.false());
});
scenario('changing query while loading', () => {
given(LOADED_FIRST_CHARACTERS);
when('query is changed', setQuery('Bridgeburners'));
when('query is changed', setQuery, 'Bridgeburners');
then('character id list is empty', getCharacterIds, (result) => result.should.be.empty());
then('it is loading', isLoading, (result) => result.should.be.true());
then('it can load more', canLoadMore, (result) => result.should.be.true());
});
scenario('changing query when over limit', () => {
given(OVER_LIMIT);
when('query is changed', setQuery('Bridgeburners'));
when('query is changed', setQuery, 'Bridgeburners');
then('characer id list is empty', getCharacterIds, (result) => result.should.be.empty());
then('it is loading', isLoading, (result) => result.should.be.true());
then('it can load more', canLoadMore, (result) => result.should.be.true());
});
scenario('changing query when finished', () => {
given(ALL_LOADED);
when('query is changed', setQuery('Bridgeburners'));
when('query is changed', setQuery, 'Bridgeburners');
then('characer id list is empty', getCharacterIds, (result) => result.should.be.empty());
then('it is loading', isLoading, (result) => result.should.be.true());
then('it can load more', canLoadMore, (result) => result.should.be.true());
});
scenario('resetting query while loading', () => {
given(LOADED_FIRST_CHARACTERS);
when('query is reset', setQuery('Bonehunters'));
when('query is reset', setQuery, 'Bonehunters');
then('characters ids are in the list', getCharacterIds,
(result) => firstBatch.forEach(({id}) => result.should.include(id)));
then('characters can be displayed', getCharacter, [1],
Expand All @@ -170,7 +170,7 @@ feature('Character Search Module', reducer, NAME, () => {
});
scenario('resetting query when over limit', () => {
given(OVER_LIMIT);
when('query is reset', setQuery('Bonehunters'));
when('query is reset', setQuery, 'Bonehunters');
then('character ids are in the list', getCharacterIds,
(result) => [].concat(firstBatch, secondBatch, thirdBatch).forEach(({id}) => result.contains(id)));
then('characters can be displayed', getCharacter, [20],
Expand All @@ -180,7 +180,7 @@ feature('Character Search Module', reducer, NAME, () => {
});
scenario('resetting query when all loaded', () => {
given(ALL_LOADED);
when('query is reset', setQuery('Bonehunters'));
when('query is reset', setQuery, 'Bonehunters');
then('character ids are in the list', getCharacterIds,
(result) => fourthSquad.forEach(({id}) => result.should.include(id)));
then('characters can be displayed', getCharacter, [fourthSquad[4].id],
Expand Down
18 changes: 10 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,21 @@
},
"homepage": "https://github.com/tomvej/mocha-redux-integration#readme",
"devDependencies": {
"babel-core": "6.24.0",
"babel-eslint": "7.2.1",
"babel-core": "6.24.1",
"babel-eslint": "7.2.3",
"babel-polyfill": "6.23.0",
"babel-preset-es2015": "6.24.0",
"babel-preset-stage-1": "6.22.0",
"babel-register": "6.24.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-stage-1": "6.24.1",
"babel-register": "6.24.1",
"chai": "3.5.0",
"chai-immutable": "1.6.0",
"dirty-chai": "1.2.2",
"eslint": "3.18.0",
"eslint-config-airbnb-base": "11.1.2",
"eslint": "3.19.0",
"eslint-config-airbnb-base": "11.2.0",
"eslint-plugin-import": "2.2.0",
"mocha": "3.2.0"
"mocha": "3.4.1",
"sinon": "2.2.0",
"sinon-chai": "2.10.0"
},
"dependencies": {
"immutable": "3.8.1",
Expand Down
16 changes: 16 additions & 0 deletions src/mochaHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const skipDependentTests = (test) => {
const siblings = test.parent.tests;
const index = siblings.indexOf(test);
siblings.slice(index + 1).forEach((dependant) => {
dependant.pending = true; // eslint-disable-line no-param-reassign
});
};

export const executeCommandWithDependentTests = (test, command) => {
try {
command();
} catch (error) {
skipDependentTests(test);
throw error;
}
};
23 changes: 4 additions & 19 deletions src/mochaUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,9 @@ import createCommonSuite from 'mocha/lib/interfaces/common';

import MockStore from './MockStore';
import ResultStore from './ResultStore';
import {executeCommandWithDependentTests} from './mochaHelpers';
import when from './when';

const execudeAndSkipDependentsOnError = (test, command) => {
try {
command();
} catch (ex) {
const siblings = test.parent.tests;
const index = siblings.indexOf(test);
siblings.slice(index + 1).forEach((dependant) => {
dependant.pending = true; // eslint-disable-line no-param-reassign
});
throw ex;
}
};

const mochaUI = (suite) => {
const suites = [suite];
Expand Down Expand Up @@ -71,7 +61,7 @@ const mochaUI = (suite) => {
});
} else {
test = new Test(`given ${title}`, function given() {
execudeAndSkipDependentsOnError(this.test, () => {
executeCommandWithDependentTests(this.test, () => {
this.store = this.test.parent.results.get(title);
});
});
Expand All @@ -84,12 +74,7 @@ const mochaUI = (suite) => {

// eslint-disable-next-line no-param-reassign
context.when = (title, ...actions) => {
const test = new Test(`when ${title}`, function when() {
invariant(this.store, 'Given must be specified for when.');
execudeAndSkipDependentsOnError(this.test, () => {
this.store = this.store.apply(...actions);
});
});
const test = new Test(`when ${title}`, when(actions));
test.file = file;
suites[0].addTest(test);
return test;
Expand Down
2 changes: 2 additions & 0 deletions src/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import 'babel-polyfill';
import chai, {should} from 'chai';
import chaiImmutable from 'chai-immutable';
import dirtyChai from 'dirty-chai';
import sinonChai from 'sinon-chai';

chai.use(chaiImmutable);
chai.use(dirtyChai);
chai.use(sinonChai);

should();
17 changes: 17 additions & 0 deletions src/when.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import invariant from 'invariant';
import {skipDependentTests} from './mochaHelpers';

const createAction = (args) => args[0].apply(null, args.slice(1));

export default (actions) => function when() {
invariant(this.store, 'Given must be specified for when');

try {
const multiple = Array.isArray(actions[0]);
const actualActions = multiple ? actions.map(createAction) : [createAction(actions)];
this.store = this.store.apply(...actualActions);
} catch (error) {
skipDependentTests(this.test);
throw error;
}
};
65 changes: 65 additions & 0 deletions src/when.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {spy} from 'sinon';
import when from './when';

describe('when test creator', () => {
const callTest = (apply, ...actions) => {
const test = when(actions);
test.call({store: {apply}});
};

const createAction = () => ({type: 'SIMPLE_ACTION'});
const addCharacter = (name, squad) => ({
type: 'ADD_CHARACTER',
name,
squad,
});

it('throws an error when there is no store', () => {
const test = when([createAction]);
(() => test.call({})).should.throw();
});
it('applies single action', () => {
const apply = spy();
callTest(apply, createAction);

apply.should.have.been.calledOnce();
apply.should.have.been.calledWith(createAction());
});
it('sets the store with applied actions to context', () => {
const updatedStore = {state: 'Store has been updated'};
const context = {store: {apply: () => updatedStore}};
when([createAction]).call(context);
context.store.should.equal(updatedStore);
});
it('applies single action with parameters', () => {
const apply = spy();
callTest(apply, addCharacter, 'Strings', 4);

apply.should.have.been.calledOnce();
apply.should.have.been.calledWith(addCharacter('Strings', 4));
});
it('applies multiple actions', () => {
const createAnotherAction = () => ({type: 'ANOTHER_ACTION'});
const apply = spy();
callTest(apply, [createAction], [createAnotherAction]);

apply.should.have.been.calledOnce();
apply.should.have.been.calledWith(createAction(), createAnotherAction());
});
it('applies multiple actions with parameters', () => {
const apply = spy();
callTest(
apply,
[addCharacter, 'Strings', 4],
[addCharacter, 'Tarr', 4],
);

apply.should.have.been.calledOnce();
apply.should.have.been.calledWith(addCharacter('Strings', 4), addCharacter('Tarr', 4));
});

it('skips dependent tests when action cannot be created');
it('skips dependent tests when action cannot be applied');
it('throws error when action cannot be created');
it('throws error when action cannt be applied');
});

0 comments on commit 337d52c

Please sign in to comment.