Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -4,7 +4,7 @@
"name": "Jxck/assert",
"license": "MIT",
"licenseDetail": [
"The MIT License (MIT)",
"The Source EULA",
"",
"Copyright (c) 2011 Jxck",
"",

View File

@@ -48,6 +48,7 @@ function main() {
console.error(e.stack || e);
});
// {{SQL CARBON EDIT}}
var loaderConfig = {
nodeRequire: require,
nodeMain: __filename,
@@ -60,6 +61,7 @@ function main() {
'bootstrap': `../${ out }/bootstrap`
},
catchError: true,
// {{SQL CARBON EDIT}}
nodeModules: [
'@angular/common',
'@angular/core',
@@ -83,6 +85,7 @@ function main() {
loaderConfig.nodeInstrumenter = function (contents, source) {
seenSources[source] = true;
// {{SQL CARBON EDIT}}
if (minimatch(source, SQL_TEST_GLOB)) {
return contents;
}
@@ -297,12 +300,14 @@ function main() {
}
});
});
// {{SQL CARBON EDIT}}
*/
// replace the default unexpected error handler to be useful during tests
loader(['vs/base/common/errors'], function(errors) {
errors.setUnexpectedErrorHandler(function (err) {
let stack = (err && err.stack) || (new Error().stack);
// {{SQL CARBON EDIT}}
//unexpectedErrors.push((err && err.message ? err.message : err) + '\n' + stack);
});

59
test/grid.html Normal file
View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Grid Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="../out/vs/loader.js"></script>
<script>
require.config({ baseUrl: '../out' });
require(['vs/base/browser/ui/splitview/grid'], ({ Grid }) => {
const grid = new Grid(document.body);
const layout = () => grid.layout(document.body.clientWidth, document.body.clientHeight);
window.onresize = layout;
layout();
});
</script>
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.node {
width: 100%;
height: 100%;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.action {
display: inline-block;
width: 16px;
height: 16px;
border: 1px solid #3c3c3c;
text-align: center;
line-height: 16px;
border-radius: 3px;
}
.action:hover {
cursor: pointer;
background-color: #ffffff54;
}
</style>
</head>
<body>
</body>
</html>

View File

@@ -10,7 +10,7 @@ npm run smoketest
npm run smoketest -- --build "path/to/code"
# Data Migration tests
npm run smoketest -- --build "path/to/code-insiders" --stable "path/to/code"
npm run smoketest -- --build "path/to/code-insiders" --stable-build "path/to/code"
```
The script calls mocha, so all mocha arguments should work fine. For example, use `-f Git` to only run the `Git` tests.

View File

@@ -7,50 +7,52 @@ import * as assert from 'assert';
import { SpectronApplication } from '../../spectron/application';
import { ProblemSeverity, Problems } from '../problems/problems';
describe('CSS', () => {
before(function () {
this.app.suiteName = 'CSS';
export function setup() {
describe('CSS', () => {
before(function () {
this.app.suiteName = 'CSS';
});
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 function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('style.css');
await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}');
let warning = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.WARNING));
await app.screenCapturer.capture('CSS Warning in editor');
assert.ok(warning, `Warning squiggle is not shown in 'style.css'.`);
await app.workbench.problems.showProblemsView();
warning = await app.client.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.WARNING));
await app.screenCapturer.capture('CSS Warning in problems view');
assert.ok(warning, 'Warning does not appear in Problems view.');
await app.workbench.problems.hideProblemsView();
});
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{}');
let error = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.ERROR));
await app.screenCapturer.capture('CSS Error in editor');
assert.ok(error, `Warning squiggle is not shown in 'style.css'.`);
const problems = new Problems(app);
await problems.showProblemsView();
error = await app.client.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.ERROR));
await app.screenCapturer.capture('CSS Error in probles view');
assert.ok(error, 'Warning does not appear in Problems view.');
await problems.hideProblemsView();
});
});
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 function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('style.css');
await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}');
let warning = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.WARNING));
await app.screenCapturer.capture('CSS Warning in editor');
assert.ok(warning, `Warning squiggle is not shown in 'style.css'.`);
await app.workbench.problems.showProblemsView();
warning = await app.client.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.WARNING));
await app.screenCapturer.capture('CSS Warning in problems view');
assert.ok(warning, 'Warning does not appear in Problems view.');
await app.workbench.problems.hideProblemsView();
});
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{}');
let error = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.ERROR));
await app.screenCapturer.capture('CSS Error in editor');
assert.ok(error, `Warning squiggle is not shown in 'style.css'.`);
const problems = new Problems(app);
await problems.showProblemsView();
error = await app.client.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.ERROR));
await app.screenCapturer.capture('CSS Error in probles view');
assert.ok(error, 'Warning does not appear in Problems view.');
await problems.hideProblemsView();
});
});
}

View File

@@ -5,193 +5,125 @@
import * as assert from 'assert';
import * as http from 'http';
import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs';
import * as stripJsonComments from 'strip-json-comments';
import { SpectronApplication, Quality } from '../../spectron/application';
import { SpectronApplication } from '../../spectron/application';
describe('Debug', () => {
let skip = false;
before(async function () {
const app = this.app as SpectronApplication;
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 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}`);
skip = true;
return;
}
if (!debug2Exists) {
console.warn(`Skipping debug tests because vscode-node-debug2 extension was not found in ${extensionsPath}`);
skip = true;
return;
}
await new Promise((c, e) => fs.symlink(debugPath, path.join(app.extensionsPath, 'vscode-node-debug'), err => err ? e(err) : c()));
await new Promise((c, e) => fs.symlink(debug2Path, path.join(app.extensionsPath, 'vscode-node-debug2'), err => err ? e(err) : c()));
await app.reload();
}
this.app.suiteName = 'Debug';
});
it('configure launch json', async function () {
if (skip) {
this.skip();
return;
}
const app = this.app as SpectronApplication;
await app.workbench.debug.openDebugViewlet();
await app.workbench.quickopen.openFile('app.js');
await app.workbench.debug.configure();
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';
fs.writeFileSync(launchJsonPath, JSON.stringify(config, undefined, 4), 'utf8');
await app.workbench.editor.waitForEditorContents('launch.json', contents => /"protocol": "inspector"/.test(contents));
await app.screenCapturer.capture('launch.json file');
assert.equal(config.configurations[0].request, 'launch');
assert.equal(config.configurations[0].type, 'node');
if (process.platform === 'win32') {
assert.equal(config.configurations[0].program, '${workspaceFolder}\\bin\\www');
} else {
assert.equal(config.configurations[0].program, '${workspaceFolder}/bin/www');
}
});
it('breakpoints', async function () {
if (skip) {
this.skip();
return;
}
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('index.js');
await app.workbench.debug.setBreakpointOnLine(6);
await app.screenCapturer.capture('breakpoints are set');
});
let port: number;
it('start debugging', async function () {
if (skip) {
this.skip();
return;
}
const app = this.app as SpectronApplication;
port = await app.workbench.debug.startDebugging();
await app.screenCapturer.capture('debugging has started');
await new Promise((c, e) => {
const request = http.get(`http://localhost:${port}`);
request.on('error', e);
app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, 'looking for index.js and line 6').then(c, e);
export function setup() {
describe('Debug', () => {
before(async function () {
const app = this.app as SpectronApplication;
app.suiteName = 'Debug';
});
await app.screenCapturer.capture('debugging is paused');
});
it('configure launch json', async function () {
const app = this.app as SpectronApplication;
it('focus stack frames and variables', async function () {
if (skip) {
this.skip();
return;
}
await app.workbench.debug.openDebugViewlet();
await app.workbench.quickopen.openFile('app.js');
await app.workbench.debug.configure();
const app = this.app as SpectronApplication;
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';
fs.writeFileSync(launchJsonPath, JSON.stringify(config, undefined, 4), 'utf8');
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables');
await app.workbench.editor.waitForEditorContents('launch.json', contents => /"protocol": "inspector"/.test(contents));
await app.screenCapturer.capture('launch.json file');
await app.workbench.debug.focusStackFrame('layer.js', 'looking for layer.js');
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 5, 'there should be 5 local variables');
await app.workbench.debug.focusStackFrame('route.js', 'looking for route.js');
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 3, 'there should be 3 local variables');
await app.workbench.debug.focusStackFrame('index.js', 'looking for index.js');
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables');
});
it('stepOver, stepIn, stepOut', async function () {
if (skip) {
this.skip();
return;
}
const app = this.app as SpectronApplication;
await app.workbench.debug.stepIn();
await app.screenCapturer.capture('debugging has stepped in');
const first = await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js', 'looking for response.js');
await app.workbench.debug.stepOver();
await app.screenCapturer.capture('debugging has stepped over');
await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js' && sf.lineNumber === first.lineNumber + 1, `looking for response.js and line ${first.lineNumber + 1}`);
await app.workbench.debug.stepOut();
await app.screenCapturer.capture('debugging has stepped out');
await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 7, `looking for index.js and line 7`);
});
it('continue', async function () {
if (skip) {
this.skip();
return;
}
const app = this.app as SpectronApplication;
await app.workbench.debug.continue();
await app.screenCapturer.capture('debugging has continued');
await new Promise((c, e) => {
const request = http.get(`http://localhost:${port}`);
request.on('error', e);
app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, `looking for index.js and line 6`).then(c, e);
assert.equal(config.configurations[0].request, 'launch');
assert.equal(config.configurations[0].type, 'node');
if (process.platform === 'win32') {
assert.equal(config.configurations[0].program, '${workspaceFolder}\\bin\\www');
} else {
assert.equal(config.configurations[0].program, '${workspaceFolder}/bin/www');
}
});
await app.screenCapturer.capture('debugging is paused');
it('breakpoints', async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('index.js');
await app.workbench.debug.setBreakpointOnLine(6);
await app.screenCapturer.capture('breakpoints are set');
});
let port: number;
it('start debugging', async function () {
const app = this.app as SpectronApplication;
port = await app.workbench.debug.startDebugging();
await app.screenCapturer.capture('debugging has started');
await new Promise((c, e) => {
const request = http.get(`http://localhost:${port}`);
request.on('error', e);
app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, 'looking for index.js and line 6').then(c, e);
});
await app.screenCapturer.capture('debugging is paused');
});
it('focus stack frames and variables', async function () {
const app = this.app as SpectronApplication;
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables');
await app.workbench.debug.focusStackFrame('layer.js', 'looking for layer.js');
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 5, 'there should be 5 local variables');
await app.workbench.debug.focusStackFrame('route.js', 'looking for route.js');
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 3, 'there should be 3 local variables');
await app.workbench.debug.focusStackFrame('index.js', 'looking for index.js');
await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables');
});
it('stepOver, stepIn, stepOut', async function () {
const app = this.app as SpectronApplication;
await app.workbench.debug.stepIn();
await app.screenCapturer.capture('debugging has stepped in');
const first = await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js', 'looking for response.js');
await app.workbench.debug.stepOver();
await app.screenCapturer.capture('debugging has stepped over');
await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js' && sf.lineNumber === first.lineNumber + 1, `looking for response.js and line ${first.lineNumber + 1}`);
await app.workbench.debug.stepOut();
await app.screenCapturer.capture('debugging has stepped out');
await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 7, `looking for index.js and line 7`);
});
it('continue', async function () {
const app = this.app as SpectronApplication;
await app.workbench.debug.continue();
await app.screenCapturer.capture('debugging has continued');
await new Promise((c, e) => {
const request = http.get(`http://localhost:${port}`);
request.on('error', e);
app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, `looking for index.js and line 6`).then(c, e);
});
await app.screenCapturer.capture('debugging is paused');
});
it('debug console', async function () {
const app = this.app as SpectronApplication;
await app.workbench.debug.waitForReplCommand('2 + 2', r => r === '4');
});
it('stop debugging', async function () {
const app = this.app as SpectronApplication;
await app.workbench.debug.stopDebugging();
await app.screenCapturer.capture('debugging has stopped');
});
});
it('debug console', async function () {
if (skip) {
this.skip();
return;
}
const app = this.app as SpectronApplication;
await app.workbench.debug.waitForReplCommand('2 + 2', r => r === '4');
});
it('stop debugging', async function () {
if (skip) {
this.skip();
return;
}
const app = this.app as SpectronApplication;
await app.workbench.debug.stopDebugging();
await app.screenCapturer.capture('debugging has stopped');
});
});
}

