text:
import _createDomElement from "../dist/internal/dom/_createDomElement.js";
import getAttr from "../dist/getAttr.js";

describe("getAttr", function() {
	it("Should return a boolean attribute from a DOM element written in HTML5 syntax.", function() {
		let inputElement = _createDomElement('<input type="checkbox" checked>');
		expect(getAttr(inputElement, "checked")).toBe(true);
	});

	it("Should return a boolean attribute from a DOM element written in HTML4 syntax.", function() {
		let inputElement = _createDomElement('<input type="checkbox" checked="checked"/>');
		expect(getAttr(inputElement, "checked")).toBe(true);
	});

	it("Should return an attribute from a DOM element.", function() {
		let linkElement = _createDomElement('<a href="#test">');
		expect(getAttr(linkElement, "href")).toBe("#test");
	});

	it("Should return true for an attribute without a value.", function() {
		let videoElement = _createDomElement('<video controls>');
		expect(getAttr(videoElement, "controls")).toBe(true);
	});

	it("Should return false for a non-existing attribute.", function() {
		let videoElement = _createDomElement('<video controls>');
		expect(getAttr(videoElement, "muted")).toBe(false);
	});
});


text:
import removeClass from "../dist/removeClass.js";

describe("removeClass", function() {
	for (let i = 0; i < 5; i++) {
		let newEl = document.createElement("div");
		newEl.className = "oneMore removeClass removeClass-" + i;
		document.body.appendChild(newEl);
	}

	it("Should add a CSS class to a single HTMLElement.", function() {
		let singleHTMLElement = document.querySelector(".removeClass-1");
		removeClass(singleHTMLElement, "oneMore");

		expect(singleHTMLElement.className).toBe("removeClass removeClass-1");
	});

	it("Should not change a CSS class when trying to remove an inexistent class.", function() {
		let singleHTMLElement = document.querySelector(".removeClass-1");
		removeClass(singleHTMLElement, "oneMore");

		expect(singleHTMLElement.className).toBe("removeClass removeClass-1");
	});

	it("Should add a CSS class to many HTMLElements.", function() {
		let elementsNodeList = document.querySelectorAll(".removeClass");

		for (let i = 0, len = elementsNodeList.length; i < len; i++) {
			elementsNodeList[i].className = "oneMore removeClass";
		}

		removeClass(elementsNodeList, "oneMore");

		for (let i = 0, len = elementsNodeList.length; i < len; i++) {
			expect(elementsNodeList[i].className).toBe("removeClass");
		}
	});
});

repo_name: leofavre/canivete

repo_language: JavaScript

mime_type: text/x-java


text:
import selfAndParents from "../dist/selfAndParents.js";

describe("selfAndParents", function() {
	it(`Should return all selfAndParents of a DOM element.`, function() {
		var domChild = document.createElement("div");
		expect(selfAndParents(domChild)).toEqual([
			domChild
		]);

		var domParent = document.createElement("div");
		domParent.appendChild(domChild);
		expect(selfAndParents(domChild)).toEqual([
			domChild,
			domParent
		]);

		var domGrandparent = document.createElement("div");
		domGrandparent.appendChild(domParent);
		expect(selfAndParents(domChild)).toEqual([
			domChild,
			domParent,
			domGrandparent
		]);

		document.body.appendChild(domGrandparent);
		expect(selfAndParents(domChild)).toEqual([
			domChild,
			domParent,
			domGrandparent,
			document.body,
			document.querySelector("html"),
			document
		]);
	});

	it(`Should throw an error when trying to find selfAndParents of something other than a DOM element.`, function() {
		expect(() => selfAndParents("laser")).toThrow();
		expect(() => selfAndParents(0)).toThrow();
		expect(() => selfAndParents(document.createTextNode("laser"))).toThrow();
		expect(() => selfAndParents(document.querySelectorAll("div"))).toThrow();
	});

	it(`Should return an array with document for document and an array with window for window.`, function() {
		expect(selfAndParents(window)).toEqual([window]);
		expect(selfAndParents(document)).toEqual([document]);
	});
});


text:
import _domElementsToArray from "../dist/internal/dom/_domElementsToArray.js";

describe("_domElementsToArray", function() {
	for (let i = 0; i < 5; i++) {
		let newEl = document.createElement("div");
		newEl.className = "domElementsToArray domElementsToArray-" + i;
		document.body.appendChild(newEl);
	}

	it("Should convert a single HTMLElement to an Array.", function() {
		let singleHTMLElement = document.querySelector(".domElementsToArray-1");
		let elementsArray = _domElementsToArray(singleHTMLElement);

		expect(Array.isArray(singleHTMLElement)).toBe(false);
		expect(Array.isArray(elementsArray)).toBe(true);
		expect(elementsArray.length).toBe(1);
	});

	it("Should convert a NodeList with many elements to an Array.", function() {
		let elementsNodeList = document.querySelectorAll(".domElementsToArray");
		let elementsArray = _domElementsToArray(elementsNodeList);

		expect(Array.isArray(elementsNodeList)).toBe(false);
		expect(Array.isArray(elementsArray)).toBe(true);
		expect(elementsArray.length).toBe(5);
	});

	it("Should convert a NodeList with one element to an Array.", function() {
		let elementsNodeList = document.querySelectorAll(".domElementsToArray-1");
		let elementsArray = _domElementsToArray(elementsNodeList);

		expect(Array.isArray(elementsNodeList)).toBe(false);
		expect(Array.isArray(elementsArray)).toBe(true);
		expect(elementsArray.length).toBe(1);
	});

	it("Should convert an HTMLCollection with many elements to an Array.", function() {
		let elementsHTMLCollection = document.getElementsByClassName("domElementsToArray");
		let elementsArray = _domElementsToArray(elementsHTMLCollection);

		expect(Array.isArray(elementsHTMLCollection)).toBe(false);
		expect(Array.isArray(elementsArray)).toBe(true);
		expect(elementsArray.length).toBe(5);
	});

	it("Should convert an HTMLCollection with one element to an Array.", function() {
		let elementsHTMLCollection = document.getElementsByClassName("domElementsToArray-1");
		let elementsArray = _domElementsToArray(elementsHTMLCollection);

		expect(Array.isArray(elementsHTMLCollection)).toBe(false);
		expect(Array.isArray(elementsArray)).toBe(true);
		expect(elementsArray.length).toBe(1);
	});

	it("Should allow an Array of HTMLElements as parameter.", function() {
		let elementsHTMLElementArray = [document.querySelector(".domElementsToArray-1"), document.querySelector(".domElementsToArray-2")];
		let elementsArray = _domElementsToArray(elementsHTMLElementArray);

		expect(Array.isArray(elementsHTMLElementArray)).toBe(true);
		expect(Array.isArray(elementsArray)).toBe(true);
		expect(elementsArray.length).toBe(2);
	});

	it("Should allow a Set of HTMLElements as parameter.", function() {
		let elementsHTMLElementSet = new Set();
		elementsHTMLElementSet.add(document.querySelector(".domElementsToArray-1"));
		elementsHTMLElementSet.add(document.querySelector(".domElementsToArray-2"));
		let elementsArray = _domElementsToArray(elementsHTMLElementSet);

		expect(Array.isArray(elementsHTMLElementSet)).toBe(false);
		expect(Array.isArray(elementsArray)).toBe(true);
		expect(elementsArray.length).toBe(2);
	});

	it("Should accept undefined, null, empty Arrays or empty Sets as parameters.", function() {
		let emptySet = new Set();

		expect(() => _domElementsToArray()).not.toThrow();
		expect(() => _domElementsToArray([])).not.toThrow();
		expect(() => _domElementsToArray(emptySet)).not.toThrow();
	});

	it("Should throw an error if the parameter is not empty, an HTMLElement or a group of HTMLElements.", function() {
		expect(() => _domElementsToArray(125)).toThrow();
		expect(() => _domElementsToArray("String")).toThrow();
		expect(() => _domElementsToArray({})).toThrow();
	});
});


text:
import getDistanceBetweenCoords from "../dist/getDistanceBetweenCoords.js";

describe("getDistanceBetweenCoords", function() {
	const errorMsg = "Two arrays of numbers with the same length, representing cartesian coordinates, are expected as parameters.";

	it("Should calculate de distance between two points on a surface.", function() {
		expect(getDistanceBetweenCoords([2, 1], [5, 5])).toBe(5);
	});

	it("Should calculate de distance between two points on a surface.", function() {
		expect(getDistanceBetweenCoords([0, 0], [3, 4])).toBe(5);
	});

	it("Should calculate de distance between two points on a 3D space.", function() {
		expect(getDistanceBetweenCoords([2, 1, 8], [5, 5, 8])).toBe(5);
	});

	it("Should calculate de distance between two points on a 3D space.", function() {
		expect(getDistanceBetweenCoords([2, 1, 8], [5, 5, 0])).toBe(Math.sqrt(89));
	});

	it("Should calculate de distance between two points on a 3D space.", function() {
		expect(getDistanceBetweenCoords([2, 1, 8, 0], [5, 5, 8, 2])).toBe(Math.sqrt(29));
	});

	it("Should calculate de distance between two points in a line.", function() {
		expect(getDistanceBetweenCoords([4], [8])).toBe(4);
	});

	it("Should calculate de distance between two points in a line.", function() {
		expect(getDistanceBetweenCoords([2], [5])).toBe(3);
	});

	it("Should calculate de distance between two points in a line.", function() {
		expect(getDistanceBetweenCoords([-2], [-5])).toBe(3);
	});

	it("Should ignore extra parameters, as only two are expected.", function() {
		expect(getDistanceBetweenCoords([-2], [-5], [1001])).toBe(3);
	});

	it("Should throw an error if less than two coordinates are passed as parameters.", function() {
		expect(() => getDistanceBetweenCoords()).toThrow();
	});

	it("Should throw an error if less than two coordinates are passed as parameters.", function() {
		expect(() => getDistanceBetweenCoords([2, 1])).toThrow();
	});

	it("Should throw an error if any of the coordinates is not an array.", function() {
		expect(() => getDistanceBetweenCoords([-2, 5], -5)).toThrow();
	});

	it("Should throw an error if any of the coordinates is not an array.", function() {
		expect(() => getDistanceBetweenCoords(-5, [2, 5])).toThrow();
	});

	it("Should throw an error if coordinates do not have the same length.", function() {
		expect(() => getDistanceBetweenCoords([2, 1], [5, 3, 8])).toThrow();
	});
});


text:
import toSum from "../dist/toSum.js";

describe("toSum", function() {
	it(`Should return the sum of all items in an array when used with Array.prototype.reduce().`, function() {
		expect(
			[3, 5, 7, 9].reduce(toSum())
		).toBe(24);

		expect(
			[-10, 10].reduce(toSum())
		).toBe(0);
	});

	it("Should work without parentheses", function() {
		expect(
			[3, 5, 7, 9].reduce(toSum)
		).toBe(24);

		expect(
			[-10, 10].reduce(toSum)
		).toBe(0);
	});
});


text:
import _createDomElement from "../dist/internal/dom/_createDomElement.js";
import setAttr from "../dist/setAttr.js";

