Files
azuredatastudio/test/automation/src/quickaccess.ts
Karl Burtram 8a3d08f0de Merge vscode 1.67 (#20883)
* Fix initial build breaks from 1.67 merge (#2514)

* Update yarn lock files

* Update build scripts

* Fix tsconfig

* Build breaks

* WIP

* Update yarn lock files

* Misc breaks

* Updates to package.json

* Breaks

* Update yarn

* Fix breaks

* Breaks

* Build breaks

* Breaks

* Breaks

* Breaks

* Breaks

* Breaks

* Missing file

* Breaks

* Breaks

* Breaks

* Breaks

* Breaks

* Fix several runtime breaks (#2515)

* Missing files

* Runtime breaks

* Fix proxy ordering issue

* Remove commented code

* Fix breaks with opening query editor

* Fix post merge break

* Updates related to setup build and other breaks (#2516)

* Fix bundle build issues

* Update distro

* Fix distro merge and update build JS files

* Disable pipeline steps

* Remove stats call

* Update license name

* Make new RPM dependencies a warning

* Fix extension manager version checks

* Update JS file

* Fix a few runtime breaks

* Fixes

* Fix runtime issues

* Fix build breaks

* Update notebook tests (part 1)

* Fix broken tests

* Linting errors

* Fix hygiene

* Disable lint rules

* Bump distro

* Turn off smoke tests

* Disable integration tests

* Remove failing "activate" test

* Remove failed test assertion

* Disable other broken test

* Disable query history tests

* Disable extension unit tests

* Disable failing tasks
2022-10-19 19:13:18 -07:00

207 lines
6.2 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Editors } from './editors';
import { Code } from './code';
import { QuickInput } from './quickinput';
import { basename, isAbsolute } from 'path';
enum QuickAccessKind {
Files = 1,
Commands,
Symbols
}
export class QuickAccess {
constructor(private code: Code, private editors: Editors, private quickInput: QuickInput) { }
async openFileQuickAccessAndWait(searchValue: string, expectedFirstElementNameOrExpectedResultCount: string | number): Promise<void> {
// make sure the file quick access is not "polluted"
// with entries from the editor history when opening
await this.runCommand('workbench.action.clearEditorHistory');
const PollingStrategy = {
Stop: true,
Continue: false
};
let retries = 0;
let success = false;
while (++retries < 10) {
let retry = false;
try {
await this.openQuickAccessWithRetry(QuickAccessKind.Files, searchValue);
await this.quickInput.waitForQuickInputElements(elementNames => {
this.code.logger.log('QuickAccess: resulting elements: ', elementNames);
// Quick access seems to be still running -> retry
if (elementNames.length === 0) {
this.code.logger.log('QuickAccess: file search returned 0 elements, will continue polling...');
return PollingStrategy.Continue;
}
// Quick access does not seem healthy/ready -> retry
const firstElementName = elementNames[0];
if (firstElementName === 'No matching results') {
this.code.logger.log(`QuickAccess: file search returned "No matching results", will retry...`);
retry = true;
return PollingStrategy.Stop;
}
// Expected: number of results
if (typeof expectedFirstElementNameOrExpectedResultCount === 'number') {
if (elementNames.length === expectedFirstElementNameOrExpectedResultCount) {
success = true;
return PollingStrategy.Stop;
}
this.code.logger.log(`QuickAccess: file search returned ${elementNames.length} results but was expecting ${expectedFirstElementNameOrExpectedResultCount}, will retry...`);
retry = true;
return PollingStrategy.Stop;
}
// Expected: string
else {
if (firstElementName === expectedFirstElementNameOrExpectedResultCount) {
success = true;
return PollingStrategy.Stop;
}
this.code.logger.log(`QuickAccess: file search returned ${firstElementName} as first result but was expecting ${expectedFirstElementNameOrExpectedResultCount}, will retry...`);
retry = true;
return PollingStrategy.Stop;
}
});
} catch (error) {
this.code.logger.log(`QuickAccess: file search waitForQuickInputElements threw an error ${error}, will retry...`);
retry = true;
}
if (!retry) {
break;
}
await this.quickInput.closeQuickInput();
}
if (!success) {
if (typeof expectedFirstElementNameOrExpectedResultCount === 'string') {
throw new Error(`Quick open file search was unable to find '${expectedFirstElementNameOrExpectedResultCount}' after 10 attempts, giving up.`);
} else {
throw new Error(`Quick open file search was unable to find ${expectedFirstElementNameOrExpectedResultCount} result items after 10 attempts, giving up.`);
}
}
}
async openFile(path: string): Promise<void> {
if (!isAbsolute(path)) {
// we require absolute paths to get a single
// result back that is unique and avoid hitting
// the search process to reduce chances of
// search needing longer.
throw new Error('QuickAccess.openFile requires an absolute path');
}
const fileName = basename(path);
// quick access shows files with the basename of the path
await this.openFileQuickAccessAndWait(path, basename(path));
// open first element
await this.quickInput.selectQuickInputElement(0);
// wait for editor being focused
await this.editors.waitForActiveTab(fileName);
await this.editors.selectTab(fileName);
}
private async openQuickAccessWithRetry(kind: QuickAccessKind, value?: string): Promise<void> {
let retries = 0;
// Other parts of code might steal focus away from quickinput :(
while (retries < 5) {
// Open via keybinding
switch (kind) {
case QuickAccessKind.Files:
await this.code.dispatchKeybinding(process.platform === 'darwin' ? 'cmd+p' : 'ctrl+p');
break;
case QuickAccessKind.Symbols:
await this.code.dispatchKeybinding(process.platform === 'darwin' ? 'cmd+shift+o' : 'ctrl+shift+o');
break;
case QuickAccessKind.Commands:
await this.code.dispatchKeybinding(process.platform === 'darwin' ? 'cmd+shift+p' : 'ctrl+shift+p');
break;
}
// Await for quick input widget opened
try {
await this.quickInput.waitForQuickInputOpened(10);
break;
} catch (err) {
if (++retries > 5) {
throw new Error(`QuickAccess.openQuickAccessWithRetry(kind: ${kind}) failed: ${err}`);
}
// Retry
await this.code.dispatchKeybinding('escape');
}
}
// Type value if any
if (value) {
await this.quickInput.type(value);
}
}
async runCommand(commandId: string, keepOpen?: boolean): Promise<void> {
// open commands picker
await this.openQuickAccessWithRetry(QuickAccessKind.Commands, `>${commandId}`);
// wait for best choice to be focused
await this.quickInput.waitForQuickInputElementFocused();
// wait and click on best choice
await this.quickInput.selectQuickInputElement(0, keepOpen);
}
async openQuickOutline(): Promise<void> {
let retries = 0;
while (++retries < 10) {
// open quick outline via keybinding
await this.openQuickAccessWithRetry(QuickAccessKind.Symbols);
const text = await this.quickInput.waitForQuickInputElementText();
// Retry for as long as no symbols are found
if (text === 'No symbol information for the file') {
this.code.logger.log(`QuickAccess: openQuickOutline indicated 'No symbol information for the file', will retry...`);
// close and retry
await this.quickInput.closeQuickInput();
continue;
}
}
}
}