mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
VS Code merge to df8fe74bd55313de0dd2303bc47a4aab0ca56b0e (#17979)
* Merge from vscode 504f934659740e9d41501cad9f162b54d7745ad9 * delete unused folders * distro * Bump build node version * update chokidar * FIx hygiene errors * distro * Fix extension lint issues * Remove strict-vscode * Add copyright header exemptions * Bump vscode-extension-telemetry to fix webpacking issue with zone.js * distro * Fix failing tests (revert marked.js back to current one until we decide to update) * Skip searchmodel test * Fix mac build * temp debug script loading * Try disabling coverage * log error too * Revert "log error too" This reverts commit af0183e5d4ab458fdf44b88fbfab9908d090526f. * Revert "temp debug script loading" This reverts commit 3d687d541c76db2c5b55626c78ae448d3c25089c. * Add comments explaining coverage disabling * Fix ansi_up loading issue * Merge latest from ads * Use newer option * Fix compile * add debug logging warn * Always log stack * log more * undo debug * Update to use correct base path (+cleanup) * distro * fix compile errors * Remove strict-vscode * Fix sql editors not showing * Show db dropdown input & fix styling * Fix more info in gallery * Fix gallery asset requests * Delete unused workflow * Fix tapable resolutions for smoke test compile error * Fix smoke compile * Disable crash reporting * Disable interactive Co-authored-by: ADS Merger <karlb@microsoft.com>
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
"npm-run-all": "^4.1.5",
|
||||
"tmp": "0.1.0",
|
||||
"tree-kill": "1.2.2",
|
||||
"typescript": "3.7.5",
|
||||
"typescript": "^4.3.2",
|
||||
"vscode-uri": "^2.0.3",
|
||||
"watch": "^1.0.2"
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export class Application {
|
||||
private _workbench: Workbench | undefined;
|
||||
|
||||
constructor(private options: ApplicationOptions) {
|
||||
this._userDataPath = options.userDataDir;
|
||||
this._workspacePathOrFolder = options.workspacePath;
|
||||
}
|
||||
|
||||
@@ -64,18 +65,14 @@ export class Application {
|
||||
return this.options.extensionsPath;
|
||||
}
|
||||
|
||||
private _userDataPath: string;
|
||||
get userDataPath(): string {
|
||||
return this.options.userDataDir;
|
||||
return this._userDataPath;
|
||||
}
|
||||
|
||||
async start(expectWalkthroughPart = true): Promise<any> {
|
||||
async start(): Promise<any> {
|
||||
await this._start();
|
||||
await this.code.waitForElement('.object-explorer-view'); // {{SQL CARBON EDIT}} We have a different startup view
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/118748
|
||||
// if (expectWalkthroughPart) {
|
||||
// await this.code.waitForElement(`.editor-instance > div > div.welcomePageFocusElement[tabIndex="0"]`);
|
||||
// }
|
||||
}
|
||||
|
||||
async restart(options: { workspaceOrFolder?: string, extraArgs?: string[] }): Promise<any> {
|
||||
@@ -121,17 +118,8 @@ export class Application {
|
||||
|
||||
private async startApplication(extraArgs: string[] = []): Promise<any> {
|
||||
this._code = await spawn({
|
||||
codePath: this.options.codePath,
|
||||
workspacePath: this.workspacePathOrFolder,
|
||||
userDataDir: this.options.userDataDir,
|
||||
extensionsPath: this.options.extensionsPath,
|
||||
logger: this.options.logger,
|
||||
verbose: this.options.verbose,
|
||||
log: this.options.log,
|
||||
extraArgs,
|
||||
remote: this.options.remote,
|
||||
web: this.options.web,
|
||||
browser: this.options.browser
|
||||
...this.options,
|
||||
extraArgs: [...(this.options.extraArgs || []), ...extraArgs],
|
||||
});
|
||||
|
||||
this._workbench = new Workbench(this._code, this.userDataPath);
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import { tmpName } from 'tmp';
|
||||
import { IDriver, connect as connectElectronDriver, IDisposable, IElement, Thenable } from './driver';
|
||||
import { IDriver, connect as connectElectronDriver, IDisposable, IElement, Thenable, ILocalizedStrings, ILocaleInfo } from './driver';
|
||||
import { connect as connectPlaywrightDriver, launch } from './playwrightDriver';
|
||||
import { Logger } from './logger';
|
||||
import { ncp } from 'ncp';
|
||||
@@ -97,11 +97,9 @@ export interface SpawnOptions {
|
||||
verbose?: boolean;
|
||||
extraArgs?: string[];
|
||||
log?: string;
|
||||
/** Run in the test resolver */
|
||||
remote?: boolean;
|
||||
/** Run in the web */
|
||||
web?: boolean;
|
||||
/** A specific browser to use (requires web: true) */
|
||||
headless?: boolean;
|
||||
browser?: 'chromium' | 'webkit' | 'firefox';
|
||||
}
|
||||
|
||||
@@ -123,18 +121,19 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
||||
copyExtension(options.extensionsPath, 'vscode-notebook-tests');
|
||||
|
||||
if (options.web) {
|
||||
await launch(options.userDataDir, options.workspacePath, options.codePath, options.extensionsPath);
|
||||
connectDriver = connectPlaywrightDriver.bind(connectPlaywrightDriver, options.browser);
|
||||
await launch(options.userDataDir, options.workspacePath, options.codePath, options.extensionsPath, Boolean(options.verbose));
|
||||
connectDriver = connectPlaywrightDriver.bind(connectPlaywrightDriver, options);
|
||||
return connect(connectDriver, child, '', handle, options.logger);
|
||||
}
|
||||
|
||||
const env = process.env;
|
||||
const env = { ...process.env };
|
||||
const codePath = options.codePath;
|
||||
const outPath = codePath ? getBuildOutPath(codePath) : getDevOutPath();
|
||||
|
||||
const args = [
|
||||
options.workspacePath,
|
||||
'--skip-release-notes',
|
||||
'--skip-welcome',
|
||||
'--disable-telemetry',
|
||||
'--no-cached-data',
|
||||
'--disable-updates',
|
||||
@@ -143,6 +142,7 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
||||
'--disable-workspace-trust',
|
||||
`--extensions-dir=${options.extensionsPath}`,
|
||||
`--user-data-dir=${options.userDataDir}`,
|
||||
`--logsPath=${path.join(repoPath, '.build', 'logs', 'smoke-tests')}`,
|
||||
'--driver', handle
|
||||
];
|
||||
|
||||
@@ -172,6 +172,7 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
||||
env['TESTRESOLVER_DATA_FOLDER'] = remoteDataDir;
|
||||
}
|
||||
|
||||
const spawnOptions: cp.SpawnOptions = { env };
|
||||
|
||||
args.push('--enable-proposed-api=vscode.vscode-notebook-tests');
|
||||
|
||||
@@ -181,6 +182,7 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
||||
|
||||
if (options.verbose) {
|
||||
args.push('--driver-verbose');
|
||||
spawnOptions.stdio = ['ignore', 'inherit', 'inherit'];
|
||||
}
|
||||
|
||||
if (options.log) {
|
||||
@@ -192,7 +194,6 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
||||
}
|
||||
|
||||
const electronPath = codePath ? getBuildElectronPath(codePath) : getDevElectronPath();
|
||||
const spawnOptions: cp.SpawnOptions = { env };
|
||||
child = cp.spawn(electronPath, args, spawnOptions);
|
||||
instances.add(child);
|
||||
child.once('exit', () => instances.delete(child!));
|
||||
@@ -235,7 +236,7 @@ async function poll<T>(
|
||||
} else {
|
||||
lastError = 'Did not pass accept function';
|
||||
}
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
lastError = Array.isArray(e.stack) ? e.stack.join(os.EOL) : e.stack;
|
||||
}
|
||||
|
||||
@@ -293,7 +294,10 @@ export class Code {
|
||||
}
|
||||
|
||||
async exit(): Promise<void> {
|
||||
await this.driver.exitApplication();
|
||||
const veto = await this.driver.exitApplication();
|
||||
if (veto === true) {
|
||||
throw new Error('Code exit was blocked by a veto.');
|
||||
}
|
||||
}
|
||||
|
||||
async waitForTextContent(selector: string, textContent?: string, accept?: (result: string) => boolean, retryCount?: number): Promise<string> {
|
||||
@@ -372,6 +376,16 @@ export class Code {
|
||||
await poll(() => this.driver.writeInTerminal(windowId, selector, value), () => true, `writeInTerminal '${selector}'`);
|
||||
}
|
||||
|
||||
async getLocaleInfo(): Promise<ILocaleInfo> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
return await this.driver.getLocaleInfo(windowId);
|
||||
}
|
||||
|
||||
async getLocalizedStrings(): Promise<ILocalizedStrings> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
return await this.driver.getLocalizedStrings(windowId);
|
||||
}
|
||||
|
||||
private async getActiveWindowId(): Promise<number> {
|
||||
if (typeof this._activeWindowId !== 'number') {
|
||||
const windows = await this.driver.getWindowIds();
|
||||
|
||||
@@ -23,6 +23,7 @@ export * from './settings';
|
||||
export * from './statusbar';
|
||||
export * from './terminal';
|
||||
export * from './viewlet';
|
||||
export * from './localization';
|
||||
export * from './workbench';
|
||||
export * from './driver';
|
||||
|
||||
|
||||
19
test/automation/src/localization.ts
Normal file
19
test/automation/src/localization.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Code } from './code';
|
||||
import { ILocalizedStrings, ILocaleInfo } from './driver';
|
||||
|
||||
export class Localization {
|
||||
constructor(private code: Code) { }
|
||||
|
||||
async getLocaleInfo(): Promise<ILocaleInfo> {
|
||||
return this.code.getLocaleInfo();
|
||||
}
|
||||
|
||||
async getLocalizedStrings(): Promise<ILocalizedStrings> {
|
||||
return this.code.getLocalizedStrings();
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ import * as kill from 'tree-kill';
|
||||
const width = 1200;
|
||||
const height = 800;
|
||||
|
||||
const root = join(__dirname, '..', '..', '..');
|
||||
const logsPath = join(root, '.build', 'logs', 'smoke-tests-browser');
|
||||
|
||||
const vscodeToPlaywrightKey: { [key: string]: string } = {
|
||||
cmd: 'Meta',
|
||||
ctrl: 'Control',
|
||||
@@ -29,7 +32,9 @@ const vscodeToPlaywrightKey: { [key: string]: string } = {
|
||||
esc: 'Escape'
|
||||
};
|
||||
|
||||
function buildDriver(browser: playwright.Browser, page: playwright.Page): IDriver {
|
||||
let traceCounter = 1;
|
||||
|
||||
function buildDriver(browser: playwright.Browser, context: playwright.BrowserContext, page: playwright.Page): IDriver {
|
||||
const driver: IDriver = {
|
||||
_serviceBrand: undefined,
|
||||
getWindowIds: () => {
|
||||
@@ -41,7 +46,17 @@ function buildDriver(browser: playwright.Browser, page: playwright.Page): IDrive
|
||||
return buffer.toString('base64');
|
||||
},
|
||||
reloadWindow: (windowId) => Promise.resolve(),
|
||||
exitApplication: () => browser.close(),
|
||||
exitApplication: async () => {
|
||||
try {
|
||||
await context.tracing.stop({ path: join(logsPath, `playwright-trace-${traceCounter++}.zip`) });
|
||||
} catch (error) {
|
||||
console.warn(`Failed to stop playwright tracing.`); // do not fail the build when this fails
|
||||
}
|
||||
await browser.close();
|
||||
await teardown();
|
||||
|
||||
return false;
|
||||
},
|
||||
dispatchKeybinding: async (windowId, keybinding) => {
|
||||
const chords = keybinding.split(' ');
|
||||
for (let i = 0; i < chords.length; i++) {
|
||||
@@ -82,7 +97,9 @@ function buildDriver(browser: playwright.Browser, page: playwright.Page): IDrive
|
||||
getElementXY: (windowId, selector, xoffset?, yoffset?) => page.evaluate(`window.driver.getElementXY('${selector}', ${xoffset}, ${yoffset})`),
|
||||
typeInEditor: (windowId, selector, text) => page.evaluate(`window.driver.typeInEditor('${selector}', '${text}')`),
|
||||
getTerminalBuffer: (windowId, selector) => page.evaluate(`window.driver.getTerminalBuffer('${selector}')`),
|
||||
writeInTerminal: (windowId, selector, text) => page.evaluate(`window.driver.writeInTerminal('${selector}', '${text}')`)
|
||||
writeInTerminal: (windowId, selector, text) => page.evaluate(`window.driver.writeInTerminal('${selector}', '${text}')`),
|
||||
getLocaleInfo: (windowId) => page.evaluate(`window.driver.getLocaleInfo()`),
|
||||
getLocalizedStrings: (windowId) => page.evaluate(`window.driver.getLocalizedStrings()`)
|
||||
};
|
||||
return driver;
|
||||
}
|
||||
@@ -91,11 +108,12 @@ function timeout(ms: number): Promise<void> {
|
||||
return new Promise<void>(r => setTimeout(r, ms));
|
||||
}
|
||||
|
||||
let port = 9000;
|
||||
let server: ChildProcess | undefined;
|
||||
let endpoint: string | undefined;
|
||||
let workspacePath: string | undefined;
|
||||
|
||||
export async function launch(userDataDir: string, _workspacePath: string, codeServerPath = process.env.VSCODE_REMOTE_SERVER_PATH, extPath: string): Promise<void> {
|
||||
export async function launch(userDataDir: string, _workspacePath: string, codeServerPath = process.env.VSCODE_REMOTE_SERVER_PATH, extPath: string, verbose: boolean): Promise<void> {
|
||||
workspacePath = _workspacePath;
|
||||
|
||||
const agentFolder = userDataDir;
|
||||
@@ -105,31 +123,54 @@ export async function launch(userDataDir: string, _workspacePath: string, codeSe
|
||||
VSCODE_REMOTE_SERVER_PATH: codeServerPath,
|
||||
...process.env
|
||||
};
|
||||
const args = ['--browser', 'none', '--driver', 'web', '--extensions-dir', extPath];
|
||||
|
||||
const args = ['--disable-telemetry', '--port', `${port++}`, '--browser', 'none', '--driver', 'web', '--extensions-dir', extPath];
|
||||
|
||||
let serverLocation: string | undefined;
|
||||
if (codeServerPath) {
|
||||
serverLocation = join(codeServerPath, `server.${process.platform === 'win32' ? 'cmd' : 'sh'}`);
|
||||
console.log(`Starting built server from '${serverLocation}'`);
|
||||
args.push(`--logsPath=${logsPath}`);
|
||||
|
||||
if (verbose) {
|
||||
console.log(`Starting built server from '${serverLocation}'`);
|
||||
console.log(`Storing log files into '${logsPath}'`);
|
||||
}
|
||||
} else {
|
||||
serverLocation = join(__dirname, '..', '..', '..', `resources/server/web.${process.platform === 'win32' ? 'bat' : 'sh'}`);
|
||||
console.log(`Starting server out of sources from '${serverLocation}'`);
|
||||
serverLocation = join(root, `resources/server/web.${process.platform === 'win32' ? 'bat' : 'sh'}`);
|
||||
args.push('--logsPath', logsPath);
|
||||
|
||||
if (verbose) {
|
||||
console.log(`Starting server out of sources from '${serverLocation}'`);
|
||||
console.log(`Storing log files into '${logsPath}'`);
|
||||
}
|
||||
}
|
||||
|
||||
server = spawn(
|
||||
serverLocation,
|
||||
args,
|
||||
{ env }
|
||||
);
|
||||
server.stderr?.on('data', error => console.log(`Server stderr: ${error}`));
|
||||
server.stdout?.on('data', data => console.log(`Server stdout: ${data}`));
|
||||
|
||||
if (verbose) {
|
||||
server.stderr?.on('data', error => console.log(`Server stderr: ${error}`));
|
||||
server.stdout?.on('data', data => console.log(`Server stdout: ${data}`));
|
||||
}
|
||||
|
||||
process.on('exit', teardown);
|
||||
process.on('SIGINT', teardown);
|
||||
process.on('SIGTERM', teardown);
|
||||
|
||||
endpoint = await waitForEndpoint();
|
||||
}
|
||||
|
||||
function teardown(): void {
|
||||
async function teardown(): Promise<void> {
|
||||
if (server) {
|
||||
kill(server.pid);
|
||||
try {
|
||||
await new Promise<void>((c, e) => kill(server!.pid, err => err ? e(err) : c()));
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
|
||||
server = undefined;
|
||||
}
|
||||
}
|
||||
@@ -145,17 +186,39 @@ function waitForEndpoint(): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
export function connect(browserType: 'chromium' | 'webkit' | 'firefox' = 'chromium'): Promise<{ client: IDisposable, driver: IDriver }> {
|
||||
interface Options {
|
||||
readonly browser?: 'chromium' | 'webkit' | 'firefox';
|
||||
readonly headless?: boolean;
|
||||
}
|
||||
|
||||
export function connect(options: Options = {}): Promise<{ client: IDisposable, driver: IDriver }> {
|
||||
return new Promise(async (c) => {
|
||||
const browser = await playwright[browserType].launch({ headless: false });
|
||||
const browser = await playwright[options.browser ?? 'chromium'].launch({ headless: options.headless ?? false });
|
||||
const context = await browser.newContext({ permissions: ['clipboard-read'] }); // {{SQL CARBON EDIT}} avoid permissison request
|
||||
try {
|
||||
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
} catch (error) {
|
||||
console.warn(`Failed to start playwright tracing.`); // do not fail the build when this fails
|
||||
}
|
||||
const page = await context.newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
const payloadParam = `[["enableProposedApi",""]]`;
|
||||
page.on('pageerror', async error => console.error(`Playwright ERROR: page error: ${error}`));
|
||||
page.on('crash', page => console.error('Playwright ERROR: page crash'));
|
||||
page.on('response', async response => {
|
||||
if (response.status() >= 400) {
|
||||
console.error(`Playwright ERROR: HTTP status ${response.status()} for ${response.url()}`);
|
||||
}
|
||||
});
|
||||
const payloadParam = `[["enableProposedApi",""],["skipWelcome","true"]]`;
|
||||
await page.goto(`${endpoint}&folder=vscode-remote://localhost:9888${URI.file(workspacePath!).path}&payload=${payloadParam}`);
|
||||
const result = {
|
||||
client: { dispose: () => browser.close() && teardown() },
|
||||
driver: buildDriver(browser, page)
|
||||
client: {
|
||||
dispose: () => {
|
||||
browser.close();
|
||||
teardown();
|
||||
}
|
||||
},
|
||||
driver: buildDriver(browser, context, page)
|
||||
};
|
||||
c(result);
|
||||
});
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Editors } from './editors';
|
||||
import { Code } from './code';
|
||||
import { Terminal } from './terminal';
|
||||
import { Notebook } from './notebook';
|
||||
import { Localization } from './localization';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { ConnectionDialog } from './sql/connectionDialog';
|
||||
@@ -55,6 +56,7 @@ export class Workbench {
|
||||
readonly keybindingsEditor: KeybindingsEditor;
|
||||
readonly terminal: Terminal;
|
||||
readonly notebook: Notebook;
|
||||
readonly localization: Localization;
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
readonly connectionDialog: ConnectionDialog;
|
||||
@@ -96,5 +98,6 @@ export class Workbench {
|
||||
this.addRemoteBookDialog = new AddRemoteBookDialog(code);
|
||||
// {{END}}
|
||||
this.notebook = new Notebook(this.quickaccess, code);
|
||||
this.localization = new Localization(code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,10 +659,10 @@ tree-kill@1.2.2:
|
||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||
|
||||
typescript@3.7.5:
|
||||
version "3.7.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
|
||||
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
|
||||
typescript@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
|
||||
integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
||||
Reference in New Issue
Block a user