View File

@@ -16,7 +16,7 @@ const STEP_IN = `.debug-actions-widget .debug-action.step-into`;
const STEP_OUT = `.debug-actions-widget .debug-action.step-out`;
const CONTINUE = `.debug-actions-widget .debug-action.continue`;
const GLYPH_AREA = '.margin-view-overlays>:nth-child';
const BREAKPOINT_GLYPH = '.debug-breakpoint-glyph';
const BREAKPOINT_GLYPH = '.debug-breakpoint';
const PAUSE = `.debug-actions-widget .debug-action.pause`;
const DEBUG_STATUS_BAR = `.statusbar.debugging`;
const NOT_DEBUG_STATUS_BAR = `.statusbar:not(debugging)`;

View File

@@ -5,69 +5,71 @@
import { SpectronApplication } from '../../spectron/application';
describe('Editor', () => {
before(function () {
this.app.suiteName = 'Editor';
export function setup() {
describe('Editor', () => {
before(function () {
this.app.suiteName = 'Editor';
});
it('shows correct quick outline', async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('www');
await app.workbench.editor.openOutline();
await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6);
});
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);
await references.waitForReferencesCountInTitle(3);
await references.waitForReferencesCount(3);
await references.close();
});
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);
await app.screenCapturer.capture('Rename result');
});
// it('folds/unfolds the code correctly', async function () {
// await app.workbench.quickopen.openFile('www');
// // Fold
// await app.workbench.editor.foldAtLine(3);
// await app.workbench.editor.waitUntilShown(3);
// await app.workbench.editor.waitUntilHidden(4);
// await app.workbench.editor.waitUntilHidden(5);
// // Unfold
// await app.workbench.editor.unfoldAtLine(3);
// await app.workbench.editor.waitUntilShown(3);
// await app.workbench.editor.waitUntilShown(4);
// await app.workbench.editor.waitUntilShown(5);
// });
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);
await app.workbench.waitForActiveTab('index.d.ts');
});
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);
await peek.waitForFile('index.d.ts');
});
});
it('shows correct quick outline', async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('www');
await app.workbench.editor.openOutline();
await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6);
});
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);
await references.waitForReferencesCountInTitle(3);
await references.waitForReferencesCount(3);
await references.close();
});
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);
await app.screenCapturer.capture('Rename result');
});
// it('folds/unfolds the code correctly', async function () {
// await app.workbench.quickopen.openFile('www');
// // Fold
// await app.workbench.editor.foldAtLine(3);
// await app.workbench.editor.waitUntilShown(3);
// await app.workbench.editor.waitUntilHidden(4);
// await app.workbench.editor.waitUntilHidden(5);
// // Unfold
// await app.workbench.editor.unfoldAtLine(3);
// await app.workbench.editor.waitUntilShown(3);
// await app.workbench.editor.waitUntilShown(4);
// await app.workbench.editor.waitUntilShown(5);
// });
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);
await app.workbench.waitForActiveTab('index.d.ts');
});
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);
await peek.waitForFile('index.d.ts');
});
});
}

