fix: close and recreate macOS windows safely

This commit is contained in:
鲨鱼辣椒 committed 2026-09-29 19:50:25 +08:00
1 parent f443f3bc66
commit b5e6c663ef
19 files changed
+1079 -172

No files matched your search

+61
View File
@@ -1742,6 +1742,67 @@ describe('AgentBrowserModule', () => {
expect(adapter.resetPartitions).toEqual([agentBrowserPartition(projectPath)]);
});
it.each(['close', 'replace-preview', 'switch-project'] as const)(
'waits for old preview cleanup and cancels stale opens when reopening after %s',
async (scenario) => {
const adapter = new FakeAdapter();
const preview = new FakePreviewDataSession();
adapter.onCreate = (view) => {
view.webContents.debugger.responders.set('Page.addScriptToEvaluateOnNewDocument', async () => ({
identifier: 'script-root',
}));
};
const module = new AgentBrowserModule(adapter, { previewDataSession: preview });
await module.open({
projectId: 'clock', projectPath, url: 'http://127.0.0.1:4173/', injectProjectData: true,
});
let finishCleanup!: () => void;
const cleanup = new Promise<void>((resolve) => { finishCleanup = resolve; });
const cleanupStarted = vi.fn(async () => await cleanup);
adapter.views[0].webContents.debugger.responders.set(
'Page.removeScriptToEvaluateOnNewDocument', cleanupStarted,
);
const superseded = scenario === 'close' ? undefined : module.open({
projectId: 'clock',
projectPath: scenario === 'switch-project' ? `${projectPath}-other` : projectPath,
url: 'http://localhost:3001/',
});
const supersededResult = superseded?.catch((error: unknown) => error);
if (superseded) await vi.waitFor(() => expect(cleanupStarted).toHaveBeenCalledOnce());
const closing = module.close();
await vi.waitFor(() => expect(cleanupStarted).toHaveBeenCalledOnce());
const reopening = module.open({
projectId: 'clock', projectPath, url: 'http://localhost:3002/',
});
await Promise.resolve();
expect(adapter.views).toHaveLength(1);
finishCleanup();
await expect(closing).resolves.toMatchObject({ state: 'closed' });
if (supersededResult) await expect(supersededResult).resolves.toMatchObject({ code: 'CLOSED' });
await expect(reopening).resolves.toMatchObject({
state: 'attached', generation: 2, url: 'http://localhost:3002/',
});
expect(adapter.views).toHaveLength(2);
expect(adapter.destroyed).toBe(1);
expect(adapter.views[1].webContents.destroyed).toBe(false);
},
);
it('cleans up a new view if its host window has already closed', async () => {
const adapter = new FakeAdapter();
vi.spyOn(adapter, 'mount').mockImplementation(() => { throw new Error('window-closed'); });
const module = new AgentBrowserModule(adapter);
await expect(module.open({
projectId: 'clock', projectPath, url: 'http://localhost:3001/',
})).rejects.toThrow('window-closed');
expect(adapter.destroyed).toBe(1);
expect(adapter.views[0].webContents.destroyed).toBe(true);
await expect(module.getSnapshot()).resolves.toMatchObject({ state: 'closed' });
});
it('does not reopen a project partition until profile reset has finished', async () => {
const adapter = new FakeAdapter();
let finishReset: (() => void) | undefined;