/** @vitest-environment jsdom */ import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { createGameCreationAppManifest } from '../../../packages/shared/src/contracts/gameCreationApp'; import ProjectDevelopmentView from '../src/view/project-development'; const openUrl = vi.fn(async () => undefined); vi.mock('@tauri-apps/plugin-opener', () => ({ openUrl: (url: string) => openUrl(url), })); const PREVIEW_URL = 'http://127.0.0.1:4173/'; function installInvoke() { window.__TAURI__ = { core: { invoke: vi.fn(async (command: string, args?: Record) => { if (command === 'read_local_project_resource_graph') { return { resourceIds: [], referenceEdges: [], taskFlows: [], categories: [], diagnostics: [], }; } if (command === 'read_local_project_resource_canvas_layout') { return { schemaVersion: 'game-creator-resource-layout.v1', projectId: args?.expectedProjectId, mode: args?.mode, revision: 0, positions: [], updatedAt: 0, }; } throw new Error(`unexpected invoke ${command}`); }), }, } as unknown as typeof window.__TAURI__; } function renderRunView(options: { withPreview?: boolean } = {}) { installInvoke(); const manifest = createGameCreationAppManifest( 'run-preview-browser-open', '运行页浏览器入口', ); const onNotice = vi.fn(); render( 项目总控} onHomeOpen={vi.fn()} onProjectsOpen={vi.fn()} onNotice={onNotice} />, ); return { onNotice }; } afterEach(() => { document.body.innerHTML = ''; vi.clearAllMocks(); vi.restoreAllMocks(); }); describe('运行页「在浏览器打开」', () => { it('点顶栏那枚按钮就把当前预览地址交给系统浏览器', async () => { renderRunView(); const entry = await screen.findByRole('button', { name: '在浏览器打开', }); // 入口住在工作台顶栏的动作区里,与版本入口同一排;预览地址本身不再以文字出现。 expect(entry.closest('.game-workbench-view-actions')).not.toBeNull(); expect(document.body.textContent ?? '').not.toContain(PREVIEW_URL); expect(document.querySelector('.game-run-status-hint')).toBeNull(); fireEvent.click(entry); await waitFor(() => expect(openUrl).toHaveBeenCalledWith(PREVIEW_URL)); // 成功不弹提示:浏览器真的起来了,用户自己看得见。 expect(openUrl).toHaveBeenCalledTimes(1); }); it('没有活预览时不渲染这枚入口', async () => { renderRunView({ withPreview: false }); await screen.findByRole('tab', { name: '运行' }); expect(screen.queryByRole('button', { name: '在浏览器打开' })).toBeNull(); }); it('打开失败时把原因交给统一提示通道,而不是静默吞掉', async () => { openUrl.mockRejectedValueOnce(new Error('permission denied')); const { onNotice } = renderRunView(); fireEvent.click( await screen.findByRole('button', { name: '在浏览器打开' }), ); await waitFor(() => expect(onNotice).toHaveBeenCalledWith({ tone: 'error', message: '在浏览器打开失败:permission denied', }), ); }); });