View File

@@ -5,38 +5,40 @@
import { SpectronApplication } from '../../spectron/application';
describe('Explorer', () => {
before(function () {
this.app.suiteName = 'Explorer';
export function setup() {
describe('Explorer', () => {
before(function () {
this.app.suiteName = 'Explorer';
});
it('quick open search produces correct result', async function () {
const app = this.app as SpectronApplication;
const expectedNames = [
'.eslintrc.json',
'tasks.json',
'app.js',
'index.js',
'users.js',
'package.json',
'jsconfig.json'
];
await app.workbench.quickopen.openQuickOpen('.js');
await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m)));
await app.client.keys(['Escape', 'NULL']);
});
it('quick open respects fuzzy matching', async function () {
const app = this.app as SpectronApplication;
const expectedNames = [
'tasks.json',
'app.js',
'package.json'
];
await app.workbench.quickopen.openQuickOpen('a.s');
await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m)));
await app.client.keys(['Escape', 'NULL']);
});
});
it('quick open search produces correct result', async function () {
const app = this.app as SpectronApplication;
const expectedNames = [
'.eslintrc.json',
'tasks.json',
'app.js',
'index.js',
'users.js',
'package.json',
'jsconfig.json'
];
await app.workbench.quickopen.openQuickOpen('.js');
await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m)));
await app.client.keys(['Escape', 'NULL']);
});
it('quick open respects fuzzy matching', async function () {
const app = this.app as SpectronApplication;
const expectedNames = [
'tasks.json',
'app.js',
'package.json'
];
await app.workbench.quickopen.openQuickOpen('a.s');
await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m)));
await app.client.keys(['Escape', 'NULL']);
});
});
}

View File

