74 lines
2.8 KiB
TypeScript
74 lines
2.8 KiB
TypeScript
// @vitest-environment jsdom
|
|
// SPEC: PJ2026-010405 云端控制台.
|
|
// Implementation reference: draft-2026-07-13-p0-cloud-console.
|
|
// Responsibility: 验证 OpenCode frame URL 换票完成后仍等待 iframe load,并提供失败、超时与重试状态。
|
|
|
|
import { flushPromises, mount } from "@vue/test-utils";
|
|
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
import OpenCodeFrameView from "./OpenCodeFrameView.vue";
|
|
|
|
vi.mock("@/config/runtime", () => ({
|
|
opencodeFrameUrl: () => "https://opencode.example.test"
|
|
}));
|
|
|
|
function successfulFrameUrlResponse(): Response {
|
|
return new Response(JSON.stringify({ url: "/opencode/proxy/?ticket=redacted" }), {
|
|
status: 200,
|
|
headers: { "content-type": "application/json" }
|
|
});
|
|
}
|
|
|
|
describe("OpenCodeFrameView", () => {
|
|
beforeEach(() => {
|
|
vi.stubGlobal("fetch", vi.fn(async () => successfulFrameUrlResponse()));
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
test("waits for iframe load before reporting ready", async () => {
|
|
const wrapper = mount(OpenCodeFrameView);
|
|
await flushPromises();
|
|
|
|
expect(wrapper.get('[data-testid="opencode-load-state"]').text()).toBe("loading");
|
|
expect(wrapper.get("iframe").attributes("src")).toBe("/opencode/proxy/?ticket=redacted");
|
|
expect(wrapper.get("[role='status']").text()).toContain("OpenCode 加载中");
|
|
|
|
await wrapper.get("iframe").trigger("load");
|
|
expect(wrapper.get('[data-testid="opencode-load-state"]').text()).toBe("ready");
|
|
expect(wrapper.find("[role='status']").exists()).toBe(false);
|
|
wrapper.unmount();
|
|
});
|
|
|
|
test("shows a retry after iframe error and starts a fresh bounded load", async () => {
|
|
const wrapper = mount(OpenCodeFrameView);
|
|
await flushPromises();
|
|
|
|
await wrapper.get("iframe").trigger("error");
|
|
expect(wrapper.get('[data-testid="opencode-load-state"]').text()).toBe("error");
|
|
expect(wrapper.get("[role='status']").text()).toContain("iframe 加载失败");
|
|
expect(wrapper.find("iframe").exists()).toBe(false);
|
|
|
|
await wrapper.get("button").trigger("click");
|
|
await flushPromises();
|
|
expect(fetch).toHaveBeenCalledTimes(2);
|
|
expect(wrapper.get('[data-testid="opencode-load-state"]').text()).toBe("loading");
|
|
expect(wrapper.find("iframe").exists()).toBe(true);
|
|
wrapper.unmount();
|
|
});
|
|
|
|
test("fails a frame that does not load within the bounded timeout", async () => {
|
|
vi.useFakeTimers();
|
|
const wrapper = mount(OpenCodeFrameView);
|
|
await flushPromises();
|
|
|
|
await vi.advanceTimersByTimeAsync(15_000);
|
|
expect(wrapper.get('[data-testid="opencode-load-state"]').text()).toBe("error");
|
|
expect(wrapper.get("[role='status']").text()).toContain("iframe 加载超时");
|
|
expect(wrapper.find("iframe").exists()).toBe(false);
|
|
wrapper.unmount();
|
|
});
|
|
});
|