Add util tests

This commit is contained in:
Josh Johnson 2018-05-28 17:56:36 +01:00
parent bfb6571ce9
commit f286dbc653
6 changed files with 349 additions and 30 deletions

View File

@ -26,6 +26,7 @@
"devDependencies": true
}],
"no-console": ["warn", { "allow": ["warn", "error"] }],
"no-plusplus": "off",
"no-unused-expressions": "off",
"no-underscore-dangle": "off",
"prettier/prettier": ["error", {

View File

@ -15,7 +15,7 @@ function ignoreExtensions(extensions = [], returnValue = {}) {
return returnValue;
}
extensions.forEach((ext) => {
extensions.forEach(ext => {
require.extensions[ext] = noop;
});
}
@ -35,7 +35,7 @@ function mockRAF(global) {
global.requestAnimationFrame = callback => callbacksQueue.push(callback) - 1;
global.cancelAnimationFrame = (id) => {
global.cancelAnimationFrame = id => {
callbacksQueue[id] = false;
};
}
@ -46,6 +46,7 @@ global.navigator = {
userAgent: 'node.js',
};
global.CustomEvent = window.CustomEvent;
global.Element = window.Element;
global.HTMLElement = window.HTMLElement;
global.HTMLOptionElement = window.HTMLOptionElement;
global.HTMLOptGroupElement = window.HTMLOptGroupElement;

View File

@ -86,11 +86,10 @@
],
"nyc": {
"include": [
"src/**/**/**/**/**/*.js"
"src/scripts/**/**/*.js"
],
"exclude": [
"src/**/**/**/**/**/*.test.js",
"src/scripts/src/lib/polyfills.js"
"src/scripts/**/**/*.test.js"
]
}
}

View File

@ -38,15 +38,15 @@ export const generateId = function(element, prefix) {
(element.name && `${element.name}-${generateChars(2)}`) ||
generateChars(4);
id = id.replace(/(:|\.|\[|\]|,)/g, '');
id = prefix + id;
id = `${prefix}-${id}`;
return id;
};
/**
* Tests the type of an object
* @param {String} type Type to test object against
* @param {Object} obj Object to be tested
* Gets the type of an object
* Why not use typeof? See here: http: //bonsaiden.github.io/JavaScript-Garden/#types.typeof
* @param {Object} obj Object to check
* @return {Boolean}
*/
export const getType = function(obj) {
@ -69,14 +69,9 @@ export const isType = function(type, obj) {
* @param {Object} obj Object to be tested
* @return {Boolean}
*/
export const isElement = o =>
typeof HTMLElement === 'object'
? o instanceof HTMLElement // DOM2
: o &&
typeof o === 'object' &&
o !== null &&
o.nodeType === 1 &&
typeof o.nodeName === 'string';
export const isElement = (element) => {
return element instanceof Element;
};
/**
* Merges unspecified amount of objects into new object
@ -294,8 +289,14 @@ export const sortByAlpha = (a, b) => {
const labelA = (a.label || a.value).toLowerCase();
const labelB = (b.label || b.value).toLowerCase();
if (labelA < labelB) return -1;
if (labelA > labelB) return 1;
if (labelA < labelB) {
return -1;
}
if (labelA > labelB) {
return 1;
}
return 0;
};
@ -364,20 +365,20 @@ export const reduceToValues = (items, key = 'value') => {
/**
* Fetch properties from object
* @param {Object} object Related object
* @param {String} properties Properties from object
* @param {Object} object Related object
* @param {String} path Path to value
*/
export const fetchFromObject = (object, properties) => {
const index = properties.indexOf('.');
export const fetchFromObject = (object, path) => {
const index = path.indexOf('.');
if (index > -1) {
return fetchFromObject(
object[properties.substring(0, index)],
properties.substr(index + 1),
object[path.substring(0, index)],
path.substr(index + 1),
);
}
return object[properties];
return object[path];
};
export const isIE11 = () =>
@ -386,13 +387,13 @@ export const isIE11 = () =>
navigator.userAgent.match(/rv[ :]11/)
);
export const existsInArray = (array, value) =>
export const existsInArray = (array, value, key = 'value') =>
array.some(item => {
if (isType('String', value)) {
return item.value === value.trim();
return item[key] === value.trim();
}
return item.value === value;
return item[key] === value;
});
/**

View File

@ -1,5 +1,22 @@
import { expect } from 'chai';
import { reduceToValues } from './utils';
import { stub } from 'sinon';
import {
reduceToValues,
getRandomNumber,
generateChars,
generateId,
getType,
isType,
isElement,
stripHTML,
sortByAlpha,
sortByScore,
fetchFromObject,
existsInArray,
cloneObject,
regexFilter,
dispatchEvent,
} from './utils';
describe('utils', () => {
describe('reduceToValues', () => {
@ -49,4 +66,265 @@ describe('utils', () => {
expect(actualResponse).to.eql(expectedResponse);
});
});
describe('getRandomNumber', () => {
it('returns random number between range', () => {
for (let index = 0; index < 10; index++) {
const output = getRandomNumber(1, 10);
expect(output).to.be.a('number');
expect(output).to.be.within(1, 10);
}
});
});
describe('generateChars', () => {
it('generates a string of random chars with given length', () => {
const output = generateChars(10);
expect(output).to.be.a('string');
expect(output).to.have.length(10);
});
});
describe('generateId', () => {
describe('when given element has id value', () => {
it('generates a unique prefixed id based on given elements id', () => {
const element = document.createElement('div');
element.id = 'test-id';
const prefix = 'test-prefix';
const output = generateId(element, prefix);
expect(output).to.equal(`${prefix}-${element.id}`);
});
});
describe('when given element has no id value but name value', () => {
it('generates a unique prefixed id based on given elements name plus 2 random characters', () => {
const element = document.createElement('div');
element.name = 'test-name';
const prefix = 'test-prefix';
const output = generateId(element, prefix);
const expectedOutput = `${prefix}-${element.name}-`;
expect(output).to.contain(expectedOutput);
expect(output).to.have.length(expectedOutput.length + 2);
});
});
describe('when given element has no id value and no name value', () => {
it('generates a unique prefixed id based on 4 random characters', () => {
const element = document.createElement('div');
const prefix = 'test-prefix';
const output = generateId(element, prefix);
const expectedOutput = `${prefix}-`;
expect(output).to.contain(expectedOutput);
expect(output).to.have.length(expectedOutput.length + 4);
});
});
});
describe('getType', () => {
it('returns type of given object', () => {
expect(getType({})).to.equal('Object');
expect(getType(1)).to.equal('Number');
expect(getType(true)).to.equal('Boolean');
expect(getType([])).to.equal('Array');
expect(getType(() => {})).to.equal('Function');
expect(getType(new Error())).to.equal('Error');
expect(getType(new RegExp())).to.equal('RegExp');
expect(getType(new String())).to.equal('String'); // eslint-disable-line
expect(getType('')).to.equal('String');
});
});
describe('isType', () => {
it('checks with given object type equals given type', () => {
expect(isType('Object', {})).to.equal(true);
expect(isType('String', {})).to.equal(false);
});
});
describe('isElement', () => {
it('checks with given object is an element', () => {
const element = document.createElement('div');
expect(isElement(element)).to.equal(true);
expect(isElement({})).to.equal(false);
});
});
describe('stripHTML', () => {
it('strips HTML from value', () => {
const value = '<script>somethingMalicious();</script>';
const output = stripHTML(value);
expect(output).to.equal(
'&lt;script&rt;somethingMalicious();&lt;/script&rt;',
);
});
});
describe('sortByAlpha', () => {
describe('sorting an array', () => {
it('sorts by value alphabetically', () => {
const values = [
{ value: 'The Strokes' },
{ value: 'Arctic Monkeys' },
{ value: 'Oasis' },
{ value: 'Tame Impala' },
];
const output = values.sort(sortByAlpha);
expect(output).to.eql([
{ value: 'Arctic Monkeys' },
{ value: 'Oasis' },
{ value: 'Tame Impala' },
{ value: 'The Strokes' },
]);
});
it('sorts by label alphabetically', () => {
const values = [
{ label: 'The Strokes' },
{ label: 'Arctic Monkeys' },
{ label: 'Oasis' },
{ label: 'Tame Impala' },
];
const output = values.sort(sortByAlpha);
expect(output).to.eql([
{ label: 'Arctic Monkeys' },
{ label: 'Oasis' },
{ label: 'Tame Impala' },
{ label: 'The Strokes' },
]);
});
});
});
describe('sortByScore', () => {
describe('sorting an array', () => {
it('sorts by score ascending', () => {
const values = [
{ score: 10 },
{ score: 3001 },
{ score: 124 },
{ score: 400 },
];
const output = values.sort(sortByScore);
expect(output).to.eql([
{ score: 10 },
{ score: 124 },
{ score: 400 },
{ score: 3001 },
]);
});
});
});
describe('dispatchEvent', () => {
it('dispatches custom event of given type on given element', () => {
const fakeElement = {
dispatchEvent: stub(),
};
const eventType = 'testEvent';
const customArgs = {
testing: true,
};
dispatchEvent(fakeElement, eventType, customArgs);
expect(fakeElement.dispatchEvent.called).to.equal(true);
const event = fakeElement.dispatchEvent.lastCall.args[0];
expect(event).to.be.instanceof(CustomEvent);
expect(event.bubbles).to.equal(true);
expect(event.cancelable).to.equal(true);
expect(event.detail).to.equal(customArgs);
});
});
describe('regexFilter', () => {
it('tests given regex against given value', () => {
// An email address regex
const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
expect(regexFilter('joe@bloggs.com', regex)).to.equal(true);
expect(regexFilter('joe bloggs', regex)).to.equal(false);
});
});
describe('reduceToValues', () => {
it('reduces an array of objects to an array of values using given key', () => {
const values = [
{ name: 'The Strokes' },
{ name: 'Arctic Monkeys' },
{ name: 'Oasis' },
{ name: 'Tame Impala' },
];
const output = reduceToValues(values, 'name');
expect(output).to.eql([
'The Strokes',
'Arctic Monkeys',
'Oasis',
'Tame Impala',
]);
});
});
describe('fetchFromObject', () => {
it('fetches value from object using given path', () => {
const object = {
band: {
name: 'The Strokes',
},
};
const output = fetchFromObject(object, 'band.name');
expect(output).to.equal(object.band.name);
});
});
describe('existsInArray', () => {
it('determines whether a value exists within given array', () => {
const values = [
{ value: 'The Strokes' },
{ value: 'Arctic Monkeys' },
{ value: 'Oasis' },
{ value: 'Tame Impala' },
];
expect(existsInArray(values, 'Oasis', 'value')).to.equal(true);
expect(existsInArray(values, 'The Beatles', 'value')).to.equal(false);
});
});
describe('cloneObject', () => {
it('deeply clones a given object', () => {
const object = {
levelOne: {
id: 1,
levelTwo: {
id: 2,
levelThree: {
id: 3,
levelFour: {
id: 4,
},
},
},
},
};
const output = cloneObject(object);
expect(output).to.not.equal(object);
expect(output).to.eql(object);
});
});
});

View File

@ -15,4 +15,43 @@ describe('reducers/rootReducer', () => {
expect(state.choices).to.equal(choices(undefined, {}));
expect(state.items).to.equal(items(undefined, {}));
});
describe('CLEAR_ALL', () => {
it('resets state', () => {
const output = rootReducer(
{
items: [1, 2, 3],
groups: [1, 2, 3],
choices: [1, 2, 3],
},
{
type: 'CLEAR_ALL',
},
);
expect(output).to.eql({
items: [],
groups: [],
choices: [],
});
});
});
describe('RESET_TO', () => {
it('replaces state with given state', () => {
const output = rootReducer(
{
items: [1, 2, 3],
groups: [1, 2, 3],
choices: [1, 2, 3],
},
{
type: 'RESET_TO',
state: {},
},
);
expect(output).to.eql({});
});
});
});