@@ -6,31 +6,33 @@
import * as assert from 'assert';
import { SpectronApplication, Quality } from '../../spectron/application';
describe('Extensions', () => {
before(function () {
this.app.suiteName = 'Extensions';
export function setup() {
describe('Extensions', () => {
before(function () {
this.app.suiteName = 'Extensions';
});
it(`install and activate vscode-smoketest-check extension`, async function () {
const app = this.app as SpectronApplication;
if (app.quality === Quality.Dev) {
this.skip();
return;
}
const extensionName = 'vscode-smoketest-check';
await app.workbench.extensions.openExtensionsViewlet();
const installed = await app.workbench.extensions.installExtension(extensionName);
assert.ok(installed);
await app.reload();
await app.workbench.extensions.waitForExtensionsViewlet();
await app.workbench.quickopen.runCommand('Smoke Test Check');
const statusbarText = await app.workbench.statusbar.getStatusbarTextByTitle('smoke test');
await app.screenCapturer.capture('Statusbar');
assert.equal(statusbarText, 'VS Code Smoke Test Check');
});
});
it(`install and activate vscode-smoketest-check extension`, async function () {
const app = this.app as SpectronApplication;
if (app.quality === Quality.Dev) {
this.skip();
return;
}
const extensionName = 'vscode-smoketest-check';
await app.workbench.extensions.openExtensionsViewlet();
const installed = await app.workbench.extensions.installExtension(extensionName);
assert.ok(installed);
await app.reload();
await app.workbench.extensions.waitForExtensionsViewlet();
await app.workbench.quickopen.runCommand('Smoke Test Check');
const statusbarText = await app.workbench.statusbar.getStatusbarTextByTitle('smoke test');
await app.screenCapturer.capture('Statusbar');
assert.equal(statusbarText, 'VS Code Smoke Test Check');
});
});
}

View File

@@ -3,84 +3,79 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as cp from 'child_process';
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"]';
describe('Git', () => {
before(function () {
this.app.suiteName = 'Git';
export function setup() {
describe('Git', () => {
before(async function () {
const app = this.app as SpectronApplication;
app.suiteName = 'Git';
});
it('reflects working tree changes', async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
await app.workbench.quickopen.openFile('app.js');
await app.workbench.editor.waitForTypeInEditor('app.js', '.foo{}');
await app.workbench.saveOpenedFile();
await app.workbench.quickopen.openFile('index.jade');
await app.workbench.editor.waitForTypeInEditor('index.jade', 'hello world');
await app.workbench.saveOpenedFile();
await app.workbench.scm.refreshSCMViewlet();
await app.workbench.scm.waitForChange('app.js', 'Modified');
await app.workbench.scm.waitForChange('index.jade', 'Modified');
await app.screenCapturer.capture('changes');
});
it('opens diff editor', async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
await app.workbench.scm.openChange('app.js');
await app.client.waitForElement(DIFF_EDITOR_LINE_INSERT);
});
it('stages correctly', async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
await app.workbench.scm.waitForChange('app.js', 'Modified');
await app.workbench.scm.stage('app.js');
await app.workbench.scm.waitForChange('app.js', 'Index Modified');
await app.workbench.scm.unstage('app.js');
await app.workbench.scm.waitForChange('app.js', 'Modified');
});
it(`stages, commits changes and verifies outgoing change`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
await app.workbench.scm.waitForChange('app.js', 'Modified');
await app.workbench.scm.stage('app.js');
await app.workbench.scm.waitForChange('app.js', 'Index Modified');
await app.workbench.scm.commit('first commit');
await app.client.waitForText(SYNC_STATUSBAR, ' 0↓ 1↑');
await app.workbench.quickopen.runCommand('Git: Stage All Changes');
await app.workbench.scm.waitForChange('index.jade', 'Index Modified');
await app.workbench.scm.commit('second commit');
await app.client.waitForText(SYNC_STATUSBAR, ' 0↓ 2↑');
cp.execSync('git reset --hard origin/master', { cwd: app.workspacePath });
});
});
it('reflects working tree changes', async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
await app.workbench.quickopen.openFile('app.js');
await app.workbench.editor.waitForTypeInEditor('app.js', '.foo{}');
await app.workbench.saveOpenedFile();
await app.workbench.quickopen.openFile('index.jade');
await app.workbench.editor.waitForTypeInEditor('index.jade', 'hello world');
await app.workbench.saveOpenedFile();
await app.workbench.scm.refreshSCMViewlet();
const appJs = await app.workbench.scm.waitForChange(c => c.name === 'app.js');
const indexJade = await app.workbench.scm.waitForChange(c => c.name === 'index.jade');
await app.screenCapturer.capture('changes');
assert.equal(appJs.name, 'app.js');
assert.equal(appJs.type, 'Modified');
assert.equal(indexJade.name, 'index.jade');
assert.equal(indexJade.type, 'Modified');
});
it('opens diff editor', async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
const appJs = await app.workbench.scm.waitForChange(c => c.name === 'app.js');
await app.workbench.scm.openChange(appJs);
await app.client.waitForElement(DIFF_EDITOR_LINE_INSERT);
});
it('stages correctly', async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
const appJs = await app.workbench.scm.waitForChange(c => c.name === 'app.js' && c.type === 'Modified');
await app.workbench.scm.stage(appJs);
const indexAppJs = await app.workbench.scm.waitForChange(c => c.name === 'app.js' && c.type === 'Index Modified');
await app.workbench.scm.unstage(indexAppJs);
await app.workbench.scm.waitForChange(c => c.name === 'app.js' && c.type === 'Modified');
});
it(`stages, commits changes and verifies outgoing change`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.scm.openSCMViewlet();
const appJs = await app.workbench.scm.waitForChange(c => c.name === 'app.js' && c.type === 'Modified');
await app.workbench.scm.stage(appJs);
await app.workbench.scm.waitForChange(c => c.name === 'app.js' && c.type === 'Index Modified');
await app.workbench.scm.commit('first commit');
await app.client.waitForText(SYNC_STATUSBAR, ' 0↓ 1↑');
await app.workbench.quickopen.runCommand('Git: Stage All Changes');
await app.workbench.scm.waitForChange(c => c.name === 'index.jade' && c.type === 'Index Modified');
await app.workbench.scm.commit('second commit');
await app.client.waitForText(SYNC_STATUSBAR, ' 0↓ 2↑');
cp.execSync('git reset --hard origin/master', { cwd: app.workspacePath });
});
});
}

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { SpectronApplication } from '../../spectron/application';
import { Viewlet } from '../workbench/viewlet';
@@ -13,14 +12,14 @@ const SCM_RESOURCE = `${VIEWLET} .monaco-list-row > .resource`;
const SCM_RESOURCE_GROUP = `${VIEWLET} .monaco-list-row > .resource-group`;
const REFRESH_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Refresh"]`;
const COMMIT_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Commit"]`;
const SCM_RESOURCE_CLICK = name => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"]`;
const SCM_RESOURCE_GROUP_COMMAND_CLICK = name => `${SCM_RESOURCE_GROUP} .actions .action-label[title="${name}"]`;
const SCM_RESOURCE_CLICK = (name: string) => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"] .label-name`;
const SCM_RESOURCE_ACTION_CLICK = (name: string, actionName: string) => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"] .actions .action-label[title="${actionName}"]`;
const SCM_RESOURCE_GROUP_COMMAND_CLICK = (name: string) => `${SCM_RESOURCE_GROUP} .actions .action-label[title="${name}"]`;
export interface Change {
id: string;
interface Change {
name: string;
type: string;
actions: { id: string, title: string; }[];
actions: string[];
}
export class SCM extends Viewlet {
@@ -34,64 +33,67 @@ export class SCM extends Viewlet {
await this.spectron.client.waitForElement(SCM_INPUT);
}
async waitForChange(func: (change: Change) => boolean): Promise<Change> {
return await this.spectron.client.waitFor(async () => {
const changes = await this.getChanges();
return changes.filter(func)[0];
}, void 0, 'Getting changes');
waitForChange(name: string, type?: string): Promise<void> {
return this.spectron.client.waitFor(async () => {
const changes = await this.queryChanges(name, type);
return changes.length;
}, l => l > 0, 'Getting SCM changes') as Promise<any> as Promise<void>;
}
async refreshSCMViewlet(): Promise<any> {
await this.spectron.client.click(REFRESH_COMMAND);
}
async getChanges(): Promise<Change[]> {
const result = await this.spectron.webclient.selectorExecute(SCM_RESOURCE,
div => (Array.isArray(div) ? div : [div]).map(element => {
const name = element.querySelector('.label-name') as HTMLElement;
const icon = element.querySelector('.decoration-icon') as HTMLElement;
const actionElementList = element.querySelectorAll('.actions .action-label');
const actionElements: any[] = [];
private async queryChanges(name: string, type?: string): Promise<Change[]> {
const result = await this.spectron.webclient.selectorExecute(SCM_RESOURCE, (div, name, type) => {
return (Array.isArray(div) ? div : [div])
.map(element => {
const name = element.querySelector('.label-name') as HTMLElement;
const type = element.getAttribute('data-tooltip') || '';
const actionElementList = element.querySelectorAll('.actions .action-label');
const actions: string[] = [];
for (let i = 0; i < actionElementList.length; i++) {
const element = actionElementList.item(i) as HTMLElement;
actionElements.push({ element, title: element.title });
}
for (let i = 0; i < actionElementList.length; i++) {
const element = actionElementList.item(i) as HTMLElement;
actions.push(element.title);
}
return {
name: name.textContent,
type: (icon.title || ''),
element,
actionElements
};
})
);
return {
name: name.textContent,
type,
actions
};
})
.filter(change => {
if (change.name !== name) {
return false;
}
return result.map(({ name, type, element, actionElements }) => {
// const actions = actionElements.reduce((r, { element, title }) => r[title] = element.ELEMENT, {});
const actions = actionElements.map(({ element, title }) => ({ id: element.ELEMENT, title }));
return { name, type, id: element.ELEMENT, actions };
});
if (type && (change.type !== type)) {
return false;
}
return true;
});
}, name, type);
return result;
}
async openChange(change: Change): Promise<void> {
await this.spectron.client.waitAndClick(SCM_RESOURCE_CLICK(change.name));
async openChange(name: string): Promise<void> {
await this.spectron.client.waitAndClick(SCM_RESOURCE_CLICK(name));
}
async stage(change: Change): Promise<void> {
const action = change.actions.filter(a => a.title === 'Stage Changes')[0];
assert(action);
await this.spectron.client.spectron.client.elementIdClick(action.id);
async stage(name: string): Promise<void> {
await this.spectron.client.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Stage Changes'));
}
async stageAll(): Promise<void> {
await this.spectron.client.waitAndClick(SCM_RESOURCE_GROUP_COMMAND_CLICK('Stage All Changes'));
}
async unstage(change: Change): Promise<void> {
const action = change.actions.filter(a => a.title === 'Unstage Changes')[0];
assert(action);
await this.spectron.client.spectron.client.elementIdClick(action.id);
async unstage(name: string): Promise<void> {
await this.spectron.client.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Unstage Changes'));
}
async commit(message: string): Promise<void> {

View File

@@ -6,32 +6,32 @@
import * as assert from 'assert';
import { SpectronApplication } from '../../spectron/application';
describe('Multiroot', () => {
export function setup() {
describe('Multiroot', () => {
before(async function () {
this.app.suiteName = 'Multiroot';
before(async function () {
this.app.suiteName = 'Multiroot';
const app = this.app as SpectronApplication;
const app = this.app as SpectronApplication;
await app.restart([app.workspaceFilePath]);
// restart with preventing additional windows from restoring
// to ensure the window after restart is the multi-root workspace
await app.restart({ workspaceOrFolder: app.workspaceFilePath, extraArgs: ['--disable-restore-windows'] });
});
// for some reason Code opens 2 windows at this point
// so let's select the last one
await app.client.windowByIndex(1);
it('shows results from all folders', async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openQuickOpen('*.*');
await app.workbench.quickopen.waitForQuickOpenElements(names => names.length === 6);
await app.workbench.quickopen.closeQuickOpen();
});
it('shows workspace name in title', async function () {
const app = this.app as SpectronApplication;
const title = await app.client.getTitle();
await app.screenCapturer.capture('window title');
assert.ok(title.indexOf('smoketest (Workspace)') >= 0);
});
});
it('shows results from all folders', async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openQuickOpen('*.*');
await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6);
await app.workbench.quickopen.closeQuickOpen();
});
it('shows workspace name in title', async function () {
const app = this.app as SpectronApplication;
const title = await app.client.getTitle();
await app.screenCapturer.capture('window title');
assert.ok(title.indexOf('smoketest (Workspace)') >= 0);
});
});
}

View File

@@ -8,39 +8,41 @@ import * as assert from 'assert';
import { SpectronApplication } from '../../spectron/application';
import { ActivityBarPosition } from '../activitybar/activityBar';
describe('Preferences', () => {
before(function () {
this.app.suiteName = 'Preferences';
export function setup() {
describe('Preferences', () => {
before(function () {
this.app.suiteName = 'Preferences';
});
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');
assert.ok(!!lineNumbers.length, 'Line numbers are not present in the editor before disabling them.');
await app.workbench.settingsEditor.addUserSetting('editor.lineNumbers', '"off"');
await app.workbench.selectTab('app.js');
lineNumbers = await app.client.waitForElements('.line-numbers', result => !result || result.length === 0);
await app.screenCapturer.capture('line numbers hidden');
assert.ok(!lineNumbers.length, 'Line numbers are still present in the editor after disabling them.');
});
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');
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();
});
});
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');
assert.ok(!!lineNumbers.length, 'Line numbers are not present in the editor before disabling them.');
await app.workbench.settingsEditor.addUserSetting('editor.lineNumbers', '"off"');
await app.workbench.selectTab('app.js');
lineNumbers = await app.client.waitForElements('.line-numbers', result => !result || result.length === 0);
await app.screenCapturer.capture('line numbers hidden');
assert.ok(!lineNumbers.length, 'Line numbers are still present in the editor after disabling them.');
});
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');
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

@@ -50,9 +50,6 @@ export class QuickOpen {
async waitForQuickOpenOpened(): Promise<void> {
await this.spectron.client.waitForActiveElement(QuickOpen.QUICK_OPEN_INPUT);
// we gotta wait 50 milliseconds due to https://github.com/Microsoft/vscode/blob/master/src/vs/platform/list/browser/listService.ts#L59
await new Promise(c => setTimeout(c, 50));
}
private async waitForQuickOpenClosed(): Promise<void> {

View File

@@ -5,52 +5,54 @@
import { SpectronApplication } from '../../spectron/application';
describe('Search', () => {
before(function () {
this.app.suiteName = 'Search';
export function setup() {
describe('Search', () => {
before(function () {
this.app.suiteName = 'Search';
});
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');
await app.workbench.search.waitForResultText('14 results in 5 files');
});
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');
await app.workbench.search.submitSearch();
await app.workbench.search.waitForResultText('4 results in 1 file');
await app.workbench.search.setFilesToIncludeText('');
await app.workbench.search.hideQueryDetails();
});
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('10 results in 4 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.expandReplace();
await app.workbench.search.setReplaceText('ydob');
await app.workbench.search.replaceFileMatch(1);
await app.workbench.saveOpenedFile();
await app.workbench.search.waitForResultText('10 results in 4 files');
await app.workbench.search.searchFor('ydob');
await app.workbench.search.setReplaceText('body');
await app.workbench.search.replaceFileMatch(1);
await app.workbench.saveOpenedFile();
});
});
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');
await app.workbench.search.waitForResultText('14 results in 5 files');
});
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');
await app.workbench.search.submitSearch();
await app.workbench.search.waitForResultText('4 results in 1 file');
await app.workbench.search.setFilesToIncludeText('');
await app.workbench.search.hideQueryDetails();
});
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('10 results in 4 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.expandReplace();
await app.workbench.search.setReplaceText('ydob');
await app.workbench.search.replaceFileMatch(1);
await app.workbench.saveOpenedFile();
await app.workbench.search.waitForResultText('10 results in 4 files');
await app.workbench.search.searchFor('ydob');
await app.workbench.search.setReplaceText('body');
await app.workbench.search.replaceFileMatch(1);
await app.workbench.saveOpenedFile();
});
});
}

