Skip to content

Commit

Permalink
Refactor tests to remain 100% coverage with node 7
Browse files Browse the repository at this point in the history
  • Loading branch information
reneviering committed Dec 23, 2016
1 parent f757bb1 commit 036b2b3
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 67 deletions.
95 changes: 51 additions & 44 deletions __tests__/router.spec.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,15 @@
import {createRouter} from '../index.js';
let hashChangeHandlers = [];
let loadHandlers = [];

jest.mock('../core/dataProvider.js');

// window mock
window.addEventListener = (eventName, handler) => {
if (eventName === 'hashchange') {
hashChangeHandlers.push(handler);
}

if (eventName === 'load') {
loadHandlers.push(handler);
}
};

let lastHash;

const simulateHashChange = hash => {
if (lastHash !== hash) {
window.location.hash = hash;
hashChangeHandlers.forEach(handler => handler());
}
window.location.hash = hash;
window.dispatchEvent(new Event('hashchange'));
};

const simulateLoad = hash => {
window.location.hash = hash;
loadHandlers.forEach(handler => handler());
};

const clearHandlers = () => {
hashChangeHandlers = [];
loadHandlers = [];
window.dispatchEvent(new Event('load'));
};

describe('router', () => {
Expand All @@ -44,7 +22,6 @@ describe('router', () => {
});

beforeEach(() => {
clearHandlers();
domEntryPoint.innerHTML = '';
});

Expand Down Expand Up @@ -141,8 +118,12 @@ describe('router', () => {
});
simulateLoad('');
simulateHashChange('');
expect(domEntryPoint.innerHTML).toEqual('<p>I am the default route</p>');
expect(spy.mock.calls.length).toBe(2);

setTimeout(() => {
expect(domEntryPoint.innerHTML).toEqual('<p>I am the default route</p>');
expect(spy.mock.calls.length).toBe(2);
}, 0);

});

describe('no routeHandler is defined', () => {
Expand All @@ -155,7 +136,9 @@ describe('router', () => {
simulateLoad('');
simulateHashChange('');
};

expect(init).not.toThrow();

});
});
});
Expand All @@ -171,8 +154,12 @@ describe('router', () => {
});
simulateLoad('');
simulateHashChange('');
expect(domEntryPoint.innerHTML).toEqual(expectedRenderedTemplate);
expect(spy.mock.calls.length).toBe(2);

setTimeout(() => {
expect(domEntryPoint.innerHTML).toEqual(expectedRenderedTemplate);
expect(spy.mock.calls.length).toBe(2);
}, 0);

});
});

Expand All @@ -192,8 +179,12 @@ describe('router', () => {
});
simulateLoad('');
simulateHashChange('');
expect(domEntryPoint.innerHTML).toEqual('<p>Rendered from template.html</p>');
expect(spy.mock.calls.length).toBe(2);

setTimeout(() => {
expect(domEntryPoint.innerHTML).toEqual('<p>Rendered from template.html</p>');
expect(spy.mock.calls.length).toBe(2);
}, 0);

});
});

Expand All @@ -209,10 +200,18 @@ describe('router', () => {
routeHandler: () => {},
dispose: spy
})
.addRoute('home', () => {});
.addRoute('home', {
routeHandler: () => {},
templateString: 'asdfasfasf',
dispose: () => {}
});
simulateHashChange('');
simulateHashChange('home');
expect(spy.mock.calls.length).toEqual(1);

setTimeout(() => {
expect(spy.mock.calls.length).toEqual(1);
}, 0);

});
});
});
Expand All @@ -225,7 +224,11 @@ describe('router', () => {
router
.addRoute('', spy, {dataToPass});
simulateHashChange('');
expect(spy.mock.calls[0][2]).toEqual({dataToPass});

setTimeout(() => {
expect(spy.mock.calls[0][2]).toEqual({dataToPass});
}, 0);

});

test('data is passed as last parameter into routeHandler function of routes with more complex configuration', () => {
Expand All @@ -239,7 +242,11 @@ describe('router', () => {
routeHandler: spy
}, {dataToPass});
simulateHashChange('');
expect(spy.mock.calls[0][2]).toEqual({dataToPass});

setTimeout(() => {
expect(spy.mock.calls[0][2]).toEqual({dataToPass});
}, 0);

});
});

