App.test.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // npx jest src/__tests__/App.test.tsx
  2. import React from "react"
  3. import { render, screen, act, cleanup } from "@testing-library/react"
  4. import "@testing-library/jest-dom"
  5. import AppWithProviders from "../App"
  6. jest.mock("../utils/vscode", () => ({
  7. vscode: {
  8. postMessage: jest.fn(),
  9. },
  10. }))
  11. jest.mock("../components/chat/ChatView", () => ({
  12. __esModule: true,
  13. default: function ChatView({ isHidden }: { isHidden: boolean }) {
  14. return (
  15. <div data-testid="chat-view" data-hidden={isHidden}>
  16. Chat View
  17. </div>
  18. )
  19. },
  20. }))
  21. jest.mock("../components/settings/SettingsView", () => ({
  22. __esModule: true,
  23. default: function SettingsView({ onDone }: { onDone: () => void }) {
  24. return (
  25. <div data-testid="settings-view" onClick={onDone}>
  26. Settings View
  27. </div>
  28. )
  29. },
  30. }))
  31. jest.mock("../components/history/HistoryView", () => ({
  32. __esModule: true,
  33. default: function HistoryView({ onDone }: { onDone: () => void }) {
  34. return (
  35. <div data-testid="history-view" onClick={onDone}>
  36. History View
  37. </div>
  38. )
  39. },
  40. }))
  41. jest.mock("../components/mcp/McpView", () => ({
  42. __esModule: true,
  43. default: function McpView({ onDone }: { onDone: () => void }) {
  44. return (
  45. <div data-testid="mcp-view" onClick={onDone}>
  46. MCP View
  47. </div>
  48. )
  49. },
  50. }))
  51. jest.mock("../components/prompts/PromptsView", () => ({
  52. __esModule: true,
  53. default: function PromptsView({ onDone }: { onDone: () => void }) {
  54. return (
  55. <div data-testid="prompts-view" onClick={onDone}>
  56. Prompts View
  57. </div>
  58. )
  59. },
  60. }))
  61. jest.mock("../context/ExtensionStateContext", () => ({
  62. useExtensionState: () => ({
  63. didHydrateState: true,
  64. showWelcome: false,
  65. shouldShowAnnouncement: false,
  66. }),
  67. ExtensionStateContextProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
  68. }))
  69. describe("App", () => {
  70. beforeEach(() => {
  71. jest.clearAllMocks()
  72. window.removeEventListener("message", () => {})
  73. })
  74. afterEach(() => {
  75. cleanup()
  76. window.removeEventListener("message", () => {})
  77. })
  78. const triggerMessage = (action: string) => {
  79. const messageEvent = new MessageEvent("message", {
  80. data: {
  81. type: "action",
  82. action,
  83. },
  84. })
  85. window.dispatchEvent(messageEvent)
  86. }
  87. it("shows chat view by default", () => {
  88. render(<AppWithProviders />)
  89. const chatView = screen.getByTestId("chat-view")
  90. expect(chatView).toBeInTheDocument()
  91. expect(chatView.getAttribute("data-hidden")).toBe("false")
  92. })
  93. it("switches to settings view when receiving settingsButtonClicked action", async () => {
  94. render(<AppWithProviders />)
  95. act(() => {
  96. triggerMessage("settingsButtonClicked")
  97. })
  98. const settingsView = await screen.findByTestId("settings-view")
  99. expect(settingsView).toBeInTheDocument()
  100. const chatView = screen.getByTestId("chat-view")
  101. expect(chatView.getAttribute("data-hidden")).toBe("true")
  102. })
  103. it("switches to history view when receiving historyButtonClicked action", async () => {
  104. render(<AppWithProviders />)
  105. act(() => {
  106. triggerMessage("historyButtonClicked")
  107. })
  108. const historyView = await screen.findByTestId("history-view")
  109. expect(historyView).toBeInTheDocument()
  110. const chatView = screen.getByTestId("chat-view")
  111. expect(chatView.getAttribute("data-hidden")).toBe("true")
  112. })
  113. it("switches to MCP view when receiving mcpButtonClicked action", async () => {
  114. render(<AppWithProviders />)
  115. act(() => {
  116. triggerMessage("mcpButtonClicked")
  117. })
  118. const mcpView = await screen.findByTestId("mcp-view")
  119. expect(mcpView).toBeInTheDocument()
  120. const chatView = screen.getByTestId("chat-view")
  121. expect(chatView.getAttribute("data-hidden")).toBe("true")
  122. })
  123. it("switches to prompts view when receiving promptsButtonClicked action", async () => {
  124. render(<AppWithProviders />)
  125. act(() => {
  126. triggerMessage("promptsButtonClicked")
  127. })
  128. const promptsView = await screen.findByTestId("prompts-view")
  129. expect(promptsView).toBeInTheDocument()
  130. const chatView = screen.getByTestId("chat-view")
  131. expect(chatView.getAttribute("data-hidden")).toBe("true")
  132. })
  133. it("returns to chat view when clicking done in settings view", async () => {
  134. render(<AppWithProviders />)
  135. act(() => {
  136. triggerMessage("settingsButtonClicked")
  137. })
  138. const settingsView = await screen.findByTestId("settings-view")
  139. act(() => {
  140. settingsView.click()
  141. })
  142. const chatView = screen.getByTestId("chat-view")
  143. expect(chatView.getAttribute("data-hidden")).toBe("false")
  144. expect(screen.queryByTestId("settings-view")).not.toBeInTheDocument()
  145. })
  146. it.each(["history", "mcp", "prompts"])("returns to chat view when clicking done in %s view", async (view) => {
  147. render(<AppWithProviders />)
  148. act(() => {
  149. triggerMessage(`${view}ButtonClicked`)
  150. })
  151. const viewElement = await screen.findByTestId(`${view}-view`)
  152. act(() => {
  153. viewElement.click()
  154. })
  155. const chatView = screen.getByTestId("chat-view")
  156. expect(chatView.getAttribute("data-hidden")).toBe("false")
  157. expect(screen.queryByTestId(`${view}-view`)).not.toBeInTheDocument()
  158. })
  159. })