View File

@@ -6,7 +6,7 @@
import { SpectronApplication } from '../../spectron/application';
import { Viewlet } from '../workbench/viewlet';
const VIEWLET = 'div[id="workbench.view.search"] .search-viewlet';
const VIEWLET = 'div[id="workbench.view.search"] .search-view';
const INPUT = `${VIEWLET} .search-widget .search-container .monaco-inputbox input`;
const INCLUDE_INPUT = `${VIEWLET} .query-details .monaco-inputbox input[aria-label="Search Include Patterns"]`;
@@ -84,4 +84,4 @@ export class Search extends Viewlet {
async waitForResultText(text: string): Promise<void> {
await this.spectron.client.waitForText(`${VIEWLET} .messages[aria-hidden="false"] .message>p`, text);
}
}
}

View File

@@ -8,90 +8,92 @@ import * as assert from 'assert';
import { SpectronApplication, Quality } from '../../spectron/application';
import { StatusBarElement } from './statusbar';
describe('Statusbar', () => {
before(function () {
this.app.suiteName = 'Statusbar';
export function setup() {
describe('Statusbar', () => {
before(function () {
this.app.suiteName = 'Statusbar';
});
it('verifies presence of all default status bar elements', async function () {
const app = this.app as SpectronApplication;
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.BRANCH_STATUS);
if (app.quality !== Quality.Dev) {
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.FEEDBACK_ICON);
}
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.SYNC_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.PROBLEMS_STATUS);
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.ENCODING_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.EOL_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.INDENTATION_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.LANGUAGE_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.SELECTION_STATUS);
});
it(`verifies that 'quick open' opens when clicking on status bar elements`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.statusbar.clickOn(StatusBarElement.BRANCH_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.clickOn(StatusBarElement.INDENTATION_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.statusbar.clickOn(StatusBarElement.ENCODING_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.statusbar.clickOn(StatusBarElement.EOL_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.statusbar.clickOn(StatusBarElement.LANGUAGE_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
});
it(`verifies that 'Problems View' appears when clicking on 'Problems' status element`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.statusbar.clickOn(StatusBarElement.PROBLEMS_STATUS);
await app.workbench.problems.waitForProblemsView();
});
it(`verifies that 'Tweet us feedback' pop-up appears when clicking on 'Feedback' icon`, async function () {
const app = this.app as SpectronApplication;
if (app.quality === Quality.Dev) {
return this.skip();
}
await app.workbench.statusbar.clickOn(StatusBarElement.FEEDBACK_ICON);
assert.ok(!!await app.client.waitForElement('.feedback-form'));
});
it(`checks if 'Go to Line' works if called from the status bar`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.clickOn(StatusBarElement.SELECTION_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.submit(':15');
await app.workbench.editor.waitForHighlightingLine(15);
});
it(`verifies if changing EOL is reflected in the status bar`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.clickOn(StatusBarElement.EOL_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.selectQuickOpenElement(1);
await app.workbench.statusbar.waitForEOL('CRLF');
});
});
it('verifies presence of all default status bar elements', async function () {
const app = this.app as SpectronApplication;
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.BRANCH_STATUS);
if (app.quality !== Quality.Dev) {
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.FEEDBACK_ICON);
}
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.SYNC_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.PROBLEMS_STATUS);
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.ENCODING_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.EOL_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.INDENTATION_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.LANGUAGE_STATUS);
await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.SELECTION_STATUS);
});
it(`verifies that 'quick open' opens when clicking on status bar elements`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.statusbar.clickOn(StatusBarElement.BRANCH_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.clickOn(StatusBarElement.INDENTATION_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.statusbar.clickOn(StatusBarElement.ENCODING_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.statusbar.clickOn(StatusBarElement.EOL_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
await app.workbench.statusbar.clickOn(StatusBarElement.LANGUAGE_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.closeQuickOpen();
});
it(`verifies that 'Problems View' appears when clicking on 'Problems' status element`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.statusbar.clickOn(StatusBarElement.PROBLEMS_STATUS);
await app.workbench.problems.waitForProblemsView();
});
it(`verifies that 'Tweet us feedback' pop-up appears when clicking on 'Feedback' icon`, async function () {
const app = this.app as SpectronApplication;
if (app.quality === Quality.Dev) {
return this.skip();
}
await app.workbench.statusbar.clickOn(StatusBarElement.FEEDBACK_ICON);
assert.ok(!!await app.client.waitForElement('.feedback-form'));
});
it(`checks if 'Go to Line' works if called from the status bar`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.clickOn(StatusBarElement.SELECTION_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.submit(':15');
await app.workbench.editor.waitForHighlightingLine(15);
});
it(`verifies if changing EOL is reflected in the status bar`, async function () {
const app = this.app as SpectronApplication;
await app.workbench.quickopen.openFile('app.js');
await app.workbench.statusbar.clickOn(StatusBarElement.EOL_STATUS);
await app.workbench.quickopen.waitForQuickOpenOpened();
await app.workbench.quickopen.selectQuickOpenElement(1);
await app.workbench.statusbar.waitForEOL('CRLF');
});
});
}

