api-test-button.test.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * @vitest-environment happy-dom
  3. */
  4. import type { ReactNode } from "react";
  5. import { act } from "react";
  6. import { createRoot } from "react-dom/client";
  7. import { NextIntlClientProvider } from "next-intl";
  8. import { beforeEach, describe, expect, test, vi } from "vitest";
  9. import { ApiTestButton } from "@/app/[locale]/settings/providers/_components/forms/api-test-button";
  10. import apiTestMessages from "../../../../messages/en/settings/providers/form/apiTest.json";
  11. import providerTypesMessages from "../../../../messages/en/settings/providers/form/providerTypes.json";
  12. const { getProviderTestPresetsMock } = vi.hoisted(() => ({
  13. getProviderTestPresetsMock: vi.fn(),
  14. }));
  15. vi.mock("@/actions/providers", () => ({
  16. getProviderTestPresets: getProviderTestPresetsMock,
  17. testProviderGemini: vi.fn(),
  18. testProviderUnified: vi.fn(),
  19. }));
  20. vi.mock("sonner", () => ({
  21. toast: {
  22. error: vi.fn(),
  23. success: vi.fn(),
  24. warning: vi.fn(),
  25. },
  26. }));
  27. function render(node: ReactNode) {
  28. const container = document.createElement("div");
  29. document.body.appendChild(container);
  30. const root = createRoot(container);
  31. act(() => {
  32. root.render(node);
  33. });
  34. return {
  35. container,
  36. unmount: () => {
  37. act(() => {
  38. root.unmount();
  39. });
  40. container.remove();
  41. },
  42. };
  43. }
  44. async function flushTicks(times = 1) {
  45. for (let i = 0; i < times; i++) {
  46. await act(async () => {
  47. await new Promise((resolve) => setTimeout(resolve, 0));
  48. });
  49. }
  50. }
  51. function buildMessages() {
  52. return {
  53. settings: {
  54. providers: {
  55. form: {
  56. apiTest: apiTestMessages,
  57. providerTypes: providerTypesMessages,
  58. },
  59. },
  60. },
  61. };
  62. }
  63. describe("ApiTestButton", () => {
  64. beforeEach(() => {
  65. vi.clearAllMocks();
  66. getProviderTestPresetsMock.mockResolvedValue({
  67. ok: true,
  68. data: [
  69. {
  70. id: "cx_base",
  71. description: "legacy preset",
  72. defaultSuccessContains: "pong",
  73. defaultModel: "gpt-5.1-codex",
  74. },
  75. ],
  76. });
  77. });
  78. test("供应商检测 UI 不应再要求手动选择格式、模板、关键字或超时", async () => {
  79. const { unmount } = render(
  80. <NextIntlClientProvider locale="en" timeZone="UTC" messages={buildMessages()}>
  81. <ApiTestButton
  82. providerUrl="https://api.example.com"
  83. apiKey="sk-test"
  84. providerType="openai-compatible"
  85. enableMultiProviderTypes
  86. />
  87. </NextIntlClientProvider>
  88. );
  89. await flushTicks(2);
  90. const text = document.body.textContent || "";
  91. expect(getProviderTestPresetsMock).not.toHaveBeenCalled();
  92. expect(text).toContain(apiTestMessages.model);
  93. expect(text).not.toContain(apiTestMessages.apiFormat);
  94. expect(text).not.toContain(apiTestMessages.requestConfig);
  95. expect(text).not.toContain(apiTestMessages.successContains);
  96. expect(text).not.toContain(apiTestMessages.timeout.label);
  97. unmount();
  98. });
  99. });