Path: blob/main/test/smoke/src/areas/workbench/data-loss.test.ts
3520 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { join } from 'path';6import { Application, ApplicationOptions, Logger, Quality } from '../../../../automation';7import { createApp, timeout, installDiagnosticsHandler, installAppAfterHandler, getRandomUserDataDir, suiteLogsPath, suiteCrashPath } from '../../utils';89export function setup(ensureStableCode: () => { stableCodePath: string | undefined; stableCodeVersion: { major: number; minor: number; patch: number } | undefined }, logger: Logger) {10describe('Data Loss (insiders -> insiders)', function () {1112// Double the timeout since these tests involve 2 startups13this.timeout(4 * 60 * 1000);1415let app: Application | undefined = undefined;1617// Shared before/after handling18installDiagnosticsHandler(logger, () => app);19installAppAfterHandler(() => app);2021it('verifies opened editors are restored', async function () {22app = createApp({23...this.defaultOptions,24logsPath: suiteLogsPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored'),25crashesPath: suiteCrashPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored')26});27await app.start();2829// Open 3 editors30await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'bin', 'www'));31await app.workbench.quickaccess.runCommand('View: Keep Editor');32await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'app.js'));33await app.workbench.quickaccess.runCommand('View: Keep Editor');34await app.workbench.editors.newUntitledFile();3536await app.restart();3738// Verify 3 editors are open39await app.workbench.editors.selectTab('Untitled-1');40await app.workbench.editors.selectTab('app.js');41await app.workbench.editors.selectTab('www');4243await app.stop();44app = undefined;45});4647it('verifies editors can save and restore', async function () {48app = createApp({49...this.defaultOptions,50logsPath: suiteLogsPath(this.defaultOptions, 'test_verifies_editors_can_save_and_restore'),51crashesPath: suiteCrashPath(this.defaultOptions, 'test_verifies_editors_can_save_and_restore')52});53await app.start();5455const textToType = 'Hello, Code';5657// open editor and type58await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'app.js'));59await app.workbench.editor.waitForTypeInEditor('app.js', textToType);60await app.workbench.editors.waitForTab('app.js', true);6162// save63await app.workbench.editors.saveOpenedFile();64await app.workbench.editors.waitForTab('app.js', false);6566// restart67await app.restart();6869// verify contents70await app.workbench.editor.waitForEditorContents('app.js', contents => contents.indexOf(textToType) > -1);7172await app.stop();73app = undefined;74});7576it('verifies that "hot exit" works for dirty files (without delay)', function () {77return testHotExit.call(this, 'test_verifies_that_hot_exit_works_for_dirty_files_without_delay', undefined, undefined);78});7980it('verifies that "hot exit" works for dirty files (with delay)', function () {81return testHotExit.call(this, 'test_verifies_that_hot_exit_works_for_dirty_files_with_delay', 2000, undefined);82});8384it('verifies that auto save triggers on shutdown', function () {85return testHotExit.call(this, 'test_verifies_that_auto_save_triggers_on_shutdown', undefined, true);86});8788async function testHotExit(this: import('mocha').Context, title: string, restartDelay: number | undefined, autoSave: boolean | undefined) {89app = createApp({90...this.defaultOptions,91logsPath: suiteLogsPath(this.defaultOptions, title),92crashesPath: suiteCrashPath(this.defaultOptions, title)93});94await app.start();9596if (autoSave) {97await app.workbench.settingsEditor.addUserSetting('files.autoSave', '"afterDelay"');98}99100const textToTypeInUntitled = 'Hello from Untitled';101102await app.workbench.editors.newUntitledFile();103await app.workbench.editor.waitForTypeInEditor('Untitled-1', textToTypeInUntitled);104await app.workbench.editors.waitForTab('Untitled-1', true);105106const textToType = 'Hello, Code';107await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'readme.md'));108await app.workbench.editor.waitForTypeInEditor('readme.md', textToType);109await app.workbench.editors.waitForTab('readme.md', !autoSave);110111if (typeof restartDelay === 'number') {112// this is an OK use of a timeout in a smoke test:113// we want to simulate a user having typed into114// the editor and pausing for a moment before115// terminating116await timeout(restartDelay);117}118119await app.restart();120121await app.workbench.editors.waitForTab('readme.md', !autoSave);122await app.workbench.editors.waitForTab('Untitled-1', true);123124await app.workbench.editors.selectTab('readme.md');125await app.workbench.editor.waitForEditorContents('readme.md', contents => contents.indexOf(textToType) > -1);126127await app.workbench.editors.selectTab('Untitled-1');128await app.workbench.editor.waitForEditorContents('Untitled-1', contents => contents.indexOf(textToTypeInUntitled) > -1);129130await app.stop();131app = undefined;132}133});134135describe('Data Loss (stable -> insiders)', function () {136137// Double the timeout since these tests involve 2 startups138this.timeout(4 * 60 * 1000);139140let insidersApp: Application | undefined = undefined;141let stableApp: Application | undefined = undefined;142143// Shared before/after handling144installDiagnosticsHandler(logger, () => insidersApp ?? stableApp);145installAppAfterHandler(() => insidersApp ?? stableApp, async () => stableApp?.stop());146147it('verifies opened editors are restored', async function () {148const { stableCodePath, stableCodeVersion } = ensureStableCode();149if (!stableCodePath) {150this.skip();151}152153// macOS: the first launch of stable Code will trigger154// additional checks in the OS (notarization validation)155// so it can take a very long time. as such we install156// a retry handler to make sure we do not fail as a157// consequence.158if (process.platform === 'darwin') {159this.retries(2);160}161162const userDataDir = getRandomUserDataDir(this.defaultOptions.userDataDir);163const logsPath = suiteLogsPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored_from_stable');164const crashesPath = suiteCrashPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored_from_stable');165166const stableOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);167stableOptions.codePath = stableCodePath;168stableOptions.userDataDir = userDataDir;169stableOptions.quality = Quality.Stable;170stableOptions.logsPath = logsPath;171stableOptions.crashesPath = crashesPath;172stableOptions.version = stableCodeVersion ?? { major: 0, minor: 0, patch: 0 };173174stableApp = new Application(stableOptions);175await stableApp.start();176177// Open 3 editors178await stableApp.workbench.quickaccess.openFile(join(stableApp.workspacePathOrFolder, 'bin', 'www'));179await stableApp.workbench.quickaccess.runCommand('View: Keep Editor');180await stableApp.workbench.quickaccess.openFile(join(stableApp.workspacePathOrFolder, 'app.js'));181await stableApp.workbench.quickaccess.runCommand('View: Keep Editor');182await stableApp.workbench.editors.newUntitledFile();183184await stableApp.stop();185stableApp = undefined;186187const insiderOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);188insiderOptions.userDataDir = userDataDir;189insiderOptions.logsPath = logsPath;190insiderOptions.crashesPath = crashesPath;191192insidersApp = new Application(insiderOptions);193await insidersApp.start();194195// Verify 3 editors are open196await insidersApp.workbench.editors.selectTab('Untitled-1');197await insidersApp.workbench.editors.selectTab('app.js');198await insidersApp.workbench.editors.selectTab('www');199200await insidersApp.stop();201insidersApp = undefined;202});203204it('verifies that "hot exit" works for dirty files (without delay)', async function () {205return testHotExit.call(this, `test_verifies_that_hot_exit_works_for_dirty_files_without_delay_from_stable`, undefined);206});207208it('verifies that "hot exit" works for dirty files (with delay)', async function () {209return testHotExit.call(this, `test_verifies_that_hot_exit_works_for_dirty_files_with_delay_from_stable`, 2000);210});211212async function testHotExit(this: import('mocha').Context, title: string, restartDelay: number | undefined) {213const { stableCodePath, stableCodeVersion } = ensureStableCode();214if (!stableCodePath) {215this.skip();216}217218const userDataDir = getRandomUserDataDir(this.defaultOptions.userDataDir);219const logsPath = suiteLogsPath(this.defaultOptions, title);220const crashesPath = suiteCrashPath(this.defaultOptions, title);221222const stableOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);223stableOptions.codePath = stableCodePath;224stableOptions.userDataDir = userDataDir;225stableOptions.quality = Quality.Stable;226stableOptions.logsPath = logsPath;227stableOptions.crashesPath = crashesPath;228stableOptions.version = stableCodeVersion ?? { major: 0, minor: 0, patch: 0 };229230stableApp = new Application(stableOptions);231await stableApp.start();232233const textToTypeInUntitled = 'Hello from Untitled';234235await stableApp.workbench.editors.newUntitledFile();236await stableApp.workbench.editor.waitForTypeInEditor('Untitled-1', textToTypeInUntitled);237await stableApp.workbench.editors.waitForTab('Untitled-1', true);238239const textToType = 'Hello, Code';240await stableApp.workbench.quickaccess.openFile(join(stableApp.workspacePathOrFolder, 'readme.md'));241await stableApp.workbench.editor.waitForTypeInEditor('readme.md', textToType);242await stableApp.workbench.editors.waitForTab('readme.md', true);243244if (typeof restartDelay === 'number') {245// this is an OK use of a timeout in a smoke test246// we want to simulate a user having typed into247// the editor and pausing for a moment before248// terminating249await timeout(restartDelay);250}251252await stableApp.stop();253stableApp = undefined;254255const insiderOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);256insiderOptions.userDataDir = userDataDir;257insiderOptions.logsPath = logsPath;258insiderOptions.crashesPath = crashesPath;259260insidersApp = new Application(insiderOptions);261await insidersApp.start();262263await insidersApp.workbench.editors.waitForTab('readme.md', true);264await insidersApp.workbench.editors.waitForTab('Untitled-1', true);265266await insidersApp.workbench.editors.selectTab('readme.md');267await insidersApp.workbench.editor.waitForEditorContents('readme.md', contents => contents.indexOf(textToType) > -1);268269await insidersApp.workbench.editors.selectTab('Untitled-1');270await insidersApp.workbench.editor.waitForEditorContents('Untitled-1', contents => contents.indexOf(textToTypeInUntitled) > -1);271272await insidersApp.stop();273insidersApp = undefined;274}275});276}277278279