describe("setAttr", function() {
	it("Should add the attribute name to the tag if passed true.", function() {
		let singleHTMLElement = _createDomElement("
");
		setAttr(singleHTMLElement, "data-active", true);

		expect(singleHTMLElement.hasAttribute("data-active")).toBe(true);
		expect(singleHTMLElement.getAttribute("data-active")).toBe("");
		expect(singleHTMLElement.dataset.active).toBe("");
	});

	it("Should remove the attribute name to the tag if passed false.", function() {
		let singleHTMLElement = _createDomElement("
");
		setAttr(singleHTMLElement, "data-active", false);

		expect(singleHTMLElement.hasAttribute("data-active")).toBe(false);
		expect(singleHTMLElement.getAttribute("data-active")).toBe(null);
		expect(singleHTMLElement.dataset.active).toBe(undefined);
	});

	it("Should add the attribute name to the tag if passed a string.", function() {
		let oneElement = _createDomElement('
Level 42
');
		setAttr(oneElement, "data-level", 42);

		expect(oneElement.getAttribute("data-level")).toBe("42");
		expect(oneElement.dataset.level).toBe("42");

		let otherElement = _createDomElement('News');
		setAttr(otherElement, "class", "button");

		expect(otherElement.getAttribute("class")).toBe("button");
		expect(otherElement.className).toBe("button");
	});

	it("Should accept a group of DOM nodes.", function() {
		let listElement = _createDomElement('

A

B

C

'),
		manyElements = listElement.querySelectorAll("li");

		setAttr(manyElements, "class", "item");

		expect(manyElements[0].getAttribute("class")).toBe("item");
		expect(manyElements[0].className).toBe("item");
		expect(manyElements[1].getAttribute("class")).toBe("item");
		expect(manyElements[1].className).toBe("item");
	});

	it("Should accept a group of DOM nodes.", function() {
		let domElA = _createDomElement("
"),
			domElB = _createDomElement("
");

		setAttr([domElA, domElB], "data-level", 42);

		expect(domElA.getAttribute("data-level")).toBe("42");
		expect(domElB.getAttribute("data-level")).toBe("42");
		expect(domElA.dataset.level).toBe("42");
		expect(domElB.dataset.level).toBe("42");
	});

	it("Should accept a group of DOM nodes.", function() {
		let domElA = _createDomElement("
"),
			domElB = _createDomElement("
");

		domElA.className = "setAttr";
		domElB.className = "setAttr";

		document.body.appendChild(domElA);
		document.body.appendChild(domElB);

		let manyElements = document.querySelectorAll(".setAttr");

		setAttr(manyElements, "data-level", 42);

		expect(manyElements[0].getAttribute("data-level")).toBe("42");
		expect(manyElements[1].getAttribute("data-level")).toBe("42");
		expect(manyElements[0].dataset.level).toBe("42");
		expect(manyElements[1].dataset.level).toBe("42");
	});
});


text:
import addClass from "../dist/addClass.js";

describe("addClass", function() {
	for (let i = 0; i < 5; i++) {
		let newEl = document.createElement("div");
		newEl.className = "addClass addClass-" + i;
		document.body.appendChild(newEl);
	}

	it("Should add a CSS class to a single HTMLElement.", function() {
		let singleHTMLElement = document.querySelector(".addClass-1");
		addClass(singleHTMLElement, "oneMore");

		expect(singleHTMLElement.className).toBe("addClass addClass-1 oneMore");
	});

	it("Should not repeat the addition of the same CSS class.", function() {
		let singleHTMLElement = document.querySelector(".addClass-1");
		addClass(singleHTMLElement, "oneMore");

		expect(singleHTMLElement.className).toBe("addClass addClass-1 oneMore");
	});

	it("Should add a CSS class to many HTMLElements.", function() {
		let elementsNodeList = document.querySelectorAll(".addClass");

		for (let i = 0, len = elementsNodeList.length; i < len; i++) {
			elementsNodeList[i].className = "addClass";
		}

		addClass(elementsNodeList, "oneMore");

		for (let i = 0, len = elementsNodeList.length; i < len; i++) {
			expect(elementsNodeList[i].className).toBe("addClass oneMore");
		}
	});
});


text:
import _isValidDelimiterArray from "../dist/internal/bem/_isValidDelimiterArray.js";

describe("_isValidDelimiterArray", function() {
	it(`"Should return false if passed anything other than a BEM delimiter array.`, function() {
		expect(_isValidDelimiterArray()).toBe(false);
		expect(_isValidDelimiterArray(0)).toBe(false);
		expect(_isValidDelimiterArray("")).toBe(false);
		expect(_isValidDelimiterArray("__ -- -")).toBe(false);
		expect(_isValidDelimiterArray({})).toBe(false);
		expect(_isValidDelimiterArray([])).toBe(false);
		expect(_isValidDelimiterArray(["", "", ""])).toBe(false);
		expect(_isValidDelimiterArray(["__", "--"])).toBe(false);
		expect(_isValidDelimiterArray(["__", "--", ""])).toBe(false);
		expect(_isValidDelimiterArray(["__", "", "-"])).toBe(false);
		expect(_isValidDelimiterArray(["", "--", "-"])).toBe(false);
	});

	it(`"Should return true if passed a valid BEM delimiter array: with 3 non-empty strings.`, function() {
		expect(_isValidDelimiterArray(["__", "--", "-"])).toBe(true);
		expect(_isValidDelimiterArray(["__", "_", "_"])).toBe(true);
		expect(_isValidDelimiterArray(["-", "--", "--"])).toBe(true);
	});
});


text:
import parents from "../dist/parents.js";

describe("parents", function() {
	it(`Should return all parents of a DOM element.`, function() {
		var domChild = document.createElement("div");
		expect(parents(domChild)).toEqual([]);

		var domParent = document.createElement("div");
		domParent.appendChild(domChild);
		expect(parents(domChild)).toEqual([
			domParent
		]);

		var domGrandparent = document.createElement("div");
		domGrandparent.appendChild(domParent);
		expect(parents(domChild)).toEqual([
			domParent,
			domGrandparent
		]);

		document.body.appendChild(domGrandparent);
		expect(parents(domChild)).toEqual([
			domParent,
			domGrandparent,
			document.body,
			document.querySelector("html"),
			document
		]);
	});

	it(`Should throw an error when trying to find parents of something other than a DOM element.`, function() {
		expect(() => parents("laser")).toThrow();
		expect(() => parents(0)).toThrow();
		expect(() => parents(document.createTextNode("laser"))).toThrow();
		expect(() => parents(document.querySelectorAll("div"))).toThrow();
	});

	it(`Should return empty arrays for document and window.`, function() {
		expect(parents(window)).toEqual([]);
		expect(parents(document)).toEqual([]);
	});
});


text:
import timeSince from "../dist/timeSince.js";

describe("timeSince", function() {
	it(`"Should return the time passed since a timestamp, in milliseconds.`, function(done) {
		let timestamp = +new Date(),
			result = 0;

		setTimeout(() => {
			result = timeSince(timestamp);
			expect(result >= 230).toBe(true);
			done();
		}, 230);
	});
});


text:
import _getCoords from "../dist/internal/geometry/_getCoords.js";

describe("_getCoords", function() {
	let maskEl = document.createElement("div");
	maskEl.style.cssText = "position: fixed; top: 250px; left: 150px; width: 150px; height: 300px; display: block; background: rgba(153, 0, 153, 0.3);";
	document.body.appendChild(maskEl);

	it("Should be able to get coordinates from a DOMElement", function() {
		expect(_getCoords(maskEl).top).toBe(250);
		expect(_getCoords(maskEl).bottom).toBe(550);
		expect(_getCoords(maskEl).left).toBe(150);
		expect(_getCoords(maskEl).right).toBe(300);
	});

	let maskRect = maskEl.getBoundingClientRect();

	it("Should be able to get coordinates from a DOMRect", function() {
		expect(_getCoords(maskRect).top).toBe(250);
		expect(_getCoords(maskRect).bottom).toBe(550);
		expect(_getCoords(maskRect).left).toBe(150);
		expect(_getCoords(maskRect).right).toBe(300);
	});

	let maskObj = {
		top: 250,
		bottom: 550,
		left: 150,
		right: 300
	};

	it("Should be able to get coordinates from a plain Object", function() {
		expect(_getCoords(maskObj).top).toBe(250);
		expect(_getCoords(maskObj).bottom).toBe(550);
		expect(_getCoords(maskObj).left).toBe(150);
		expect(_getCoords(maskObj).right).toBe(300);
	});

	let wrongObj = {
		top: "250px",
		bottom: "550px",
		left: "150px",
		right: "300px"
	};

	let otherWrongObj = {
		top: 250,
		bottom: 550
	};

	it("Should throw an error if the second parameter is not undefined, a DOM element or an object like a DOMRect (containing top, bottom, left and right parameters).", function() {
		expect(() => _getCoords(wrongObj)).toThrow();
		expect(() => _getCoords(otherWrongObj)).toThrow();
		expect(() => _getCoords(189)).toThrow();
		expect(() => _getCoords("String")).toThrow();
		expect(() => _getCoords([250, 350, 150, 300])).toThrow();
	});
});


text:
import oneOutOf from "../dist/oneOutOf.js";

function testRandomness(num) {
	let expectedPositive = 1 / num;
	let expectedNegative = 1 - expectedPositive;
	let expectedRatio = expectedPositive / expectedNegative;
	let expectedRatioPercent = 100 * expectedRatio;

	let positives = 0;
	let negatives = 0;

	for (let i = 0; i < 1000000; i++) {
		if (oneOutOf(num)) {
			positives++;
		}
		else {
			negatives++;
		}
	}

	let actualRatio = positives / negatives;

	return it(`Should return true approximately ${expectedRatioPercent}% of times with oneOutOf(${num}).`, function() {
		expect(actualRatio < (expectedRatio + 0.01) && actualRatio > (expectedRatio - 0.01)).toBe(true);
	});
}

describe("oneOutOf", function() {
	testRandomness(2);
	testRandomness(5);
	testRandomness(10);
	testRandomness(25);
	testRandomness(100);
	testRandomness(250000);

	it("Should return true when 1 is used as parameter.", function() {
		expect(oneOutOf(1)).toBe(true);
	});

	it("Should throw an error is the parameter is not a number greater than 1.", function() {
		expect(() => oneOutOf()).toThrow();
		expect(() => oneOutOf(0)).toThrow();
		expect(() => oneOutOf(-45)).toThrow();
		expect(() => oneOutOf("25")).toThrow();
		expect(() => oneOutOf([])).toThrow();
		expect(() => oneOutOf({})).toThrow();
	});
});


text:
import _createDomElement from "../dist/internal/dom/_createDomElement.js";
import setAttrs from "../dist/setAttrs.js";

describe("setAttrs", function() {
	it("Should set many attributes at once.", function() {
		let singleHTMLElement = _createDomElement("
");
		setAttrs(singleHTMLElement, {
			"data-active": true,
			"data-level": 42
		});

		expect(singleHTMLElement.hasAttribute("data-active")).toBe(true);
		expect(singleHTMLElement.getAttribute("data-active")).toBe("");
		expect(singleHTMLElement.dataset.active).toBe("");

		expect(singleHTMLElement.hasAttribute("data-level")).toBe(true);
		expect(singleHTMLElement.getAttribute("data-level")).toBe("42");
		expect(singleHTMLElement.dataset.level).toBe("42");
	});

	it("Should set many attributes at once.", function() {
		let oneElement = _createDomElement('
Level 42
');

		setAttrs(oneElement, {
			"data-level": 42,
			"class": "level"
		});

		expect(oneElement.getAttribute("data-level")).toBe("42");
		expect(oneElement.getAttribute("class")).toBe("level");
		expect(oneElement.dataset.level).toBe("42");
		expect(oneElement.className).toBe("level");
	});

	it("Should accept a group of DOM nodes.", function() {
		let listElement = _createDomElement('

A

B

C

'),
			manyElements = listElement.querySelectorAll("li");

		setAttrs(manyElements, {
			"data-level": 42,
			"class": "item"
		});

		expect(manyElements[0].getAttribute("data-level")).toBe("42");
		expect(manyElements[0].getAttribute("class")).toBe("item");
		expect(manyElements[0].dataset.level).toBe("42");
		expect(manyElements[0].className).toBe("item");
	});

	it("Should add the attribute name to the tag if passed true.", function() {
		let singleHTMLElement = _createDomElement("
");
		setAttrs(singleHTMLElement, {
			"data-active": true
		});

		expect(singleHTMLElement.hasAttribute("data-active")).toBe(true);
		expect(singleHTMLElement.getAttribute("data-active")).toBe("");
		expect(singleHTMLElement.dataset.active).toBe("");
	});

	it("Should remove the attribute name to the tag if passed false.", function() {
		let singleHTMLElement = _createDomElement("
");
		setAttrs(singleHTMLElement, {
			"data-active": false
		});

		expect(singleHTMLElement.hasAttribute("data-active")).toBe(false);
		expect(singleHTMLElement.getAttribute("data-active")).toBe(null);
		expect(singleHTMLElement.dataset.active).toBe(undefined);
	});

	it("Should accept a group of DOM nodes.", function() {
		let domElA = _createDomElement("
"),
			domElB = _createDomElement("
");

		setAttrs([domElA, domElB], {
			"data-level": 42
		});

		expect(domElA.getAttribute("data-level")).toBe("42");
		expect(domElB.getAttribute("data-level")).toBe("42");
		expect(domElA.dataset.level).toBe("42");
		expect(domElB.dataset.level).toBe("42");
	});

	it("Should accept a group of DOM nodes.", function() {
		let domElA = _createDomElement("
"),
			domElB = _createDomElement("
");

		domElA.className = "setAttrs";
		domElB.className = "setAttrs";

		document.body.appendChild(domElA);
		document.body.appendChild(domElB);

		let manyElements = document.querySelectorAll(".setAttrs");

		setAttrs(manyElements, {
			"data-level": 42
		});

		expect(manyElements[0].getAttribute("data-level")).toBe("42");
		expect(manyElements[1].getAttribute("data-level")).toBe("42");
		expect(manyElements[0].dataset.level).toBe("42");
		expect(manyElements[1].dataset.level).toBe("42");
	});
});


text:
import getEventPath from "../dist/getEventPath.js";
import trigger from "../dist/trigger.js";

describe("getEventPath", function() {
	it(`Should return an array with all DOM elements affected by an event.`, function(done) {
		let domChild = document.createElement("div"),
			domParent = document.createElement("div"),
			domGrandparent = document.createElement("div"),
			body = document.body,
			html = document.querySelector("html");

		domParent.appendChild(domChild);
		domGrandparent.appendChild(domParent);
		body.appendChild(domGrandparent);

		const dealWithChildEvent = evt => {
			expect(getEventPath(evt)).toEqual([
				domChild,
				domParent,
				domGrandparent,
				body,
				html,
				document,
				window
			]);
		};

		const dealWithGrandparentEvent = evt => {
			expect(getEventPath(evt)).toEqual([
				domGrandparent,
				body,
				html,
				document,
				window
			]);

			done();
		};

		domChild.addEventListener("test", dealWithChildEvent);
		domGrandparent.addEventListener("test", dealWithGrandparentEvent);

		trigger(domChild, "test");
		trigger(domGrandparent, "test");
	});

	it(`Should always end with window.`, function(done) {
		const dealWithWindowEvent = evt => {
			expect(getEventPath(evt)).toEqual([window]);
			done();
		};

		window.addEventListener("test", dealWithWindowEvent);
		trigger(window, "test");
	});

	it(`Should return undefined when trying to run getEventPath on something other than an event.`, function() {
		expect(getEventPath(document.createElement("div"))).toBe(undefined);
		expect(getEventPath("laser")).toBe(undefined);
		expect(getEventPath(0)).toBe(undefined);
		expect(getEventPath(document.createTextNode("laser"))).toBe(undefined);
		expect(getEventPath(document.querySelectorAll("div"))).toBe(undefined);
		expect(getEventPath(window)).toBe(undefined);
		expect(getEventPath(document)).toBe(undefined);
	});
});


text:
import byAlphabeticalOrder from "../dist/byAlphabeticalOrder.js";

describe("byAlphabeticalOrder", function() {
	it("Should order an array by alphabetical order.", function() {
		expect(
			["Athos", "Porthos", "Aramis"].sort(byAlphabeticalOrder())
		).toEqual(["Aramis", "Athos", "Porthos"]);
	});

	it("Should function without parentheses.", function() {
		expect(
			["Athos", "Porthos", "Aramis"].sort(byAlphabeticalOrder)
		).toEqual(["Aramis", "Athos", "Porthos"]);
	});

	it("Should function with accented latin characters usign native localeCompare.", function() {
		expect(
			["Áureo", "Árvore", "Ética", "Elástico", "Arte", "Entusiasta"].sort(byAlphabeticalOrder)
		).toEqual(["Arte", "Árvore", "Áureo", "Elástico", "Entusiasta", "Ética"]);
	});

	it("Should function with accented latin characters (upper or lower case) usign native localeCompare.", function() {
		expect(
			["áureo", "Árvore", "Ética", "Elástico", "arte", "entusiasta"].sort(byAlphabeticalOrder)
		).toEqual(["arte", "Árvore", "áureo", "Elástico", "entusiasta", "Ética"]);
	});

	it("Should not fail with an array with a single element.", function() {
		expect(
			["laser"].sort(byAlphabeticalOrder)
		).toEqual(["laser"]);
	});
});


text:
import _removeClassesBeginningWithButNot from "../dist/internal/classname/_removeClassesBeginningWithButNot.js";

describe("_removeClassesBeginningWithButNot", function() {
	for (let i = 0; i < 5; i++) {
		let newEl = document.createElement("div");
		newEl.className = "menu__item button button__active button__level--" + i;
		document.body.appendChild(newEl);
	}

	it("Should remove one or many CSS classes from a single HTMLElement.", function() {
		let singleHTMLElement = document.querySelector(".button__level--1");
		_removeClassesBeginningWithButNot(singleHTMLElement, "button");

		expect(singleHTMLElement.className).toBe("menu__item button");
	});

	it("Should not change a CSS class when trying to remove an inexistent class.", function() {
		let singleHTMLElement = document.querySelector(".button__level--2");
		_removeClassesBeginningWithButNot(singleHTMLElement, "bogus");

		expect(singleHTMLElement.className).toBe("menu__item button button__active button__level--2");
	});

	it("Should remove one or many CSS classes from many HTMLElements.", function() {
		let elementsNodeList = document.querySelectorAll(".button");

		_removeClassesBeginningWithButNot(elementsNodeList, "button");

		for (let i = 0, len = elementsNodeList.length; i < len; i++) {
			expect(elementsNodeList[i].className).toBe("menu__item button");
		}
	});
});


text:
import beforeLast from "../dist/beforeLast.js";

describe("beforeLast", function() {
	it(`Should find "Par" before the last "a" in "Parallelepiped".`, function() {
		expect(
			beforeLast("Parallelepiped", "a")
		).toBe("Par");
	});

	it(`Should find "Parallelepip" before the last "e" in "Parallelepiped".`, function() {
		expect(
			beforeLast("Parallelepiped", "e")
		).toBe("Parallelepip");
	});

	it(`"Should find "Paralle" before the last "le" in "Parallelepiped".`, function() {
		expect(
			beforeLast("Parallelepiped", "le")
		).toBe("Paralle");
	});

	it(`"Should not find anything before the last "P" in "Parallelepiped".`, function() {
		expect(
			beforeLast("Parallelepiped", "P")
		).toBe("");
	});

	it(`"Should find "😋" before the last "📋" in "😋📋👌".`, function() {
		expect(
			beforeLast("😋📋👌", "📋")
		).toBe("😋");
	});

	it(`"Should not find anything before the last "x" in "Parallelepiped".`, function() {
		expect(
			beforeLast("Parallelepiped", "x")
		).toBe(undefined);
	});

	it(`"Should not find anything if the delimiter is ommited.`, function() {
		expect(
			beforeLast("Parallelepiped")
		).toBe(undefined);
	});

	it(`Should find "Parallelepiped" before the last "" in "Parallelepiped".`, function() {
		expect(
			beforeLast("Parallelepiped", "")
		).toBe("Parallelepiped");
	});

	it(`Should throw an error if the first parameter is not a string.`, function() {
		expect(
			() => beforeLast(undefined, "")
		).toThrow();
	});
});


text:
import _isValidModifierObject from "../dist/internal/bem/_isValidModifierObject.js";

describe("_isValidModifierObject", function() {
	it(`"Should return false if passed anything other than a BEM modifier object.`, function() {
		expect(_isValidModifierObject(0)).toBe(false);
		expect(_isValidModifierObject("")).toBe(false);
		expect(_isValidModifierObject("__ -- -")).toBe(false);
		expect(_isValidModifierObject([])).toBe(false);
		expect(_isValidModifierObject()).toBe(false);

		expect(_isValidModifierObject({
			"active": null
		})).toBe(false);

		expect(_isValidModifierObject({
			"active": undefined
		})).toBe(false);
	});

	it(`"Should return true if passed a valid BEM modifier object: with boolean, string or number as properties`, function() {
		expect(_isValidModifierObject({})).toBe(true);

		expect(_isValidModifierObject({
			"active": true
		})).toBe(true);

		expect(_isValidModifierObject({
			"active": false,
			"level": 42
		})).toBe(true);

		expect(_isValidModifierObject({
			"active": 42
		})).toBe(true);

		expect(_isValidModifierObject({
			"active": "42"
		})).toBe(true);
	});
});


text:
import toClosestProp from "../dist/toClosestProp.js";

describe("toClosestProp", function() {
	var mockup = [{
		city: "Rio de Janeiro",
		temperature: 96,
		demographics: {
			population: 6.32
		}
	}, {
		city: "São Paulo",
		temperature: 82.5,
		demographics: {
			population: 12.04
		}
	}, {
		city: "Curitiba",
		temperature: 70,
		demographics: {
			population: 1.752
		}
	}, {
		city: "Florianópolis",
		temperature: 86,
		demographics: {
			population: 0.249
		}
	}];

	it(`Should conclude that Curitiba has the closest temperature to 75 amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toClosestProp("temperature", 75))
		).toBe(mockup[2]); // Curitiba
	});

	it(`Should conclude that Rio de Janeiro has the closest population to 5 amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toClosestProp("demographics.population", 5))
		).toBe(mockup[0]); // Rio de Janeiro
	});

	var test = [{
		n: "a",
		p: 2
	}, {
		n: "b",
		p: 4
	}, {
		n: "c",
		p: 6
	}, {
		n: "d",
		p: 2
	}, {
		n: "e",
		p: 4
	}];

	it(`Should return the first result when two or more are found.`, function() {
		expect(
			test.reduce(toClosestProp("p", 3))
		).toBe(test[0]);
	});
});


text:
import listen from "../dist/listen.js";
import trigger from "../dist/trigger.js";

describe("listen", function() {
	it("Should allow document as parameter.", function() {
		let eventCallback = jasmine.createSpy("eventCallback");
		expect(() => listen(document, "open", eventCallback)).not.toThrow();
	});

	it("Should allow window as parameter.", function() {
		let eventCallback = jasmine.createSpy("eventCallback");
		expect(() => listen(window, "open", eventCallback)).not.toThrow();
	});

	it("Should allow many dom elements, including document and window, as parameter.", function() {
		let eventCallback = jasmine.createSpy("eventCallback"),
			singleDiv = document.createElement("div");

		expect(() => listen([singleDiv, document, window], "open", eventCallback)).not.toThrow();
	});

	it("Should listen for a single event of a single DOM element.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			singleDiv = document.createElement("div");

		document.body.appendChild(singleDiv);

		listen(singleDiv, "open", eventCallback);

		trigger(singleDiv, "open", false);

		setTimeout(() => {
			expect(eventCallback.calls.count()).toBe(1);
			done();
		}, 20);
	});

	it("Should listen for multiple events of a single DOM element.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			singleDiv = document.createElement("div");

		document.body.appendChild(singleDiv);

		listen(singleDiv, "one two three", eventCallback);

		trigger(singleDiv, "one", false);
		trigger(singleDiv, "two", false);
		trigger(singleDiv, "three", false);

		setTimeout(() => {
			expect(eventCallback.calls.count()).toBe(3);
			done();
		}, 20);
	});

	it("Should listen for multiple events of multiple DOM elements.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			multipleDivs = [document.createElement("div"), document.createElement("div")];

		document.body.appendChild(multipleDivs[0]);
		document.body.appendChild(multipleDivs[1]);

		listen(multipleDivs, "one two three", eventCallback);

		trigger(multipleDivs[0], "one", false);
		trigger(multipleDivs[0], "two", false);
		trigger(multipleDivs[0], "three", false);
		trigger(multipleDivs[1], "one", false);
		trigger(multipleDivs[1], "two", false);
		trigger(multipleDivs[1], "three", false);

		setTimeout(() => {
			expect(eventCallback.calls.count()).toBe(6);
			done();
		}, 20);
	});
});


text:
import afterFirst from "../dist/afterFirst.js";

describe("afterFirst", function() {
	it(`Should find "rallelepiped" after the first "a" in "Parallelepiped".`, function() {
		expect(
			afterFirst("Parallelepiped", "a")
		).toBe("rallelepiped");
	});

	it(`Should find "lepiped" after the first "e" in "Parallelepiped".`, function() {
		expect(
			afterFirst("Parallelepiped", "e")
		).toBe("lepiped");
	});

	it(`"Should find "lepiped" after the first "le" in "Parallelepiped".`, function() {
		expect(
			afterFirst("Parallelepiped", "le")
		).toBe("lepiped");
	});

	it(`"Should find "arallelepiped" after the first "P" in "Parallelepiped".`, function() {
		expect(
			afterFirst("Parallelepiped", "P")
		).toBe("arallelepiped");
	});

	it(`"Should find "👌" after the first "📋" in "😋📋👌".`, function() {
		expect(
			afterFirst("😋📋👌", "📋")
		).toBe("👌");
	});

	it(`"Should not find anything after the first "x" in "Parallelepiped".`, function() {
		expect(
			afterFirst("Parallelepiped", "x")
		).toBe(undefined);
	});

	it(`"Should not find anything if the delimiter is ommited.`, function() {
		expect(
			afterFirst("Parallelepiped")
		).toBe(undefined);
	});

	it(`Should find "Parallelepiped" after the first "" in "Parallelepiped".`, function() {
		expect(
			afterFirst("Parallelepiped", "")
		).toBe("Parallelepiped");
	});

	it(`Should throw an error if the first parameter is not a string.`, function() {
		expect(
			() => afterFirst(undefined, "")
		).toThrow();
	});
});


text:
import modifyBemClass from "../dist/modifyBemClass.js";
import modifyBemClassCompact from "../dist/modifyBemClassCompact.js";

const delimiterData = {
	"bemDelimitersA": ["__", "--", "-"],
	"bemDelimitersB": ["__", "_", "_"],
	"bemDelimitersC": ["-", "--", "--"]
};

const modifyBemClassData = {
	"bemDelimitersA": [{
		original: "menu",
		expectation: "menu menu--active",
		changes: {
			"menu": {
				"active": true
			}
		}
	}, {
		original: "menu menu--active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu--active menu--level-40",
		expectation: "menu menu--level-42",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu menu--active menu--level-40 landing__menu",
		expectation: "menu menu--level-42 landing__menu landing__menu--active",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			},
			"landing__menu": {
				"active": true
			}
		}
	}, {
		original: "",
		expectation: "element",
		changes: {
			"element": {}
		}
	}, {
		original: "--active --level-40",
		expectation: "--level-42",
		changes: {
			"": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu",
		expectation: "menu",
		changes: {}
	}],
	"bemDelimitersB": [{
		original: "menu",
		expectation: "menu menu_active",
		changes: {
			"menu": {
				"active": true
			}
		}
	}, {
		original: "menu menu_active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu_active menu_level_40",
		expectation: "menu menu_level_42",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu menu_active menu_level_40 landing__menu",
		expectation: "menu menu_level_42 landing__menu landing__menu_active",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			},
			"landing__menu": {
				"active": true
			}
		}
	}, {
		original: "",
		expectation: "element",
		changes: {
			"element": {}
		}
	}, {
		original: "_active _level_40",
		expectation: "_level_42",
		changes: {
			"": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu",
		expectation: "menu",
		changes: {}
	}],
	"bemDelimitersC": [{
		original: "menu",
		expectation: "menu menu--active",
		changes: {
			"menu": {
				"active": true
			}
		}
	}, {
		original: "menu menu--active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu--active menu--level--40",
		expectation: "menu menu--level--42",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu menu--active menu--level--40 landing-menu",
		expectation: "menu menu--level--42 landing-menu landing-menu--active",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			},
			"landing-menu": {
				"active": true
			}
		}
	}, {
		original: "",
		expectation: "element",
		changes: {
			"element": {}
		}
	}, {
		original: "--active --level--40",
		expectation: "--level--42",
		changes: {
			"": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu",
		expectation: "menu",
		changes: {}
	}]
};

const modifyBemClassDataCompact = {
	"bemDelimitersA": [{
		original: "menu",
		expectation: "menu--active",
		changes: {
			"menu": {
				"active": true
			}
		}
	}, {
		original: "menu--active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu--active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu--active menu--level-40",
		expectation: "menu--level-42",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu--active menu--level-40 landing__menu",
		expectation: "menu--level-42 landing__menu--active",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			},
			"landing__menu": {
				"active": true
			}
		}
	}, {
		original: "",
		expectation: "element",
		changes: {
			"element": {}
		}
	}, {
		original: "--active --level-40",
		expectation: "--level-42",
		changes: {
			"": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu",
		expectation: "menu",
		changes: {}
	}],
	"bemDelimitersB": [{
		original: "menu",
		expectation: "menu_active",
		changes: {
			"menu": {
				"active": true
			}
		}
	}, {
		original: "menu_active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu_active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu_active menu_level_40",
		expectation: "menu_level_42",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu_active menu_level_40 landing__menu",
		expectation: "menu_level_42 landing__menu_active",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			},
			"landing__menu": {
				"active": true
			}
		}
	}, {
		original: "",
		expectation: "element",
		changes: {
			"element": {}
		}
	}, {
		original: "_active _level_40",
		expectation: "_level_42",
		changes: {
			"": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu",
		expectation: "menu",
		changes: {}
	}],
	"bemDelimitersC": [{
		original: "menu",
		expectation: "menu--active",
		changes: {
			"menu": {
				"active": true
			}
		}
	}, {
		original: "menu--active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu--active",
		expectation: "menu",
		changes: {
			"menu": {
				"active": false
			}
		}
	}, {
		original: "menu menu--active menu--level--40",
		expectation: "menu--level--42",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu--active menu--level--40 landing-menu",
		expectation: "menu--level--42 landing-menu--active",
		changes: {
			"menu": {
				"active": false,
				"level": 42
			},
			"landing-menu": {
				"active": true
			}
		}
	}, {
		original: "",
		expectation: "element",
		changes: {
			"element": {}
		}
	}, {
		original: "--active --level--40",
		expectation: "--level--42",
		changes: {
			"": {
				"active": false,
				"level": 42
			}
		}
	}, {
		original: "menu",
		expectation: "menu",
		changes: {}
	}]
};

function makeBemTestsFromData(method, delimiterData, methodData) {
	Object.keys(delimiterData).forEach(function(delimiter) {
		methodData[delimiter].forEach(function(data) {
			let delimiterArr = delimiterData[delimiter];
			makeBemTest(method, makeBemDescription(data, delimiterArr), data.original, data.expectation, data.changes, delimiterArr);
		});
	});
}

function makeBemTest(method, description, initialClassName, expectation, bemObj, delimiterArr) {
	return it(description, function() {
		let domEl = makeBemDivWithClassName(initialClassName);
		method(domEl, bemObj, delimiterArr);
		expect(domEl.className.split(" ").sort()).toEqual(expectation.split(" ").sort());
	});
}

function makeBemDescription(data, delimiterArr) {
	let sortedOriginal = data.original.split(" ").sort().join(" "),
		sortedExpectation = data.expectation.split(" ").sort().join(" "),
		bemObjJson = JSON.stringify(data.changes),
		delimiterStr = `"` + delimiterArr.slice(0, 2).join(`", "`) + `" e "` + delimiterArr.slice(2) + `"`;

	return `A classe "${sortedOriginal}" vira "${sortedExpectation}" modificada com um objeto ${bemObjJson} e delimitadores ${delimiterStr}.`;
}

function makeBemDivWithClassName(className) {
	var domEl = document.createElement("div");
	domEl.className = className;
	return domEl;
}

describe("modifyBemClass", function() {
	makeBemTestsFromData(modifyBemClass, delimiterData, modifyBemClassData);
});

describe("modifyBemClassCompact", function() {
	makeBemTestsFromData(modifyBemClassCompact, delimiterData, modifyBemClassDataCompact);
});


text:
import trigger from "../dist/trigger.js";

describe("trigger", function() {
	it(`Should trigger a custom event, captured by the emmiter itself.`, function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			popupLayer = document.createElement("div");

		document.body.appendChild(popupLayer);

		popupLayer.addEventListener("open", evt => {
			eventCallback();
			expect(eventCallback).toHaveBeenCalled();
			done();
		});

		trigger(popupLayer, "open", false);
	});

	it(`Should trigger a custom event, captured by window because the event bubbles.`, function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			popupLayer = document.createElement("div");

		document.body.appendChild(popupLayer);

		window.addEventListener("open", evt => {
			eventCallback();
			expect(eventCallback).toHaveBeenCalled();
			done();
		});

		trigger(popupLayer, "open", true); // bubbles
	});

	it(`Should trigger a custom event, not captured by window because the event does not bubble.`, function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			popupLayer = document.createElement("div");

		document.body.appendChild(popupLayer);

		window.addEventListener("open", evt => {
			eventCallback();
		});

		trigger(popupLayer, "open", false); // does not bubble

		setTimeout(() => {
			expect(eventCallback).not.toHaveBeenCalled();
			done();
		}, 100);
	});

	it(`Should be able to access event details.`, function(done) {
		let popupLayer = document.createElement("div");

		document.body.appendChild(popupLayer);

		popupLayer.addEventListener("open", evt => {
			expect(evt.detail).toBe("customDetail");
			done();
		});

		trigger(popupLayer, "open", false, false, "customDetail");
	});
});


text:
import _isString from "../dist/internal/helpers/_isString.js";

describe("_isString", function() {
	it(`"Should return false if passed anything other than a string.`, function() {
		expect(_isString()).toBe(false);
		expect(_isString([])).toBe(false);
		expect(_isString({})).toBe(false);
		expect(_isString(null)).toBe(false);
		expect(_isString(undefined)).toBe(false);
		expect(_isString(NaN)).toBe(false);
		expect(_isString(new Set())).toBe(false);
		expect(_isString(new WeakSet())).toBe(false);
		expect(_isString(new Map())).toBe(false);
		expect(_isString(new WeakMap())).toBe(false);
		expect(_isString(document.createElement("div"))).toBe(false);
		expect(_isString(15)).toBe(false);
		expect(_isString(15.45)).toBe(false);
		expect(_isString(Math.PI)).toBe(false);
		expect(_isString("")).toBe(true);
		expect(_isString("345")).toBe(true);
		expect(_isString(new String("window"))).toBe(true);
		expect(_isString(new String("😋📋👌"))).toBe(true);
		expect(_isString(0)).toBe(false);
		expect(_isString(1)).toBe(false);
		expect(_isString(true)).toBe(false);
		expect(_isString(false)).toBe(false);
	});
});


text:
import toAverage from "../dist/toAverage.js";

describe("toAverage", function() {
	it(`Should return the average of all items in an array when used with Array.prototype.reduce().`, function() {
		expect(
			[3, 5, 7, 9].reduce(toAverage())
		).toBe(6);

		expect(
			[-10, 10].reduce(toAverage())
		).toBe(0);
	});

	it("Should function without parentheses.", function() {
		expect(
			[3, 5, 7, 9].reduce(toAverage)
		).toBe(6);

		expect(
			[-10, 10].reduce(toAverage)
		).toBe(0);
	});
});


text:
import afterLast from "../dist/afterLast.js";

describe("afterLast", function() {
	it(`Should find "llelepiped" after the last "a" in "Parallelepiped".`, function() {
		expect(
			afterLast("Parallelepiped", "a")
		).toBe("llelepiped");
	});

	it(`Should find "d" after the last "e" in "Parallelepiped".`, function() {
		expect(
			afterLast("Parallelepiped", "e")
		).toBe("d");
	});

	it(`"Should find "piped" after the last "le" in "Parallelepiped".`, function() {
		expect(
			afterLast("Parallelepiped", "le")
		).toBe("piped");
	});

	it(`"Should find "arallelepiped" after the last "P" in "Parallelepiped".`, function() {
		expect(
			afterLast("Parallelepiped", "P")
		).toBe("arallelepiped");
	});

	it(`"Should find "👌" after the last "📋" in "😋📋👌".`, function() {
		expect(
			afterLast("😋📋👌", "📋")
		).toBe("👌");
	});

	it(`"Should not find anything after the last "x" in "Parallelepiped".`, function() {
		expect(
			afterLast("Parallelepiped", "x")
		).toBe(undefined);
	});

	it(`"Should not find anything if the delimiter is ommited.`, function() {
		expect(
			afterLast("Parallelepiped")
		).toBe(undefined);
	});

	it(`Should find "" after the last "" in "Parallelepiped".`, function() {
		expect(
			afterLast("Parallelepiped", "")
		).toBe("");
	});

	it(`Should throw an error if the first parameter is not a string.`, function() {
		expect(
			() => afterLast(undefined, "")
		).toThrow();
	});
});


text:
import _isPlainObject from "../dist/internal/helpers/_isPlainObject.js";

class Foo {
	constructor(a) {
		this.a = 1;
	}
}

function Doo(a) { this.a = 1; }

describe("_isPlainObject", function() {
	it(`"Should return false if passed anything other than a plain object.`, function() {
		expect(_isPlainObject()).toBe(false);
		expect(_isPlainObject([])).toBe(false);
		expect(_isPlainObject({})).toBe(true);
		expect(_isPlainObject(null)).toBe(false);
		expect(_isPlainObject(undefined)).toBe(false);
		expect(_isPlainObject(NaN)).toBe(false);
		expect(_isPlainObject(new Set())).toBe(false);
		expect(_isPlainObject(new WeakSet())).toBe(false);
		expect(_isPlainObject(new Map())).toBe(false);
		expect(_isPlainObject(new WeakMap())).toBe(false);
		expect(_isPlainObject(document.createElement("div"))).toBe(false);
		expect(_isPlainObject(15)).toBe(false);
		expect(_isPlainObject(15.45)).toBe(false);
		expect(_isPlainObject(Math.PI)).toBe(false);
		expect(_isPlainObject("")).toBe(false);
		expect(_isPlainObject("345")).toBe(false);
		expect(_isPlainObject(new String("window"))).toBe(false);
		expect(_isPlainObject(new String("😋📋👌"))).toBe(false);
		expect(_isPlainObject(0)).toBe(false);
		expect(_isPlainObject(1)).toBe(false);
		expect(_isPlainObject(true)).toBe(false);
		expect(_isPlainObject(false)).toBe(false);

		expect(_isPlainObject(new Object())).toBe(true);
		expect(_isPlainObject({ 'x': 0, 'y': 0 })).toBe(true);
		expect(_isPlainObject(Object.create(null))).toBe(true);
		expect(_isPlainObject(Object.create(Object.prototype))).toBe(true);
		expect(_isPlainObject(Object.prototype)).toBe(true);
		expect(_isPlainObject(Object)).toBe(false);
		expect(_isPlainObject(Math)).toBe(false);
		expect(_isPlainObject(Math.abs)).toBe(false);
		expect(_isPlainObject(new Foo())).toBe(false);
		expect(_isPlainObject(new Doo())).toBe(false);
		expect(_isPlainObject([1, 2, 3])).toBe(false);
		expect(_isPlainObject(Object)).toBe(false);
		expect(_isPlainObject(null)).toBe(false);
		expect(_isPlainObject('str')).toBe(false);
		expect(_isPlainObject(5)).toBe(false);
		expect(_isPlainObject(true)).toBe(false);
		expect(_isPlainObject(undefined)).toBe(false);
		expect(_isPlainObject(new Date())).toBe(false);
	});
});


text:
import toLargestProp from "../dist/toLargestProp.js";

describe("toLargestProp", function() {
	var mockup = [{
		city: "Rio de Janeiro",
		temperature: 96,
		demographics: {
			population: 6.32
		}
	}, {
		city: "São Paulo",
		temperature: 82.5,
		demographics: {
			population: 12.04
		}
	}, {
		city: "Curitiba",
		temperature: 70,
		demographics: {
			population: 1.752
		}
	}, {
		city: "Florianópolis",
		temperature: 86,
		demographics: {
			population: 0.249
		}
	}];

	it(`Should conclude that Rio de Janeiro has the largest temperature amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toLargestProp("temperature"))
		).toBe(mockup[0]); // Rio de Janeiro
	});

	it(`Should conclude that São Paulo has the largest population amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toLargestProp("demographics.population"))
		).toBe(mockup[1]); // São Paulo
	});

	var test = [{
		n: "a",
		p: 2
	}, {
		n: "b",
		p: 8
	}, {
		n: "c",
		p: 6
	}, {
		n: "d",
		p: 2
	}, {
		n: "e",
		p: 8
	}];

	it(`Should return the first result when two or more are found.`, function() {
		expect(
			test.reduce(toLargestProp("p"))
		).toBe(test[1]);
	});
});


