wip: single application run in goddamn smoketests

This commit is contained in:
Joao Moreno 2017-10-25 21:41:45 +02:00
parent a89b4e8ae8
commit 7e9bb8ad28
17 changed files with 250 additions and 209 deletions

View file

@ -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{}');

View file

@ -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';

View file

@ -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);

View file

@ -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',

View file

@ -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();

View file

@ -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 });
});
});

View file

@ -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);
});
});
// 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);
// });
// });

View file

@ -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();
});
});

View file

@ -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<void> {
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<void> {
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');
}
}

View file

@ -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');

View file

@ -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'));

View file

@ -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';

View file

@ -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.`);
});
});
// 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.`);
// });
// });

View file

@ -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;
}

View file

@ -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<void> {
}).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';
// import './areas/statusbar/statusbar.test';
// import './areas/extensions/extensions.test';
// import './areas/workbench/localization.test';

View file

@ -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<number> {
@ -43,13 +37,27 @@ export async function findFreePort(): Promise<number> {
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<void>) | 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<any> {
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);
}

View file

@ -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<any> {