// @vitest-environment jsdom import { act, cleanup, render, screen } from '@testing-library/react'; import React from 'react'; import { describe, expect, test } from 'vitest'; import { manage, runInAction } from '../src'; import { auto, Component } from '../src/react'; describe('React', () => { class Store { public count = 0; public increase() { this.count += 1; } } const testCases = [ { name: 'Functional component', createComponents: () => { const store = manage(new Store()); const renderHistory: number[] = []; const App = auto((props: { store: Store }) => { const { store } = props; renderHistory.push(store.count); return (
{store.count}
); }); return { App, store, renderHistory }; } }, { name: 'Class component', createComponents: () => { const store = manage(new Store()); const renderHistory: number[] = []; class App extends Component<{ store: Store }> { render() { const { store } = this.props; renderHistory.push(store.count); return (
{store.count}
); } } return { App, store, renderHistory }; } } ]; testCases.forEach(({ name, createComponents }) => { test(`transaction - ${name}`, async () => { const { App, store, renderHistory } = createComponents(); store.count = 0; render( ); // only one re-render for batch act(() => { runInAction(() => { act(() => { store.count += 1; }); act(() => { store.count += 1; }); act(() => { store.count += 1; }); }); }); // note: this cannot be tested precisely, because React may batch re-renders // 3 re-renders without batch act(() => { store.count += 1; }); act(() => { store.count += 1; }); act(() => { store.count += 1; }); const span = screen.getByRole('count'); expect(parseInt(span.textContent!.trim(), 10)).toBe(store.count); expect(store.count).toBe(6); expect(renderHistory).toEqual([0, 3, 4, 5, 6]); cleanup(); }); }); });