import * as React from "react";
import { renderHook, render, act } from "@testing-library/react-native";
import { View } from "react-native";
import { useSequentialLoader, useSequentialRenderItem } from "..";
describe("flatList hooks", () => {
describe("useSequentialRenderItem", () => {
it("returns function and loading indicator ", () => {
const mockData = [{ test: true }];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
expect(typeof result.current.renderItem).toBe("function");
expect(typeof result.current.allLoaded).toBeTruthy();
});
it("returns works with empty data", () => {
const mockData = [];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
expect(typeof result.current.renderItem).toBe("function");
expect(typeof result.current.allLoaded).toBeTruthy();
});
describe("Data passed to renderItem function", () => {
it("passes correct item element over", () => {
const element = { id: 1 };
const mockData = [element];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
result.current.renderItem(({ item }) => {
expect(item).toBe(element);
});
});
it("passes onLoadFinished method to renderItem", () => {
const element = { id: 1 };
const mockData = [element];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
result.current.renderItem(({ onLoadFinished }) => {
expect(onLoadFinished).toBeDefined();
});
});
});
describe("Calling onLoadFinished callback", () => {
it("allLoaded return true after onLoadFinished is called for all components", () => {
const element1 = { id: 1 };
const element2 = { id: 2 };
const mockData = [element1, element2];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
expect(result.current.allLoaded).toBe(false);
result.current.renderItem(
({ onLoadFinished }) => {
onLoadFinished();
},
{ index: 0 }
);
expect(result.current.allLoaded).toBe(false);
act(() => {
result.current.renderItem(
({ onLoadFinished }) => {
onLoadFinished();
},
{ index: 1 }
);
});
expect(result.current.allLoaded).toBe(true);
});
});
describe("Rendering wrapper", () => {
it("wraps the elements in the View with display: none style", async () => {
const element1 = { id: 1 };
const element2 = { id: 2 };
const mockData = [element1, element2];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
const res = render(
result.current.renderItem(
() => {
return ;
},
{ item: element1 }
)
);
const element = res.root.findByProps({
testID: "sequential-river-wrapper-1",
});
expect(element.props.style.display).toEqual("none");
});
it("calling on LoadFinish flips the View style to flex", () => {
const element1 = { id: 1 };
const element2 = { id: 2 };
const mockData = [element1, element2];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
act(() => {
result.current.renderItem(
({ onLoadFinished }) => {
onLoadFinished();
},
{ item: element1, index: 0 }
);
});
const { root } = render(
result.current.renderItem(
({ onLoadFinished }) => {
onLoadFinished();
return ;
},
{ item: element1, index: 1 }
)
);
const element = root.findByProps({
testID: "sequential-river-wrapper-1",
});
expect(element.props.style.display).toEqual("flex");
});
it("View stays hidden if previous views are not loaded", () => {
const element1 = { id: 1 };
const element2 = { id: 2 };
const mockData = [element1, element2];
const { result } = renderHook(() => useSequentialRenderItem(mockData));
const { root } = render(
result.current.renderItem(
({ onLoadFinished }) => {
onLoadFinished();
return ;
},
{ item: element1, index: 1 }
)
);
const element = root.findByProps({
testID: "sequential-river-wrapper-1",
});
expect(element.props.style.display).toEqual("none");
});
});
});
describe("useSequentialLoader", () => {
it("returns correct elements", () => {
const mockData = [{ test: true }];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
expect(typeof result.current.isReadyToRender).toBe("function");
expect(typeof result.current.onLoadFinished).toBe("function");
expect(typeof result.current.onViewableItemsChanged).toBe("function");
expect(typeof result.current.isRendered).toBe("function");
expect(typeof result.current.allLoaded).toBe("boolean");
});
});
describe("isReadyToRender", () => {
const viewableMock = {
viewableItems: [
{ index: 0, item: 1, key: "1", isViewable: true },
{ index: 1, item: 2, key: "2", isViewable: true },
],
changed: [],
};
it("returns true when element is flagged as rendered", () => {
const mockData = [1, 2];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onViewableItemsChanged(viewableMock);
result.current.onLoadFinished(1)();
});
expect(result.current.isReadyToRender(1)).toBe(true);
});
it("returns false when element is not flagged as rendered", () => {
const mockData = [1, 2];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onViewableItemsChanged(viewableMock);
});
expect(result.current.isReadyToRender(1)).toBe(false);
});
it("always returns true for index 0", () => {
const mockData = [1, 2];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
expect(result.current.isReadyToRender(0)).toBe(true);
});
it("returns false if there are no viewable items", () => {
const mockData = [1, 2];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onLoadFinished(1)();
});
expect(result.current.isReadyToRender(1)).toBe(false);
});
it("returns true if it's in the viewport and previous element is loaded", () => {
const mockData = [1, 2, 3];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onViewableItemsChanged(viewableMock);
result.current.onLoadFinished(0)();
result.current.onLoadFinished(1)();
});
expect(result.current.isReadyToRender(2)).toBe(true);
});
it("returns true if it's first, second or third component outside the viewport and previous element are loaded", () => {
const mockData = [1, 2, 3, 4, 5];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onViewableItemsChanged(viewableMock);
result.current.onLoadFinished(0)();
result.current.onLoadFinished(1)();
});
expect(result.current.isReadyToRender(2)).toBe(true);
act(() => {
result.current.onLoadFinished(2)();
});
expect(result.current.isReadyToRender(2)).toBe(true);
act(() => {
result.current.onLoadFinished(3)();
});
expect(result.current.isReadyToRender(3)).toBe(true);
act(() => {
result.current.onLoadFinished(4)();
});
expect(result.current.isReadyToRender(4)).toBe(true);
expect(result.current.isReadyToRender(5)).toBe(false);
});
describe("allLoaded", () => {
it("returns true if onLoadFinished was called for all elements", () => {
const mockData = [1, 2];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onLoadFinished(0)();
result.current.onLoadFinished(1)();
});
expect(result.current.allLoaded).toBe(true);
});
it("returns true if onLoadFinished wasn't called for all elements", () => {
const mockData = [1, 2];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
expect(result.current.allLoaded).toBe(false);
});
});
describe("isRendered", () => {
it("returns true if onLoadFinished was called for x element", () => {
const mockData = [1, 2];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onLoadFinished(1)();
});
expect(result.current.isRendered(1)).toBe(true);
});
it("returns true if onLoadFinished wasn't called for x element", () => {
const mockData = [1, 2, 3];
const { result } = renderHook(() =>
useSequentialLoader(true, mockData.length)
);
act(() => {
result.current.onLoadFinished(1)();
});
expect(result.current.isRendered(2)).toBe(false);
});
});
});
});