From 7a43ad81ed347c941b525fa4afb48ae9034e96d0 Mon Sep 17 00:00:00 2001 From: VictorPaiu Date: Wed, 26 Nov 2025 15:42:31 +0100 Subject: [PATCH] Fixed default vs code smoke tests for sagemaker --- patches/test/sagemaker-testing.series | 3 +- patches/test/sagemaker/fix-smoke-tests.diff | 170 ++++++++++++++ .../sagemaker-smoke-testing-entry.diff | 208 +++++++++++++++++- 3 files changed, 371 insertions(+), 10 deletions(-) create mode 100644 patches/test/sagemaker/fix-smoke-tests.diff diff --git a/patches/test/sagemaker-testing.series b/patches/test/sagemaker-testing.series index 58f55ad..4940e2b 100644 --- a/patches/test/sagemaker-testing.series +++ b/patches/test/sagemaker-testing.series @@ -1 +1,2 @@ -sagemaker/sagemaker-smoke-testing-entry.diff \ No newline at end of file +sagemaker/sagemaker-smoke-testing-entry.diff +sagemaker/fix-smoke-tests.diff \ No newline at end of file diff --git a/patches/test/sagemaker/fix-smoke-tests.diff b/patches/test/sagemaker/fix-smoke-tests.diff new file mode 100644 index 0000000..193a394 --- /dev/null +++ b/patches/test/sagemaker/fix-smoke-tests.diff @@ -0,0 +1,170 @@ +Index: code-editor-src/test/automation/src/quickaccess.ts +=================================================================== +--- code-editor-src.orig/test/automation/src/quickaccess.ts ++++ code-editor-src/test/automation/src/quickaccess.ts +@@ -6,7 +6,7 @@ + import { Editors } from './editors'; + import { Code } from './code'; + import { QuickInput } from './quickinput'; +-import { basename, isAbsolute } from 'path'; ++import { basename } from 'path'; + + enum QuickAccessKind { + Files = 1, +@@ -110,13 +110,6 @@ export class QuickAccess { + } + + async openFile(path: string): Promise { +- 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); + +Index: code-editor-src/test/automation/src/terminal.ts +=================================================================== +--- code-editor-src.orig/test/automation/src/terminal.ts ++++ code-editor-src/test/automation/src/terminal.ts +@@ -216,7 +216,7 @@ export class Terminal { + const description: IElement | undefined = await this.code.waitForElement(`${Selector.Tabs}[data-index="${i}"] ${Selector.TabsEntry} ${Selector.Description}`, () => true); + + const label: TerminalLabel = { +- name: title.textContent.replace(/^[├┌└]\s*/, ''), ++ name: title.textContent.replace(/^[├┌└]\s*/, '').replace(description?.textContent || '', '').trim(), + description: description?.textContent + }; + // It's a new group if the tab does not start with ├ or └ +Index: code-editor-src/test/automation/src/settings.ts +=================================================================== +--- code-editor-src.orig/test/automation/src/settings.ts ++++ code-editor-src/test/automation/src/settings.ts +@@ -48,11 +48,23 @@ export class SettingsEditor { + + async clearUserSettings(): Promise { + await this.openUserSettingsFile(); ++ ++ // Add delay to ensure editor is ready ++ await new Promise(resolve => setTimeout(resolve, 500)); ++ + await this.quickaccess.runCommand('editor.action.selectAll'); + await this.code.sendKeybinding('Delete', async () => { + await this.editor.waitForEditorContents('settings.json', contents => contents === ''); + }); + await this.editor.waitForTypeInEditor('settings.json', `{`); // will auto close } ++ ++ // Add default settings before closing ++ await this.editor.waitForTypeInEditor('settings.json', [ ++ '"extensions.openNotebookData": { "notebookKey": null, "clusterId": null, "region": null },', ++ '"workbench.colorTheme": "Default Dark Modern",', ++ '"editor.wordWrap": "on"' ++ ].join('')); ++ + await this.editors.saveOpenedFile(); + await this.quickaccess.runCommand('workbench.action.closeActiveEditor'); + } +Index: code-editor-src/test/smoke/src/areas/terminal/terminal-profiles.test.ts +=================================================================== +--- code-editor-src.orig/test/smoke/src/areas/terminal/terminal-profiles.test.ts ++++ code-editor-src/test/smoke/src/areas/terminal/terminal-profiles.test.ts +@@ -6,8 +6,8 @@ + import { Application, Terminal, TerminalCommandId, TerminalCommandIdWithValue, SettingsEditor } from '../../../../automation'; + import { setTerminalTestSettings } from './terminal-helpers'; + +-const CONTRIBUTED_PROFILE_NAME = `JavaScript Debug Terminal`; +-const ANY_PROFILE_NAME = '^((?!JavaScript Debug Terminal).)*$'; ++const CONTRIBUTED_PROFILE_NAME = `sh`; ++const ANY_PROFILE_NAME = '^(?!^sh$).*$'; + + export function setup(options?: { skipSuite: boolean }) { + (options?.skipSuite ? describe.skip : describe)('Terminal Profiles', () => { +Index: code-editor-src/test/smoke/src/areas/multiroot/multiroot.test.ts +=================================================================== +--- code-editor-src.orig/test/smoke/src/areas/multiroot/multiroot.test.ts ++++ code-editor-src/test/smoke/src/areas/multiroot/multiroot.test.ts +@@ -3,51 +3,39 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import { writeFileSync } from 'fs'; +-import { join, dirname } from 'path'; ++ + import { Application, Logger } from '../../../../automation'; + import { installAllHandlers } from '../../utils'; + +-function toUri(path: string): string { +- if (process.platform === 'win32') { +- return `${path.replace(/\\/g, '/')}`; +- } +- +- return `${path}`; +-} +- +-function createWorkspaceFile(workspacePath: string): string { +- const workspaceFilePath = join(dirname(workspacePath), 'smoketest.code-workspace'); +- const workspace = { +- folders: [ +- { path: toUri(join(workspacePath, 'public')) }, +- { path: toUri(join(workspacePath, 'routes')) }, +- { path: toUri(join(workspacePath, 'views')) } +- ], +- settings: { +- 'workbench.startupEditor': 'none', +- 'workbench.enableExperiments': false, +- 'typescript.disableAutomaticTypeAcquisition': true, +- 'json.schemaDownload.enable': false, +- 'npm.fetchOnlinePackageInfo': false, +- 'npm.autoDetect': 'off', +- 'workbench.editor.languageDetection': false, +- "workbench.localHistory.enabled": false +- } +- }; +- +- writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, '\t')); +- +- return workspaceFilePath; ++async function createWorkspaceFile(app: Application, workspacePath: string): Promise { ++ // Create workspace file in current directory (vscode-smoketest-express) ++ await app.workbench.terminal.createTerminal(); ++ await app.workbench.terminal.runCommandInTerminal(`cd "${workspacePath}"`); ++ await app.workbench.terminal.runCommandInTerminal('WORKSPACE_DIR=$(pwd)'); ++ await app.workbench.terminal.runCommandInTerminal('printf \'{"folders":[{"path":"%s/public"},{"path":"%s/routes"},{"path":"%s/views"}],"settings":{"workbench.startupEditor":"none","workbench.enableExperiments":false,"typescript.disableAutomaticTypeAcquisition":true,"json.schemaDownload.enable":false,"npm.fetchOnlinePackageInfo":false,"npm.autoDetect":"off","workbench.editor.languageDetection":false,"workbench.localHistory.enabled":false}}\' "$WORKSPACE_DIR" "$WORKSPACE_DIR" "$WORKSPACE_DIR" > smoketest.code-workspace'); ++ await new Promise(resolve => setTimeout(resolve, 500)); ++ ++ // Open the workspace ++ await app.workbench.quickaccess.runCommand('workbench.action.openWorkspace'); ++ await app.workbench.quickinput.waitForQuickInputOpened(); ++ await app.workbench.quickinput.type(`${workspacePath}/smoketest.code-workspace`); ++ await new Promise(resolve => setTimeout(resolve, 500)); ++ await app.code.sendKeybinding('enter'); ++ await new Promise(resolve => setTimeout(resolve, 5000)); ++ await app.code.waitForElement('.monaco-workbench') + } + + export function setup(logger: Logger) { + describe('Multiroot', () => { + + // Shared before/after handling +- installAllHandlers(logger, opts => { +- const workspacePath = createWorkspaceFile(opts.workspacePath); +- return { ...opts, workspacePath }; ++ installAllHandlers(logger); ++ ++ before(async function () { ++ const app = this.app as Application; ++ const workspacePath = this.defaultOptions.workspacePath; ++ // The app already started with a regular folder, now we need to create the multiroot setup ++ await createWorkspaceFile(app, workspacePath); + }); + + it('shows results from all folders', async function () { +@@ -72,4 +60,4 @@ export function setup(logger: Logger) { + await app.code.waitForTitle(title => /smoketest \(Workspace\)/i.test(title)); + }); + }); +-} ++} +\ No newline at end of file diff --git a/patches/test/sagemaker/sagemaker-smoke-testing-entry.diff b/patches/test/sagemaker/sagemaker-smoke-testing-entry.diff index 3008bd7..b0f6343 100644 --- a/patches/test/sagemaker/sagemaker-smoke-testing-entry.diff +++ b/patches/test/sagemaker/sagemaker-smoke-testing-entry.diff @@ -29,7 +29,7 @@ Index: code-editor-src/test/automation/src/playwrightBrowser.ts if (tracing) { try { await measureAndLog(() => context.tracing.start({ screenshots: true, snapshots }), 'context.tracing.start()', logger); -@@ -149,6 +158,151 @@ async function launchBrowser(options: La +@@ -149,6 +158,144 @@ async function launchBrowser(options: La return { browser, context, page, pageLoadedPromise }; } @@ -151,13 +151,6 @@ Index: code-editor-src/test/automation/src/playwrightBrowser.ts + // Wait for clone to complete + await page.waitForTimeout(10000); + -+ // Install npm dependencies for the test project -+ await page.keyboard.type('cd /home/sagemaker-user/vscode-smoketest-express && npm install'); -+ await page.keyboard.press('Enter'); -+ -+ // Wait for npm install to complete -+ await page.waitForTimeout(10000); -+ + // Navigate to workspace with payload parameters (like launchBrowser) + const payloadParam = `[${[ + '["enableProposedApi",""]', @@ -185,7 +178,50 @@ Index: code-editor-src/test/smoke/src/main.ts =================================================================== --- code-editor-src.orig/test/smoke/src/main.ts +++ code-editor-src/test/smoke/src/main.ts -@@ -211,7 +211,10 @@ else { +@@ -5,16 +5,9 @@ + + import * as fs from 'fs'; + import { gracefulify } from 'graceful-fs'; +-import * as cp from 'child_process'; + import * as path from 'path'; +-import * as os from 'os'; + import * as minimist from 'minimist'; +-import * as rimraf from 'rimraf'; +-import * as vscodetest from '@vscode/test-electron'; +-import fetch from 'node-fetch'; +-import { Quality, MultiLogger, Logger, ConsoleLogger, FileLogger, measureAndLog, getDevElectronPath, getBuildElectronPath, getBuildVersion } from '../../automation'; +-import { retry, timeout } from './utils'; +- ++import { Quality, MultiLogger, Logger, ConsoleLogger, FileLogger, getDevElectronPath, getBuildElectronPath, getBuildVersion } from '../../automation'; + import { setup as setupDataLossTests } from './areas/workbench/data-loss.test'; + import { setup as setupPreferencesTests } from './areas/preferences/preferences.test'; + import { setup as setupSearchTests } from './areas/search/search.test'; +@@ -118,23 +111,10 @@ try { + logger.log(`Error enabling graceful-fs: ${error}`); + } + +-const testDataPath = path.join(os.tmpdir(), 'vscsmoke'); +-if (fs.existsSync(testDataPath)) { +- rimraf.sync(testDataPath); +-} +-fs.mkdirSync(testDataPath, { recursive: true }); +-process.once('exit', () => { +- try { +- rimraf.sync(testDataPath); +- } catch { +- // noop +- } +-}); ++const testDataPath = '/home/sagemaker-user'; + +-const testRepoUrl = 'https://github.com/microsoft/vscode-smoketest-express'; + const workspacePath = path.join(testDataPath, 'vscode-smoketest-express'); + const extensionsPath = path.join(testDataPath, 'extensions-dir'); +-fs.mkdirSync(extensionsPath, { recursive: true }); + + function fail(errorMessage): void { + logger.log(errorMessage); +@@ -211,7 +191,10 @@ else { const testCodeServerPath = opts.build || process.env.VSCODE_REMOTE_SERVER_PATH; if (typeof testCodeServerPath === 'string') { @@ -197,6 +233,160 @@ Index: code-editor-src/test/smoke/src/main.ts fail(`Cannot find Code server at ${testCodeServerPath}.`); } else { logger.log(`Running web smoke tests against ${testCodeServerPath}`); +@@ -233,121 +216,6 @@ logger.log(`VS Code product quality: ${q + + const userDataDir = path.join(testDataPath, 'd'); + +-async function setupRepository(): Promise { +- if (opts['test-repo']) { +- logger.log('Copying test project repository:', opts['test-repo']); +- rimraf.sync(workspacePath); +- // not platform friendly +- if (process.platform === 'win32') { +- cp.execSync(`xcopy /E "${opts['test-repo']}" "${workspacePath}"\\*`); +- } else { +- cp.execSync(`cp -R "${opts['test-repo']}" "${workspacePath}"`); +- } +- } else { +- if (!fs.existsSync(workspacePath)) { +- logger.log('Cloning test project repository...'); +- const res = cp.spawnSync('git', ['clone', testRepoUrl, workspacePath], { stdio: 'inherit' }); +- if (!fs.existsSync(workspacePath)) { +- throw new Error(`Clone operation failed: ${res.stderr.toString()}`); +- } +- } else { +- logger.log('Cleaning test project repository...'); +- cp.spawnSync('git', ['fetch'], { cwd: workspacePath, stdio: 'inherit' }); +- cp.spawnSync('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: workspacePath, stdio: 'inherit' }); +- cp.spawnSync('git', ['clean', '-xdf'], { cwd: workspacePath, stdio: 'inherit' }); +- } +- } +-} +- +-async function ensureStableCode(): Promise { +- let stableCodePath = opts['stable-build']; +- if (!stableCodePath) { +- const current = parseVersion(version!); +- const versionsReq = await retry(() => measureAndLog(() => fetch('https://update.code.visualstudio.com/api/releases/stable'), 'versionReq', logger), 1000, 20); +- +- if (!versionsReq.ok) { +- throw new Error('Could not fetch releases from update server'); +- } +- +- const versions: string[] = await measureAndLog(() => versionsReq.json(), 'versionReq.json()', logger); +- const stableVersion = versions.find(raw => { +- const version = parseVersion(raw); +- return version.major < current.major || (version.major === current.major && version.minor < current.minor); +- }); +- +- if (!stableVersion) { +- throw new Error(`Could not find suitable stable version for ${version}`); +- } +- +- logger.log(`Found VS Code v${version}, downloading previous VS Code version ${stableVersion}...`); +- +- let lastProgressMessage: string | undefined = undefined; +- let lastProgressReportedAt = 0; +- const stableCodeDestination = path.join(testDataPath, 's'); +- const stableCodeExecutable = await retry(() => measureAndLog(() => vscodetest.download({ +- cachePath: stableCodeDestination, +- version: stableVersion, +- extractSync: true, +- reporter: { +- report: report => { +- let progressMessage = `download stable code progress: ${report.stage}`; +- const now = Date.now(); +- if (progressMessage !== lastProgressMessage || now - lastProgressReportedAt > 10000) { +- lastProgressMessage = progressMessage; +- lastProgressReportedAt = now; +- +- if (report.stage === 'downloading') { +- progressMessage += ` (${report.bytesSoFar}/${report.totalBytes})`; +- } +- +- logger.log(progressMessage); +- } +- }, +- error: error => logger.log(`download stable code error: ${error}`) +- } +- }), 'download stable code', logger), 1000, 3, () => new Promise((resolve, reject) => { +- rimraf(stableCodeDestination, { maxBusyTries: 10 }, error => { +- if (error) { +- reject(error); +- } else { +- resolve(); +- } +- }); +- })); +- +- if (process.platform === 'darwin') { +- // Visual Studio Code.app/Contents/MacOS/Electron +- stableCodePath = path.dirname(path.dirname(path.dirname(stableCodeExecutable))); +- } else { +- // VSCode/Code.exe (Windows) | VSCode/code (Linux) +- stableCodePath = path.dirname(stableCodeExecutable); +- } +- +- opts['stable-version'] = parseVersion(stableVersion); +- } +- +- if (!fs.existsSync(stableCodePath)) { +- throw new Error(`Cannot find Stable VSCode at ${stableCodePath}.`); +- } +- +- logger.log(`Using stable build ${stableCodePath} for migration tests`); +- +- opts['stable-build'] = stableCodePath; +-} +- +-async function setup(): Promise { +- logger.log('Test data path:', testDataPath); +- logger.log('Preparing smoketest setup...'); +- +- if (!opts.web && !opts.remote && opts.build) { +- // only enabled when running with --build and not in web or remote +- await measureAndLog(() => ensureStableCode(), 'ensureStableCode', logger); +- } +- await measureAndLog(() => setupRepository(), 'setupRepository', logger); +- +- logger.log('Smoketest setup done!\n'); +-} +- + // Before all tests run setup + before(async function () { + this.timeout(5 * 60 * 1000); // increase since we download VSCode +@@ -371,31 +239,6 @@ before(async function () { + extraArgs: (opts.electronArgs || '').split(' ').map(arg => arg.trim()).filter(arg => !!arg) + }; + +- await setup(); +-}); +- +-// After main suite (after all tests) +-after(async function () { +- try { +- let deleted = false; +- await measureAndLog(() => Promise.race([ +- new Promise((resolve, reject) => rimraf(testDataPath, { maxBusyTries: 10 }, error => { +- if (error) { +- reject(error); +- } else { +- deleted = true; +- resolve(); +- } +- })), +- timeout(30000).then(() => { +- if (!deleted) { +- throw new Error('giving up after 30s'); +- } +- }) +- ]), 'rimraf(testDataPath)', logger); +- } catch (error) { +- logger.log(`Unable to delete smoke test workspace: ${error}. This indicates some process is locking the workspace folder.`); +- } + }); + + describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => { Index: code-editor-src/test/automation/src/code.ts =================================================================== --- code-editor-src.orig/test/automation/src/code.ts