import { signal } from "@preact-signals/unified-signals"; import React from "react"; import { MockInstance, SpyInstance, describe, expect, it, vi } from "vitest"; import { createRenderer } from "../../../__tests__/utils"; import { For } from "../components/For"; describe("For()", () => { const { root, reactRoot, act } = createRenderer(); const itemAndIndexToString = (item: number, index: number) => [item, index].join("."); it("should render correctly", async () => { const arr = [1, 2, 3]; const A = vi.fn(() => arr}>{itemAndIndexToString}); await reactRoot().render(); expect(A).toHaveBeenCalledOnce(); const expectCorrect = () => [...root.children].forEach((child, index) => { expect(child).is.instanceOf(Text); expect(child).has.property( "data", itemAndIndexToString(arr[index]!, index) ); }); expectCorrect(); }); it("should be reactive", async () => { const arr = signal([1, 2, 3]); const A = vi.fn(() => {(item) => item * 2}); await reactRoot().render(); expect(A).toHaveBeenCalledOnce(); const expectCorrect = () => [...root.children].forEach((child, index) => { expect(child).is.instanceOf(Text); expect(child).has.property( "data", itemAndIndexToString(arr.peek()[index]!, index) ); }); expectCorrect(); await act(() => { arr.value = [4, 5, 6]; }); expectCorrect(); expect(A).toHaveBeenCalledOnce(); }); it("should add keys implicitly for strings and number arrays", async () => { const SpyFor = vi.fn(For); const error = vi.spyOn(console, "error"); // const log = vi.fn(); // const originalConsole = Object.assign({}, console); await reactRoot().render(<>{[<>1, 2]}); const hasKeyWarning = (fn: MockInstance) => fn.mock.calls.some((args) => args .join("") .includes('Each child in a list should have a unique "key"') ); expect(hasKeyWarning(error)).toBeTruthy(); error.mockClear(); { const arr = [1, 2, 3]; const A = () => ( arr}>{(item: number) => item * 2} ); await reactRoot().render(); expect(SpyFor).toHaveBeenCalledOnce(); expect(hasKeyWarning(error)).toBeFalsy(); } { const arr = [{ v: 5 }, { v: 2 }, { v: 3 }]; const A = () => ( arr} keyExtractor={(v: { v: number }) => v.v}> {(item: { v: number }) => item.v * 2} ); await reactRoot().render(); expect(SpyFor).toHaveBeenCalledTimes(2); expect(hasKeyWarning(error)).toBeFalsy(); } }); });