text:
import toClosest from "../dist/toClosest.js";

describe("toClosest", function() {
	it(`Should return the closest value to a specific number in an array when used with Array.prototype.reduce().`, function() {
		expect(
			[3, 5, 7, 9].reduce(toClosest(6))
		).toBe(5);

		expect(
			[9, 7, 5, 3].reduce(toClosest(6))
		).toBe(7);

		expect(
			[128, 17, -5, 78].reduce(toClosest(6))
		).toBe(17);

		expect(
			[128, 18, -5, 78].reduce(toClosest(6))
		).toBe(-5);

		expect(
			[3, 5, 7, 9].reduce(toClosest(-2))
		).toBe(3);
	});
});


text:
import hasClass from "../dist/hasClass.js";

describe("hasClass", function() {
	it("Should verify if an HTMLElement has a CSS class.", function() {
		let oneElement = document.createElement("a");
		oneElement.className = "link reference";

		expect(hasClass(oneElement, "link")).toBe(true);
		expect(hasClass(oneElement, "button")).toBe(false);
	});
});


text:
import formatBemClass from "../dist/formatBemClass.js";

describe("formatBemClass", function() {
	let delimiters = ["__", "--", "-"];

	it("Should format a CSS classe according to the BEM methodology.", function() {
		expect(formatBemClass("menu", null,   null,     null,  delimiters)).toBe("menu");
		expect(formatBemClass("menu", "item", null,     null,  delimiters)).toBe("menu__item");
		expect(formatBemClass("menu", "item", "active", null,  delimiters)).toBe("menu__item");
		expect(formatBemClass("menu", "item", "active", false, delimiters)).toBe("menu__item");
		expect(formatBemClass("menu", "item", "active", true,  delimiters)).toBe("menu__item--active");
		expect(formatBemClass("menu", "item", "level",  42,    delimiters)).toBe("menu__item--level-42");
		expect(formatBemClass("menu", "item", "level",  "42",  delimiters)).toBe("menu__item--level-42");
		expect(formatBemClass("menu", null,   "active", null,  delimiters)).toBe("menu");
		expect(formatBemClass("menu", null,   "active", false, delimiters)).toBe("menu");
		expect(formatBemClass("menu", null,   "active", true,  delimiters)).toBe("menu--active");
		expect(formatBemClass("menu", null,   "level",  42,    delimiters)).toBe("menu--level-42");
		expect(formatBemClass("menu", null,   "level",  "42",  delimiters)).toBe("menu--level-42");
		expect(formatBemClass("",     null,   "active", null,  delimiters)).toBe("");
		expect(formatBemClass("",     null,   "active", false, delimiters)).toBe("");
		expect(formatBemClass("",     null,   "active", true,  delimiters)).toBe("--active");
		expect(formatBemClass("",     null,   "level",  "42",  delimiters)).toBe("--level-42");
		expect(formatBemClass(null,   null,   "active", null,  delimiters)).toBe("");
		expect(formatBemClass(null,   null,   "active", false, delimiters)).toBe("");
		expect(formatBemClass(null,   null,   "active", true,  delimiters)).toBe("--active");
		expect(formatBemClass(null,   null,   "level",  "42",  delimiters)).toBe("--level-42");
	});

	it("Should format a CSS classe according to the BEM methodology even when BEM entity parameters are ommited.", function() {
		expect(formatBemClass("menu",                          delimiters)).toBe("menu");
		expect(formatBemClass("menu", "item",                  delimiters)).toBe("menu__item");
		expect(formatBemClass("menu", "item", "active",        delimiters)).toBe("menu__item--active");
		expect(formatBemClass("menu", "item", "active", false, delimiters)).toBe("menu__item");
		expect(formatBemClass("menu", "item", "active", true,  delimiters)).toBe("menu__item--active");
		expect(formatBemClass("menu", "item", "level",  42,    delimiters)).toBe("menu__item--level-42");
		expect(formatBemClass("menu", "item", "level",  "42",  delimiters)).toBe("menu__item--level-42");
		expect(formatBemClass("menu", null,   "active",        delimiters)).toBe("menu--active");
		expect(formatBemClass("menu", null,   "active", false, delimiters)).toBe("menu");
		expect(formatBemClass("menu", null,   "active", true,  delimiters)).toBe("menu--active");
		expect(formatBemClass("menu", null,   "level",  42,    delimiters)).toBe("menu--level-42");
		expect(formatBemClass("menu", null,   "level",  "42",  delimiters)).toBe("menu--level-42");
		expect(formatBemClass("",     null,   "active",        delimiters)).toBe("--active");
		expect(formatBemClass("",     null,   "active", false, delimiters)).toBe("");
		expect(formatBemClass("",     null,   "active", true,  delimiters)).toBe("--active");
		expect(formatBemClass("",     null,   "level",  "42",  delimiters)).toBe("--level-42");
		expect(formatBemClass(null,   null,   "active",        delimiters)).toBe("--active");
		expect(formatBemClass(null,   null,   "active", false, delimiters)).toBe("");
		expect(formatBemClass(null,   null,   "active", true,  delimiters)).toBe("--active");
		expect(formatBemClass(null,   null,   "level",  "42",  delimiters)).toBe("--level-42");
	});

	it("Should ignore empty BEM entities", function(){
		expect(formatBemClass("menu", "",        "active", delimiters)).toBe("menu--active");
		expect(formatBemClass("menu", undefined, "active", delimiters)).toBe("menu--active");
		expect(formatBemClass("menu", null,      "active", delimiters)).toBe("menu--active");
	});

	it("Should not accept less than two parameters", function(){
		expect(() => formatBemClass()).toThrow();
		expect(() => formatBemClass("menu")).toThrow();
	});
});


