mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
refactor(test): migrate useSwitchControls test from react-test-renderer to ink render
This commit is contained in:
@@ -43,7 +43,6 @@
|
||||
"dotenv": "^16.6.1",
|
||||
"eslint": "^9",
|
||||
"eslint-config-prettier": "^10",
|
||||
"react-test-renderer": "^19.2.0",
|
||||
"shx": "^0.3.3",
|
||||
"ts-node": "^10",
|
||||
"tsx": "^4.20.6",
|
||||
@@ -1519,8 +1518,6 @@
|
||||
|
||||
"react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="],
|
||||
|
||||
"react-is": ["react-is@19.2.3", "", {}, "sha512-qJNJfu81ByyabuG7hPFEbXqNcWSU3+eVus+KJs+0ncpGfMyYdvSmxiJxbWR65lYi1I+/0HBcliO029gc4F+PnA=="],
|
||||
|
||||
"react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="],
|
||||
|
||||
"react-reconciler": ["react-reconciler@0.33.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA=="],
|
||||
@@ -1533,8 +1530,6 @@
|
||||
|
||||
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
|
||||
|
||||
"react-test-renderer": ["react-test-renderer@19.2.3", "", { "dependencies": { "react-is": "^19.2.3", "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-TMR1LnSFiWZMJkCgNf5ATSvAheTT2NvKIwiVwdBPHxjBI7n/JbWd4gaZ16DVd9foAXdvDz+sB5yxZTwMjPRxpw=="],
|
||||
|
||||
"react-textarea-autosize": ["react-textarea-autosize@8.5.9", "", { "dependencies": { "@babel/runtime": "^7.20.13", "use-composed-ref": "^1.3.0", "use-latest": "^1.2.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A=="],
|
||||
|
||||
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
|
||||
|
||||
+1
-2
@@ -65,8 +65,7 @@
|
||||
"ts-node": "^10",
|
||||
"tsx": "^4.20.6",
|
||||
"typescript": "^5",
|
||||
"vitest": "^3.2.4",
|
||||
"react-test-renderer": "^19.2.0"
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"whatwg-url": "14.2.0",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import TestRenderer, { act, type ReactTestRenderer } from 'react-test-renderer';
|
||||
import React, { act, useEffect } from 'react';
|
||||
import { PassThrough } from 'node:stream';
|
||||
import { render, type Instance } from 'ink';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { useSwitchControls, type ConfirmationMode, type ActionInProgress } from './useSwitchControls';
|
||||
|
||||
@@ -16,11 +17,48 @@ type SwitchState = {
|
||||
|
||||
let inputHandler: ((input: string, key: Key) => void | Promise<void>) | null = null;
|
||||
|
||||
vi.mock('ink', () => ({
|
||||
useInput: (handler: (input: string, key: Key) => void | Promise<void>) => {
|
||||
inputHandler = handler;
|
||||
}
|
||||
}));
|
||||
vi.mock('ink', async () => {
|
||||
const actual = await vi.importActual<typeof import('ink')>('ink');
|
||||
return {
|
||||
...actual,
|
||||
useInput: (handler: (input: string, key: Key) => void | Promise<void>) => {
|
||||
inputHandler = handler;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const createInkStreams = (): {
|
||||
stdout: NodeJS.WriteStream;
|
||||
stderr: NodeJS.WriteStream;
|
||||
stdin: NodeJS.ReadStream;
|
||||
} => {
|
||||
const stdout = new PassThrough() as NodeJS.WriteStream & {
|
||||
isTTY?: boolean;
|
||||
columns?: number;
|
||||
rows?: number;
|
||||
};
|
||||
const stderr = new PassThrough() as NodeJS.WriteStream & {
|
||||
isTTY?: boolean;
|
||||
columns?: number;
|
||||
rows?: number;
|
||||
};
|
||||
const stdin = new PassThrough() as NodeJS.ReadStream & {
|
||||
isTTY?: boolean;
|
||||
};
|
||||
|
||||
Object.assign(stdout, { isTTY: true, columns: 80, rows: 24 });
|
||||
Object.assign(stderr, { isTTY: true, columns: 80, rows: 24 });
|
||||
Object.assign(stdin, { isTTY: false });
|
||||
|
||||
return { stdout, stderr, stdin };
|
||||
};
|
||||
|
||||
const getActEnvironment = (): boolean | undefined =>
|
||||
(globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT;
|
||||
|
||||
const setActEnvironment = (value: boolean | undefined) => {
|
||||
(globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = value;
|
||||
};
|
||||
|
||||
function HookProbe(props: {
|
||||
onExit?: () => void;
|
||||
@@ -41,18 +79,27 @@ function HookProbe(props: {
|
||||
}
|
||||
|
||||
describe('useSwitchControls', () => {
|
||||
let renderer: ReactTestRenderer | null = null;
|
||||
let renderer: Instance | null = null;
|
||||
let latestState: SwitchState | null = null;
|
||||
let previousActEnvironment: boolean | undefined;
|
||||
|
||||
const mount = async (opts: { onExit?: () => void; onSwitch?: () => void }) => {
|
||||
const { stdout, stderr, stdin } = createInkStreams();
|
||||
await act(async () => {
|
||||
renderer = TestRenderer.create(
|
||||
renderer = render(
|
||||
React.createElement(HookProbe, {
|
||||
...opts,
|
||||
onState: (state) => {
|
||||
latestState = state;
|
||||
}
|
||||
})
|
||||
}),
|
||||
{
|
||||
stdout,
|
||||
stderr,
|
||||
stdin,
|
||||
exitOnCtrlC: false,
|
||||
patchConsole: false
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
@@ -84,20 +131,26 @@ describe('useSwitchControls', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
previousActEnvironment = getActEnvironment();
|
||||
setActEnvironment(true);
|
||||
vi.useFakeTimers();
|
||||
inputHandler = null;
|
||||
latestState = null;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
afterEach(async () => {
|
||||
await act(async () => {
|
||||
vi.runOnlyPendingTimers();
|
||||
});
|
||||
if (renderer) {
|
||||
act(() => {
|
||||
renderer?.unmount();
|
||||
await act(async () => {
|
||||
renderer.unmount();
|
||||
});
|
||||
renderer.cleanup();
|
||||
renderer = null;
|
||||
}
|
||||
vi.runOnlyPendingTimers();
|
||||
vi.useRealTimers();
|
||||
setActEnvironment(previousActEnvironment);
|
||||
});
|
||||
|
||||
it('forwards Ctrl-C to process when onExit is missing', async () => {
|
||||
|
||||
Reference in New Issue
Block a user