Add util tests
This commit is contained in:
parent
bfb6571ce9
commit
f286dbc653
|
@ -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", {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
@ -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(
|
||||
'<script&rt;somethingMalicious();</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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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({});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue