JavaScript UI component library, includes the latest Fancybox
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

354 lines
9.3 KiB

import { extend } from "../src/shared/utils/extend.js";
import { resolve } from "../src/shared/utils/resolve.js";
import { round } from "../src/shared/utils/round.js";
import { throttle } from "../src/shared/utils/throttle.js";
import { isPlainObject } from "../src/shared/utils/isPlainObject.js";
import { getFullWidth, getFullHeight } from "../src/shared/utils/getDimensions.js";
import { isScrollable } from "../src/shared/utils/isScrollable.js";
import { getTextNodeFromPoint } from "../src/shared/utils/getTextNodeFromPoint.js";
import { ResizeObserver } from "../src/shared/utils/ResizeObserver.js";
const expect = chai.expect;
function delay(time = 500) {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
}
describe("Utils", function () {
describe("extend", function () {
it("extends object with other object", function () {
let obj = { a: 3, b: 5 };
extend(obj, { a: 4, c: 8 });
expect(obj).to.deep.equal({ a: 4, b: 5, c: 8 });
});
it("does not pollute original object", function () {
let obj = { a: 3, b: 5 };
extend({}, obj, { a: 4, c: 8 });
expect(obj).to.deep.equal({ a: 3, b: 5 });
});
it("copies property values", function () {
let arr = [1, 2, 3];
let obj = { a: 3, b: 5 };
extend(obj, { c: arr });
arr.push(4);
expect(obj).to.deep.equal({ a: 3, b: 5, c: [1, 2, 3, 4] });
});
it("supports deep cloning, copies the reference values", function () {
let arr = [1, 2, 3];
let obj = { a: 3, b: 5 };
extend(true, obj, { c: arr });
arr.push(4);
expect(obj).to.deep.equal({ a: 3, b: 5, c: [1, 2, 3] });
});
});
describe("getDimensions", function () {
const template = `
<div id="root">
<div id="container" style="width: 100px;height:100px;overflow:auto;">
<div id="target" style="width:200px;height:200px;"></div>
</div>
</div>`;
let elements;
beforeEach(() => {
document.body.insertAdjacentHTML("beforeend", template);
elements = {
root: document.getElementById("root"),
container: document.getElementById("container"),
target: document.getElementById("target"),
};
});
afterEach(() => {
if (document.body.contains(elements.root)) {
document.body.removeChild(elements.root);
}
elements = {};
});
it("returns full width of element", function () {
expect(getFullWidth(elements.container)).to.equal(200);
});
it("returns full height of element", function () {
expect(getFullHeight(elements.container)).to.equal(200);
});
});
describe("isScrollable", function () {
const template = `
<div id="root">
<div id="container" style="width: 100px;height:100px;overflow:auto;">
<div id="target" style="width:200px;height:200px;"></div>
</div>
</div>`;
let elements;
beforeEach(() => {
document.body.insertAdjacentHTML("beforeend", template);
elements = {
root: document.getElementById("root"),
container: document.getElementById("container"),
target: document.getElementById("target"),
};
});
afterEach(() => {
if (document.body.contains(elements.root)) {
document.body.removeChild(elements.root);
}
elements = {};
});
it("returns scrollable element", function () {
expect(isScrollable(elements.container)).to.equal(elements.container);
});
it("detects scrollable parent", function () {
expect(isScrollable(elements.target)).to.equal(elements.container);
});
it("returns false when element is not scrollable and no scrollable parent found", function () {
expect(isScrollable(elements.root)).to.be.false;
});
});
describe("getTextNodeFromPoint", function () {
const template = `
<div id="root">
<div id="container" style="position:fixed; top: 0; left: 0;padding: 50px;">
<p id="target" style="margin: 0;padding: 0;">WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW<br />WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW</p>
</div>
</div>`;
let elements;
beforeEach(() => {
document.body.insertAdjacentHTML("beforeend", template);
elements = {
root: document.getElementById("root"),
container: document.getElementById("container"),
target: document.getElementById("target"),
};
});
afterEach(() => {
if (document.body.contains(elements.root)) {
document.body.removeChild(elements.root);
}
elements = {};
});
it("detects text node", function () {
expect(getTextNodeFromPoint(elements.target, 100, 55)).to.not.be.false;
expect(getTextNodeFromPoint(elements.target, 100, 15)).to.be.false;
});
});
describe("isPlainObject", function () {
it("detects plain objects", function () {
expect(isPlainObject({})).to.be.true;
expect(isPlainObject({ a: 1 })).to.be.true;
});
it("returns `false` for non-Object objects", function () {
function Foo() {
this.a = 1;
}
const element = document.createElement("div");
const arr = ["a", "b"];
expect(isPlainObject(new Foo())).to.be.false;
expect(isPlainObject(element)).to.be.false;
expect(isPlainObject(arr)).to.be.false;
expect(isPlainObject(Error)).to.be.false;
expect(isPlainObject(Math)).to.be.false;
expect(isPlainObject("a")).to.be.false;
});
});
describe("ResizeObserver", function () {
const template = `
<div id="root" style="position:fixed;top:0;left:0;width:600px;height:600px;overflow:visible;background:rgba(0,0,0,0.4);">
<div id="container" style="display:flex;max-width:600px">
<div id="target1" style="width: 200px;height: 100px;"></div>
<div id="target2" style="width: 200px;height: 100px;"></div>
</div>
</div>`;
let elements;
let observer;
beforeEach(() => {
document.body.insertAdjacentHTML("beforeend", template);
elements = {
root: document.getElementById("root"),
container: document.getElementById("container"),
target1: document.getElementById("target1"),
target2: document.getElementById("target2"),
};
});
afterEach(() => {
if (observer) {
observer.disconnect();
observer = null;
}
if (document.body.contains(elements.root)) {
document.body.removeChild(elements.root);
}
elements = {};
});
it("can be instantiated", function () {
observer = new ResizeObserver(() => {});
expect(observer).to.be.an.instanceof(ResizeObserver);
});
it("triggers after resizing element", async function () {
let width = 0;
let height = 0;
observer = new ResizeObserver(function (entries) {
// Polyfill does not provide `contentRect`
const entry = entries[0];
width = entry.contentRect ? entry.contentRect.width : entry.getBoundingClientRect().width;
height = entry.contentRect ? entry.contentRect.height : entry.getBoundingClientRect().height;
});
observer.observe(elements.target1);
await delay(50);
elements.target1.setAttribute("style", "width:100px;height:250px");
await delay(50);
expect(width).to.equal(100);
expect(height).to.equal(250);
elements.target1.setAttribute("style", "width:222px;height:333px");
await delay(50);
expect(width).to.equal(222);
expect(height).to.equal(333);
});
});
describe("resolve", function () {
it("should access nested JavaScript objects by string path", function () {
const obj = {
a: {
b: {
c: "d",
},
},
};
expect(resolve("a.b.c", obj)).to.be.equal("d");
});
it("should access nested arays by string path", function () {
const obj = [
["a", "b"],
["c", "d"],
];
expect(resolve("1.1", obj)).to.be.equal("d");
});
});
describe("round", function () {
it("rounds with default precision 10000", async function () {
expect(round(12.3456789)).to.be.equal(12.3457);
});
it("rounds with custom precision", async function () {
expect(round(12.3456789, 10)).to.be.equal(12.3);
});
it("converts to number", async function () {
expect(round("12.3456789", 100)).to.be.equal(12.35);
});
it("always returns number", async function () {
expect(round(null)).to.be.equal(0);
});
});
describe("throttle", function () {
it("limits function calls", async function () {
let callCount = 0,
throttled = throttle(function () {
callCount++;
}, 32);
throttled();
throttled();
throttled();
expect(callCount).to.be.equal(1);
await delay(128);
expect(callCount).to.be.equal(1);
});
it("triggers a second throttled call as soon as possible", async function () {
let callCount = 0,
throttled = throttle(function () {
callCount++;
}, 32);
throttled();
throttled();
expect(callCount).to.be.equal(1);
await delay(64);
throttled();
throttled();
expect(callCount).to.be.equal(2);
await delay(64);
throttled();
throttled();
expect(callCount).to.be.equal(3);
});
});
});