text:
import _createDomElement from "../dist/internal/dom/_createDomElement.js";
import removeAttrs from "../dist/removeAttrs.js";

describe("removeAttrs", function() {
	it("Should remove many attributes from a DOM element.", function() {
		let videoHTMLElement = document.createElement("video");
		videoHTMLElement.setAttribute("controls", "");
		videoHTMLElement.setAttribute("data-paused", "");

		removeAttrs(videoHTMLElement, ["controls", "data-paused"]);

		expect(videoHTMLElement.hasAttribute("controls")).toBe(false);
		expect(videoHTMLElement.getAttribute("controls")).toBe(null);

		expect(videoHTMLElement.hasAttribute("data-paused")).toBe(false);
		expect(videoHTMLElement.getAttribute("controls")).toBe(null);
		expect(videoHTMLElement.dataset.paused).toBe(undefined);
	});

	it("Should remove many attributes from a DOM element.", function() {
		let oneElement = _createDomElement('
Level 42
');
		removeAttrs(oneElement, ["data-level", "class"]);

		expect(oneElement.getAttribute("data-level")).toBe(null);
		expect(oneElement.getAttribute("class")).toBe(null);
		expect(oneElement.dataset.level).toBe(undefined);
		expect(oneElement.className).toBe("");
	});

	it("Should accept a group of DOM nodes.", function() {
		let domElA = document.createElement("div"),
			domElB = document.createElement("div");

		domElA.className = "removeAttr";
		domElA.dataset.level = 42;
		domElB.className = "removeAttr";
		domElB.dataset.level = 42;

		document.body.appendChild(domElA);
		document.body.appendChild(domElB);

		let manyElements = document.querySelectorAll(".removeAttr");

		removeAttrs(manyElements, ["data-level", "class"]);

		expect(manyElements[0].getAttribute("data-level")).toBe(null);
		expect(manyElements[0].getAttribute("class")).toBe(null);
		expect(manyElements[0].dataset.level).toBe(undefined);
		expect(manyElements[0].className).toBe("");
	});

	it("Should accept a group of DOM nodes.", function() {
		let listElement = _createDomElement('

A

B

'),
			manyElements = listElement.querySelectorAll("li");

		removeAttrs(manyElements, ["data-level", "class"]);

		expect(manyElements[0].getAttribute("data-level")).toBe(null);
		expect(manyElements[1].getAttribute("data-level")).toBe(null);
		expect(manyElements[0].getAttribute("class")).toBe(null);
		expect(manyElements[1].getAttribute("class")).toBe(null);
		expect(manyElements[0].dataset.level).toBe(undefined);
		expect(manyElements[1].dataset.level).toBe(undefined);
		expect(manyElements[0].className).toBe("");
		expect(manyElements[1].className).toBe("");
	});
});


text:
import byProps from "../dist/byProps.js";

describe("byProps", function() {

	const unsortedNumeric = [{
		value: 15
	}, {
		value: -20
	}, {
		value: 15.2
	}, {
		value: 3
	}, {
		value: 0.8
	}, {
		value: 1300
	}];

	const sortedNumeric = [{
		value: -20
	}, {
		value: 0.8
	}, {
		value: 3
	}, {
		value: 15
	}, {
		value: 15.2
	}, {
		value: 1300
	}];

	const sortedNumericDESC = [{
		value: 1300
	}, {
		value: 15.2
	}, {
		value: 15
	}, {
		value: 3
	}, {
		value: 0.8
	}, {
		value: -20
	}];

	const sortedNumericAbsolute = [{
		value: 0.8
	}, {
		value: 3
	}, {
		value: 15
	}, {
		value: 15.2
	}, {
		value: -20
	}, {
		value: 1300
	}];

	const sortedNumericAbsoluteDESC = [{
		value: 1300
	}, {
		value: -20
	}, {
		value: 15.2
	}, {
		value: 15
	}, {
		value: 3
	}, {
		value: 0.8
	}];

	const deepUnsortedNumeric = [{
		value: {
			inner: 15
		}
	}, {
		value: {
			inner: -20
		}
	}, {
		value: {
			inner: 15.2
		}
	}, {
		value: {
			inner: 3
		}
	}, {
		value: {
			inner: 0.8
		}
	}, {
		value: {
			inner: 1300
		}
	}];

	const deepSortedNumeric = [{
		value: {
			inner: -20
		}
	}, {
		value: {
			inner: 0.8
		}
	}, {
		value: {
			inner: 3
		}
	}, {
		value: {
			inner: 15
		}
	}, {
		value: {
			inner: 15.2
		}
	}, {
		value: {
			inner: 1300
		}
	}];

	const deepSortedNumericDESC = [{
		value: {
			inner: 1300
		}
	}, {
		value: {
			inner: 15.2
		}
	}, {
		value: {
			inner: 15
		}
	}, {
		value: {
			inner: 3
		}
	}, {
		value: {
			inner: 0.8
		}
	}, {
		value: {
			inner: -20
		}
	}];

	const deepSortedNumericAbsolute = [{
		value: {
			inner: 0.8
		}
	}, {
		value: {
			inner: 3
		}
	}, {
		value: {
			inner: 15
		}
	}, {
		value: {
			inner: 15.2
		}
	}, {
		value: {
			inner: -20
		}
	}, {
		value: {
			inner: 1300
		}
	}];

	const deepSortedNumericAbsoluteDESC = [{
		value: {
			inner: 1300
		}
	}, {
		value: {
			inner: -20
		}
	}, {
		value: {
			inner: 15.2
		}
	}, {
		value: {
			inner: 15
		}
	}, {
		value: {
			inner: 3
		}
	}, {
		value: {
			inner: 0.8
		}
	}];

	const unsortedPortugueseWords = [{
		value: "Áureo"
	}, {
		value: "Árvore"
	}, {
		value: "Ética"
	}, {
		value: "Elástico"
	}, {
		value: "Arte"
	}, {
		value: "Entusiasta"
	}];

	const sortedPortugueseWords = [{
		value: "Arte"
	}, {
		value: "Árvore"
	}, {
		value: "Áureo"
	}, {
		value: "Elástico"
	}, {
		value: "Entusiasta"
	}, {
		value: "Ética"
	}];

	const singleObject = [{
		value: "laser"
	}];

	const deepSingleObject = [{
		value: {
			inner: "laser"
		}
	}];

	const unsortedStores = [{
		name: "Richards",
		city: "Rio de Janeiro",
		state: "RJ"
	}, {
		name: "Ellus",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "Salinas",
		city: "Búzios",
		state: "RJ"
	}, {
		name: "VR",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "Bobstore",
		city: "Curitiba",
		state: "PR"
	}];

	const sortedStoresByStateCityName = [{
		name: "Bobstore",
		city: "Curitiba",
		state: "PR"
	}, {
		name: "Salinas",
		city: "Búzios",
		state: "RJ"
	}, {
		name: "Richards",
		city: "Rio de Janeiro",
		state: "RJ"
	}, {
		name: "Ellus",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "VR",
		city: "São Paulo",
		state: "SP"
	}];

	const sortedStoresByNameCityState = [{
		name: "Bobstore",
		city: "Curitiba",
		state: "PR"
	}, {
		name: "Ellus",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "Richards",
		city: "Rio de Janeiro",
		state: "RJ"
	}, {
		name: "Salinas",
		city: "Búzios",
		state: "RJ"
	}, {
		name: "VR",
		city: "São Paulo",
		state: "SP"
	}];

	const sortedStoresByStateDESCCityName = [{
		name: "Ellus",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "VR",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "Salinas",
		city: "Búzios",
		state: "RJ"
	}, {
		name: "Richards",
		city: "Rio de Janeiro",
		state: "RJ"
	}, {
		name: "Bobstore",
		city: "Curitiba",
		state: "PR"
	}];

	const deepUnsortedStores = [{
		name: "Richards",
		location: {
			city: "Rio de Janeiro",
			state: "RJ"
		},
	}, {
		name: "Ellus",
		location: {
			city: "São Paulo",
			state: "SP"
		},
	}, {
		name: "Salinas",
		location: {
			city: "Búzios",
			state: "RJ"
		},
	}, {
		name: "VR",
		location: {
			city: "São Paulo",
			state: "SP"
		},
	}, {
		name: "Bobstore",
		location: {
			city: "Curitiba",
			state: "PR"
		},
	}];

	const deepSortedStoresByStateDESCCityName = [{
		name: "Ellus",
		location: {
			city: "São Paulo",
			state: "SP"
		}
	}, {
		name: "VR",
		location: {
			city: "São Paulo",
			state: "SP"
		}
	}, {
		name: "Salinas",
		location: {
			city: "Búzios",
			state: "RJ"
		}
	}, {
		name: "Richards",
		location: {
			city: "Rio de Janeiro",
			state: "RJ"
		}
	}, {
		name: "Bobstore",
		location: {
			city: "Curitiba",
			state: "PR"
		}
	}];

	const unsortedWords = [{
		value: "Word"
	}, {
		value: "Computer"
	}, {
		value: "Planet"
	}, {
		value: "Lever"
	}];

	const sortedWordsBySecondLetterAndBeyond = [{
		value: "Lever"
	}, {
		value: "Planet"
	}, {
		value: "Computer"
	}, {
		value: "Word"
	}, ];

	it("Should sort object properties with numeric values correctly, passing a path as paremeter.", function() {
		expect(unsortedNumeric.sort(byProps("value")))
			.toEqual(sortedNumeric);
	});

	it("Should sort object properties with numeric values correctly, passing a composed path as paremeter.", function() {
		expect(deepUnsortedNumeric.sort(byProps("value.inner")))
			.toEqual(deepSortedNumeric);
	});

	it("Should sort object properties with numeric values correctly, passing a sort field with a path and reverse set to true as parameter.", function() {
		expect(unsortedNumeric.sort(byProps({
				path: "value",
				reverse: true
			})))
			.toEqual(sortedNumericDESC);
	});

	it("Should sort object properties with numeric values correctly, passing a sort field with a composed path and reverse set to true as parameter.", function() {
		expect(deepUnsortedNumeric.sort(byProps({
				path: "value.inner",
				reverse: true
			})))
			.toEqual(deepSortedNumericDESC);
	});

	it("Should sort object properties with numeric values correctly, as if they were absolute numbers, passing a sort field with a path and a primer function as parameter.", function() {
		expect(unsortedNumeric.sort(byProps({
				path: "value",
				primer: num => Math.abs(num)
			})))
			.toEqual(sortedNumericAbsolute);
	});

	it("Should sort object properties with numeric values correctly, as if they were absolute numbers, passing a sort field with a composed path and a primer function as parameter.", function() {
		expect(deepUnsortedNumeric.sort(byProps({
				path: "value.inner",
				primer: num => Math.abs(num)
			})))
			.toEqual(deepSortedNumericAbsolute);
	});

	it("Should be able to combine primer and reverse properties of the sort field.", function() {
		expect(unsortedNumeric.sort(byProps({
				path: "value",
				primer: Math.abs,
				reverse: true
			})))
			.toEqual(sortedNumericAbsoluteDESC);
	});

	it("Should be able to combine primer and reverse properties of the sort field with a composed path.", function() {
		expect(deepUnsortedNumeric.sort(byProps({
				path: "value.inner",
				primer: Math.abs,
				reverse: true
			})))
			.toEqual(deepSortedNumericAbsoluteDESC);
	});

	it("Should not fail with accented latin characters.", function() {
		expect(unsortedPortugueseWords.sort(byProps("value")))
			.toEqual(sortedPortugueseWords);
	});

	it("Should not fail with an array with a single object.", function() {
		expect(singleObject.sort(byProps("value")))
			.toEqual(singleObject);
	});

	it("Should not fail with an array with a single object, even with composed paths.", function() {
		expect(deepSingleObject.sort(byProps("value.inner")))
			.toEqual(deepSingleObject);
	});

	it("Should be able to use combined sorting properties as strings.", function() {
		expect(unsortedStores.sort(byProps("state", "city", "name")))
			.toEqual(sortedStoresByStateCityName);

		expect(unsortedStores.sort(byProps("name", "city", "state")))
			.toEqual(sortedStoresByNameCityState);
	});

	it("Should be able to use combined sorting properties as objects or strings.", function() {
		expect(unsortedStores.sort(byProps({
				path: "state",
				reverse: true
			}, "city", "name")))
			.toEqual(sortedStoresByStateDESCCityName);

		expect(unsortedStores.sort(byProps({
				path: "state",
				reverse: true
			}, {
				path: "city"
			}, {
				path: "name"
			})))
			.toEqual(sortedStoresByStateDESCCityName);
	});

	it("Should be able to use combined sorting properties as objects and composed paths.", function() {
		expect(deepUnsortedStores.sort(byProps({
				path: "location.state",
				reverse: true
			}, {
				path: "location.city"
			}, {
				path: "name"
			})))
			.toEqual(deepSortedStoresByStateDESCCityName);
	});

	it("Should be able to create weird sortings with the primer function, for exemple, sorting from the second letter and beyond.", function() {
		expect(unsortedWords.sort(byProps({
				path: "value",
				primer: str => str.slice(1)
			})))
			.toEqual(sortedWordsBySecondLetterAndBeyond);
	});

	it("Should throw an error if no sort criterias are passed as parameters.", function() {
		expect(() => unsortedWords.sort(byProps())).toThrow();
	});
});


text:
import getClippingInfo from "../dist/getClippingInfo.js";

describe("getClippingInfo", function() {
	let domEl = document.createElement("div");
	let maskEl = document.createElement("div");

	domEl.style.cssText = "position: absolute; width: 40px; height: 40px; display: block; background: rgba(153, 0, 153, 0.3);";
	maskEl.style.cssText = "position: relative; width: 100px; height: 100px; display: block; background: rgba(153, 0, 153, 0.3);";

	maskEl.appendChild(domEl);
	document.body.appendChild(maskEl);

	function changeSize(domEl, newWidth, newHeight) {
		domEl.style.width = newWidth + "px";
		domEl.style.height = newHeight + "px";
	}

	function changePosition(domEl, newTop, newLeft) {
		domEl.style.top = newTop + "px";
		domEl.style.left = newLeft + "px";
	}

	function changeClippingInfo(domEl, maskEl, newTop, newLeft) {
		changePosition(domEl, newTop, newLeft);
		return getClippingInfo(domEl, maskEl);
	}

	const availableKeys = [
		"isOffTop",
		"isOffBottom",
		"isOffLeft",
		"isOffRight",
		"isOff",
		"isClippedTop",
		"isClippedBottom",
		"isClippedLeft",
		"isClippedRight",
		"isClipped",
		"isFullyVisible",
		"isPartiallyVisible",
		"isInvisible",
		"isAsVisibleAsPossible",
		"isNotAsVisibleAsPossible"
	];

	function testClippingInfo(keys, availableKeys, currentInfo) {
		for (let i = 0, len = availableKeys.length; i < len; i++) {
			let currentKey = availableKeys[i];

			if (keys.includes(currentKey)) {
				expect(currentInfo[currentKey]).toBe(true);
			}
			else {
				expect(currentInfo[currentKey]).toBe(false);
			}
		}
	}

	function testMultipleCoordinates(keys, newTops, newLefts, domEl, maskEl, availableKeys) {
		let currentInfo;

		newTops = Array.isArray(newTops) ? newTops : [newTops];
		newLefts = Array.isArray(newLefts) ? newLefts : [newLefts];

		newTops.forEach(newTop => {
			newLefts.forEach(newLeft => {
				currentInfo = changeClippingInfo(domEl, maskEl, newTop, newLeft);
				testClippingInfo(keys, availableKeys, currentInfo);
			});
		});
	}

	// Child.width < Mask.width && Child.height < Mask.height

	// Contained

	it("Should change the size of the child.", function() {
		changeSize(domEl, 40, 40);
	});

	it("Should behave like the child is fully contained by the mask.", function() {
		testMultipleCoordinates(
			["isFullyVisible", "isAsVisibleAsPossible"], [0, 30, 60], [0, 30, 60],
			domEl, maskEl, availableKeys
		);
	});

	it("Should change the size of the child.", function() {
		changeSize(domEl, 100, 40);
	});

	it("Should behave like the child (long) is fully contained by the mask.", function() {
		testMultipleCoordinates(
			["isFullyVisible", "isAsVisibleAsPossible"], [0, 30, 60], 0,
			domEl, maskEl, availableKeys
		);
	});

	it("Should change the size of the child.", function() {
		changeSize(domEl, 40, 100);
	});

	it("Should behave like the child (wide) is fully contained by the mask.", function() {
		testMultipleCoordinates(
			["isFullyVisible", "isAsVisibleAsPossible"], 0, [0, 30, 60],
			domEl, maskEl, availableKeys
		);
	});

	it("Should change the size of the child.", function() {
		changeSize(domEl, 100, 100);
	});

	it("Should behave like the child (full) is fully contained by the mask.", function() {
		testMultipleCoordinates(
			["isFullyVisible", "isAsVisibleAsPossible"], 0, 0,
			domEl, maskEl, availableKeys
		);
	});

	// Outside

	it("Should change the size of the child.", function() {
		changeSize(domEl, 40, 40);
	});

	it("Should behave like the child is outside, above and on the left.", function() {
		testMultipleCoordinates(
			["isOffTop", "isOffLeft", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [-60, -40], [-60, -40],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside and above.", function() {
		testMultipleCoordinates(
			["isOffTop", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [-60, -40], [-20, 0, 30, 60, 80],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside, above and on the right.", function() {
		testMultipleCoordinates(
			["isOffTop", "isOffRight", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [-60, -40], [100, 120],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside and on the right.", function() {
		testMultipleCoordinates(
			["isOffRight", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [-20, 0, 30, 60, 80], [100, 120],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside, below and on the right.", function() {
		testMultipleCoordinates(
			["isOffBottom", "isOffRight", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [100, 120], [100, 120],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside and below.", function() {
		testMultipleCoordinates(
			["isOffBottom", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [100, 120], [-20, 0, 30, 60, 80],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside, below and on the left.", function() {
		testMultipleCoordinates(
			["isOffBottom", "isOffLeft", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [100, 120], [-60, -40],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside and on the left.", function() {
		testMultipleCoordinates(
			["isOffLeft", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [-20, 0, 30, 60, 80], [-60, -40],
			domEl, maskEl, availableKeys
		);
	});

	// Clipped

	it("Should behave like the child is clipped and positioned above and on the left.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedLeft", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], -20, -20,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned above.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], -20, [0, 30, 60],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned above and on the right.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedRight", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], -20, 80,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned on the right.", function() {
		testMultipleCoordinates(
			["isClippedRight", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], [0, 30, 60], 80,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned below and on the right.", function() {
		testMultipleCoordinates(
			["isClippedBottom", "isClippedRight", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], 80, 80,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned below.", function() {
		testMultipleCoordinates(
			["isClippedBottom", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], 80, [0, 30, 60],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned below and on the left.", function() {
		testMultipleCoordinates(
			["isClippedLeft", "isClippedBottom", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], 80, -20,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned on the left.", function() {
		testMultipleCoordinates(
			["isClippedLeft", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], [0, 30, 60], -20,
			domEl, maskEl, availableKeys
		);
	});

	// Child.width < Mask.width && Child.height > Mask.height

	it("Should change the size of the child.", function() {
		changeSize(domEl, 120, 40);
	});

	it("Should behave like the child is outside and above.", function() {
		testMultipleCoordinates(
			["isOffTop", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [-60, -40], -10,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned above.", function() {
		testMultipleCoordinates(
			["isClippedLeft", "isClippedRight", "isClippedTop", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], -10, -10,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is as visible as possible.", function() {
		testMultipleCoordinates(
			["isClippedLeft", "isClippedRight", "isClipped", "isPartiallyVisible", "isAsVisibleAsPossible"], [0, 30, 60], -10,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned below.", function() {
		testMultipleCoordinates(
			["isClippedLeft", "isClippedRight", "isClippedBottom", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], 70, -10,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside and below.", function() {
		testMultipleCoordinates(
			["isOffBottom", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], [100, 120], -10,
			domEl, maskEl, availableKeys
		);
	});

	// Child.width > Mask.width && Child.height < Mask.height

	it("Should change the size of the child.", function() {
		changeSize(domEl, 40, 120);
	});

	it("Should behave like the child is outside and on the left.", function() {
		testMultipleCoordinates(
			["isOffLeft", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], -10, [-60, -40],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned on the left.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedBottom", "isClippedLeft", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], -10, -10,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is as visible as possible.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedBottom", "isClipped", "isPartiallyVisible", "isAsVisibleAsPossible"], -10, [0, 30, 60],
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is clipped and positioned on the right.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedBottom", "isClippedRight", "isClipped", "isPartiallyVisible", "isNotAsVisibleAsPossible"], -10, 70,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child is outside and on the right.", function() {
		testMultipleCoordinates(
			["isOffRight", "isOff", "isInvisible", "isNotAsVisibleAsPossible"], -10, [100, 120],
			domEl, maskEl, availableKeys
		);
	});

	// Child.width > Mask.width && Child.height > Mask.height

	it("Should change the size of the child.", function() {
		changeSize(domEl, 120, 120);
	});

	it("Should behave like the child contains the mask and is centered.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedBottom", "isClippedLeft", "isClippedRight", "isClipped", "isPartiallyVisible", "isAsVisibleAsPossible"], -10, -10,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child contains the mask and is positioned to the top and to the left.", function() {
		testMultipleCoordinates(
			["isClippedBottom", "isClippedRight", "isClipped", "isPartiallyVisible", "isAsVisibleAsPossible"], 0, 0,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child contains the mask and is positioned to the top and to the right.", function() {
		testMultipleCoordinates(
			["isClippedBottom", "isClippedLeft", "isClipped", "isPartiallyVisible", "isAsVisibleAsPossible"], 0, -20,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child contains the mask and is positioned to the bottom and to the left.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedRight", "isClipped", "isPartiallyVisible", "isAsVisibleAsPossible"], -20, 0,
			domEl, maskEl, availableKeys
		);
	});

	it("Should behave like the child contains the mask and is positioned to the bottom and to the right.", function() {
		testMultipleCoordinates(
			["isClippedTop", "isClippedLeft", "isClipped", "isPartiallyVisible", "isAsVisibleAsPossible"], -20, -20,
			domEl, maskEl, availableKeys
		);
	});
});


text:
import beforeFirst from "../dist/beforeFirst.js";

describe("beforeFirst", function() {
	it(`Should find "P" before the first "a" in "Parallelepiped".`, function() {
		expect(
			beforeFirst("Parallelepiped", "a")
		).toBe("P");
	});

	it(`Should find "Parall" before the first "e" in "Parallelepiped".`, function() {
		expect(
			beforeFirst("Parallelepiped", "e")
		).toBe("Parall");
	});

	it(`"Should find "Paral" before the first "le" in "Parallelepiped".`, function() {
		expect(
			beforeFirst("Parallelepiped", "le")
		).toBe("Paral");
	});

	it(`"Should not find anything before the first "P" in "Parallelepiped".`, function() {
		expect(
			beforeFirst("Parallelepiped", "P")
		).toBe("");
	});

	it(`"Should find "😋" before the first "📋" in "😋📋👌".`, function() {
		expect(
			beforeFirst("😋📋👌", "📋")
		).toBe("😋");
	});

	it(`"Should not find anything before the first "x" in "Parallelepiped".`, function() {
		expect(
			beforeFirst("Parallelepiped", "x")
		).toBe(undefined);
	});

	it(`"Should not find anything if the delimiter is ommited.`, function() {
		expect(
			beforeFirst("Parallelepiped")
		).toBe(undefined);
	});

	it(`Should find "" before the first "" in "Parallelepiped".`, function() {
		expect(
			beforeFirst("Parallelepiped", "")
		).toBe("");
	});

	it(`Should throw an error if the first parameter is not a string.`, function() {
		expect(
			() => beforeFirst(undefined, "")
		).toThrow();
	});
});


text:
import _createDomElement from "../dist/internal/dom/_createDomElement.js";
import removeAttr from "../dist/removeAttr.js";

describe("removeAttr", function() {
	it("Should remove an attribute from a DOM element.", function() {
		let videoHTMLElement = document.createElement("video");
		videoHTMLElement.setAttribute("controls", "");
		videoHTMLElement.setAttribute("data-paused", "");

		removeAttr(videoHTMLElement, "controls");
		removeAttr(videoHTMLElement, "data-paused");

		expect(videoHTMLElement.hasAttribute("controls")).toBe(false);
		expect(videoHTMLElement.getAttribute("controls")).toBe(null);

		expect(videoHTMLElement.hasAttribute("data-paused")).toBe(false);
		expect(videoHTMLElement.getAttribute("controls")).toBe(null);
		expect(videoHTMLElement.dataset.paused).toBe(undefined);
	});

	it("Should remove an attribute from a DOM element.", function() {
		let oneElement = _createDomElement('
Level 42
');
		removeAttr(oneElement, "data-level");

		expect(oneElement.getAttribute("data-level")).toBe(null);
		expect(oneElement.dataset.level).toBe(undefined);
	});

	it("Should remove an attribute from a DOM element.", function() {
		let oneElement = _createDomElement('News');
		removeAttr(oneElement, "class");

		expect(oneElement.getAttribute("class")).toBe(null);
		expect(oneElement.className).toBe("");
	});

	it("Should accept a group of DOM nodes.", function() {
		let domElA = document.createElement("div"),
			domElB = document.createElement("div");

		domElA.className = "removeAttr";
		domElA.dataset.level = 42;
		domElB.className = "removeAttr";
		domElB.dataset.level = 42;

		document.body.appendChild(domElA);
		document.body.appendChild(domElB);

		let manyElements = document.querySelectorAll(".removeAttr");

		removeAttr(manyElements, "data-level");

		expect(manyElements[0].getAttribute("data-level")).toBe(null);
		expect(manyElements[1].getAttribute("data-level")).toBe(null);
		expect(manyElements[0].dataset.level).toBe(undefined);
		expect(manyElements[1].dataset.level).toBe(undefined);
	});

	it("Should accept a group of DOM nodes.", function() {
		let listElement = _createDomElement('

A

B

'),
			manyElements = listElement.querySelectorAll("li");

		removeAttr(manyElements, "class");

		expect(manyElements[0].getAttribute("class")).toBe(null);
		expect(manyElements[1].getAttribute("class")).toBe(null);
		expect(manyElements[0].className).toBe("");
		expect(manyElements[1].className).toBe("");
	});
});


text:
import ignore from "../dist/ignore.js";
import listen from "../dist/listen.js";
import trigger from "../dist/trigger.js";

describe("ignore", function() {
	it("Should allow document as parameter.", function() {
		let eventCallback = jasmine.createSpy("eventCallback");
		expect(() => ignore(document, "open", eventCallback)).not.toThrow();
	});

	it("Should allow window as parameter.", function() {
		let eventCallback = jasmine.createSpy("eventCallback");
		expect(() => ignore(window, "open", eventCallback)).not.toThrow();
	});

	it("Should allow many dom elements, including document and window, as parameter.", function() {
		let eventCallback = jasmine.createSpy("eventCallback"),
			singleDiv = document.createElement("div");

		expect(() => ignore([singleDiv, document, window], "open", eventCallback)).not.toThrow();
	});

	it("Should ignore a single event of a single DOM element.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			singleDiv = document.createElement("div");

		document.body.appendChild(singleDiv);

		listen(singleDiv, "open", eventCallback);
		ignore(singleDiv, "open", eventCallback);

		trigger(singleDiv, "open", false);

		setTimeout(() => {
			expect(eventCallback).not.toHaveBeenCalled();
			done();
		}, 20);
	});

	it("Should ignore multiple events of a single DOM element.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			singleDiv = document.createElement("div");

		document.body.appendChild(singleDiv);

		listen(singleDiv, "one two three", eventCallback);
		ignore(singleDiv, "one two three", eventCallback);

		trigger(singleDiv, "one", false);
		trigger(singleDiv, "two", false);
		trigger(singleDiv, "three", false);

		setTimeout(() => {
			expect(eventCallback).not.toHaveBeenCalled();
			done();
		}, 20);
	});

	it("Should ignore multiple events of multiple DOM elements.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			multipleDivs = [document.createElement("div"), document.createElement("div")];

		document.body.appendChild(multipleDivs[0]);
		document.body.appendChild(multipleDivs[1]);

		listen(multipleDivs, "one two three", eventCallback);
		ignore(multipleDivs, "one two three", eventCallback);

		trigger(multipleDivs[0], "one", false);
		trigger(multipleDivs[0], "two", false);
		trigger(multipleDivs[0], "three", false);
		trigger(multipleDivs[1], "one", false);
		trigger(multipleDivs[1], "two", false);
		trigger(multipleDivs[1], "three", false);

		setTimeout(() => {
			expect(eventCallback).not.toHaveBeenCalled();
			done();
		}, 20);
	});

	it("Should be able to ignore some of all the attached events.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			multipleDivs = [document.createElement("div"), document.createElement("div")];

		document.body.appendChild(multipleDivs[0]);
		document.body.appendChild(multipleDivs[1]);

		listen(multipleDivs, "one two three", eventCallback);
		ignore(multipleDivs, "one two", eventCallback);

		trigger(multipleDivs[0], "one", false);
		trigger(multipleDivs[0], "two", false);
		trigger(multipleDivs[0], "three", false);
		trigger(multipleDivs[1], "one", false);
		trigger(multipleDivs[1], "two", false);
		trigger(multipleDivs[1], "three", false);

		setTimeout(() => {
			expect(eventCallback.calls.count()).toBe(2);
			done();
		}, 20);
	});

	it("Should be able to ignore some of all the attached events.", function(done) {
		let eventCallback = jasmine.createSpy("eventCallback"),
			multipleDivs = [document.createElement("div"), document.createElement("div")];

		document.body.appendChild(multipleDivs[0]);
		document.body.appendChild(multipleDivs[1]);

		listen(multipleDivs, "one two three", eventCallback);
		ignore(multipleDivs[0], "one two three", eventCallback);

		trigger(multipleDivs[0], "one", false);
		trigger(multipleDivs[0], "two", false);
		trigger(multipleDivs[0], "three", false);
		trigger(multipleDivs[1], "one", false);
		trigger(multipleDivs[1], "two", false);
		trigger(multipleDivs[1], "three", false);

		setTimeout(() => {
			expect(eventCallback.calls.count()).toBe(3);
			done();
		}, 20);
	});
});


text:
import waitInPromise from "../dist/waitInPromise.js";

describe("waitInPromise", function() {
	it(`Should delay the chaining of the Promise by 100ms and pass along the previously resolved value to the next .then().`, function(done) {
		let timerCallback = jasmine.createSpy("timerCallback");

		Promise.resolve("previousValue")
			.then(waitInPromise(100))
			.then(value => expect(value).toBe("previousValue"))
			.then(timerCallback)
			.then(() => expect(timerCallback).toHaveBeenCalled())
			.then(done);

		expect(timerCallback).not.toHaveBeenCalled();
	});

	it(`Should resolve the Promise without delay if the parameter passed is not a number.`, function(done) {
		let timerCallback = jasmine.createSpy("timerCallback");

		Promise.resolve("previousValue")
			.then(waitInPromise(undefined))
			.then(timerCallback);

		setTimeout(function() {
			expect(timerCallback).toHaveBeenCalled();
			done();
		}, 10);
	});

	it("Should pass along the original Promise argument", function(done) {
		let timerCallback = jasmine.createSpy("timerCallback");

		Promise.resolve("previousValue")
			.then(waitInPromise(undefined))
			.then(value => expect(value).toBe("previousValue"))
			.then(timerCallback);

		setTimeout(function() {
			expect(timerCallback).toHaveBeenCalled();
			done();
		}, 10);
	});
});


text:
import _isBoolean from "../dist/internal/helpers/_isBoolean.js";

describe("_isBoolean", function() {
	it(`"Should return false if passed anything other than a string.`, function() {
		expect(_isBoolean()).toBe(false);
		expect(_isBoolean([])).toBe(false);
		expect(_isBoolean({})).toBe(false);
		expect(_isBoolean(null)).toBe(false);
		expect(_isBoolean(undefined)).toBe(false);
		expect(_isBoolean(NaN)).toBe(false);
		expect(_isBoolean(new Set())).toBe(false);
		expect(_isBoolean(new WeakSet())).toBe(false);
		expect(_isBoolean(new Map())).toBe(false);
		expect(_isBoolean(new WeakMap())).toBe(false);
		expect(_isBoolean(document.createElement("div"))).toBe(false);
		expect(_isBoolean(15)).toBe(false);
		expect(_isBoolean(15.45)).toBe(false);
		expect(_isBoolean(Math.PI)).toBe(false);
		expect(_isBoolean("")).toBe(false);
		expect(_isBoolean("345")).toBe(false);
		expect(_isBoolean(new String("window"))).toBe(false);
		expect(_isBoolean(new String("😋📋👌"))).toBe(false);
		expect(_isBoolean(0)).toBe(false);
		expect(_isBoolean(1)).toBe(false);
		expect(_isBoolean(true)).toBe(true);
		expect(_isBoolean(false)).toBe(true);
	});
});


text:
import _isValidBemObject from "../dist/internal/bem/_isValidBemObject.js";

describe("_isValidBemObject", function() {
	it(`"Should return false if passed anything other than a BEM modifier object.`, function() {
		expect(_isValidBemObject(0)).toBe(false);
		expect(_isValidBemObject("")).toBe(false);
		expect(_isValidBemObject("__ -- -")).toBe(false);
		expect(_isValidBemObject([])).toBe(false);
		expect(_isValidBemObject()).toBe(false);

		expect(_isValidBemObject({
			"menu": null
		})).toBe(false);

		expect(_isValidBemObject({
			"menu": undefined
		})).toBe(false);

		expect(_isValidBemObject({
			"menu": 42
		})).toBe(false);

		expect(_isValidBemObject({
			"menu": false
		})).toBe(false);

		expect(_isValidBemObject({
			"menu": true
		})).toBe(false);

		expect(_isValidBemObject({
			"menu": []
		})).toBe(false);
	});

	it(`"Should return true if passed a valid BEM modifier object: with boolean, string or number as properties`, function() {
		expect(_isValidBemObject({})).toBe(true);

		expect(_isValidBemObject({
			"menu": {}
		})).toBe(true);

		expect(_isValidBemObject({
			"menu": {
				"active": true
			}
		})).toBe(true);

		expect(_isValidBemObject({
			"menu": {
				"active": true,
				"level": "42",
				"test": 24
			},
			"button": {
				"active": true
			}
		})).toBe(true);
	});
});


text:
import deepGroupBy from "../dist/deepGroupBy.js";

describe("deepGroupBy", function() {
	const stores = [{
		name: "Iguatemi",
		city: "Campinas",
		state: "SP"
	}, {
		name: "Jardins",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "Iguatemi",
		city: "São Paulo",
		state: "SP"
	}, {
		name: "Pedras",
		city: "Búzios",
		state: "RJ"
	}, {
		name: "Ipanema",
		city: "Rio de Janeiro",
		state: "RJ"
	}, {
		name: "Leblon",
		city: "Rio de Janeiro",
		state: "RJ"
	}, {
		name: "ParkShopping",
		city: "Brasília",
		state: "DF"
	}];

	const getNamesFirstCharacter = item => item.name.slice(0, 1);
	const getCityName = item => item.city;
	const getStateName = item => item.state;

	it("Should group stores by the first letter of their names.", function() {
		expect(deepGroupBy(stores, getNamesFirstCharacter)).toEqual({
			"I": [{
				name: "Iguatemi",
				city: "Campinas",
				state: "SP"
			}, {
				name: "Iguatemi",
				city: "São Paulo",
				state: "SP"
			}, {
				name: "Ipanema",
				city: "Rio de Janeiro",
				state: "RJ"
			}],
			"J": [{
				name: "Jardins",
				city: "São Paulo",
				state: "SP"
			}],
			"P": [{
				name: "Pedras",
				city: "Búzios",
				state: "RJ"
			}, {
				name: "ParkShopping",
				city: "Brasília",
				state: "DF"
			}],
			"L": [{
				name: "Leblon",
				city: "Rio de Janeiro",
				state: "RJ"
			}]
		});
	});

	it("Should group stores by state and city.", function() {
		expect(deepGroupBy(stores, getStateName, getCityName)).toEqual({
			"SP": {
				"Campinas": [{
					name: "Iguatemi",
					city: "Campinas",
					state: "SP"
				}],
				"São Paulo": [{
					name: "Jardins",
					city: "São Paulo",
					state: "SP"
				}, {
					name: "Iguatemi",
					city: "São Paulo",
					state: "SP"
				}]
			},
			"RJ": {
				"Búzios": [{
					name: "Pedras",
					city: "Búzios",
					state: "RJ"
				}],
				"Rio de Janeiro": [{
					name: "Ipanema",
					city: "Rio de Janeiro",
					state: "RJ"
				}, {
					name: "Leblon",
					city: "Rio de Janeiro",
					state: "RJ"
				}]
			},
			"DF": {
				"Brasília": [{
					name: "ParkShopping",
					city: "Brasília",
					state: "DF"
				}]
			}
		});
	});

	it("Should group stores by the first letter of their names and the name of the city.", function() {
		expect(deepGroupBy(stores, getNamesFirstCharacter, getCityName)).toEqual({
			"I": {
				"Campinas": [{
					name: "Iguatemi",
					city: "Campinas",
					state: "SP"
				}],
				"São Paulo": [{
					name: "Iguatemi",
					city: "São Paulo",
					state: "SP"
				}],
				"Rio de Janeiro": [{
					name: "Ipanema",
					city: "Rio de Janeiro",
					state: "RJ"
				}]
			},
			"J": {
				"São Paulo": [{
					name: "Jardins",
					city: "São Paulo",
					state: "SP"
				}]
			},
			"P": {
				"Búzios": [{
					name: "Pedras",
					city: "Búzios",
					state: "RJ"
				}],
				"Brasília": [{
					name: "ParkShopping",
					city: "Brasília",
					state: "DF"
				}]
			},
			"L": {
				"Rio de Janeiro": [{
					name: "Leblon",
					city: "Rio de Janeiro",
					state: "RJ"
				}]
			}
		});
	});
});


text:
import toAverageProp from "../dist/toAverageProp.js";

describe("toAverageProp", function() {
	var mockup = [{
		city: "Rio de Janeiro",
		temperature: 96,
		demographics: {
			population: 6.32
		}
	}, {
		city: "São Paulo",
		temperature: 82.5,
		demographics: {
			population: 12.04
		}
	}, {
		city: "Curitiba",
		temperature: 70,
		demographics: {
			population: 1.752
		}
	}, {
		city: "Florianópolis",
		temperature: 86,
		demographics: {
			population: 0.249
		}
	}];

	it(`Should conclude that São Paulo has the average temperature amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toAverageProp("temperature"))
		).toBe(mockup[1]); // São Paulo
	});

	it(`Should conclude that Rio de Janeiro has the average population amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toAverageProp("demographics.population"))
		).toBe(mockup[0]); // Rio de Janeiro
	});

	var test = [{
		n: "a",
		p: 2
	}, {
		n: "b",
		p: 4
	}, {
		n: "c",
		p: 6
	}, {
		n: "d",
		p: 2
	}, {
		n: "e",
		p: 4
	}];

	it(`Should return the first result when two or more are found.`, function() {
		expect(
			test.reduce(toAverageProp("p"))
		).toBe(test[1]);
	});
});


text:
import toSmallestProp from "../dist/toSmallestProp.js";

describe("toSmallestProp", function() {
	var mockup = [{
		city: "Rio de Janeiro",
		temperature: 96,
		demographics: {
			population: 6.32
		}
	}, {
		city: "São Paulo",
		temperature: 82.5,
		demographics: {
			population: 12.04
		}
	}, {
		city: "Curitiba",
		temperature: 70,
		demographics: {
			population: 1.752
		}
	}, {
		city: "Florianópolis",
		temperature: 86,
		demographics: {
			population: 0.249
		}
	}];

	it(`Should conclude that Curitiba has the smallest temperature amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toSmallestProp("temperature"))
		).toBe(mockup[2]); // Curitiba
	});

	it(`Should conclude that Florianópolis has the smallest temperature amongst the cities in the array.`, function() {
		expect(
			mockup.reduce(toSmallestProp("demographics.population"))
		).toBe(mockup[3]); // Florianópolis
	});

	var test = [{
		n: "a",
		p: 2
	}, {
		n: "b",
		p: 8
	}, {
		n: "c",
		p: 6
	}, {
		n: "d",
		p: 2
	}, {
		n: "e",
		p: 8
	}];

	it(`Should return the first result when two or more are found.`, function() {
		expect(
			test.reduce(toSmallestProp("p"))
		).toBe(test[0]);
	});
});


text:
import _random from "./internal/helpers/_random.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * Returns `true` approximately one out of `num` times,
 * randomly.
 *
 * @category Random
 *
 * @param  {number} num A number greater than zero.
 * @return {boolean} Returns `true` approximately one out of `num` times.
 *
 * @example
 * oneOutOf(2);
 * // => true
 *
 * oneOutOf(2);
 * // => false
 */
const oneOutOf = num => {
	_throwErrorIf((!Number.isFinite(num) || num < 1), "A number greater than 1 is expected as parameter.");
	return (num === 1) ? true : _random(1, num) === num;
};

export default oneOutOf;