testing: be more consistent about focus actions, add context menu to reveal
Fixes #119649
This commit is contained in:
parent
3aff04dcae
commit
ca43526452
2 changed files with 70 additions and 37 deletions
|
@ -9,10 +9,13 @@ import { Codicon } from 'vs/base/common/codicons';
|
|||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { isDefined } from 'vs/base/common/types';
|
||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyFalseExpr, ContextKeyTrueExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
@ -23,10 +26,13 @@ import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol
|
|||
import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane';
|
||||
import { FocusedViewContext } from 'vs/workbench/common/views';
|
||||
import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { REVEAL_IN_EXPLORER_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands';
|
||||
import * as icons from 'vs/workbench/contrib/testing/browser/icons';
|
||||
import { ITestExplorerFilterState } from 'vs/workbench/contrib/testing/browser/testingExplorerFilter';
|
||||
import { TestingExplorerView, TestingExplorerViewModel } from 'vs/workbench/contrib/testing/browser/testingExplorerView';
|
||||
import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browser/testingOutputPeek';
|
||||
import { TestExplorerViewMode, TestExplorerViewSorting, Testing } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { InternalTestItem, TestIdPath, TestIdWithSrc, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTestItem, ITestItem, TestIdPath, TestIdWithSrc, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestingAutoRun } from 'vs/workbench/contrib/testing/common/testingAutoRun';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { isFailedState } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
|
@ -500,8 +506,11 @@ export class EditFocusedTest extends ViewAction<TestingExplorerView> {
|
|||
super({
|
||||
id: 'testing.editFocusedTest',
|
||||
viewId: Testing.ExplorerViewId,
|
||||
title: localize('testing.editFocusedTest', "Open Focused Test in Editor"),
|
||||
title: localize('testing.editFocusedTest', "Go to Test"),
|
||||
f1: false,
|
||||
menu: {
|
||||
id: MenuId.TestItem,
|
||||
},
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.EditorContrib - 10,
|
||||
when: FocusedViewContext.isEqualTo(Testing.ExplorerViewId),
|
||||
|
@ -510,13 +519,60 @@ export class EditFocusedTest extends ViewAction<TestingExplorerView> {
|
|||
});
|
||||
}
|
||||
|
||||
public async run(accessor: ServicesAccessor, test?: ITestItem, preserveFocus?: boolean) {
|
||||
if (test) {
|
||||
await this.runForTest(accessor, test, preserveFocus);
|
||||
} else {
|
||||
await super.run(accessor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public runInView(_accessor: ServicesAccessor, view: TestingExplorerView) {
|
||||
public runInView(accessor: ServicesAccessor, view: TestingExplorerView) {
|
||||
const selected = view.viewModel.tree.getFocus().find(isDefined);
|
||||
if (selected) {
|
||||
view.viewModel.openEditorForItem(selected, false);
|
||||
if (selected?.test) {
|
||||
this.runForTest(accessor, selected.test.item, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
private async runForTest(accessor: ServicesAccessor, test: ITestItem, preserveFocus = true) {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const fileService = accessor.get(IFileService);
|
||||
const editorService = accessor.get(IEditorService);
|
||||
|
||||
accessor.get(ITestExplorerFilterState).reveal.value = [test.extId];
|
||||
|
||||
let isFile = true;
|
||||
try {
|
||||
if (!(await fileService.resolve(test.uri)).isFile) {
|
||||
isFile = false;
|
||||
}
|
||||
} catch {
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (!isFile) {
|
||||
await commandService.executeCommand(REVEAL_IN_EXPLORER_COMMAND_ID, test.uri);
|
||||
return;
|
||||
}
|
||||
|
||||
const pane = await editorService.openEditor({
|
||||
resource: test.uri,
|
||||
options: {
|
||||
selection: test.range && { startColumn: test.range.startColumn, startLineNumber: test.range.startLineNumber },
|
||||
preserveFocus,
|
||||
},
|
||||
});
|
||||
|
||||
// if the user selected a failed test and now they didn't, hide the peek
|
||||
const control = pane?.getControl();
|
||||
if (isCodeEditor(control)) {
|
||||
TestingOutputPeekController.get(control).removePeek();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import { Disposable, dispose, IDisposable, MutableDisposable } from 'vs/base/com
|
|||
import { isDefined } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import 'vs/css!./media/testing';
|
||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { localize } from 'vs/nls';
|
||||
import { createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
|
@ -52,7 +51,7 @@ import { HierarchicalByLocationProjection } from 'vs/workbench/contrib/testing/b
|
|||
import { HierarchicalByNameProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName';
|
||||
import { testingHiddenIcon, testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons';
|
||||
import { ITestExplorerFilterState, TestExplorerFilterState, TestingExplorerFilter } from 'vs/workbench/contrib/testing/browser/testingExplorerFilter';
|
||||
import { ITestingPeekOpener, TestingOutputPeekController } from 'vs/workbench/contrib/testing/browser/testingOutputPeek';
|
||||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/browser/testingOutputPeek';
|
||||
import { ITestingProgressUiService } from 'vs/workbench/contrib/testing/browser/testingProgressUiService';
|
||||
import { TestExplorerStateFilter, TestExplorerViewMode, TestExplorerViewSorting, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { TestIdPath, TestItemExpandState } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
|
@ -62,7 +61,7 @@ import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResu
|
|||
import { ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
import { IWorkspaceTestCollectionService, TestSubscriptionListener } from 'vs/workbench/contrib/testing/common/workspaceTestCollectionService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { DebugAction, HideOrShowTestAction, RunAction } from './testExplorerActions';
|
||||
import { DebugAction, EditFocusedTest, HideOrShowTestAction, RunAction } from './testExplorerActions';
|
||||
|
||||
export class TestingExplorerView extends ViewPane {
|
||||
public viewModel!: TestingExplorerViewModel;
|
||||
|
@ -278,7 +277,7 @@ export class TestingExplorerViewModel extends Disposable {
|
|||
@ITestService private readonly testService: ITestService,
|
||||
@ITestExplorerFilterState private readonly filterState: TestExplorerFilterState,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@ITestResultService private readonly testResults: ITestResultService,
|
||||
|
@ -368,10 +367,12 @@ export class TestingExplorerViewModel extends Disposable {
|
|||
this.updatePreferredProjection();
|
||||
|
||||
this.onDidChangeSelection = this.tree.onDidChangeSelection;
|
||||
this._register(this.tree.onDidChangeSelection(evt => {
|
||||
this._register(this.tree.onDidChangeSelection(async evt => {
|
||||
const selected = evt.elements[0];
|
||||
if (selected && evt.browserEvent && !selected.children.size) {
|
||||
this.openEditorForItem(selected);
|
||||
if (selected && evt.browserEvent && selected.expandable === TestItemExpandState.NotExpandable) {
|
||||
if (!(await this.tryPeekError(selected)) && selected?.test) {
|
||||
this.instantiationService.invokeFunction(accessor => new EditFocusedTest().run(accessor, selected.test!.item, true));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -469,30 +470,6 @@ export class TestingExplorerViewModel extends Disposable {
|
|||
this.tree.collapseAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an editor for the item. If there is a failure associated with the
|
||||
* test item, it will be shown.
|
||||
*/
|
||||
public async openEditorForItem(item: ITestTreeElement, preserveFocus = true) {
|
||||
if (await this.tryPeekError(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pane = await this.editorService.openEditor({
|
||||
resource: item.uri,
|
||||
options: {
|
||||
selection: item.range && { startColumn: item.range.startColumn, startLineNumber: item.range.startLineNumber },
|
||||
preserveFocus,
|
||||
},
|
||||
});
|
||||
|
||||
// if the user selected a failed test and now they didn't, hide the peek
|
||||
const control = pane?.getControl();
|
||||
if (isCodeEditor(control)) {
|
||||
TestingOutputPeekController.get(control).removePeek();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to peek the first test error, if the item is in a failed state.
|
||||
*/
|
||||
|
@ -908,7 +885,7 @@ const getTestItemActions = (
|
|||
|
||||
const result = { primary, secondary };
|
||||
const actionsDisposable = createAndFillInActionBarActions(menu, {
|
||||
arg: element.test?.item.extId,
|
||||
arg: element.test?.item,
|
||||
shouldForwardArgs: true,
|
||||
}, result, 'inline');
|
||||
|
||||
|
|
Loading…
Reference in a new issue