diff --git a/test/automation/src/code.ts b/test/automation/src/code.ts index ae612626c9e..d3c697873a1 100644 --- a/test/automation/src/code.ts +++ b/test/automation/src/code.ts @@ -30,6 +30,7 @@ export interface LaunchOptions { readonly headless?: boolean; readonly browser?: 'chromium' | 'webkit' | 'firefox' | 'chromium-msedge' | 'chromium-chrome'; readonly quality: Quality; + version: { major: number; minor: number; patch: number }; } interface ICodeInstance { @@ -89,7 +90,7 @@ export async function launch(options: LaunchOptions): Promise { const { serverProcess, driver } = await measureAndLog(() => launchPlaywrightBrowser(options), 'launch playwright (browser)', options.logger); registerInstance(serverProcess, options.logger, 'server'); - return new Code(driver, options.logger, serverProcess, undefined, options.quality); + return new Code(driver, options.logger, serverProcess, undefined, options.quality, options.version); } // Electron smoke tests (playwright) @@ -97,7 +98,7 @@ export async function launch(options: LaunchOptions): Promise { const { electronProcess, driver } = await measureAndLog(() => launchPlaywrightElectron(options), 'launch playwright (electron)', options.logger); const { safeToKill } = registerInstance(electronProcess, options.logger, 'electron'); - return new Code(driver, options.logger, electronProcess, safeToKill, options.quality); + return new Code(driver, options.logger, electronProcess, safeToKill, options.quality, options.version); } } @@ -110,7 +111,8 @@ export class Code { readonly logger: Logger, private readonly mainProcess: cp.ChildProcess, private readonly safeToKill: Promise | undefined, - readonly quality: Quality + readonly quality: Quality, + readonly version: { major: number; minor: number; patch: number } ) { this.driver = new Proxy(driver, { get(target, prop) { @@ -131,6 +133,10 @@ export class Code { }); } + get editContextEnabled(): boolean { + return !(this.quality === Quality.Stable && this.version.major === 1 && this.version.minor < 101); + } + async startTracing(name: string): Promise { return await this.driver.startTracing(name); } diff --git a/test/automation/src/debug.ts b/test/automation/src/debug.ts index 43f974ebec9..2b8623bb013 100644 --- a/test/automation/src/debug.ts +++ b/test/automation/src/debug.ts @@ -9,7 +9,6 @@ import { Code, findElement } from './code'; import { Editors } from './editors'; import { Editor } from './editor'; import { IElement } from './driver'; -import { Quality } from './application'; const VIEWLET = 'div[id="workbench.view.debug"]'; const DEBUG_VIEW = `${VIEWLET}`; @@ -133,7 +132,7 @@ export class Debug extends Viewlet { async waitForReplCommand(text: string, accept: (result: string) => boolean): Promise { await this.commands.runCommand('Debug: Focus on Debug Console View'); - const selector = this.code.quality === Quality.Stable ? REPL_FOCUSED_TEXTAREA : REPL_FOCUSED_NATIVE_EDIT_CONTEXT; + const selector = !this.code.editContextEnabled ? REPL_FOCUSED_TEXTAREA : REPL_FOCUSED_NATIVE_EDIT_CONTEXT; await this.code.waitForActiveElement(selector); await this.code.waitForSetValue(selector, text); diff --git a/test/automation/src/editor.ts b/test/automation/src/editor.ts index 6587b28edaf..37e152d3e66 100644 --- a/test/automation/src/editor.ts +++ b/test/automation/src/editor.ts @@ -6,7 +6,6 @@ import { References } from './peek'; import { Commands } from './workbench'; import { Code } from './code'; -import { Quality } from './application'; const RENAME_BOX = '.monaco-editor .monaco-editor.rename-box'; const RENAME_INPUT = `${RENAME_BOX} .rename-input`; @@ -107,7 +106,7 @@ export class Editor { } private _editContextSelector() { - return this.code.quality === Quality.Stable ? 'textarea' : '.native-edit-context'; + return !this.code.editContextEnabled ? 'textarea' : '.native-edit-context'; } async waitForEditorContents(filename: string, accept: (contents: string) => boolean, selectorPrefix = ''): Promise { diff --git a/test/automation/src/editors.ts b/test/automation/src/editors.ts index b2321e947de..0f2e54722d0 100644 --- a/test/automation/src/editors.ts +++ b/test/automation/src/editors.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Quality } from './application'; import { Code } from './code'; export class Editors { @@ -53,7 +52,7 @@ export class Editors { } async waitForActiveEditor(fileName: string, retryCount?: number): Promise { - const selector = `.editor-instance .monaco-editor[data-uri$="${fileName}"] ${this.code.quality === Quality.Stable ? 'textarea' : '.native-edit-context'}`; + const selector = `.editor-instance .monaco-editor[data-uri$="${fileName}"] ${!this.code.editContextEnabled ? 'textarea' : '.native-edit-context'}`; return this.code.waitForActiveElement(selector, retryCount); } diff --git a/test/automation/src/extensions.ts b/test/automation/src/extensions.ts index 06bd324465f..8c40cdff0de 100644 --- a/test/automation/src/extensions.ts +++ b/test/automation/src/extensions.ts @@ -8,7 +8,6 @@ import { Code } from './code'; import { ncp } from 'ncp'; import { promisify } from 'util'; import { Commands } from './workbench'; -import { Quality } from './application'; import path = require('path'); import fs = require('fs'); @@ -21,7 +20,7 @@ export class Extensions extends Viewlet { async searchForExtension(id: string): Promise { await this.commands.runCommand('Extensions: Focus on Extensions View', { exactLabelMatch: true }); - await this.code.waitForTypeInEditor(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-editor ${this.code.quality === Quality.Stable ? 'textarea' : '.native-edit-context'}`, `@id:${id}`); + await this.code.waitForTypeInEditor(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-editor ${!this.code.editContextEnabled ? 'textarea' : '.native-edit-context'}`, `@id:${id}`); await this.code.waitForTextContent(`div.part.sidebar div.composite.title h2`, 'Extensions: Marketplace'); let retrials = 1; diff --git a/test/automation/src/notebook.ts b/test/automation/src/notebook.ts index 3ba9101a1de..7596d1888a8 100644 --- a/test/automation/src/notebook.ts +++ b/test/automation/src/notebook.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Quality } from './application'; import { Code } from './code'; import { QuickAccess } from './quickaccess'; import { QuickInput } from './quickinput'; @@ -47,7 +46,7 @@ export class Notebook { await this.code.waitForElement(editor); - const editContext = `${editor} ${this.code.quality === Quality.Stable ? 'textarea' : '.native-edit-context'}`; + const editContext = `${editor} ${!this.code.editContextEnabled ? 'textarea' : '.native-edit-context'}`; await this.code.waitForActiveElement(editContext); await this.code.waitForTypeInEditor(editContext, text); diff --git a/test/automation/src/scm.ts b/test/automation/src/scm.ts index 2277bcb2875..0fb54bd15d2 100644 --- a/test/automation/src/scm.ts +++ b/test/automation/src/scm.ts @@ -6,7 +6,6 @@ import { Viewlet } from './viewlet'; import { IElement } from './driver'; import { findElement, findElements, Code } from './code'; -import { Quality } from './application'; const VIEWLET = 'div[id="workbench.view.scm"]'; const SCM_INPUT_NATIVE_EDIT_CONTEXT = `${VIEWLET} .scm-editor .native-edit-context`; @@ -79,6 +78,6 @@ export class SCM extends Viewlet { } private _editContextSelector(): string { - return this.code.quality === Quality.Stable ? SCM_INPUT_TEXTAREA : SCM_INPUT_NATIVE_EDIT_CONTEXT; + return !this.code.editContextEnabled ? SCM_INPUT_TEXTAREA : SCM_INPUT_NATIVE_EDIT_CONTEXT; } } diff --git a/test/automation/src/settings.ts b/test/automation/src/settings.ts index f4a8afb3165..ab961478b37 100644 --- a/test/automation/src/settings.ts +++ b/test/automation/src/settings.ts @@ -7,7 +7,6 @@ import { Editor } from './editor'; import { Editors } from './editors'; import { Code } from './code'; import { QuickAccess } from './quickaccess'; -import { Quality } from './application'; const SEARCH_BOX_NATIVE_EDIT_CONTEXT = '.settings-editor .suggest-input-container .monaco-editor .native-edit-context'; const SEARCH_BOX_TEXTAREA = '.settings-editor .suggest-input-container .monaco-editor textarea'; @@ -26,7 +25,7 @@ export class SettingsEditor { await this.editors.selectTab('settings.json'); await this.code.sendKeybinding('right', () => - this.editor.waitForEditorSelection('settings.json', (s) => this._acceptEditorSelection(this.code.quality, s))); + this.editor.waitForEditorSelection('settings.json', (s) => this._acceptEditorSelection(this.code.editContextEnabled, s))); await this.editor.waitForTypeInEditor('settings.json', `"${setting}": ${value},`); await this.editors.saveOpenedFile(); } @@ -42,7 +41,7 @@ export class SettingsEditor { await this.editors.selectTab('settings.json'); await this.code.sendKeybinding('right', () => - this.editor.waitForEditorSelection('settings.json', (s) => this._acceptEditorSelection(this.code.quality, s))); + this.editor.waitForEditorSelection('settings.json', (s) => this._acceptEditorSelection(this.code.editContextEnabled, s))); await this.editor.waitForTypeInEditor('settings.json', settings.map(v => `"${v[0]}": ${v[1]},`).join('')); await this.editors.saveOpenedFile(); } @@ -85,11 +84,11 @@ export class SettingsEditor { } private _editContextSelector() { - return this.code.quality === Quality.Stable ? SEARCH_BOX_TEXTAREA : SEARCH_BOX_NATIVE_EDIT_CONTEXT; + return !this.code.editContextEnabled ? SEARCH_BOX_TEXTAREA : SEARCH_BOX_NATIVE_EDIT_CONTEXT; } - private _acceptEditorSelection(quality: Quality, s: { selectionStart: number; selectionEnd: number }): boolean { - if (quality === Quality.Stable) { + private _acceptEditorSelection(editContextEnabled: boolean, s: { selectionStart: number; selectionEnd: number }): boolean { + if (!editContextEnabled) { return true; } return s.selectionStart === 1 && s.selectionEnd === 1; diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index 9788813f225..123076e130e 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -7,7 +7,7 @@ import { join } from 'path'; import { Application, ApplicationOptions, Logger, Quality } from '../../../../automation'; import { createApp, timeout, installDiagnosticsHandler, installAppAfterHandler, getRandomUserDataDir, suiteLogsPath, suiteCrashPath } from '../../utils'; -export function setup(ensureStableCode: () => string | undefined, logger: Logger) { +export function setup(ensureStableCode: () => { stableCodePath: string | undefined; stableCodeVersion: { major: number; minor: number; patch: number } | undefined }, logger: Logger) { describe('Data Loss (insiders -> insiders)', function () { // Double the timeout since these tests involve 2 startups @@ -146,7 +146,7 @@ export function setup(ensureStableCode: () => string | undefined, logger: Logger installAppAfterHandler(() => insidersApp ?? stableApp, async () => stableApp?.stop()); it('verifies opened editors are restored', async function () { - const stableCodePath = ensureStableCode(); + const { stableCodePath, stableCodeVersion } = ensureStableCode(); if (!stableCodePath) { this.skip(); } @@ -170,6 +170,7 @@ export function setup(ensureStableCode: () => string | undefined, logger: Logger stableOptions.quality = Quality.Stable; stableOptions.logsPath = logsPath; stableOptions.crashesPath = crashesPath; + stableOptions.version = stableCodeVersion ?? { major: 0, minor: 0, patch: 0 }; stableApp = new Application(stableOptions); await stableApp.start(); @@ -210,7 +211,7 @@ export function setup(ensureStableCode: () => string | undefined, logger: Logger }); async function testHotExit(this: import('mocha').Context, title: string, restartDelay: number | undefined) { - const stableCodePath = ensureStableCode(); + const { stableCodePath, stableCodeVersion } = ensureStableCode(); if (!stableCodePath) { this.skip(); } @@ -225,6 +226,7 @@ export function setup(ensureStableCode: () => string | undefined, logger: Logger stableOptions.quality = Quality.Stable; stableOptions.logsPath = logsPath; stableOptions.crashesPath = crashesPath; + stableOptions.version = stableCodeVersion ?? { major: 0, minor: 0, patch: 0 }; stableApp = new Application(stableOptions); await stableApp.start(); diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index d8120ea0675..bdc5a3776e2 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -322,6 +322,8 @@ async function ensureStableCode(): Promise { // VSCode/Code.exe (Windows) | VSCode/code (Linux) stableCodePath = path.dirname(stableCodeExecutable); } + + opts['stable-version'] = parseVersion(stableVersion); } if (!fs.existsSync(stableCodePath)) { @@ -352,6 +354,7 @@ before(async function () { this.defaultOptions = { quality, + version: parseVersion(version ?? '0.0.0'), codePath: opts.build, workspacePath, userDataDir, @@ -396,7 +399,7 @@ after(async function () { }); describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => { - if (!opts.web) { setupDataLossTests(() => opts['stable-build'] /* Do not change, deferred for a reason! */, logger); } + if (!opts.web) { setupDataLossTests(() => { return { stableCodePath: opts['stable-build'], stableCodeVersion: opts['stable-version'] } /* Do not change, deferred for a reason! */; }, logger); } setupPreferencesTests(logger); setupSearchTests(logger); if (!opts.web) { setupNotebookTests(logger); }