View File

@@ -5,36 +5,38 @@
import { SpectronApplication } from '../../spectron/application';
describe('Dataloss', () => {
before(function () {
this.app.suiteName = 'Dataloss';
export function setup() {
describe('Dataloss', () => {
before(function () {
this.app.suiteName = 'Dataloss';
});
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';
const textToTypeInUntitled = 'Hello, Unitled Code';
await app.workbench.editor.waitForTypeInEditor(untitled, textToTypeInUntitled);
await app.screenCapturer.capture('Untitled file before reload');
const readmeMd = 'readme.md';
const textToType = 'Hello, Code';
await app.workbench.explorer.openFile(readmeMd);
await app.workbench.editor.waitForTypeInEditor(readmeMd, textToType);
await app.screenCapturer.capture(`${readmeMd} before reload`);
await app.reload();
await app.screenCapturer.capture('After reload');
await app.workbench.waitForActiveTab(readmeMd, true);
await app.screenCapturer.capture(`${readmeMd} after reload`);
await app.workbench.editor.waitForEditorContents(readmeMd, c => c.indexOf(textToType) > -1);
await app.workbench.waitForTab(untitled, true);
await app.workbench.selectTab(untitled, true);
await app.screenCapturer.capture('Untitled file after reload');
await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1);
});
});
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';
const textToTypeInUntitled = 'Hello, Unitled Code';
await app.workbench.editor.waitForTypeInEditor(untitled, textToTypeInUntitled);
await app.screenCapturer.capture('Untitled file before reload');
const readmeMd = 'readme.md';
const textToType = 'Hello, Code';
await app.workbench.explorer.openFile(readmeMd);
await app.workbench.editor.waitForTypeInEditor(readmeMd, textToType);
await app.screenCapturer.capture(`${readmeMd} before reload`);
await app.reload();
await app.screenCapturer.capture('After reload');
await app.workbench.waitForActiveTab(readmeMd, true);
await app.screenCapturer.capture(`${readmeMd} after reload`);
await app.workbench.editor.waitForEditorContents(readmeMd, c => c.indexOf(textToType) > -1);
await app.workbench.waitForTab(untitled, true);
await app.workbench.selectTab(untitled, true);
await app.screenCapturer.capture('Untitled file after reload');
await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1);
});
});
}

View File

@@ -3,85 +3,130 @@
* Licensed under the Source EULA. 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, Quality } from '../../spectron/application';
import * as rimraf from 'rimraf';
// describe('Data Migration', () => {
export interface ICreateAppFn {
(quality: Quality): SpectronApplication | null;
}
// if (!STABLE_PATH) {
// return;
// }
export function setup(userDataDir: string, createApp: ICreateAppFn) {
// let app: SpectronApplication;
// afterEach(() => app.stop());
describe('Data Migration', () => {
afterEach(async function () {
await new Promise((c, e) => rimraf(userDataDir, { maxBusyTries: 10 }, err => err ? e(err) : c()));
});
// 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 stableApp = createApp(Quality.Stable);
// // Setting up stable version
// let app = new SpectronApplication(STABLE_PATH);
// await app.start('Data Migration');
if (!stableApp) {
this.skip();
return;
}
// await app.workbench.newUntitledFile();
// await app.workbench.editor.waitForTypeInEditor('Untitled-1', textToType);
await stableApp.start();
stableApp.suiteName = 'Data Migration';
// 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
const textToType = 'Very dirty file';
// app = new SpectronApplication(LATEST_PATH);
// await app.start('Data Migration');
await stableApp.workbench.newUntitledFile();
await stableApp.workbench.editor.waitForTypeInEditor('Untitled-1', textToType);
// assert.ok(await app.workbench.waitForActiveTab('Untitled-1', true), `Untitled-1 tab is not present after migration.`);
await stableApp.stop();
await new Promise(c => setTimeout(c, 500)); // wait until all resources are released (e.g. locked local storage)
// await app.workbench.editor.waitForEditorContents('Untitled-1', c => c.indexOf(textToType) > -1);
// await app.screenCapturer.capture('Untitled file text');
// });
// Checking latest version for the restored state
const app = createApp(Quality.Insiders);
// 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.';
if (!app) {
return assert(false);
}
// // Setting up stable version
// let app = new SpectronApplication(STABLE_PATH, fileName);
// await Util.removeFile(`${fileName}`);
// await app.start('Data Migration');
await app.start(false);
app.suiteName = 'Data Migration';
// await app.workbench.editor.waitForTypeInEditor('plainFile', firstTextPart);
// await app.workbench.saveOpenedFile();
// await app.workbench.editor.waitForTypeInEditor('plainFile', secondTextPart);
assert.ok(await app.workbench.waitForActiveTab('Untitled-1', true), `Untitled-1 tab is not present after migration.`);
// await app.stop();
// await new Promise(c => setTimeout(c, 1000)); // wait until all resources are released (e.g. locked local storage)
await app.workbench.editor.waitForEditorContents('Untitled-1', c => c.indexOf(textToType) > -1);
await app.screenCapturer.capture('Untitled file text');
// // Checking latest version for the restored state
// app = new SpectronApplication(LATEST_PATH);
// await app.start('Data Migration');
await app.stop();
});
// 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);
it('checks if the newly created dirty file is restored migrating from stable to latest', async function () {
const stableApp = createApp(Quality.Stable);
// await Util.removeFile(`${fileName}`);
// });
if (!stableApp) {
this.skip();
return;
}
// 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 stableApp.start();
stableApp.suiteName = 'Data Migration';
// await app.workbench.quickopen.openFile(fileName1);
// await app.workbench.quickopen.openFile(fileName2);
// await app.workbench.quickopen.openFile(fileName3);
// await app.stop();
const fileName = 'app.js';
const textPart = 'This is going to be an unsaved file';
// app = new SpectronApplication(LATEST_PATH);
// await app.start('Data Migration');
await stableApp.workbench.quickopen.openFile(fileName);
// 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.`);
// });
// });
await stableApp.workbench.editor.waitForTypeInEditor(fileName, textPart);
await stableApp.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
const app = createApp(Quality.Insiders);
if (!app) {
return assert(false);
}
await app.start(false);
app.suiteName = 'Data Migration';
assert.ok(await app.workbench.waitForActiveTab(fileName), `dirty file tab is not present after migration.`);
await app.workbench.editor.waitForEditorContents(fileName, c => c.indexOf(textPart) > -1);
await app.stop();
});
it('checks if opened tabs are restored migrating from stable to latest', async function () {
const stableApp = createApp(Quality.Stable);
if (!stableApp) {
this.skip();
return;
}
await stableApp.start();
stableApp.suiteName = 'Data Migration';
const fileName1 = 'app.js', fileName2 = 'jsconfig.json', fileName3 = 'readme.md';
await stableApp.workbench.quickopen.openFile(fileName1);
await stableApp.workbench.quickopen.runCommand('View: Keep Editor');
await stableApp.workbench.quickopen.openFile(fileName2);
await stableApp.workbench.quickopen.runCommand('View: Keep Editor');
await stableApp.workbench.quickopen.openFile(fileName3);
await stableApp.stop();
const app = createApp(Quality.Insiders);
if (!app) {
return assert(false);
}
await app.start(false);
app.suiteName = '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.`);
await app.stop();
});
});
}