Expand All @@ -254,15 +261,15 @@ describe('router', () => {
remove: undefined
};

const init = () => {
const router = createRouter(domEntryPointMock);
router
.addRoute('', () => {});
simulateHashChange('');
const router = createRouter(domEntryPointMock);
router
.addRoute('', () => {})
.addRoute('home', () => {});
simulateHashChange('');
simulateHashChange('home');
setTimeout(() => {
expect(domEntryPointMock.removeNode.mock.calls.length).toEqual(1);
};
expect(init).not.toThrow();

});
});
});
});
27 changes: 27 additions & 0 deletions core/__mocks__/httpRequestFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export class XMLHttpRequestFactory {
constructor() {
this.shouldFail = false;
this.readyState = 4;
}

onreadystatechange() {}
open(httpVerb, url) {
if (url === '/path/to/success') {
this.shouldFail = false;
}

if (url === '/path/to/error') {
this.shouldFail = true;
}

if (url === '/path/to/not/ready') {
this.shouldFail = false;
this.readyState = 0;
}
}
send() {
if (this.shouldFail === false) {
this.onreadystatechange();
}
}
}
30 changes: 8 additions & 22 deletions core/__tests__/dataProvider.spec.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,22 @@
import {loadTemplate} from '../dataProvider';

// Add a simple XMLHttpRequest mock which already succeeds to test functionality of the dataProvider

const initXMLHttpReqestMock = shouldFail => {
class XMLHttpRequestMock {
constructor() {
this.readyState = shouldFail === true ? 0 : 4;
}
onreadystatechange() {}
open() {}
send() {
this.onreadystatechange();
}
}
window.XMLHttpRequest = XMLHttpRequestMock;

};
jest.mock('../httpRequestFactory.js');

describe('loadTemplate()', () => {
test('invokes successCallback with template string if template is loaded', () => {
initXMLHttpReqestMock(false);
const spy = jest.fn();
loadTemplate('', spy);

loadTemplate('/path/to/success', spy);
expect(spy.mock.calls.length).toBe(1);
});

test('does not invoke successCallback if template could not get loaded', () => {
initXMLHttpReqestMock(true);
const spy = jest.fn();
loadTemplate('', spy);
loadTemplate('/path/to/error', spy);
expect(spy.mock.calls.length).toBe(0);
});

test('does not invoke successCallback if template loading is not ready', () => {
const spy = jest.fn();
loadTemplate('/path/to/not/ready', spy);
expect(spy.mock.calls.length).toBe(0);
});
});
29 changes: 29 additions & 0 deletions core/__tests__/templates.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {renderTemplates} from '../templates';
jest.mock('../dataProvider.js');

describe('template rendering', () => {
test('renders templateString, if it is defined inside the routeConfiguration', () => {
Expand All @@ -21,6 +22,34 @@ describe('template rendering', () => {
expect(spy.mock.calls.length).toEqual(0);
});

test('renders templateUrl, if it is defined inside the routeConfiguration', () => {
let domEntryPointMock = {
innerHTML: ''
};

const spy = jest.fn();
renderTemplates({templateUrl: 'path/to/template.html'}, domEntryPointMock, spy);
expect(domEntryPointMock.innerHTML).toEqual('<p>Rendered from template.html</p>');
expect(spy.mock.calls.length).toEqual(1);
});

test('renders templateId, if it is defined inside the routeConfiguration', () => {
let domEntryPointMock = {
innerHTML: ''
};

const templateScript = document.createElement('script');
templateScript.setAttribute('id', 'template4711');
templateScript.setAttribute('type', 'text/template');
templateScript.innerHTML = '<p>Rendered from template script with id 4711</p>';
document.body.appendChild(templateScript);

const spy = jest.fn();
renderTemplates({templateId: 'template4711'}, domEntryPointMock, spy);
expect(domEntryPointMock.innerHTML).toEqual('<p>Rendered from template script with id 4711</p>');
expect(spy.mock.calls.length).toEqual(1);
});

test('nothing is rendered if no routeConfiguration is defined', () => {
const d = {
innerHTML: ''
Expand Down
4 changes: 3 additions & 1 deletion core/dataProvider.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {XMLHttpRequestFactory} from './httpRequestFactory.js';

export const loadTemplate = (templateUrl, successCallback) => {
var xhr = new XMLHttpRequest();
var xhr = new XMLHttpRequestFactory();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
successCallback(xhr.responseText);
Expand Down
1 change: 1 addition & 0 deletions core/httpRequestFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const XMLHttpRequestFactory = window.XMLHttpRequest;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"core/dataProvider.js",
"core/routeParams.js",
"core/templates.js",
"core/httpRequestFactory.js",
"index.js"
],
"scripts": {
Expand Down

0 comments on commit 036b2b3

Please sign in to comment.