add more unit tests for js services

This commit is contained in:
Felix Hamann 2019-05-26 20:37:09 +02:00
parent 1bc0170bc2
commit b32c80b457
7 changed files with 318 additions and 28 deletions

View File

@ -11,7 +11,7 @@ export class HtmlHelpers {
.then(
(responseText) => {
const docFrag = document.createRange().createContextualFragment(responseText);
let idPrefix;
let idPrefix = '';
if (!options.keepIds) {
idPrefix = this._getIdPrefix();
this._prefixIds(docFrag, idPrefix);

View File

@ -2,6 +2,7 @@ import { HtmlHelpers } from "./html-helpers";
describe('HtmlHelpers', () => {
let htmlHelpers;
beforeEach(() => {
htmlHelpers = new HtmlHelpers();
});
@ -10,13 +11,17 @@ describe('HtmlHelpers', () => {
expect(htmlHelpers).toBeTruthy();
});
describe('parseResponse', () => {
it('should return a promise with idPrefix and element', (done) => {
const response = {
text: () => Promise.resolve('<div>Test</div>'),
};
describe('parseResponse()', () => {
let fakeHttpResponse;
htmlHelpers.parseResponse(response).then(result => {
beforeEach(() => {
fakeHttpResponse = {
text: () => Promise.resolve('<div id="test-div">Test</div>'),
};
});
it('should return a promise with idPrefix and element', (done) => {
htmlHelpers.parseResponse(fakeHttpResponse).then(result => {
expect(result.idPrefix).toBeDefined();
expect(result.element).toBeDefined();
expect(result.element.textContent).toMatch('Test');
@ -25,34 +30,25 @@ describe('HtmlHelpers', () => {
});
it('should nudge IDs', (done) => {
const response = {
text: () => Promise.resolve('<div id="test-div">Test</div>'),
};
htmlHelpers.parseResponse(response).then(result => {
htmlHelpers.parseResponse(fakeHttpResponse).then(result => {
expect(result.idPrefix).toBeDefined();
expect(result.element).toBeDefined();
const origElement = result.element.querySelector('#test-div');
expect(origElement).toBeFalsy();
const nudgedElement = result.element.querySelector('#' + result.idPrefix + 'test-div');
expect(nudgedElement).toBeTruthy();
const elementWithOrigId = result.element.querySelector('#test-div');
expect(elementWithOrigId).toBeFalsy();
const elementWithNudgedId = result.element.querySelector('#' + result.idPrefix + 'test-div');
expect(elementWithNudgedId).toBeTruthy();
done();
});
});
it('should not nudge IDs with option "keepIds"', (done) => {
const response = {
text: () => Promise.resolve('<div id="test-div">Test</div>'),
};
const options = { keepIds: true };
htmlHelpers.parseResponse(response, options).then(result => {
expect(result.idPrefix).not.toBeDefined();
htmlHelpers.parseResponse(fakeHttpResponse, options).then(result => {
expect(result.idPrefix).toBe('');
expect(result.element).toBeDefined();
const origElement = result.element.querySelector('#test-div');
expect(origElement).toBeTruthy();
const nudgedElement = result.element.querySelector('#' + result.idPrefix + 'test-div');
expect(nudgedElement).toBeFalsy();
const elementWithOrigId = result.element.querySelector('#test-div');
expect(elementWithOrigId).toBeTruthy();
done();
});
});

View File

@ -0,0 +1,116 @@
import { HttpClient } from "./http-client";
const TEST_URL = 'http://example.com';
const FAKE_RESPONSE = {
data: 'data',
};
describe('HttpClient', () => {
let httpClient;
beforeEach(() => {
httpClient = new HttpClient();
// setup and spy on fake fetch API
spyOn(window, 'fetch').and.returnValue(Promise.resolve(FAKE_RESPONSE));
});
it('should create', () => {
expect(httpClient).toBeTruthy();
});
describe('get()', () => {
let params;
beforeEach(() => {
params = {
url: TEST_URL,
};
});
it('should GET the given url', () => {
httpClient.get(params);
expect(window.fetch).toHaveBeenCalledWith(params.url, jasmine.objectContaining({ method: 'GET' }));
});
it('should return a promise', (done) => {
const result = httpClient.get(params);
result.then((response) => {
expect(response).toEqual(FAKE_RESPONSE);
done();
});
});
});
describe('post()', () => {
let params;
beforeEach(() => {
params = {
url: TEST_URL,
};
});
it('should POST the given url', () => {
httpClient.post(params);
expect(window.fetch).toHaveBeenCalledWith(params.url, jasmine.objectContaining({ method: 'POST' }));
});
it('should return a promise', (done) => {
const result = httpClient.post(params);
result.then((response) => {
expect(response).toEqual(FAKE_RESPONSE);
done();
});
});
});
describe('Response Interceptors', () => {
it('can be added', () => {
const interceptor = () => {};
expect(httpClient._responseInterceptors.length).toBe(0);
httpClient.addResponseInterceptor(interceptor);
expect(httpClient._responseInterceptors.length).toBe(1);
httpClient.addResponseInterceptor(interceptor);
expect(httpClient._responseInterceptors.length).toBe(2);
});
describe('get called', () => {
let intercepted1;
let intercepted2;
const interceptors = {
interceptor1: () => intercepted1 = true,
interceptor2: () => intercepted2 = true,
};
beforeEach(() => {
intercepted1 = false;
intercepted2 = false;
spyOn(interceptors, 'interceptor1').and.callThrough();
spyOn(interceptors, 'interceptor2').and.callThrough();
httpClient.addResponseInterceptor(interceptors.interceptor1);
httpClient.addResponseInterceptor(interceptors.interceptor2);
});
it('for GET requests', (done) => {
httpClient.get({ url: TEST_URL }).then(() => {
expect(intercepted1).toBeTruthy();
expect(intercepted2).toBeTruthy();
expect(interceptors.interceptor1).toHaveBeenCalledWith(FAKE_RESPONSE, jasmine.any(Object));
expect(interceptors.interceptor2).toHaveBeenCalledWith(FAKE_RESPONSE, jasmine.any(Object));
done();
});
});
it('for POST requests', (done) => {
httpClient.post({ url: TEST_URL }).then(() => {
expect(intercepted1).toBeTruthy();
expect(intercepted2).toBeTruthy();
expect(interceptors.interceptor1).toHaveBeenCalledWith(FAKE_RESPONSE, jasmine.any(Object));
expect(interceptors.interceptor2).toHaveBeenCalledWith(FAKE_RESPONSE, jasmine.any(Object));
done();
});
});
});
});
});

View File

@ -0,0 +1,51 @@
import { I18n } from "./i18n";
describe('I18n', () => {
let i18n;
beforeEach(() => {
i18n = new I18n();
});
// helper function
function expectTranslation(id, value) {
expect(i18n.translations[id]).toMatch(value);
}
it('should create', () => {
expect(i18n).toBeTruthy();
});
describe('add()', () => {
it('should add the translation', () => {
i18n.add('id1', 'translated-id1');
expectTranslation('id1', 'translated-id1');
});
});
describe('addMany()', () => {
it('should add many translations', () => {
i18n.addMany({
id1: 'translated-id1',
id2: 'translated-id2',
id3: 'translated-id3',
});
expectTranslation('id1', 'translated-id1');
expectTranslation('id2', 'translated-id2');
expectTranslation('id3', 'translated-id3');
});
});
describe('get()', () => {
it('should return stored translations', () => {
i18n.translations.id1 = 'something';
expect(i18n.get('id1')).toMatch('something');
});
it('should throw error if translation is missing', () => {
expect(() => {
i18n.get('id1');
}).toThrow();
});
});
});

View File

@ -46,10 +46,10 @@ export class UtilRegistry {
}
setApp(appInstance) {
this.appInstance = appInstance;
this._appInstance = appInstance;
}
setupAll = (scope) => {
setupAll(scope) {
if (DEBUG_MODE > 1) {
console.info('registered js utilities:');
console.table(this._registeredUtils);
@ -70,7 +70,7 @@ export class UtilRegistry {
let utilInstance = null;
try {
utilInstance = util.setup(element, this.appInstance);
utilInstance = util.setup(element, this._appInstance);
} catch(err) {
if (DEBUG_MODE > 0) {
console.warn('Error while trying to initialize a utility!', { util , element, err });

View File

@ -0,0 +1,126 @@
import { UtilRegistry } from "./util-registry";
const TEST_UTILS = [{
name: 'util1',
selector: '#some-id',
setup: () => {},
}, {
name: 'util2',
selector: '[uw-util]',
setup: () => {},
}];
describe('UtilRegistry', () => {
let utilRegistry;
beforeEach(() => {
utilRegistry = new UtilRegistry();
});
it('should create', () => {
expect(utilRegistry).toBeTruthy();
});
describe('register()', () => {
it('should allow to add utilities', () => {
utilRegistry.register(TEST_UTILS[0]);
const foundUtil = utilRegistry.find(TEST_UTILS[0].name);
expect(foundUtil).toEqual(TEST_UTILS[0]);
});
});
describe('deregister()', () => {
it('should remove util', () => {
// register util
utilRegistry.register(TEST_UTILS[0]);
let foundUtil = utilRegistry.find('util1');
expect(foundUtil).toBeTruthy();
// deregister util
utilRegistry.deregister(TEST_UTILS[0].name);
foundUtil = utilRegistry.find('util1');
expect(foundUtil).toBeFalsy();
});
it('should destroy util instances if requested', () => {
pending('TBD');
});
});
describe('setup()', () => {
it('should catch errors thrown by the utility', () => {
spyOn(TEST_UTILS[0], 'setup').and.throwError('some error');
expect(() => {
utilRegistry.setup(TEST_UTILS[0]);
}).not.toThrow();
});
it('should pass the app instance', () => {
const scope = document.createElement('div');
const utilElement = document.createElement('div');
utilElement.id = 'some-id';
scope.appendChild(utilElement);
const fakeApp = { fn: () => {} };
utilRegistry.setApp(fakeApp);
spyOn(TEST_UTILS[0], 'setup');
utilRegistry.setup(TEST_UTILS[0], scope);
expect(TEST_UTILS[0].setup).toHaveBeenCalledWith(utilElement, fakeApp);
});
describe('given no scope', () => {
it('should use fallback scope', () => {
spyOn(TEST_UTILS[0], 'setup');
utilRegistry.setup(TEST_UTILS[0]);
expect(TEST_UTILS[0].setup).not.toHaveBeenCalled();
});
});
describe('given a scope', () => {
let scope;
let utilElement1;
let utilElement2;
beforeEach(() => {
scope = document.createElement('div');
utilElement1 = document.createElement('div');
utilElement2 = document.createElement('div');
utilElement1.setAttribute('uw-util', '');
utilElement2.setAttribute('uw-util', '');
scope.appendChild(utilElement1);
scope.appendChild(utilElement2);
});
it('should call the utilities\' setup function for each matching element', () => {
spyOn(TEST_UTILS[1], 'setup');
utilRegistry.setup(TEST_UTILS[1], scope);
// 2 matching elements in scope
expect(TEST_UTILS[1].setup.calls.count()).toBe(2);
expect(TEST_UTILS[1].setup.calls.argsFor(0)).toEqual([utilElement1, undefined]);
expect(TEST_UTILS[1].setup.calls.argsFor(1)).toEqual([utilElement2, undefined]);
});
});
});
describe('setupAll()', () => {
it('should setup all the utilities', () => {
spyOn(utilRegistry, 'setup');
utilRegistry.register(TEST_UTILS[0]);
utilRegistry.register(TEST_UTILS[1]);
utilRegistry.setupAll();
expect(utilRegistry.setup.calls.count()).toBe(2);
expect(utilRegistry.setup.calls.argsFor(0)).toEqual([TEST_UTILS[0], undefined]);
expect(utilRegistry.setup.calls.argsFor(1)).toEqual([TEST_UTILS[1], undefined]);
});
it('should pass the given scope', () => {
spyOn(utilRegistry, 'setup');
utilRegistry.register(TEST_UTILS[0]);
const scope = document.createElement('div');
utilRegistry.setupAll(scope);
expect(utilRegistry.setup).toHaveBeenCalledWith(TEST_UTILS[0], scope);
});
});
});

View File

@ -15,6 +15,7 @@
"yesod:test": "./test.sh",
"frontend:lint": "eslint frontend/src",
"frontend:test": "karma start --conf karma.conf.js",
"frontend:test:watch": "karma start --conf karma.conf.js --single-run false",
"frontend:build": "webpack",
"frontend:build:watch": "webpack --watch"
},