use-terminal.test.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { beforeAll, describe, expect, it, vi } from "vitest";
  2. import { render } from "@testing-library/react";
  3. import { afterEach } from "node:test";
  4. import { useTerminal } from "#/hooks/useTerminal";
  5. import { SocketProvider } from "#/context/socket";
  6. import { Command } from "#/state/commandSlice";
  7. interface TestTerminalComponentProps {
  8. commands: Command[];
  9. secrets: string[];
  10. }
  11. function TestTerminalComponent({
  12. commands,
  13. secrets,
  14. }: TestTerminalComponentProps) {
  15. const ref = useTerminal(commands, secrets);
  16. return <div ref={ref} />;
  17. }
  18. describe("useTerminal", () => {
  19. const mockTerminal = vi.hoisted(() => ({
  20. loadAddon: vi.fn(),
  21. open: vi.fn(),
  22. write: vi.fn(),
  23. writeln: vi.fn(),
  24. onKey: vi.fn(),
  25. attachCustomKeyEventHandler: vi.fn(),
  26. dispose: vi.fn(),
  27. }));
  28. beforeAll(() => {
  29. // mock ResizeObserver
  30. window.ResizeObserver = vi.fn().mockImplementation(() => ({
  31. observe: vi.fn(),
  32. unobserve: vi.fn(),
  33. disconnect: vi.fn(),
  34. }));
  35. // mock Terminal
  36. vi.mock("@xterm/xterm", async (importOriginal) => ({
  37. ...(await importOriginal<typeof import("@xterm/xterm")>()),
  38. Terminal: vi.fn().mockImplementation(() => mockTerminal),
  39. }));
  40. });
  41. afterEach(() => {
  42. vi.clearAllMocks();
  43. });
  44. it("should render", () => {
  45. render(<TestTerminalComponent commands={[]} secrets={[]} />, {
  46. wrapper: SocketProvider,
  47. });
  48. });
  49. it("should render the commands in the terminal", () => {
  50. const commands: Command[] = [
  51. { content: "echo hello", type: "input" },
  52. { content: "hello", type: "output" },
  53. ];
  54. render(<TestTerminalComponent commands={commands} secrets={[]} />, {
  55. wrapper: SocketProvider,
  56. });
  57. expect(mockTerminal.writeln).toHaveBeenNthCalledWith(1, "echo hello");
  58. expect(mockTerminal.writeln).toHaveBeenNthCalledWith(2, "hello");
  59. });
  60. it("should hide secrets in the terminal", () => {
  61. const secret = "super_secret_github_token";
  62. const anotherSecret = "super_secret_another_token";
  63. const commands: Command[] = [
  64. {
  65. content: `export GITHUB_TOKEN=${secret},${anotherSecret},${secret}`,
  66. type: "input",
  67. },
  68. { content: secret, type: "output" },
  69. ];
  70. render(
  71. <TestTerminalComponent
  72. commands={commands}
  73. secrets={[secret, anotherSecret]}
  74. />,
  75. {
  76. wrapper: SocketProvider,
  77. },
  78. );
  79. // BUG: `vi.clearAllMocks()` does not clear the number of calls
  80. // therefore, we need to assume the order of the calls based
  81. // on the test order
  82. expect(mockTerminal.writeln).toHaveBeenNthCalledWith(
  83. 3,
  84. `export GITHUB_TOKEN=${"*".repeat(10)},${"*".repeat(10)},${"*".repeat(10)}`,
  85. );
  86. expect(mockTerminal.writeln).toHaveBeenNthCalledWith(4, "*".repeat(10));
  87. });
  88. });