1import { act, create, type ReactTestRenderer } from "react-test-renderer";
2import { afterEach, beforeEach, expect, it, vi } from "vite-plus/test";
3
4const state = vi.hoisted(() => ({
5 create: vi.fn(),
6 write: vi.fn(),
7 resetAndWrite: vi.fn(),
8 dispose: vi.fn(),
9}));
10vi.mock("../../terminal/TerminalSurface", () => ({ TerminalSurface: { create: state.create } }));
11vi.mock("../ThreadTerminalDrawer", () => ({ terminalThemeFromApp: () => ({}) }));
12
13import ProviderAuthTerminal from "./ProviderAuthTerminal";
14
15let renderer: ReactTestRenderer | undefined;
16
17beforeEach(() => {
18 vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
19 state.create.mockReset();
20 state.write.mockReset();
21 state.resetAndWrite.mockReset();
22 state.dispose.mockReset();
23});
24
25afterEach(async () => {
26 await act(async () => renderer?.unmount());
27 renderer = undefined;
28 vi.unstubAllGlobals();
29});
30
31it("replays the latest sign-in output after async setup, then appends live deltas", async () => {
32 let finish: (() => void) | undefined;
33 state.create.mockReturnValue(
34 new Promise((resolve) => {
35 finish = () => resolve(state);
36 }),
37 );
38 const onResponse = vi.fn();
39 await act(async () => {
40 renderer = create(
41 <ProviderAuthTerminal output="old" outputOffset={3} onResponse={onResponse} />,
42 {
43 createNodeMock: () => ({}),
44 },
45 );
46 });
47 await act(async () => {
48 renderer!.update(
49 <ProviderAuthTerminal output="old🌱" outputOffset={5} onResponse={onResponse} />,
50 );
51 });
52 await act(async () => finish!());
53 expect(state.resetAndWrite).toHaveBeenCalledExactlyOnceWith("old🌱");
54 expect(state.write).not.toHaveBeenCalled();
55 await act(async () => {
56 renderer!.update(
57 <ProviderAuthTerminal output="old🌱next" outputOffset={9} onResponse={onResponse} />,
58 );
59 });
60 expect(state.write).toHaveBeenCalledExactlyOnceWith("next");
61 await act(async () => {
62 renderer!.update(
63 <ProviderAuthTerminal output="fresh" outputOffset={2} onResponse={onResponse} />,
64 );
65 });
66 expect(state.resetAndWrite).toHaveBeenLastCalledWith("fresh");
67});
68
69it("disposes a terminal whose setup completes after sign-in closes", async () => {
70 let finish: (() => void) | undefined;
71 state.create.mockReturnValue(
72 new Promise((resolve) => {
73 finish = () => resolve(state);
74 }),
75 );
76 await act(async () => {
77 renderer = create(<ProviderAuthTerminal output="hello" onResponse={vi.fn()} />, {
78 createNodeMock: () => ({}),
79 });
80 });
81 await act(async () => renderer!.unmount());
82 renderer = undefined;
83 await act(async () => finish!());
84 expect(state.dispose).toHaveBeenCalledOnce();
85 expect(state.resetAndWrite).not.toHaveBeenCalled();
86 expect(state.write).not.toHaveBeenCalled();
87});