UNPKG

chrome-devtools-frontend

Version:
192 lines (163 loc) • 7.34 kB
// Copyright 2025 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Persistence from '../../models/persistence/persistence.js'; import * as Workspace from '../../models/workspace/workspace.js'; import {createTestFilesystem, setupAutomaticFileSystem} from '../../testing/AiAssistanceHelpers.js'; import {assertScreenshot, renderElementIntoDOM, setColorScheme} from '../../testing/DOMHelpers.js'; import {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js'; import {createViewFunctionStub, type ViewFunctionStub} from '../../testing/ViewFunctionHelpers.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as AiAssistance from './ai_assistance.js'; describeWithEnvironment('SelectWorkspaceDialog', () => { const root = '/path/to/my-automatic-file-system'; beforeEach(() => { setupAutomaticFileSystem(); }); afterEach(() => { const workspace = Workspace.Workspace.WorkspaceImpl.instance(); for (const project of workspace.projects()) { workspace.removeProject(project); } Persistence.AutomaticFileSystemManager.AutomaticFileSystemManager.removeInstance(); }); async function createComponent(): Promise<{ view: ViewFunctionStub<typeof AiAssistance.SelectWorkspaceDialog>, component: AiAssistance.SelectWorkspaceDialog, onProjectSelected: sinon.SinonSpy<[Workspace.Workspace.Project], void>, hideDialogSpy: sinon.SinonSpy<[], void>, project: Persistence.FileSystemWorkspaceBinding.FileSystem, }> { createTestFilesystem('file://test1'); const {project} = createTestFilesystem('file://test2'); const dialog = new UI.Dialog.Dialog('select-workspace'); const hideDialogSpy = sinon.spy(dialog, 'hide'); const view = createViewFunctionStub(AiAssistance.SelectWorkspaceDialog); const onProjectSelected = sinon.spy() as sinon.SinonSpy<[Workspace.Workspace.Project], void>; const component = new AiAssistance.SelectWorkspaceDialog({dialog, onProjectSelected}, view); component.markAsRoot(); const container = document.createElement('div'); renderElementIntoDOM(container); component.show(container); await view.nextInput; sinon.assert.callCount(view, 1); assert.strictEqual(view.input.selectedIndex, 0); return {view, component, onProjectSelected, hideDialogSpy, project}; } describe('screenshots', () => { function renderViewForScreenshots() { const noop = () => {}; const target = document.createElement('div'); target.style.maxWidth = '420px'; target.style.maxHeight = '600px'; target.style.padding = '12px'; renderElementIntoDOM(target); AiAssistance.SELECT_WORKSPACE_DIALOG_DEFAULT_VIEW( { folders: [ { name: 'workspace-project', path: 'workspace-project', }, { name: 'another-project', path: 'another-project', } ], selectedIndex: 0, showAutomaticWorkspaceNudge: false, onProjectSelected: noop, onSelectButtonClick: noop, onCancelButtonClick: noop, onAddFolderButtonClick: noop, onListItemKeyDown: noop, }, undefined, target); } it('should render correctly in light mode', async () => { renderViewForScreenshots(); await assertScreenshot('ai_assistance/select-workspace-dialog-light-default.png'); }); it('should render correctly in dark mode', async () => { setColorScheme('dark'); renderViewForScreenshots(); await assertScreenshot('ai_assistance/select-workspace-dialog-dark-default.png'); }); }); it('selects a project', async () => { const {view, onProjectSelected, hideDialogSpy, project} = await createComponent(); view.input.onProjectSelected(1); const input = await view.nextInput; sinon.assert.callCount(view, 2); assert.strictEqual(input.selectedIndex, 1); view.input.onSelectButtonClick(); assert.isTrue(onProjectSelected.calledOnceWith(project)); sinon.assert.calledOnce(hideDialogSpy); }); it('can be canceled', async () => { const {view, onProjectSelected, hideDialogSpy} = await createComponent(); view.input.onProjectSelected(1); const input = await view.nextInput; sinon.assert.callCount(view, 2); assert.strictEqual(input.selectedIndex, 1); view.input.onCancelButtonClick(); sinon.assert.notCalled(onProjectSelected); sinon.assert.calledOnce(hideDialogSpy); }); it('listens to ArrowUp/Down', async () => { const {view} = await createComponent(); view.input.onListItemKeyDown(new KeyboardEvent('keydown', {key: 'ArrowDown'})); let input = await view.nextInput; sinon.assert.callCount(view, 2); assert.strictEqual(input.selectedIndex, 1); view.input.onListItemKeyDown(new KeyboardEvent('keydown', {key: 'ArrowUp'})); input = await view.nextInput; sinon.assert.callCount(view, 3); assert.strictEqual(input.selectedIndex, 0); }); it('can add projects', async () => { const addProjectSpy = sinon.spy(Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager.instance(), 'addFileSystem'); const {view} = await createComponent(); sinon.assert.callCount(view, 1); assert.lengthOf(view.input.folders, 2); assert.strictEqual(view.input.selectedIndex, 0); view.input.onAddFolderButtonClick(); sinon.assert.calledOnce(addProjectSpy); createTestFilesystem('file://test3'); const input = await view.nextInput; sinon.assert.callCount(view, 2); assert.lengthOf(input.folders, 3); assert.strictEqual(input.folders[2].name, 'test3'); assert.strictEqual(input.selectedIndex, 2); }); it('handles project removal', async () => { const addProjectSpy = sinon.spy(Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager.instance(), 'addFileSystem'); const {view, project} = await createComponent(); view.input.onProjectSelected(1); let input = await view.nextInput; sinon.assert.callCount(view, 2); assert.lengthOf(input.folders, 2); assert.strictEqual(input.selectedIndex, 1); input.onAddFolderButtonClick(); sinon.assert.calledOnce(addProjectSpy); Workspace.Workspace.WorkspaceImpl.instance().removeProject(project); input = await view.nextInput; assert.lengthOf(input.folders, 1); assert.strictEqual(input.selectedIndex, 0); }); it('allows selecting an automatic workspace', async () => { setupAutomaticFileSystem({hasFileSystem: true}); const {view, onProjectSelected, hideDialogSpy} = await createComponent(); sinon.assert.callCount(view, 1); assert.lengthOf(view.input.folders, 3); assert.strictEqual(view.input.selectedIndex, 0); assert.strictEqual(view.input.folders[0].name, 'my-automatic-file-system'); view.input.onSelectButtonClick(); await new Promise(resolve => setTimeout(resolve, 0)); const {project: automaticFileSystemProject} = createTestFilesystem(`file://${root}`); assert.isTrue(onProjectSelected.calledOnceWith(automaticFileSystemProject)); sinon.assert.calledOnce(hideDialogSpy); }); });