// @vitest-environment jsdom import { act, cleanup, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { useRef } from 'react'; import { describe, expect, test } from 'vitest'; import { manage } from '../src'; import { auto } from '../src/react'; describe('React hooks', () => { test('default', () => { let id = 0; class Bullet { public id: number; public speed = 10; public constructor() { this.id = id++; } } class Store { public bullets: { [key: number]: Bullet } = {}; } let bulletCount = 0; const BulletComponent = auto((props: { bullet: Bullet }) => { bulletCount += 1; const { bullet } = props; const r = useRef(null); // this will throw error if we use useEffect + autoRun to implement auto return {bullet.speed}; }); let appCount = 0; const App = auto((props: { store: Store }) => { appCount += 1; const { store } = props; const r = useRef(null); // this will throw error if we use useEffect + autoRun to implement auto return ( <> hello {Object.values(store.bullets).map((bullet) => ( ))} ); }); const store = manage(new Store()); store.bullets[0] = new Bullet(); render(); expect(appCount).toBe(1); expect(bulletCount).toBe(1); act(() => { store.bullets[0].speed = 20; }); expect(appCount).toBe(1); expect(bulletCount).toBe(2); act(() => { store.bullets[0].speed = 30; }); expect(appCount).toBe(1); expect(bulletCount).toBe(3); act(() => { store.bullets[1] = new Bullet(); }); expect(appCount).toBe(2); expect(bulletCount).toBe(4); cleanup(); }); test('should not break useState', async () => { class Store { count = 0; } const store = manage(new Store()); let count = 0; const App = auto((props: { store: Store }) => { count += 1; const { store } = props; const [counter, setCounter] = React.useState(0); return ( <> {store.count}: {counter} ); }); render(); expect(count).toBe(1); const minusButton = screen.getByText('Click'); await userEvent.click(minusButton); expect(count).toBe(2); await userEvent.click(minusButton); await userEvent.click(minusButton); expect(count).toBe(4); act(() => { store.count += 1; }); expect(count).toBe(5); cleanup(); }); });