View File

@@ -7,48 +7,50 @@ import * as assert from 'assert';
import { SpectronApplication, Quality } from '../../spectron/application';
describe('Localization', () => {
before(async function () {
const app = this.app as SpectronApplication;
this.app.suiteName = 'Localization';
export function setup() {
describe('Localization', () => {
before(async function () {
const app = this.app as SpectronApplication;
this.app.suiteName = 'Localization';
if (app.quality === Quality.Dev) {
return;
}
if (app.quality === Quality.Dev) {
return;
}
await app.restart(['--locale=DE']);
await app.restart({ extraArgs: ['--locale=DE'] });
});
it(`starts with 'DE' locale and verifies title and viewlets text is in German`, async function () {
const app = this.app as SpectronApplication;
if (app.quality === Quality.Dev) {
this.skip();
return;
}
let text = await app.workbench.explorer.getOpenEditorsViewTitle();
await app.screenCapturer.capture('Open editors title');
assert(/geöffnete editoren/i.test(text));
await app.workbench.search.openSearchViewlet();
text = await app.workbench.search.getTitle();
await app.screenCapturer.capture('Search title');
assert(/suchen/i.test(text));
await app.workbench.scm.openSCMViewlet();
text = await app.workbench.scm.getTitle();
await app.screenCapturer.capture('Scm title');
assert(/quellcodeverwaltung/i.test(text));
await app.workbench.debug.openDebugViewlet();
text = await app.workbench.debug.getTitle();
await app.screenCapturer.capture('Debug title');
assert(/debuggen/i.test(text));
await app.workbench.extensions.openExtensionsViewlet();
text = await app.workbench.extensions.getTitle();
await app.screenCapturer.capture('Extensions title');
assert(/erweiterungen/i.test(text));
});
});
it(`starts with 'DE' locale and verifies title and viewlets text is in German`, async function () {
const app = this.app as SpectronApplication;
if (app.quality === Quality.Dev) {
this.skip();
return;
}
let text = await app.workbench.explorer.getOpenEditorsViewTitle();
await app.screenCapturer.capture('Open editors title');
assert(/geöffnete editoren/i.test(text));
await app.workbench.search.openSearchViewlet();
text = await app.workbench.search.getTitle();
await app.screenCapturer.capture('Search title');
assert(/suchen/i.test(text));
await app.workbench.scm.openSCMViewlet();
text = await app.workbench.scm.getTitle();
await app.screenCapturer.capture('Scm title');
assert(/quellcodeverwaltung/i.test(text));
await app.workbench.debug.openDebugViewlet();
text = await app.workbench.debug.getTitle();
await app.screenCapturer.capture('Debug title');
assert(/debuggen/i.test(text));
await app.workbench.extensions.openExtensionsViewlet();
text = await app.workbench.extensions.getTitle();
await app.screenCapturer.capture('Extensions title');
assert(/erweiterungen/i.test(text));
});
});
}

View File

@@ -51,14 +51,8 @@ export class Workbench {
}
public async saveOpenedFile(): Promise<any> {
try {
await this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty');
} catch (e) {
// ignore if there is no dirty file
return Promise.resolve();
}
await this.spectron.runCommand('workbench.action.files.save');
return this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty', element => !element);
await this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty');
await this.spectron.workbench.quickopen.runCommand('File: Save');
}
public async selectTab(tabName: string, untitled: boolean = false): Promise<void> {

View File

@@ -6,35 +6,6 @@
import * as fs from 'fs';
import { dirname } from 'path';
/**
* Contains methods that are commonly used across test areas.
*/
export class Util {
constructor() {
// noop
}
public removeFile(filePath: string): void {
try {
fs.unlinkSync(`${filePath}`);
} catch (e) {
if (e.code !== 'ENOENT') {
throw e;
}
}
}
public static removeFile(filePath: string): void {
try {
fs.unlinkSync(`${filePath}`);
} catch (e) {
if (e.code !== 'ENOENT') {
throw e;
}
}
}
}
export function nfcall<R>(fn: Function, ...args): Promise<R> {
return new Promise<R>((c, e) => fn(...args, (err, r) => err ? e(err) : c(r)));
}

View File

@@ -12,6 +12,21 @@ import * as tmp from 'tmp';
import * as rimraf from 'rimraf';
import * as mkdirp from 'mkdirp';
import { SpectronApplication, Quality } from './spectron/application';
import { setup as setupDataMigrationTests } from './areas/workbench/data-migration.test';
import { setup as setupDataLossTests } from './areas/workbench/data-loss.test';
import { setup as setupDataExplorerTests } from './areas/explorer/explorer.test';
import { setup as setupDataPreferencesTests } from './areas/preferences/preferences.test';
import { setup as setupDataSearchTests } from './areas/search/search.test';
import { setup as setupDataCSSTests } from './areas/css/css.test';
import { setup as setupDataEditorTests } from './areas/editor/editor.test';
import { setup as setupDataDebugTests } from './areas/debug/debug.test';
import { setup as setupDataGitTests } from './areas/git/git.test';
import { setup as setupDataStatusbarTests } from './areas/statusbar/statusbar.test';
import { setup as setupDataExtensionTests } from './areas/extensions/extensions.test';
import { setup as setupDataMultirootTests } from './areas/multiroot/multiroot.test';
import { setup as setupDataLocalizationTests } from './areas/workbench/localization.test';
// import './areas/terminal/terminal.test';
const tmpDir = tmp.dirSync({ prefix: 't' }) as { name: string; removeCallback: Function; };
const testDataPath = tmpDir.name;
@@ -83,12 +98,13 @@ function getBuildElectronPath(root: string): string {
let testCodePath = opts.build;
let stableCodePath = opts['stable-build'];
let electronPath: string;
let stablePath: string;
if (testCodePath) {
electronPath = getBuildElectronPath(testCodePath);
if (stableCodePath) {
process.env.VSCODE_STABLE_PATH = getBuildElectronPath(stableCodePath);
stablePath = getBuildElectronPath(stableCodePath);
}
} else {
testCodePath = getDevElectronPath();
@@ -109,7 +125,7 @@ process.env.VSCODE_KEYBINDINGS_PATH = keybindingsPath;
let quality: Quality;
if (process.env.VSCODE_DEV === '1') {
quality = Quality.Dev;
} else if ((testCodePath.indexOf('Code - Insiders') /* macOS/Windows */ || testCodePath.indexOf('code-insiders') /* Linux */) >= 0) {
} else if (electronPath.indexOf('Code - Insiders') >= 0 /* macOS/Windows */ || electronPath.indexOf('code-insiders') /* Linux */ >= 0) {
quality = Quality.Insiders;
} else {
quality = Quality.Stable;
@@ -135,7 +151,7 @@ async function setup(): Promise<void> {
console.log('*** Test data:', testDataPath);
console.log('*** Preparing smoketest setup...');
const keybindingsUrl = `https://raw.githubusercontent.com/Microsoft/vscode-docs/master/scripts/keybindings/doc.keybindings.${getKeybindingPlatform()}.json`;
const keybindingsUrl = `https://raw.githubusercontent.com/Microsoft/vscode-docs/master/build/keybindings/doc.keybindings.${getKeybindingPlatform()}.json`;
console.log('*** Fetching keybindings...');
await new Promise((c, e) => {
@@ -203,14 +219,16 @@ console.warn = function suppressWebdriverWarnings(message) {
warn.apply(console, arguments);
};
before(async function () {
// allow two minutes for setup
this.timeout(2 * 60 * 1000);
await setup();
function createApp(quality: Quality): SpectronApplication | null {
const path = quality === Quality.Stable ? stablePath : electronPath;
const app = new SpectronApplication({
if (!path) {
return null;
}
return new SpectronApplication({
quality,
electronPath,
electronPath: path,
workspacePath,
userDataDir,
extensionsPath,
@@ -218,27 +236,42 @@ before(async function () {
workspaceFilePath,
waitTime: parseInt(opts['wait-time'] || '0') || 20
});
await app.start();
this.app = app;
}
before(async function () {
// allow two minutes for setup
this.timeout(2 * 60 * 1000);
await setup();
});
after(async function () {
await this.app.stop();
await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c()));
});
// import './areas/workbench/data-migration.test';
import './areas/workbench/data-loss.test';
import './areas/explorer/explorer.test';
import './areas/preferences/preferences.test';
import './areas/search/search.test';
import './areas/css/css.test';
import './areas/editor/editor.test';
import './areas/debug/debug.test';
import './areas/git/git.test';
// import './areas/terminal/terminal.test';
import './areas/statusbar/statusbar.test';
import './areas/extensions/extensions.test';
import './areas/multiroot/multiroot.test';
import './areas/workbench/localization.test';
describe('Data Migration', () => {
setupDataMigrationTests(userDataDir, createApp);
});
describe('Everything Else', () => {
before(async function () {
const app = createApp(quality);
await app!.start();
this.app = app;
});
after(async function () {
await this.app.stop();
});
setupDataLossTests();
setupDataExplorerTests();
setupDataPreferencesTests();
setupDataSearchTests();
setupDataCSSTests();
setupDataEditorTests();
setupDataDebugTests();
setupDataGitTests();
setupDataStatusbarTests();
setupDataExtensionTests();
setupDataMultirootTests();
setupDataLocalizationTests();
});

View File

@@ -108,28 +108,31 @@ export class SpectronApplication {
this._screenCapturer.suiteName = suiteName;
}
async start(): Promise<any> {
async start(waitForWelcome: boolean = true): Promise<any> {
await this._start();
await this.waitForWelcome();
if (waitForWelcome) {
await this.waitForWelcome();
}
}
async restart(codeArgs: string[] = []): Promise<any> {
async restart(options: { workspaceOrFolder?: string, extraArgs?: string[] }): Promise<any> {
await this.stop();
await new Promise(c => setTimeout(c, 1000));
await this._start(codeArgs);
await this._start(options.workspaceOrFolder, options.extraArgs);
}
private async _start(codeArgs: string[] = []): Promise<any> {
private async _start(workspaceOrFolder = this.options.workspacePath, extraArgs: string[] = []): Promise<any> {
await this.retrieveKeybindings();
cp.execSync('git checkout .', { cwd: this.options.workspacePath });
await this.startApplication(codeArgs);
await this.startApplication(workspaceOrFolder, extraArgs);
await this.checkWindowReady();
}
async reload(): Promise<any> {
await this.workbench.quickopen.runCommand('Reload Window');
// TODO @sandy: Find a proper condition to wait for reload
await new Promise(c => setTimeout(c, 500));
await new Promise(c => setTimeout(c, 1500));
await this.checkWindowReady();
}
@@ -145,7 +148,7 @@ export class SpectronApplication {
}
}
private async startApplication(codeArgs: string[] = []): Promise<any> {
private async startApplication(workspaceOrFolder: string, extraArgs: string[] = []): Promise<any> {
let args: string[] = [];
let chromeDriverArgs: string[] = [];
@@ -154,11 +157,14 @@ export class SpectronApplication {
args.push(process.env.VSCODE_REPOSITORY as string);
}
args.push(this.options.workspacePath);
args.push(workspaceOrFolder);
// Prevent 'Getting Started' web page from opening on clean user-data-dir
args.push('--skip-getting-started');
// Prevent 'Getting Started' web page from opening on clean user-data-dir
args.push('--skip-release-notes');
// Prevent Quick Open from closing when focus is stolen, this allows concurrent smoketest suite running
args.push('--sticky-quickopen');
@@ -176,7 +182,7 @@ export class SpectronApplication {
// Ensure that running over custom extensions directory, rather than picking up the one that was used by a tester previously
args.push(`--extensions-dir=${this.options.extensionsPath}`);
args.push(...codeArgs);
args.push(...extraArgs);
chromeDriverArgs.push(`--user-data-dir=${this.options.userDataDir}`);
@@ -269,10 +275,18 @@ export class SpectronApplication {
private async checkWindowReady(): Promise<any> {
await this.webclient.waitUntilWindowLoaded();
// Spectron opens multiple terminals in Windows platform
// Workaround to focus the right window - https://github.com/electron/spectron/issues/60
// await this.client.windowByIndex(1);
// await this.app.browserWindow.focus();
// Pick the first workbench window here
const count = await this.webclient.getWindowCount();
for (let i = 0; i < count; i++) {
await this.webclient.windowByIndex(i);
if (/bootstrap\/index\.html/.test(await this.webclient.getUrl())) {
break;
}
}
await this.client.waitForElement('.monaco-workbench');
}

View File

@@ -25,10 +25,6 @@ export class SpectronClient {
this.retryCount = (waitTime * 1000) / this.retryDuration;
}
windowByIndex(index: number): Promise<any> {
return this.spectron.client.windowByIndex(index);
}
keys(keys: string[]): Promise<void> {
this.spectron.client.keys(keys);
return Promise.resolve();