From 58e88ff3ac0ef44caa56cacf823fbf12ca0eed0e Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 25 Jan 2021 12:56:27 -0800 Subject: [PATCH] testing: accessibility in explorer round 1 For https://github.com/microsoft/vscode/issues/114653 --- .../testing/browser/testExplorerActions.ts | 31 +++++++++++++++++++ .../testing/browser/testing.contribution.ts | 1 + .../testing/browser/testingExplorerView.ts | 22 +++++++------ 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts index bb5cb0a976d..84fd066308b 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -6,10 +6,13 @@ import { Action } from 'vs/base/common/actions'; import { Codicon } from 'vs/base/common/codicons'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { isDefined } from 'vs/base/common/types'; import { localize } from 'vs/nls'; import { Action2, MenuId } from 'vs/platform/actions/common/actions'; import { ContextKeyAndExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -17,6 +20,7 @@ import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { ShowViewletAction2 } from 'vs/workbench/browser/viewlet'; import { CATEGORIES } from 'vs/workbench/common/actions'; +import { FocusedViewContext } from 'vs/workbench/common/views'; import * as icons from 'vs/workbench/contrib/testing/browser/icons'; import { TestingExplorerView, TestingExplorerViewModel } from 'vs/workbench/contrib/testing/browser/testingExplorerView'; import { TestExplorerViewGrouping, TestExplorerViewMode, Testing } from 'vs/workbench/contrib/testing/common/constants'; @@ -440,3 +444,30 @@ export class ShowTestView extends ShowViewletAction2 { return Testing.ViewletId; } } + + +export class EditFocusedTest extends ViewAction { + constructor() { + super({ + id: 'testing.editFocusedTest', + viewId: Testing.ExplorerViewId, + title: localize('testing.editFocusedTest', "Open Focused Test in Editor"), + f1: false, + keybinding: { + weight: KeybindingWeight.EditorContrib - 10, + when: FocusedViewContext.isEqualTo(Testing.ExplorerViewId), + primary: KeyCode.Enter | KeyMod.Alt, + }, + }); + } + + /** + * @override + */ + public runInView(_accessor: ServicesAccessor, view: TestingExplorerView) { + const selected = view.viewModel.tree.getFocus().find(isDefined); + if (selected) { + view.viewModel.openEditorForItem(selected, false); + } + } +} diff --git a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts index 2a81ba3e41d..8c87e0e3351 100644 --- a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts +++ b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts @@ -94,6 +94,7 @@ registerAction2(Action.ShowTestView); registerAction2(Action.CollapseAllAction); registerAction2(Action.RunAllAction); registerAction2(Action.DebugAllAction); +registerAction2(Action.EditFocusedTest); Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(TestingContentProvider, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index be3344549aa..06be5f0434c 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -10,6 +10,7 @@ import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; import { ITreeEvent, ITreeFilter, ITreeNode, ITreeRenderer, ITreeSorter, TreeFilterResult, TreeVisibility } from 'vs/base/browser/ui/tree/tree'; +import * as aria from 'vs/base/browser/ui/aria/aria'; import { Action, IAction, IActionViewItem } from 'vs/base/common/actions'; import { DeferredPromise } from 'vs/base/common/async'; import { Color, RGBA } from 'vs/base/common/color'; @@ -51,9 +52,9 @@ import { StateByLocationProjection } from 'vs/workbench/contrib/testing/browser/ import { StateByNameProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateByName'; import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; import { testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons'; -import { ITestExplorerFilterState, TestingExplorerFilter, TestExplorerFilterState } from 'vs/workbench/contrib/testing/browser/testingExplorerFilter'; +import { ITestExplorerFilterState, TestExplorerFilterState, TestingExplorerFilter } from 'vs/workbench/contrib/testing/browser/testingExplorerFilter'; import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browser/testingOutputPeek'; -import { TestExplorerViewGrouping, TestExplorerViewMode, Testing } from 'vs/workbench/contrib/testing/common/constants'; +import { TestExplorerViewGrouping, TestExplorerViewMode, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { cmpPriority, isFailedState } from 'vs/workbench/contrib/testing/common/testingStates'; import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri'; @@ -343,7 +344,7 @@ export class TestingExplorerViewModel extends Disposable { * Opens an editor for the item. If there is a failure associated with the * test item, it will be shown. */ - private async openEditorForItem(item: ITestTreeElement) { + public async openEditorForItem(item: ITestTreeElement, preserveFocus = true) { if (await this.tryPeekError(item)) { return; } @@ -355,7 +356,7 @@ export class TestingExplorerViewModel extends Disposable { const pane = await this.editorService.openEditor({ resource: location.uri, - options: { selection: location.range, preserveFocus: true } + options: { selection: location.range, preserveFocus }, }); // if the user selected a failed test and now they didn't, hide the peek @@ -573,15 +574,14 @@ class ListAccessibilityProvider implements IListAccessibilityProvider { - getCompressedNodeKeyboardNavigationLabel(elements: ITestTreeElement[]) { - return this.getKeyboardNavigationLabel(elements[elements.length - 1]); - } - getKeyboardNavigationLabel(element: ITestTreeElement) { return element.label; } @@ -791,7 +791,9 @@ class TestRunProgress { } else { const collected = collectCounts(lastCount); this.messagesContainer.dataset.state = collected.failed ? 'failed' : 'running'; - this.messagesContainer.innerText = getProgressText(collected); + const doneMessage = getProgressText(collected); + this.messagesContainer.innerText = doneMessage; + aria.alert(doneMessage); } }