import { cleanup, sandbox, waitEvent, waitFor } from "./utils/utils";
import InfiniteGrid from "../../src/InfiniteGrid";
import { SampleGrid, SampleGridOptions } from "./samples/SampleGrid";
import { flat, toArray } from "../../src/utils";
import {
InfiniteGridOptions,
OnRenderComplete,
OnRequestAppend,
OnRequestPrepend,
OnContentError,
OnChangeScroll,
STATUS_TYPE,
ITEM_TYPE,
} from "../../src";
import * as sinon from "sinon";
import { MOUNT_STATE } from "@egjs/grid";
describe("test InfiniteGrid", () => {
let ig: InfiniteGrid | null;
let container: HTMLElement | null;
beforeEach(() => {
container = sandbox({ class: "sample" })!;
container!.style.cssText = "";
});
afterEach(() => {
if (ig) {
ig!.destroy();
}
ig = null;
container = null;
cleanup();
});
describe("Initialzation", () => {
it("should check if container elements are the same", () => {
// Given
container!.innerHTML = `
`;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
});
// When, Then
expect(ig!.getWrapperElement()).to.be.equals(wrapper);
expect(ig!.getScrollContainerElement()).to.be.equals(wrapper);
expect(ig!.getItems().length).to.be.equals(0);
});
it("should check if scrollContainer changes the scroll area instead of window", async () => {
// Given
container!.innerHTML = `
`;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
scrollContainer: ".scroller",
});
// When, Then
expect(ig!.getWrapperElement()).to.be.equals(wrapper);
expect(ig!.getContainerElement()).to.be.equals(wrapper);
expect(ig!.getScrollContainerElement()).to.be.equals(wrapper.parentElement);
});
});
describe("test rendering", () => {
beforeEach(() => {
// Given
container!.innerHTML = `
`;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
});
});
it("should check to render children when items are not present", async () => {
// Given
const igContainer = ig!.getContainerElement();
igContainer.innerHTML = `11
22
33
44
55
66
`;
const children = toArray(igContainer.children);
// When
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
const firstItem = ig!.getItems()[0];
// Then
ig!.getItems().forEach((item) => {
expect(item.groupKey).to.be.equals(firstItem.groupKey);
});
ig!.getGroups().forEach((group) => {
expect(group.groupKey).to.be.equals(firstItem.groupKey);
});
ig!.getVisibleGroups().forEach((group) => {
expect(group.groupKey).to.be.equals(firstItem.groupKey);
});
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 18}px`);
});
});
it("should check to render children when removing items immediately after rendering children", async () => {
// Given
const igContainer = ig!.getContainerElement();
igContainer.innerHTML = `11
22
33
44
55
66
`;
// When
ig!.renderItems();
ig!.removeByIndex(0);
await waitEvent(ig!, "renderComplete");
// Then
// 2 3 4 5 6
toArray(igContainer.children).forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 18}px`);
expect(child.innerHTML).to.be.equals(`${i + 2}${i + 2}`);
});
});
it("should check if items are rendered", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}${child}
`,
};
}));
// When
ig!.setCursors(0, 1);
const e = await waitEvent(ig!, "renderComplete");
const children = toArray(igContainer.children);
// Then
expect(e.startCursor).to.be.equals(0);
expect(e.endCursor).to.be.equals(1);
expect(ig!.getItems().map((item) => item.groupKey)).to.be.deep.equals([0, 0, 0, 1, 1, 1]);
expect(ig!.getGroups().map((group) => group.groupKey)).to.be.deep.equals([0, 1]);
expect(ig!.getVisibleGroups().map((group) => group.groupKey)).to.be.deep.equals([0, 1]);
expect(children.length).to.be.equals(6);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 18}px`);
});
});
it("should check if items are added in order even if items are added in own group", async () => {
// Given
ig!.syncItems([0, 2, 4, 6, 8, 10].map((child) => {
return {
key: child,
html: `${child}
`,
};
}));
ig!.setCursors(0, 0);
await waitEvent(ig!, "renderComplete");
// When
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((child) => {
return {
key: child,
html: `${child}
`,
};
}));
await waitEvent(ig!, "renderComplete");
// Then
expect(ig!.getItems()).to.be.lengthOf(11);
expect(ig!.getVisibleItems()).to.be.lengthOf(11);
const firstGroupKey = ig!.getItems()[0].groupKey;
ig!.getItems().forEach((item, i) => {
// All items have the same group, and the key is the same as the index.
expect(item.groupKey).to.be.equals(firstGroupKey);
expect(item.key).to.be.equals(i);
});
});
it("should check if only visible items are rendered", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
// When
await waitEvent(ig!, "renderComplete");
// one more [0, 1] => [0]
const e = await waitEvent(ig!, "renderComplete");
const children = toArray(igContainer.children);
// Then
expect(e.startCursor).to.be.equals(0);
expect(e.endCursor).to.be.equals(0);
expect(e.items).to.be.deep.equals(ig!.getVisibleItems());
expect(e.groups).to.be.deep.equals(ig!.getVisibleGroups());
expect(ig!.getVisibleGroups().map((group) => group.groupKey)).to.be.deep.equals([0]);
expect(children.length).to.be.equals(3);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 250}px`);
});
});
it("should check whether it is rendered even if gropukey is changed", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
await waitEvent(ig!, "renderComplete");
// When
// 0, 1, 2, 3, 4, 5 => 3, 4, 5
ig!.syncItems([3, 4, 5].map((child) => {
return {
groupKey: 0,
key: child,
html: `${child}
`,
};
}));
const e = await waitEvent(ig!, "renderComplete");
// Then
expect(e.startCursor).to.be.equals(0);
expect(e.endCursor).to.be.equals(0);
expect(e.groups.length).to.be.deep.equals(1);
expect(e.groups[0].groupKey).to.be.deep.equals(0);
});
it("should check whether it is rendered after changing options", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
await waitEvent(ig!, "renderComplete");
// When
// 0 => 5
ig!.gap = 5;
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(igContainer.children);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 23}px`);
});
});
it("should check that the mounte state is mounted only in the visible area after rendering.", async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
// render [0, 2]
ig!.setCursors(0, 2);
await waitEvent(ig!, "renderComplete");
// render only [0, 0]
await waitEvent(ig!, "renderComplete");
// When
// Render elements
setTimeout(() => {
// Check ready
setTimeout(() => {
ig!.setCursors(0, 2);
});
});
ig!.setCursors(0, 1);
const e = await waitEvent(ig!, "renderComplete");
// 1 ~ 1
const mounteStates = e.mounted.map((item) => item.mountState);
// 0 ~ 2
const allMountStates = e.items.map((item) => item.mountState);
await waitEvent(ig!, "renderComplete");
// Then
expect(mounteStates).to.be.lengthOf(3);
// 0 ~ 5 MOUNTED
for (let i = 0; i < 6; ++i) {
expect(allMountStates[i]).to.be.equal(MOUNT_STATE.MOUNTED);
}
// 6 ~ 8 UNMOUNTED
for (let i = 6; i < 9; ++i) {
expect(allMountStates[i]).to.be.equal(MOUNT_STATE.UNMOUNTED);
}
});
describe("test append, prepend, insert, insertByGroupIndex", () => {
it("should check if render is complete after append", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.append([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(igContainer.children);
expect(ig!.getItems().map((item) => item.groupKey)).to.be.deep.equals([0, 0, 0, 1, 1, 1]);
expect(ig!.getGroups().map((group) => group.groupKey)).to.be.deep.equals([0, 1]);
expect(ig!.getVisibleGroups().map((group) => group.groupKey)).to.be.deep.equals([0]);
expect(children.length).to.be.equals(3);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 250}px`);
});
});
it("should check if startOutline is set to 0 when prepend", async () => {
// Given
ig!.destroy();
container!.innerHTML = ``;
ig = new InfiniteGrid(container!.querySelector(".wrapper")!, {
gridConstructor: SampleGrid,
container: true,
defaultDirection: "start",
});
ig!.prepend([0, 1, 2, 3, 4].map((child) => {
return {
groupKey: Math.floor(child / 5),
key: child,
html: `${child}
`,
};
}));
await waitEvent(ig!, "renderComplete");
// Then
expect(ig!.getGroups()[0].grid.getOutlines()).to.be.deep.equals({
start: [0],
end: [1000],
});
});
it("should check if the scroll position changes when prepend", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.append([0, 1, 2, 3, 4].map((child) => {
return {
groupKey: Math.floor(child / 5),
key: `${child}`,
html: `${child}
`,
};
}));
await waitEvent(ig!, "renderComplete");
ig!.prepend([5, 6, 7, 8, 9].map((child) => {
return {
groupKey: Math.floor(child / 5),
key: child,
html: `${child}
`,
};
}));
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(igContainer.children);
expect(ig!.getItems().map((item) => item.groupKey)).to.be.deep.equals([1, 1, 1, 1, 1, 0, 0, 0, 0, 0]);
expect(ig!.getGroups().map((group) => group.groupKey)).to.be.deep.equals([1, 0]);
expect(ig!.getVisibleGroups().map((group) => group.groupKey)).to.be.deep.equals([1, 0]);
expect(ig!.getScrollContainerElement().scrollTop).to.be.equals(1000);
expect(children.length).to.be.equals(10);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 200}px`, `Index ${i} Error`);
});
});
it("should check if item can be inserted in the center", async () => {
// Given
ig!.syncItems([0, 1, 2, 6, 7, 8].map((child) => {
return {
groupKey: Math.floor(child / 5),
key: child,
html: `${child}
`,
};
}));
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// When
// 0 1 2 [3 4 5] 6 7 8
ig!.insert(3, [3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 5),
key: child,
html: `${child}
`,
};
}));
// Then
const elements: HTMLElement[] = [].slice.call(ig!.getContainerElement().children);
expect(elements.map((el) => el.innerHTML)).to.be.deep.equals(["0", "1", "2", "3", "4", "5", "6", "7", "8"]);
});
it("should check if the group is inserted to the center", async () => {
// Given
ig!.syncItems([0, 1, 2, 6, 7, 8].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// When
// 0 1 2 [3 4 5] 6 7 8
ig!.insertByGroupIndex(1, [3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
// Then
const elements: HTMLElement[] = [].slice.call(ig!.getContainerElement().children);
expect(elements.map((el) => el.innerHTML)).to.be.deep.equals(["0", "1", "2", "3", "4", "5", "6", "7", "8"]);
});
it("should check if the offset is entered correctly when prepend", async () => {
// Given
// sufficient height so that scroll size does not occur
const igScrollContainer = ig!.getScrollContainerElement();
igScrollContainer.style.height = "1000px";
ig!.isReachEnd = true;
ig!.syncItems([3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
ig!.renderItems({
useResize: true,
});
await waitEvent(ig!, "renderComplete");
const spy = sinon.spy();
// When
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: child,
html: `${child}
`,
};
}));
ig!.renderItems();
// the requestPrepend event is fired because scrollPos is 0.
ig!.once("requestPrepend", spy);
await waitEvent(ig!, "renderComplete");
// Then
expect(ig!.getStartCursor()).to.be.equals(0);
expect(ig!.getEndCursor()).to.be.equals(1);
expect(spy.called).to.be.true;
});
});
describe("test contentError event", () => {
it("should check if contentError event occurs with error image", async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: 0,
key: `key${child}`,
html: `${child === 2 ? `

` : ""}
`,
};
}));
ig!.renderItems();
// When
const e = await waitEvent(ig!, "contentError");
// Then
expect(e.item.key).to.be.equals("key2");
});
it("should check if it is recalculated if removed", async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: 0,
key: `key${child}`,
html: `${child === 2 ? `

` : ""}
`,
};
}));
ig!.on("contentError", (e) => {
e.remove();
});
// When
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(ig!.getContainerElement().children);
expect(ig!.getItems().length).to.be.equals(5);
expect(children.length).to.be.equals(5);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 150}px`);
});
});
});
describe("test scroll event", () => {
it("should check if scroll event occurs when scrolling", async () => {
// Given
const igScrollContainer = ig!.getScrollContainerElement();
const igContainer = ig!.getContainerElement();
igContainer.style.marginTop = "10px";
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// When
// start to end
igScrollContainer.scrollTop = 200;
const e1 = await waitEvent(ig!, "changeScroll");
igScrollContainer.scrollTop = 0;
// end to start
const e2 = await waitEvent(ig!, "changeScroll");
// Then
expect(e1.direction).to.be.equals("end");
expect(e1.scrollPos).to.be.equals(200);
expect(e1.relativeScrollPos).to.be.equals(190);
expect(e2.direction).to.be.equals("start");
expect(e2.scrollPos).to.be.equals(0);
expect(e2.relativeScrollPos).to.be.equals(-10);
});
it("should check if the requestAppend event occurs when scrolling to the end", async () => {
// Given
const igScrollContainer = ig!.getScrollContainerElement();
const igContainer = ig!.getContainerElement();
igContainer.style.marginTop = "10px";
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// When
// scroll to end
igScrollContainer.scrollTop = 800;
const e1 = await waitEvent(ig!, "requestAppend");
// Then
expect(e1.groupKey).to.be.equals(1);
});
it("should check if the requestPrepend event occurs when scrolling to the start", async () => {
// Given
const igScrollContainer = ig!.getScrollContainerElement();
const igContainer = ig!.getContainerElement();
igContainer.style.marginTop = "10px";
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// scroll to end
igScrollContainer.scrollTop = 800;
await waitEvent(ig!, "requestAppend");
// When
// end to start
igScrollContainer.scrollTop = 0;
const e = await waitEvent(ig!, "requestPrepend");
// Then
expect(e.groupKey).to.be.equals(0);
});
});
describe("test wait, ready for data", () => {
it("should check if the requestAppend event is not called if it is in the wait state", async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 2);
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
const requestAppendSpy1 = sinon.spy();
const requestAppendSpy2 = sinon.spy();
ig!.wait("end");
ig!.on("requestAppend", requestAppendSpy1);
// not call append
ig!.getScrollContainerElement().scrollTop = 300;
await waitFor(100);
ig!.off("requestAppend", requestAppendSpy1);
ig!.ready();
ig!.on("requestAppend", requestAppendSpy2);
// call append
ig!.getScrollContainerElement().scrollTop = 301;
await waitFor(100);
// Then
expect(requestAppendSpy1.callCount).to.be.equals(0);
expect(requestAppendSpy2.callCount).to.be.equals(1);
});
it("should check if the loading bar appears in the wait state", async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 2);
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
ig!.setLoading({
html: ``,
});
ig!.wait("end");
await waitEvent(ig!, "renderComplete");
// Then
const children = ig!.getContainerElement().children;
const lastElement = children[children.length - 1];
expect(lastElement.className).to.be.equals("loading");
});
});
describe("test remove methods", () => {
it("should checks whether the item is removed when the removeByKey method is called", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
await waitEvent(ig!, "renderComplete");
// When
// 0 1 3 4 5
ig!.removeByKey("key2");
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(igContainer.children);
expect(ig!.getItems().map((item) => item.key)).to.be.deep.equals([0, 1, 3, 4, 5].map((key) => `key${key}`));
expect(igContainer.children.length).to.be.equals(5);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 100}px`);
});
});
it("should checks whether the item is removed when the removeByIndex method is called", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
await waitEvent(ig!, "renderComplete");
// When
// 0 1 3 4 5
ig!.removeByIndex(2);
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(igContainer.children);
expect(ig!.getItems().map((item) => item.key)).to.be.deep.equals([0, 1, 3, 4, 5].map((key) => `key${key}`));
expect(igContainer.children.length).to.be.equals(5);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 100}px`);
});
});
it("should checks whether the item is removed when the removeGroupByKey method is called", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
await waitEvent(ig!, "renderComplete");
// When
// 3 4 5
ig!.removeGroupByKey(0);
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(igContainer.children);
expect(ig!.getItems().map((item) => item.key)).to.be.deep.equals([3, 4, 5].map((key) => `key${key}`));
expect(igContainer.children.length).to.be.equals(3);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 100}px`);
});
});
it("should check if invisible group can be removed when the removeGroupByIndex method is called", async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
// render all items (0, 3)
ig!.setCursors(0, 3);
await waitEvent(ig!, "renderComplete");
// (0, 2)
await waitEvent(ig!, "renderComplete");
// When
// [1, 2, 3, 4] => [1, 2, 3]
ig!.removeGroupByIndex(0);
await waitEvent(ig!, "renderComplete");
// Then
expect(ig!.getGroups().map((group) => group.groupKey)).to.be.deep.equals([1, 2, 3]);
});
it("should checks whether the item is removed when the removeGroupByIndex method is called", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 1);
await waitEvent(ig!, "renderComplete");
// When
// 3 4 5
ig!.removeGroupByIndex(0);
await waitEvent(ig!, "renderComplete");
// Then
const children = toArray(igContainer.children);
expect(ig!.getItems().map((item) => item.key)).to.be.deep.equals([3, 4, 5].map((key) => `key${key}`));
expect(igContainer.children.length).to.be.equals(3);
children.forEach((child, i) => {
expect(child.style.top).to.be.equals(`${i * 100}px`);
});
});
});
describe("test getStatus, setStatus", () => {
it("should check if status has data attribute", async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
await waitEvent(ig!, "renderComplete");
// When
const status = ig!.getStatus();
// Then
expect(status.groupManager.groups[0].items[0].data).to.be.undefined;
});
it("should check if recovery is possible When you get the full status and setStatus", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
const children = [].slice.call(igContainer.children);
const html = igContainer.outerHTML;
ig!.setStatus(ig!.getStatus());
await waitEvent(ig!, "renderComplete");
// Then
const children2 = [].slice.call(igContainer.children);
const html2 = igContainer.outerHTML;
expect(html2).to.be.equals(html);
expect(ig!.getItems().length).to.be.equals(15);
expect(ig!.getVisibleItems().length).to.be.equals(9);
expect(ig!.getGroups().length).to.be.equals(5);
expect(ig!.getVisibleGroups().length).to.be.equals(3);
children2.forEach((el, i) => {
expect(el).to.be.not.equal(children[i]);
});
});
it("should check if recovery is possible When you get the partial status and setStatus", async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
const children = [].slice.call(igContainer.children);
const html = igContainer.outerHTML;
ig!.setStatus(ig!.getStatus(STATUS_TYPE.REMOVE_INVISIBLE_GROUPS));
await waitEvent(ig!, "renderComplete");
const children2 = [].slice.call(igContainer.children);
const html2 = igContainer.outerHTML;
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// update outlines
const children3 = [].slice.call(igContainer.children);
const html3 = igContainer.outerHTML;
// Then
expect(ig!.getItems().length).to.be.equals(9);
expect(ig!.getVisibleItems().length).to.be.equals(9);
expect(ig!.getGroups().length).to.be.equals(3);
expect(ig!.getVisibleGroups().length).to.be.equals(3);
expect(html2).to.be.equals(html);
children2.forEach((el, i) => {
expect(el).to.be.not.equal(children[i]);
});
expect(html3).to.be.not.equals(html);
children3.forEach((el, i) => {
expect(el).to.be.not.equal(children[i]);
});
});
it(`should check if recovery is possible When you get the partial status with minimized invisible items and setStatus`, async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
const children = [].slice.call(igContainer.children);
const html = igContainer.outerHTML;
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS));
await waitEvent(ig!, "renderComplete");
const children2 = [].slice.call(igContainer.children);
const html2 = igContainer.outerHTML;
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// update outlines
const children3 = [].slice.call(igContainer.children);
const html3 = igContainer.outerHTML;
// Then
// items (9) virtual items (6)
expect(ig!.getItems(true).length).to.be.equals(15);
expect(ig!.getItems().length).to.be.equals(9);
expect(ig!.getVisibleItems().length).to.be.equals(9);
// groups (3) virtual groups (2)
expect(ig!.getGroups(true).length).to.be.equals(5);
expect(ig!.getGroups().length).to.be.equals(3);
expect(ig!.getVisibleGroups().length).to.be.equals(3);
expect(html2).to.be.equals(html);
children2.forEach((el, i) => {
expect(el).to.be.not.equal(children[i]);
});
expect(html3).to.be.equals(html);
children3.forEach((el, i) => {
expect(el).to.be.not.equal(children[i]);
});
});
it(`should check if recovery is possible When you get the partial status with minimized invisible groups and setStatus`, async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
const children = [].slice.call(igContainer.children);
const html = igContainer.outerHTML;
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_GROUPS));
await waitEvent(ig!, "renderComplete");
const children2 = [].slice.call(igContainer.children);
const html2 = igContainer.outerHTML;
ig!.renderItems();
await waitEvent(ig!, "renderComplete");
// update outlines
const children3 = [].slice.call(igContainer.children);
const html3 = igContainer.outerHTML;
// Then
expect(ig!.getItems(true).length).to.be.equals(9);
expect(ig!.getItems().length).to.be.equals(9);
expect(ig!.getVisibleItems().length).to.be.equals(9);
// groups (3) virtual groups (2)
expect(ig!.getGroups(true).length).to.be.equals(5);
expect(ig!.getGroups().length).to.be.equals(3);
expect(ig!.getVisibleGroups().length).to.be.equals(3);
expect(html2).to.be.equals(html);
children2.forEach((el, i) => {
expect(el).to.be.not.equal(children[i]);
});
expect(html3).to.be.equals(html);
children3.forEach((el, i) => {
expect(el).to.be.not.equal(children[i]);
});
});
it(`should check whether it is possible to restore all virtual groups in the minimized status`, async () => {
// Given
const nums = new Array(29).fill(0).map((_, i) => i);
// 0 ~ 9
ig!.syncItems(nums.map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
// 0 ~ 8
ig!.setCursors(0, 8);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS));
// visible(0 ~ 2) invisible(3 ~ 8) unchecked(9)
await waitEvent(ig!, "renderComplete");
// When
ig!.getScrollContainerElement().scrollTop = 3000;
const requestAppendEvent = await waitEvent(ig!, "requestAppend");
// 3 ~ 8
ig!.append(flat(requestAppendEvent.nextGroupKeys.map((groupKey) => {
return [0, 1, 2].map((index) => {
const child = (groupKey as number) * 3 + index;
return {
groupKey: groupKey,
key: `key${child}`,
html: `${child}
`,
};
});
})));
await waitEvent(ig!, "renderComplete");
const items = ig!.getItems(true);
const items0to26 = items.slice(0, 26);
const items27 = items.slice(27);
// Then
expect(ig!.getStartCursor()).to.be.equals(6);
expect(ig!.getEndCursor()).to.be.equals(8);
expect(items0to26.every((item) => item.type !== ITEM_TYPE.VIRTUAL)).to.be.equals(true);
expect(items27.every((item) => item.type === ITEM_TYPE.VIRTUAL)).to.be.equals(true);
});
it(`should check if requestAppend event for invisible items is triggered`, async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS));
await waitEvent(ig!, "renderComplete");
ig!.getScrollContainerElement().scrollTop = 500;
const e = await waitEvent(ig!, "requestAppend");
// Then
expect(ig!.getStartCursor()).to.be.equals(1);
expect(ig!.getEndCursor()).to.be.equals(3);
expect(e.groupKey).to.be.equals(2);
expect(e.nextGroupKey).to.be.equals(3);
});
it(`should check if requestAppend event for invisible groups is triggered`, async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// When
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_GROUPS));
await waitEvent(ig!, "renderComplete");
ig!.getScrollContainerElement().scrollTop = 500;
const e = await waitEvent(ig!, "requestAppend");
// Then
expect(ig!.getStartCursor()).to.be.equals(1);
expect(ig!.getEndCursor()).to.be.equals(3);
expect(e.groupKey).to.be.equals(2);
expect(e.nextGroupKey).to.be.equals(3);
});
it(`should check if recovery is possible with placeholders When you get the partial status with minimized invisible items and setStatus`, async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// set place holder
ig!.setPlaceholder({
html: ``,
});
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS));
// 0 ~ 9
// restore status
await waitEvent(ig!, "renderComplete");
// render changed items
await waitEvent(ig!, "renderComplete");
// When
ig!.getScrollContainerElement().scrollTop = 500;
await waitEvent(ig!, "renderComplete");
// 500 ~ 1000
// 300 / 100 100 [100 / 300 / 300 / 300] / 300 / 300
// Then
expect(ig!.getScrollContainerElement().scrollTop).to.be.equals(500);
expect(ig!.getStartCursor()).to.be.equals(1);
expect(ig!.getEndCursor()).to.be.equals(4);
// items (6) virtual items (6)
// 4 * 3 = 12
expect(ig!.getVisibleItems(true).length).to.be.equals(12);
expect(ig!.getVisibleItems().length).to.be.equals(6);
const children = [].slice.call(igContainer.children) as HTMLElement[];
children.slice(0, 6).forEach((el) => {
expect(el.classList.contains("placeholder")).to.be.false;
});
children.slice(6, 9).forEach((el) => {
expect(el.classList.contains("placeholder")).to.be.true;
});
});
it(`should check that the call requestAppend and replace placeholders`, async () => {
// Given
const igContainer = ig!.getContainerElement();
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// set place holder
ig!.setPlaceholder({
html: ``,
});
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS));
await waitEvent(ig!, "renderComplete");
ig!.on("requestAppend", ({ nextGroupKey }) => {
if (nextGroupKey) {
const groupKey = nextGroupKey as number;
ig!.append([0, 1, 2].map((child) => ({
groupKey,
key: `key${groupKey * 3 + child}`,
html: `${groupKey * 3 + child}
`,
})));
}
});
// When
ig!.getScrollContainerElement().scrollTop = 500;
await waitEvent(ig!, "requestAppend");
await waitEvent(ig!, "renderComplete");
// Then
expect(ig!.getStartCursor()).to.be.equals(1);
expect(ig!.getEndCursor()).to.be.equals(3);
// items (12) virtual items (3)
expect(ig!.getItems(true).length).to.be.equals(15);
expect(ig!.getItems().length).to.be.equals(12);
// items (9) virtual items (0)
expect(ig!.getVisibleItems(true).length).to.be.equals(9);
expect(ig!.getVisibleItems().length).to.be.equals(9);
const children = [].slice.call(igContainer.children) as HTMLElement[];
children.forEach((el) => {
expect(el.classList.contains("placeholder")).to.be.false;
});
});
it(`should check that the call requestAppend and remove placeholders`, async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
// set place holder
ig!.setPlaceholder({
html: ``,
});
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS));
await waitEvent(ig!, "renderComplete");
ig!.once("requestAppend", ({ nextGroupKey }) => {
if (nextGroupKey) {
ig!.removePlaceholders({ groupKey: nextGroupKey });
}
});
// When
ig!.getScrollContainerElement().scrollTop = 500;
await waitEvent(ig!, "requestAppend");
await waitEvent(ig!, "renderComplete");
// Then
expect(ig!.getStartCursor()).to.be.equals(1);
expect(ig!.getEndCursor()).to.be.equals(3);
// items (9) virtual items (3) remove (3)
expect(ig!.getItems(true).length).to.be.equals(12);
expect(ig!.getItems().length).to.be.equals(9);
// items (6) virtual items (3)
expect(ig!.getVisibleItems(true).length).to.be.equals(9);
expect(ig!.getVisibleItems().length).to.be.equals(6);
});
it(`should check if the placeholder is replaced when appending after adding the placeholder with no keys`, async () => {
// Given
// set place holder
ig!.setPlaceholder({
html: ``,
});
ig!.renderItems();
// When
// append placeholders
ig!.appendPlaceholders(3, 1);
await waitEvent(ig!, "renderComplete");
// placeholders
const length1 = ig!.getRenderingItems().length;
ig!.append([0, 1, 2].map((child) => {
return `${child}
`;
}), 1);
// items with placeholders
const length2 = ig!.getRenderingItems().length;
await waitEvent(ig!, "renderComplete");
// When the items are rendered, the placeholder is removed.
const length3 = ig!.getRenderingItems().length;
await waitEvent(ig!, "renderComplete");
// then
expect(length1).to.be.equals(3);
expect(length2).to.be.equals(6);
expect(length3).to.be.equals(3);
expect(ig!.getItems(true).map((item) => item.cssContentPos)).to.be.deep.equals([0, 100, 200]);
});
it(`should check if the placeholder is replaced when appending after adding the placeholder`, async () => {
// Given
ig!.append([0, 1, 2].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
// cursors (0, 0)
await waitEvent(ig!, "renderComplete");
// When
// set place holder
ig!.setPlaceholder({
html: ``,
});
// append placeholders
ig!.appendPlaceholders(3, 1);
await waitEvent(ig!, "renderComplete");
const itemsLength = ig!.getItems().length;
const allItemsLength = ig!.getItems(true).length;
ig!.append([3, 4, 5].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
await waitEvent(ig!, "renderComplete");
const itemsLength2 = ig!.getItems().length;
const allItemsLength2 = ig!.getItems(true).length;
expect(itemsLength).to.be.equals(3);
expect(allItemsLength).to.be.equals(6);
expect(itemsLength2).to.be.equals(6);
expect(allItemsLength2).to.be.equals(6);
});
it(`should check if it is included in status with virtual items`, async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// render items for all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
ig!.getScrollContainerElement().scrollTop = 800;
// scroll cursors (2 ~ 4)
await waitEvent(ig!, "renderComplete");
// When
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS, true));
await waitEvent(ig!, "renderComplete");
// restore cursors (2 ~ 4) with scroll 800
const scrollTop1 = ig!.getScrollContainerElement().scrollTop;
const startCursor1 = ig!.getStartCursor();
const endCursor1 = ig!.getEndCursor();
// restore with virtual items
ig!.setStatus(ig!.getStatus(STATUS_TYPE.MINIMIZE_INVISIBLE_ITEMS, true));
await waitEvent(ig!, "renderComplete");
// 800
// restore cursors (2 ~ 4) with scroll 800
const scrollTop2 = ig!.getScrollContainerElement().scrollTop;
const startCursor2 = ig!.getStartCursor();
const endCursor2 = ig!.getEndCursor();
// Then
expect(scrollTop1).to.be.equals(800);
expect(startCursor1).to.be.equals(2);
expect(endCursor1).to.be.equals(4);
expect(scrollTop2).to.be.equals(800);
expect(startCursor2).to.be.equals(2);
expect(endCursor2).to.be.equals(4);
});
});
describe("test scroll position", () => {
it(`should check if it is included in status with virtual items`, async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 5);
// render items for all cursors
await waitEvent(ig!, "renderComplete");
// change cursor (0, 2)
await waitEvent(ig!, "renderComplete");
// change scroll (1, 3)
// 750 (7 ~ 8) 500 ~ 1000
// 100 100 100 / 200 200 200 / 200 (v) 200 200 / 200 200 200
// 750 => 1200
ig!.getScrollContainerElement().scrollTop = 500;
await waitEvent(ig!, "renderComplete");
ig!.getItems().forEach((item) => {
item.element!.style.height = "200px";
});
ig!.renderItems({ useResize: true });
// 100 100 100 100 100 100 100
// to
// 100 100 100 200 200 200 200
await waitEvent(ig!, "renderComplete");
// 500 to 700
const correctedPos = ig!.getScrollContainerElement().scrollTop;
expect(correctedPos).to.be.equals(950);
});
});
});
describe("test scroll offset", () => {
beforeEach(() => {
container!.innerHTML = `
`;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
threshold: 0,
});
});
it(`should check if scroll position is corrected when size, pos, window size is changed (startCursor = 0)`, async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
// 커서를 전체로 지정하여 모든 아이템의 사이즈를 계산
ig!.setCursors(0, 5);
await waitEvent(ig!, "renderComplete");
// 현재 스크롤 위치에 따른 보이는 아이템 자동 변경: change cursor (0, 2)
await waitEvent(ig!, "renderComplete");
// top 100, center 350
// 브라우저간의 오차로 인한 테스트가 필요
ig!.getScrollContainerElement().scrollTop = 100;
// 스크롤 이동에 따른 보이는 아이템 자동 변경: change cursor (0, 3)
await waitEvent(ig!, "renderComplete");
// 300 + 50 => 700 (offset: 350)
// When
ig!.getItems().forEach((item) => {
item.element!.style.height = "200px";
});
// 스크롤 위치는 변경 되지 않는다.
ig!.renderItems({ useResize: true });
await waitEvent(ig!, "renderComplete");
// Then
const correctedPos = ig!.getScrollContainerElement().scrollTop;
expect(correctedPos).to.be.equals(450);
expect(ig!.getStartCursor()).to.be.equals(0);
expect(ig!.getEndCursor()).to.be.equals(1);
});
it(`should check if scroll position is corrected when size, pos, window size is changed (startCursor > 0)`, async () => {
// Given
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
// 커서를 전체로 지정하여 모든 아이템의 사이즈를 계산
ig!.setCursors(0, 5);
await waitEvent(ig!, "renderComplete");
// 현재 스크롤 위치에 따른 보이는 아이템 자동 변경: change cursor (0, 2)
await waitEvent(ig!, "renderComplete");
// top: 750, center 1000
ig!.getScrollContainerElement().scrollTop = 750;
// 스크롤 이동에 따른 보이는 아이템 자동 변경: change cursor (2, 4)
await waitEvent(ig!, "renderComplete");
const prevStartCursor = ig!.getStartCursor();
const prevEndCursor = ig!.getEndCursor();
// When
ig!.getItems().forEach((item) => {
item.element!.style.height = "200px";
});
// 600 + 300 + 50 => 600 + 700 (offset: 350)
// 스크롤 위치는 변경 되지 않는다.
// 450만큼 스크롤 차이가 발생
ig!.renderItems({ useResize: true });
await waitEvent(ig!, "renderComplete");
// Then
expect(prevStartCursor).to.be.equals(2);
expect(prevEndCursor).to.be.equals(4);
const correctedPos = ig!.getScrollContainerElement().scrollTop;
expect(correctedPos).to.be.equals(1100);
expect(ig!.getStartCursor()).to.be.equals(2);
expect(ig!.getEndCursor()).to.be.equals(3);
});
});
describe("test ResizeObserver", () => {
it(`should check if renderComplete does trigger when useResizeObserver is enabled and container's size is changed`, async () => {
// Given
container!.innerHTML = `
`;
const spy = sinon.spy();
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
useResizeObserver: true,
});
ig.on("renderComplete", spy);
// When
// occur when resize inline direction
container!.style.width = "90%";
await waitFor(100);
// not occur when resize content direction
container!.style.height = "100px";
await waitFor(100);
// Then
expect(spy.callCount).to.be.equals(1);
});
it(`should Check if ResizeObserver is also applied to children`, async () => {
// Given
container!.innerHTML = `
`;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
useResizeObserver: true,
observeChildren: true,
});
ig.renderItems();
await waitEvent(ig, "renderComplete");
// When
const item = ig.getItems()[0];
// resize child element
ig.getItems()[0].element!.style.height = "30px";
const e = await waitEvent(ig, "renderComplete");
// Then
expect(e.updated.length).to.be.equals(1);
expect(item.rect.height).to.be.equals(30);
});
it(`should check if ResizeObserver is applied only to visible items`, async () => {
// Given
container!.innerHTML = `
`;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
useResizeObserver: true,
observeChildren: true,
});
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
ig!.getScrollContainerElement().scrollTop = 500;
// partial cursors (1 ~ 3)
await waitEvent(ig!, "renderComplete");
// When
const visibleItem = ig.getVisibleItems()[0];
const invisibleItem = ig.getItems()[0];
// resize child element
visibleItem.element!.style.height = "30px";
invisibleItem.element!.style.height = "30px";
const e = await waitEvent(ig, "renderComplete");
// Then
expect(e.updated.length).to.be.equals(1);
expect(visibleItem.rect.height).to.be.equals(30);
expect(invisibleItem.rect.height).not.to.be.equals(30);
expect(ig!.getStartCursor()).to.be.equals(1);
expect(ig!.getEndCursor()).to.be.equals(3);
});
});
describe("test size group, equal size", () => {
it("should check if isEqualSize calculates the size of the items in the invisible area.", async () => {
// Given
container!.innerHTML = ``;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
isEqualSize: true,
injectCSSSize: false,
});
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
ig!.getScrollContainerElement().scrollTop = 500;
// partial cursors (1 ~ 3)
await waitEvent(ig!, "renderComplete");
// When
// Based on the first item of the currently displayed item, the size of all items is determined to be the same.
ig!.renderItems({
useResize: true,
});
await waitEvent(ig!, "renderComplete");
const visibleItem = ig!.getVisibleItems()[0];
// Then
expect(visibleItem.groupKey).to.be.equals(1);
expect(visibleItem.key).to.be.equals("key3");
ig!.getItems().forEach((item) => {
// The size of all items is the same as the "key3" item
expect(item.rect.height).to.be.equals(130);
});
});
it("should checks if the sizes of the not-equal-size items are different.", async () => {
// Given
container!.innerHTML = ``;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
isEqualSize: true,
injectCSSSize: false,
});
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
ig!.getScrollContainerElement().scrollTop = 500;
// partial cursors (1 ~ 3)
await waitEvent(ig!, "renderComplete");
// When
// Based on the first item of the currently displayed item, the size of all items is determined to be the same.
ig!.renderItems({
useResize: true,
});
await waitEvent(ig!, "renderComplete");
// Then
ig!.getItems().forEach((item, i) => {
// Except for item 7, all are the same size (130).
if (i === 7) {
expect(ig!.getItems()[7].rect.height).to.be.equals(170);
} else {
// The size of all items is the same as the "key3" item
expect(item.rect.height).to.be.equals(130);
}
});
});
it("should check if size group calculates the size of the group of items in the invisible area.", async () => {
// Given
container!.innerHTML = ``;
const wrapper = container!.querySelector(".wrapper")!;
ig = new InfiniteGrid(wrapper, {
gridConstructor: SampleGrid,
container: true,
injectCSSSize: false,
});
ig!.syncItems([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((child) => {
return {
groupKey: Math.floor(child / 3),
key: `key${child}`,
html: `${child}
`,
};
}));
ig!.setCursors(0, 4);
// all cursors
await waitEvent(ig!, "renderComplete");
// partial cursors (0 ~ 2)
await waitEvent(ig!, "renderComplete");
ig!.getScrollContainerElement().scrollTop = 500;
// partial cursors (1 ~ 3)
await waitEvent(ig!, "renderComplete");
// When
// Based on the first item of the currently displayed item, the size of all items is determined to be the same.
ig!.renderItems({
useResize: true,
});
await waitEvent(ig!, "renderComplete");
const [item1, item2] = ig!.getVisibleItems();
// Then
expect(item1.key).to.be.equals("key3");
expect(item2.key).to.be.equals("key4");
expect(item1.rect.height).to.be.equals(130);
expect(item2.rect.height).to.be.equals(140);
// The size of all items (even "0") is the same as the "key4" item
// The size of all items (odd, "1") is the same as the "key3" item
ig!.getItems().forEach((item, i) => {
expect(item.rect.height).to.be.equals(i % 2 ? 130 : 140);
});
});
});
});