From 7e9bb8ad28084d89c26d08eb3fa04931da5fa172 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Oct 2017 21:41:45 +0200 Subject: [PATCH] wip: single application run in goddamn smoketests --- test/smoke/src/areas/css/css.test.ts | 13 +- test/smoke/src/areas/debug/debug.test.ts | 44 ++++--- test/smoke/src/areas/editor/editor.test.ts | 9 +- .../smoke/src/areas/explorer/explorer.test.ts | 6 +- .../src/areas/extensions/extensions.test.ts | 4 +- test/smoke/src/areas/git/git.test.ts | 4 +- .../src/areas/multiroot/multiroot.test.ts | 40 +++--- .../src/areas/preferences/preferences.test.ts | 12 +- test/smoke/src/areas/preferences/settings.ts | 10 ++ test/smoke/src/areas/search/search.test.ts | 8 +- .../src/areas/statusbar/statusbar.test.ts | 6 +- .../src/areas/workbench/data-loss.test.ts | 5 +- .../areas/workbench/data-migration.test.ts | 120 +++++++++--------- .../src/areas/workbench/localization.test.ts | 4 +- test/smoke/src/main.ts | 76 ++++++----- test/smoke/src/spectron/application.ts | 88 +++++++------ test/smoke/src/spectron/client.ts | 10 +- 17 files changed, 250 insertions(+), 209 deletions(-) diff --git a/test/smoke/src/areas/css/css.test.ts b/test/smoke/src/areas/css/css.test.ts index d0b4c01b201..8db2e4608c9 100644 --- a/test/smoke/src/areas/css/css.test.ts +++ b/test/smoke/src/areas/css/css.test.ts @@ -8,18 +8,16 @@ import { SpectronApplication } from '../../spectron/application'; import { ProblemSeverity, Problems } from '../problems/problems'; describe('CSS', () => { - let app: SpectronApplication; - before(function () { app = new SpectronApplication(); return app.start('CSS'); }); - after(() => app.stop()); - - it('verifies quick outline', async () => { + it('verifies quick outline', async function () { + const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('style.css'); await app.workbench.editor.openOutline(); await app.workbench.quickopen.waitForQuickOpenElements(names => names.length === 2); }); - it('verifies warnings for the empty rule', async () => { + it('verifies warnings for the empty rule', async function () { + const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('style.css'); await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}'); @@ -34,7 +32,8 @@ describe('CSS', () => { await app.workbench.problems.hideProblemsView(); }); - it('verifies that warning becomes an error once setting changed', async () => { + it('verifies that warning becomes an error once setting changed', async function () { + const app = this.app as SpectronApplication; await app.workbench.settingsEditor.addUserSetting('css.lint.emptyRules', '"error"'); await app.workbench.quickopen.openFile('style.css'); await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}'); diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 5c7a759eb40..ae446ddd60b 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -9,34 +9,36 @@ import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import * as stripJsonComments from 'strip-json-comments'; -import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR, findFreePort, WORKSPACE_PATH } from '../../spectron/application'; +import { SpectronApplication, Quality, findFreePort } from '../../spectron/application'; describe('Debug', () => { - let app: SpectronApplication = new SpectronApplication(); let port: number; + before(function () { + const app = this.app as SpectronApplication; - if (app.build === VSCODE_BUILD.DEV) { - const extensionsPath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions'); + if (app.quality === Quality.Dev) { + const extensionsPath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions'); - const debugPath = path.join(extensionsPath, 'vscode-node-debug'); - const debugExists = fs.existsSync(debugPath); + const debugPath = path.join(extensionsPath, 'vscode-node-debug'); + const debugExists = fs.existsSync(debugPath); - const debug2Path = path.join(extensionsPath, 'vscode-node-debug2'); - const debug2Exists = fs.existsSync(debug2Path); + const debug2Path = path.join(extensionsPath, 'vscode-node-debug2'); + const debug2Exists = fs.existsSync(debug2Path); - if (!debugExists) { - console.warn(`Skipping debug tests because vscode-node-debug extension was not found in ${extensionsPath}`); - return; + if (!debugExists) { + console.warn(`Skipping debug tests because vscode-node-debug extension was not found in ${extensionsPath}`); + return; + } + + if (!debug2Exists) { + console.warn(`Skipping debug tests because vscode-node-debug2 extension was not found in ${extensionsPath}`); + return; + } + + fs.symlinkSync(debugPath, path.join(app.extensionsPath, 'vscode-node-debug')); + fs.symlinkSync(debug2Path, path.join(app.extensionsPath, 'vscode-node-debug2')); } - - if (!debug2Exists) { - console.warn(`Skipping debug tests because vscode-node-debug2 extension was not found in ${extensionsPath}`); - return; - } - - fs.symlinkSync(debugPath, path.join(EXTENSIONS_DIR, 'vscode-node-debug')); - fs.symlinkSync(debug2Path, path.join(EXTENSIONS_DIR, 'vscode-node-debug2')); - } + }); // We must get a different port for our smoketest express app // otherwise concurrent test runs will clash on those ports @@ -48,7 +50,7 @@ describe('Debug', () => { await app.workbench.quickopen.openFile('app.js'); await app.workbench.debug.configure(); - const launchJsonPath = path.join(WORKSPACE_PATH, '.vscode', 'launch.json'); + const launchJsonPath = path.join(app.workspacePath, '.vscode', 'launch.json'); const content = fs.readFileSync(launchJsonPath, 'utf8'); const config = JSON.parse(stripJsonComments(content)); config.configurations[0].protocol = 'inspector'; diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts index 72a537c4e23..8726fa75303 100644 --- a/test/smoke/src/areas/editor/editor.test.ts +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -6,11 +6,8 @@ import { SpectronApplication } from '../../spectron/application'; describe('Editor', () => { - let app: SpectronApplication; - before(() => { app = new SpectronApplication(); return app.start('Editor'); }); - after(() => app.stop()); - it('shows correct quick outline', async function () { + const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('www'); await app.workbench.editor.openOutline(); @@ -18,6 +15,7 @@ describe('Editor', () => { }); it(`finds 'All References' to 'app'`, async function () { + const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('www'); const references = await app.workbench.editor.findReferences('app', 7); @@ -28,6 +26,7 @@ describe('Editor', () => { }); it(`renames local 'app' variable`, async function () { + const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('www'); await app.workbench.editor.rename('www', 7, 'app', 'newApp'); await app.workbench.editor.waitForEditorContents('www', contents => contents.indexOf('newApp') > -1); @@ -51,6 +50,7 @@ describe('Editor', () => { // }); it(`verifies that 'Go To Definition' works`, async function () { + const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('app.js'); await app.workbench.editor.gotoDefinition('express', 11); @@ -59,6 +59,7 @@ describe('Editor', () => { }); it(`verifies that 'Peek Definition' works`, async function () { + const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('app.js'); const peek = await app.workbench.editor.peekDefinition('express', 11); diff --git a/test/smoke/src/areas/explorer/explorer.test.ts b/test/smoke/src/areas/explorer/explorer.test.ts index 581851e0ab8..8fdd463cff0 100644 --- a/test/smoke/src/areas/explorer/explorer.test.ts +++ b/test/smoke/src/areas/explorer/explorer.test.ts @@ -6,11 +6,8 @@ import { SpectronApplication } from '../../spectron/application'; describe('Explorer', () => { - let app: SpectronApplication; - before(() => { app = new SpectronApplication(); return app.start('Explorer'); }); - after(() => app.stop()); - it('quick open search produces correct result', async function () { + const app = this.app as SpectronApplication; const expectedNames = [ '.eslintrc.json', 'tasks.json', @@ -27,6 +24,7 @@ describe('Explorer', () => { }); it('quick open respects fuzzy matching', async function () { + const app = this.app as SpectronApplication; const expectedNames = [ 'tasks.json', 'app.js', diff --git a/test/smoke/src/areas/extensions/extensions.test.ts b/test/smoke/src/areas/extensions/extensions.test.ts index 316d0a2a72c..572ab6faa1e 100644 --- a/test/smoke/src/areas/extensions/extensions.test.ts +++ b/test/smoke/src/areas/extensions/extensions.test.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { SpectronApplication, VSCODE_BUILD } from '../../spectron/application'; +import { SpectronApplication, Quality } from '../../spectron/application'; describe('Extensions', () => { let app: SpectronApplication = new SpectronApplication(); before(() => app.start('Extensions')); after(() => app.stop()); - if (app.build !== VSCODE_BUILD.DEV) { + if (app.quality !== Quality.Dev) { it(`install and activate vscode-smoketest-check extension`, async function () { const extensionName = 'vscode-smoketest-check'; await app.workbench.extensions.openExtensionsViewlet(); diff --git a/test/smoke/src/areas/git/git.test.ts b/test/smoke/src/areas/git/git.test.ts index 57c0240b1d4..32450b9b3a3 100644 --- a/test/smoke/src/areas/git/git.test.ts +++ b/test/smoke/src/areas/git/git.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import * as cp from 'child_process'; -import { SpectronApplication, WORKSPACE_PATH } from '../../spectron/application'; +import { SpectronApplication } from '../../spectron/application'; const DIFF_EDITOR_LINE_INSERT = '.monaco-diff-editor .editor.modified .line-insert'; const SYNC_STATUSBAR = 'div[id="workbench.parts.statusbar"] .statusbar-entry a[title$="Synchronize Changes"]'; @@ -73,6 +73,6 @@ describe('Git', () => { await app.workbench.scm.commit('second commit'); await app.client.waitForText(SYNC_STATUSBAR, ' 0↓ 2↑'); - cp.execSync('git reset --hard origin/master', { cwd: WORKSPACE_PATH }); + cp.execSync('git reset --hard origin/master', { cwd: app.workspacePath }); }); }); \ No newline at end of file diff --git a/test/smoke/src/areas/multiroot/multiroot.test.ts b/test/smoke/src/areas/multiroot/multiroot.test.ts index f341f3da137..4fe8d35146f 100644 --- a/test/smoke/src/areas/multiroot/multiroot.test.ts +++ b/test/smoke/src/areas/multiroot/multiroot.test.ts @@ -3,28 +3,28 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { SpectronApplication, CODE_WORKSPACE_PATH, VSCODE_BUILD } from '../../spectron/application'; +// import * as assert from 'assert'; +// import { SpectronApplication, CODE_WORKSPACE_PATH, VSCODE_BUILD } from '../../spectron/application'; -describe('Multiroot', () => { - let app: SpectronApplication = new SpectronApplication(void 0, CODE_WORKSPACE_PATH); - if (app.build === VSCODE_BUILD.STABLE) { - return; - } +// describe('Multiroot', () => { +// let app: SpectronApplication = new SpectronApplication(void 0, CODE_WORKSPACE_PATH); +// if (app.quality === VSCODE_BUILD.STABLE) { +// return; +// } - before(() => app.start('Multi Root')); - after(() => app.stop()); +// before(() => app.start('Multi Root')); +// after(() => app.stop()); - it('shows results from all folders', async function () { - await app.workbench.quickopen.openQuickOpen('*.*'); +// it('shows results from all folders', async function () { +// await app.workbench.quickopen.openQuickOpen('*.*'); - await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6); - await app.workbench.quickopen.closeQuickOpen(); - }); +// await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6); +// await app.workbench.quickopen.closeQuickOpen(); +// }); - it('shows workspace name in title', async function () { - const title = await app.client.getTitle(); - await app.screenCapturer.capture('window title'); - assert.ok(title.indexOf('smoketest (Workspace)') >= 0); - }); -}); \ No newline at end of file +// it('shows workspace name in title', async function () { +// const title = await app.client.getTitle(); +// await app.screenCapturer.capture('window title'); +// assert.ok(title.indexOf('smoketest (Workspace)') >= 0); +// }); +// }); \ No newline at end of file diff --git a/test/smoke/src/areas/preferences/preferences.test.ts b/test/smoke/src/areas/preferences/preferences.test.ts index 4a9939bf2b3..111c2461f1d 100644 --- a/test/smoke/src/areas/preferences/preferences.test.ts +++ b/test/smoke/src/areas/preferences/preferences.test.ts @@ -9,11 +9,9 @@ import { SpectronApplication } from '../../spectron/application'; import { ActivityBarPosition } from '../activitybar/activityBar'; describe('Preferences', () => { - let app: SpectronApplication; - before(() => { app = new SpectronApplication(); return app.start('Preferences'); }); - after(() => app.stop()); - it('turns off editor line numbers and verifies the live change', async function () { + const app = this.app as SpectronApplication; + await app.workbench.explorer.openFile('app.js'); let lineNumbers = await app.client.waitForElements('.line-numbers'); await app.screenCapturer.capture('app.js has line numbers'); @@ -28,6 +26,7 @@ describe('Preferences', () => { }); it(`changes 'workbench.action.toggleSidebarPosition' command key binding and verifies it`, async function () { + const app = this.app as SpectronApplication; assert.ok(await app.workbench.activitybar.getActivityBar(ActivityBarPosition.LEFT), 'Activity bar should be positioned on the left.'); await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', ['Control', 'u'], 'Control+U'); @@ -35,4 +34,9 @@ describe('Preferences', () => { await app.client.keys(['Control', 'u', 'NULL']); assert.ok(await app.workbench.activitybar.getActivityBar(ActivityBarPosition.RIGHT), 'Activity bar was not moved to right after toggling its position.'); }); + + after(async function () { + const app = this.app as SpectronApplication; + await app.workbench.settingsEditor.clearUserSettings(); + }); }); \ No newline at end of file diff --git a/test/smoke/src/areas/preferences/settings.ts b/test/smoke/src/areas/preferences/settings.ts index ce28c1b2c9e..37352e30c8e 100644 --- a/test/smoke/src/areas/preferences/settings.ts +++ b/test/smoke/src/areas/preferences/settings.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as fs from 'fs'; +import * as path from 'path'; import { SpectronApplication } from '../../spectron/application'; export enum ActivityBarPosition { @@ -19,6 +21,7 @@ export class SettingsEditor { async addUserSetting(setting: string, value: string): Promise { await this.spectron.runCommand('workbench.action.openGlobalSettings'); + await this.spectron.client.waitAndClick(SEARCH_INPUT); await this.spectron.client.waitForActiveElement(SEARCH_INPUT); await this.spectron.client.keys(['ArrowDown', 'NULL']); @@ -32,4 +35,11 @@ export class SettingsEditor { await this.spectron.screenCapturer.capture('user settings has changed'); } + + async clearUserSettings(): Promise { + const settingsPath = path.join(this.spectron.userDataPath, 'User', 'settings.json'); + await new Promise((c, e) => fs.writeFile(settingsPath, '{}', 'utf8', err => err ? e(err) : c())); + + await this.spectron.workbench.editor.waitForEditorContents('settings.json', c => c.length === 0, '.editable-preferences-editor-container'); + } } \ No newline at end of file diff --git a/test/smoke/src/areas/search/search.test.ts b/test/smoke/src/areas/search/search.test.ts index 60972beb081..3936ad64772 100644 --- a/test/smoke/src/areas/search/search.test.ts +++ b/test/smoke/src/areas/search/search.test.ts @@ -6,11 +6,8 @@ import { SpectronApplication } from '../../spectron/application'; describe('Search', () => { - let app: SpectronApplication; - before(() => { app = new SpectronApplication(); return app.start('Search'); }); - after(() => app.stop()); - it('searches for body & checks for correct result number', async function () { + const app = this.app as SpectronApplication; await app.workbench.search.openSearchViewlet(); await app.workbench.search.searchFor('body'); @@ -18,6 +15,7 @@ describe('Search', () => { }); it('searches only for *.js files & checks for correct result number', async function () { + const app = this.app as SpectronApplication; await app.workbench.search.searchFor('body'); await app.workbench.search.showQueryDetails(); await app.workbench.search.setFilesToIncludeText('*.js'); @@ -29,12 +27,14 @@ describe('Search', () => { }); it('dismisses result & checks for correct result number', async function () { + const app = this.app as SpectronApplication; await app.workbench.search.searchFor('body'); await app.workbench.search.removeFileMatch(1); await app.workbench.search.waitForResultText('3 results in 3 files'); }); it('replaces first search result with a replace term', async function () { + const app = this.app as SpectronApplication; await app.workbench.search.searchFor('body'); await app.workbench.search.setReplaceText('ydob'); diff --git a/test/smoke/src/areas/statusbar/statusbar.test.ts b/test/smoke/src/areas/statusbar/statusbar.test.ts index 9ea1798e130..32b7c2ebe9f 100644 --- a/test/smoke/src/areas/statusbar/statusbar.test.ts +++ b/test/smoke/src/areas/statusbar/statusbar.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; -import { SpectronApplication, VSCODE_BUILD } from '../../spectron/application'; +import { SpectronApplication, Quality } from '../../spectron/application'; import { StatusBarElement } from './statusbar'; @@ -16,7 +16,7 @@ describe('Statusbar', () => { it('verifies presence of all default status bar elements', async function () { await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.BRANCH_STATUS); - if (app.build !== VSCODE_BUILD.DEV) { + if (app.quality !== Quality.Dev) { await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.FEEDBACK_ICON); } await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.SYNC_STATUS); @@ -55,7 +55,7 @@ describe('Statusbar', () => { await app.workbench.problems.waitForProblemsView(); }); - if (app.build !== VSCODE_BUILD.DEV) { + if (app.quality !== Quality.Dev) { it(`verifies that 'Tweet us feedback' pop-up appears when clicking on 'Feedback' icon`, async function () { await app.workbench.statusbar.clickOn(StatusBarElement.FEEDBACK_ICON); assert.ok(!!await app.client.waitForElement('.feedback-form')); diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index 68d7dd1b377..18f6e6cc3c4 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -6,11 +6,8 @@ import { SpectronApplication } from '../../spectron/application'; describe('Dataloss', () => { - let app: SpectronApplication; - before(() => { app = new SpectronApplication(); return app.start('Dataloss'); }); - after(() => app.stop()); - it(`verifies that 'hot exit' works for dirty files`, async function () { + const app = this.app as SpectronApplication; await app.workbench.newUntitledFile(); const untitled = 'Untitled-1'; diff --git a/test/smoke/src/areas/workbench/data-migration.test.ts b/test/smoke/src/areas/workbench/data-migration.test.ts index d52859bc1ae..98213b85803 100644 --- a/test/smoke/src/areas/workbench/data-migration.test.ts +++ b/test/smoke/src/areas/workbench/data-migration.test.ts @@ -3,85 +3,85 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; +// import * as assert from 'assert'; -import { SpectronApplication, STABLE_PATH, LATEST_PATH } from '../../spectron/application'; -import { Util } from '../../helpers/utilities'; +// import { SpectronApplication, STABLE_PATH, LATEST_PATH } from '../../spectron/application'; +// import { Util } from '../../helpers/utilities'; -describe('Data Migration', () => { +// describe('Data Migration', () => { - if (!STABLE_PATH) { - return; - } +// if (!STABLE_PATH) { +// return; +// } - let app: SpectronApplication; - afterEach(() => app.stop()); +// let app: SpectronApplication; +// afterEach(() => app.stop()); - it('checks if the Untitled file is restored migrating from stable to latest', async function () { - const textToType = 'Very dirty file'; +// it('checks if the Untitled file is restored migrating from stable to latest', async function () { +// const textToType = 'Very dirty file'; - // Setting up stable version - let app = new SpectronApplication(STABLE_PATH); - await app.start('Data Migration'); +// // Setting up stable version +// let app = new SpectronApplication(STABLE_PATH); +// await app.start('Data Migration'); - await app.workbench.newUntitledFile(); - await app.workbench.editor.waitForTypeInEditor('Untitled-1', textToType); +// await app.workbench.newUntitledFile(); +// await app.workbench.editor.waitForTypeInEditor('Untitled-1', textToType); - await app.stop(); - await new Promise(c => setTimeout(c, 500)); // wait until all resources are released (e.g. locked local storage) - // Checking latest version for the restored state +// await app.stop(); +// await new Promise(c => setTimeout(c, 500)); // wait until all resources are released (e.g. locked local storage) +// // Checking latest version for the restored state - app = new SpectronApplication(LATEST_PATH); - await app.start('Data Migration'); +// app = new SpectronApplication(LATEST_PATH); +// await app.start('Data Migration'); - assert.ok(await app.workbench.waitForActiveTab('Untitled-1', true), `Untitled-1 tab is not present after migration.`); +// assert.ok(await app.workbench.waitForActiveTab('Untitled-1', true), `Untitled-1 tab is not present after migration.`); - await app.workbench.editor.waitForEditorContents('Untitled-1', c => c.indexOf(textToType) > -1); - await app.screenCapturer.capture('Untitled file text'); - }); +// await app.workbench.editor.waitForEditorContents('Untitled-1', c => c.indexOf(textToType) > -1); +// await app.screenCapturer.capture('Untitled file text'); +// }); - it('checks if the newly created dirty file is restored migrating from stable to latest', async function () { - const fileName = 'test_data/plainFile', - firstTextPart = 'This is going to be an unsaved file', secondTextPart = '_that is dirty.'; +// it('checks if the newly created dirty file is restored migrating from stable to latest', async function () { +// const fileName = 'test_data/plainFile', +// firstTextPart = 'This is going to be an unsaved file', secondTextPart = '_that is dirty.'; - // Setting up stable version - let app = new SpectronApplication(STABLE_PATH, fileName); - await Util.removeFile(`${fileName}`); - await app.start('Data Migration'); +// // Setting up stable version +// let app = new SpectronApplication(STABLE_PATH, fileName); +// await Util.removeFile(`${fileName}`); +// await app.start('Data Migration'); - await app.workbench.editor.waitForTypeInEditor('plainFile', firstTextPart); - await app.workbench.saveOpenedFile(); - await app.workbench.editor.waitForTypeInEditor('plainFile', secondTextPart); +// await app.workbench.editor.waitForTypeInEditor('plainFile', firstTextPart); +// await app.workbench.saveOpenedFile(); +// await app.workbench.editor.waitForTypeInEditor('plainFile', secondTextPart); - await app.stop(); - await new Promise(c => setTimeout(c, 1000)); // wait until all resources are released (e.g. locked local storage) +// await app.stop(); +// await new Promise(c => setTimeout(c, 1000)); // wait until all resources are released (e.g. locked local storage) - // Checking latest version for the restored state - app = new SpectronApplication(LATEST_PATH); - await app.start('Data Migration'); +// // Checking latest version for the restored state +// app = new SpectronApplication(LATEST_PATH); +// await app.start('Data Migration'); - const filename = fileName.split('/')[1]; - assert.ok(await app.workbench.waitForActiveTab(filename), `Untitled-1 tab is not present after migration.`); - await app.workbench.editor.waitForEditorContents(filename, c => c.indexOf(firstTextPart + secondTextPart) > -1); +// const filename = fileName.split('/')[1]; +// assert.ok(await app.workbench.waitForActiveTab(filename), `Untitled-1 tab is not present after migration.`); +// await app.workbench.editor.waitForEditorContents(filename, c => c.indexOf(firstTextPart + secondTextPart) > -1); - await Util.removeFile(`${fileName}`); - }); +// await Util.removeFile(`${fileName}`); +// }); - it('cheks if opened tabs are restored migrating from stable to latest', async function () { - const fileName1 = 'app.js', fileName2 = 'jsconfig.json', fileName3 = 'readme.md'; - let app = new SpectronApplication(STABLE_PATH); - await app.start('Data Migration'); +// it('cheks if opened tabs are restored migrating from stable to latest', async function () { +// const fileName1 = 'app.js', fileName2 = 'jsconfig.json', fileName3 = 'readme.md'; +// let app = new SpectronApplication(STABLE_PATH); +// await app.start('Data Migration'); - await app.workbench.quickopen.openFile(fileName1); - await app.workbench.quickopen.openFile(fileName2); - await app.workbench.quickopen.openFile(fileName3); - await app.stop(); +// await app.workbench.quickopen.openFile(fileName1); +// await app.workbench.quickopen.openFile(fileName2); +// await app.workbench.quickopen.openFile(fileName3); +// await app.stop(); - app = new SpectronApplication(LATEST_PATH); - await app.start('Data Migration'); +// app = new SpectronApplication(LATEST_PATH); +// await app.start('Data Migration'); - assert.ok(await app.workbench.waitForTab(fileName1), `${fileName1} tab was not restored after migration.`); - assert.ok(await app.workbench.waitForTab(fileName2), `${fileName2} tab was not restored after migration.`); - assert.ok(await app.workbench.waitForTab(fileName3), `${fileName3} tab was not restored after migration.`); - }); -}); \ No newline at end of file +// assert.ok(await app.workbench.waitForTab(fileName1), `${fileName1} tab was not restored after migration.`); +// assert.ok(await app.workbench.waitForTab(fileName2), `${fileName2} tab was not restored after migration.`); +// assert.ok(await app.workbench.waitForTab(fileName3), `${fileName3} tab was not restored after migration.`); +// }); +// }); \ No newline at end of file diff --git a/test/smoke/src/areas/workbench/localization.test.ts b/test/smoke/src/areas/workbench/localization.test.ts index 059eb5415de..682745aa086 100644 --- a/test/smoke/src/areas/workbench/localization.test.ts +++ b/test/smoke/src/areas/workbench/localization.test.ts @@ -5,11 +5,11 @@ import * as assert from 'assert'; -import { SpectronApplication, VSCODE_BUILD } from '../../spectron/application'; +import { SpectronApplication, Quality } from '../../spectron/application'; describe('Localization', () => { let app: SpectronApplication = new SpectronApplication(); - if (app.build === VSCODE_BUILD.DEV) { + if (app.quality === Quality.Dev) { return; } diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index d78cc255a2c..cd0133da15c 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -11,6 +11,7 @@ import * as minimist from 'minimist'; import * as tmp from 'tmp'; import * as rimraf from 'rimraf'; import * as mkdirp from 'mkdirp'; +import { SpectronApplication, Quality } from './spectron/application'; const tmpDir = tmp.dirSync({ prefix: 't' }) as { name: string; removeCallback: Function; }; const testDataPath = tmpDir.name; @@ -26,11 +27,11 @@ const opts = minimist(args, { ] }); -process.env.ARTIFACTS_DIR = opts.log || ''; +const artifactsPath = opts.log || ''; -const workspacePath = path.join(testDataPath, 'smoketest.code-workspace'); +const workspaceFilePath = path.join(testDataPath, 'smoketest.code-workspace'); const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express'; -const testRepoLocalDir = path.join(testDataPath, 'vscode-smoketest-express'); +const workspacePath = path.join(testDataPath, 'vscode-smoketest-express'); const keybindingsPath = path.join(testDataPath, 'keybindings.json'); const extensionsPath = path.join(testDataPath, 'extensions-dir'); mkdirp.sync(extensionsPath); @@ -81,38 +82,37 @@ function getBuildElectronPath(root: string): string { let testCodePath = opts.build; let stableCodePath = opts['stable-build']; +let electronPath: string; if (testCodePath) { - process.env.VSCODE_PATH = getBuildElectronPath(testCodePath); + electronPath = getBuildElectronPath(testCodePath); if (stableCodePath) { process.env.VSCODE_STABLE_PATH = getBuildElectronPath(stableCodePath); } } else { testCodePath = getDevElectronPath(); - process.env.VSCODE_PATH = testCodePath; + electronPath = testCodePath; process.env.VSCODE_REPOSITORY = repoPath; process.env.VSCODE_DEV = '1'; process.env.VSCODE_CLI = '1'; } -if (!fs.existsSync(process.env.VSCODE_PATH || '')) { - fail(`Can't find Code at ${process.env.VSCODE_PATH}.`); +if (!fs.existsSync(electronPath || '')) { + fail(`Can't find Code at ${electronPath}.`); } -process.env.VSCODE_USER_DIR = path.join(testDataPath, 'd'); -process.env.VSCODE_EXTENSIONS_DIR = extensionsPath; -process.env.SMOKETEST_REPO = testRepoLocalDir; -process.env.VSCODE_WORKSPACE_PATH = workspacePath; +const userDataDir = path.join(testDataPath, 'd'); +// process.env.VSCODE_WORKSPACE_PATH = workspaceFilePath; process.env.VSCODE_KEYBINDINGS_PATH = keybindingsPath; -process.env.WAIT_TIME = opts['wait-time'] || '20'; +let quality: Quality; if (process.env.VSCODE_DEV === '1') { - process.env.VSCODE_EDITION = 'dev'; + quality = Quality.Dev; } else if ((testCodePath.indexOf('Code - Insiders') /* macOS/Windows */ || testCodePath.indexOf('code-insiders') /* Linux */) >= 0) { - process.env.VSCODE_EDITION = 'insiders'; + quality = Quality.Insiders; } else { - process.env.VSCODE_EDITION = 'stable'; + quality = Quality.Stable; } function getKeybindingPlatform(): string { @@ -148,37 +148,37 @@ async function setup(): Promise { }).on('error', e); }); - if (!fs.existsSync(workspacePath)) { + if (!fs.existsSync(workspaceFilePath)) { console.log('*** Creating workspace file...'); const workspace = { folders: [ { - path: toUri(path.join(testRepoLocalDir, 'public')) + path: toUri(path.join(workspacePath, 'public')) }, { - path: toUri(path.join(testRepoLocalDir, 'routes')) + path: toUri(path.join(workspacePath, 'routes')) }, { - path: toUri(path.join(testRepoLocalDir, 'views')) + path: toUri(path.join(workspacePath, 'views')) } ] }; - fs.writeFileSync(workspacePath, JSON.stringify(workspace, null, '\t')); + fs.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, '\t')); } - if (!fs.existsSync(testRepoLocalDir)) { + if (!fs.existsSync(workspacePath)) { console.log('*** Cloning test project repository...'); - cp.spawnSync('git', ['clone', testRepoUrl, testRepoLocalDir]); + cp.spawnSync('git', ['clone', testRepoUrl, workspacePath]); } else { console.log('*** Cleaning test project repository...'); - cp.spawnSync('git', ['fetch'], { cwd: testRepoLocalDir }); - cp.spawnSync('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: testRepoLocalDir }); - cp.spawnSync('git', ['clean', '-xdf'], { cwd: testRepoLocalDir }); + cp.spawnSync('git', ['fetch'], { cwd: workspacePath }); + cp.spawnSync('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: workspacePath }); + cp.spawnSync('git', ['clean', '-xdf'], { cwd: workspacePath }); } console.log('*** Running npm install...'); - cp.execSync('npm install', { cwd: testRepoLocalDir, stdio: 'inherit' }); + cp.execSync('npm install', { cwd: workspacePath, stdio: 'inherit' }); console.log('*** Smoketest setup done!\n'); } @@ -207,9 +207,21 @@ before(async function () { // allow two minutes for setup this.timeout(2 * 60 * 1000); await setup(); + + this.app = new SpectronApplication({ + quality, + electronPath, + workspacePath, + userDataDir, + extensionsPath, + artifactsPath, + waitTime: parseInt(opts['wait-time'] || '0') || 20 + }); + await this.app.start('foo'); }); -after(async () => { +after(async function () { + await this.app.stop(); await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c())); }); @@ -218,12 +230,12 @@ import './areas/workbench/data-loss.test'; import './areas/explorer/explorer.test'; import './areas/preferences/preferences.test'; import './areas/search/search.test'; -import './areas/multiroot/multiroot.test'; +// import './areas/multiroot/multiroot.test'; import './areas/css/css.test'; import './areas/editor/editor.test'; import './areas/debug/debug.test'; -import './areas/git/git.test'; +// import './areas/git/git.test'; // import './areas/terminal/terminal.test'; -import './areas/statusbar/statusbar.test'; -import './areas/extensions/extensions.test'; -import './areas/workbench/localization.test'; \ No newline at end of file +// import './areas/statusbar/statusbar.test'; +// import './areas/extensions/extensions.test'; +// import './areas/workbench/localization.test'; \ No newline at end of file diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 6eb934214bf..48643c3b8c6 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -14,21 +14,15 @@ import * as path from 'path'; import * as mkdirp from 'mkdirp'; import { sanitize } from '../helpers/utilities'; -export const LATEST_PATH = process.env.VSCODE_PATH as string; -export const STABLE_PATH = process.env.VSCODE_STABLE_PATH || ''; -export const WORKSPACE_PATH = process.env.SMOKETEST_REPO as string; -export const CODE_WORKSPACE_PATH = process.env.VSCODE_WORKSPACE_PATH as string; -export const USER_DIR = process.env.VSCODE_USER_DIR as string; -export const EXTENSIONS_DIR = process.env.VSCODE_EXTENSIONS_DIR as string; -export const VSCODE_EDITION = process.env.VSCODE_EDITION as string; -export const ARTIFACTS_DIR = process.env.ARTIFACTS_DIR as string; -export const WAIT_TIME = parseInt(process.env.WAIT_TIME as string); - -export enum VSCODE_BUILD { - DEV, - INSIDERS, - STABLE -} +// export const LATEST_PATH = process.env.VSCODE_PATH as string; +// export const STABLE_PATH = process.env.VSCODE_STABLE_PATH || ''; +// export const WORKSPACE_PATH = process.env.SMOKETEST_REPO as string; +// export const CODE_WORKSPACE_PATH = process.env.VSCODE_WORKSPACE_PATH as string; +// export const USER_DIR = process.env.VSCODE_USER_DIR as string; +// export const EXTENSIONS_DIR = process.env.VSCODE_EXTENSIONS_DIR as string; +// export const VSCODE_EDITION = process.env.VSCODE_EDITION as string; +// export const ARTIFACTS_DIR = process.env.ARTIFACTS_DIR as string; +// export const WAIT_TIME = parseInt(process.env.WAIT_TIME as string); // Just hope random helps us here, cross your fingers! export async function findFreePort(): Promise { @@ -43,13 +37,27 @@ export async function findFreePort(): Promise { throw new Error('Could not find free port!'); } +export enum Quality { + Dev, + Insiders, + Stable +} + +export interface SpectronApplicationOptions { + quality: Quality; + electronPath: string; + workspacePath: string; + userDataDir: string; + extensionsPath: string; + artifactsPath: string; + waitTime: number; +} + /** * Wraps Spectron's Application instance with its used methods. */ export class SpectronApplication { - private static count = 0; - private _client: SpectronClient; private _workbench: Workbench; private _screenCapturer: ScreenCapturer; @@ -57,19 +65,14 @@ export class SpectronApplication { private keybindings: any[]; private stopLogCollection: (() => Promise) | undefined; constructor( - private _electronPath: string = LATEST_PATH, - private _workspace: string = WORKSPACE_PATH, - private _userDir: string = USER_DIR + private options: SpectronApplicationOptions + // private _electronPath: string = LATEST_PATH, + // private _workspace: string = WORKSPACE_PATH, + // private _userDir: string = USER_DIR ) { } - get build(): VSCODE_BUILD { - switch (VSCODE_EDITION) { - case 'dev': - return VSCODE_BUILD.DEV; - case 'insiders': - return VSCODE_BUILD.INSIDERS; - } - return VSCODE_BUILD.STABLE; + get quality(): Quality { + return this.options.quality; } get app(): Application { @@ -92,9 +95,21 @@ export class SpectronApplication { return this._workbench; } + get workspacePath(): string { + return this.options.workspacePath; + } + + get extensionsPath(): string { + return this.options.extensionsPath; + } + + get userDataPath(): string { + return this.options.userDataDir; + } + async start(testSuiteName: string, codeArgs: string[] = [], env = process.env): Promise { await this.retrieveKeybindings(); - cp.execSync('git checkout .', { cwd: WORKSPACE_PATH }); + cp.execSync('git checkout .', { cwd: this.options.workspacePath }); await this.startApplication(testSuiteName, codeArgs, env); await this.checkWindowReady(); await this.waitForWelcome(); @@ -129,7 +144,7 @@ export class SpectronApplication { args.push(process.env.VSCODE_REPOSITORY as string); } - args.push(this._workspace); + args.push(this.options.workspacePath); // Prevent 'Getting Started' web page from opening on clean user-data-dir args.push('--skip-getting-started'); @@ -149,12 +164,11 @@ export class SpectronApplication { args.push('--disable-crash-reporter'); // Ensure that running over custom extensions directory, rather than picking up the one that was used by a tester previously - args.push(`--extensions-dir=${EXTENSIONS_DIR}`); + args.push(`--extensions-dir=${this.options.extensionsPath}`); args.push(...codeArgs); - const id = String(SpectronApplication.count++); - chromeDriverArgs.push(`--user-data-dir=${path.join(this._userDir, id)}`); + chromeDriverArgs.push(`--user-data-dir=${this.options.userDataDir}`); // Spectron always uses the same port number for the chrome driver // and it handles gracefully when two instances use the same port number @@ -162,7 +176,7 @@ export class SpectronApplication { // chrome driver with it, leaving the other instance in DISPAIR!!! :( const port = await findFreePort(); const opts: any = { - path: this._electronPath, + path: this.options.electronPath, port, args, env, @@ -174,8 +188,8 @@ export class SpectronApplication { let testsuiteRootPath: string | undefined = undefined; let screenshotsDirPath: string | undefined = undefined; - if (ARTIFACTS_DIR) { - testsuiteRootPath = path.join(ARTIFACTS_DIR, sanitize(testSuiteName)); + if (this.options.artifactsPath) { + testsuiteRootPath = path.join(this.options.artifactsPath, sanitize(testSuiteName)); mkdirp.sync(testsuiteRootPath); // Collect screenshots @@ -229,7 +243,7 @@ export class SpectronApplication { } this._screenCapturer = new ScreenCapturer(this.spectron, screenshotsDirPath); - this._client = new SpectronClient(this.spectron, this); + this._client = new SpectronClient(this.spectron, this, this.options.waitTime); this._workbench = new Workbench(this); } diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts index 24857764b63..9ec19afd2f5 100644 --- a/test/smoke/src/spectron/client.ts +++ b/test/smoke/src/spectron/client.ts @@ -5,7 +5,7 @@ import { Application } from 'spectron'; import { RawResult, Element } from 'webdriverio'; -import { SpectronApplication, WAIT_TIME } from './application'; +import { SpectronApplication } from './application'; /** * Abstracts the Spectron's WebdriverIO managed client property on the created Application instances. @@ -17,8 +17,12 @@ export class SpectronClient { private retryCount: number; private readonly retryDuration = 100; // in milliseconds - constructor(readonly spectron: Application, private application: SpectronApplication) { - this.retryCount = (WAIT_TIME * 1000) / this.retryDuration; + constructor( + readonly spectron: Application, + private application: SpectronApplication, + waitTime: number + ) { + this.retryCount = (waitTime * 1000) / this.retryDuration; } windowByIndex(index: number): Promise {