mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge vscode source through 1.62 release (#19981)
* Build breaks 1 * Build breaks * Build breaks * Build breaks * More build breaks * Build breaks (#2512) * Runtime breaks * Build breaks * Fix dialog location break * Update typescript * Fix ASAR break issue * Unit test breaks * Update distro * Fix breaks in ADO builds (#2513) * Bump to node 16 * Fix hygiene errors * Bump distro * Remove reference to node type * Delete vscode specific extension * Bump to node 16 in CI yaml * Skip integration tests in CI builds (while fixing) * yarn.lock update * Bump moment dependency in remote yarn * Fix drop-down chevron style * Bump to node 16 * Remove playwrite from ci.yaml * Skip building build scripts in hygine check
This commit is contained in:
@@ -51,15 +51,6 @@ export class Editor {
|
||||
return peek;
|
||||
}
|
||||
|
||||
async waitForHighlightingLine(filename: string, line: number): Promise<void> {
|
||||
const currentLineIndex = await this.getViewLineIndex(filename, line);
|
||||
if (currentLineIndex) {
|
||||
await this.code.waitForElement(`.monaco-editor .view-overlays>:nth-child(${currentLineIndex}) .current-line`);
|
||||
return;
|
||||
}
|
||||
throw new Error('Cannot find line ' + line);
|
||||
}
|
||||
|
||||
private async getSelector(filename: string, term: string, line: number): Promise<string> {
|
||||
const lineIndex = await this.getViewLineIndex(filename, line);
|
||||
const classNames = await this.getClassSelectors(filename, term, lineIndex);
|
||||
|
||||
@@ -28,6 +28,7 @@ export class Extensions extends Viewlet {
|
||||
await this.code.waitAndClick(SEARCH_BOX);
|
||||
await this.code.waitForActiveElement(SEARCH_BOX);
|
||||
await this.code.waitForTypeInEditor(SEARCH_BOX, `@id:${id}`);
|
||||
await this.code.waitForTextContent(`div.part.sidebar div.composite.title h2`, 'Extensions: Marketplace');
|
||||
await this.code.waitForElement(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[data-extension-id="${id}"]`);
|
||||
}
|
||||
|
||||
|
||||
@@ -191,35 +191,33 @@ interface Options {
|
||||
readonly headless?: boolean;
|
||||
}
|
||||
|
||||
export function connect(options: Options = {}): Promise<{ client: IDisposable, driver: IDriver }> {
|
||||
return new Promise(async (c) => {
|
||||
const browser = await playwright[options.browser ?? 'chromium'].launch({ headless: options.headless ?? false });
|
||||
const context = await browser.newContext({ permissions: ['clipboard-read'] }); // {{SQL CARBON EDIT}} avoid permissison request
|
||||
try {
|
||||
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
} catch (error) {
|
||||
console.warn(`Failed to start playwright tracing.`); // do not fail the build when this fails
|
||||
export async function connect(options: Options = {}): Promise<{ client: IDisposable, driver: IDriver }> {
|
||||
const browser = await playwright[options.browser ?? 'chromium'].launch({ headless: options.headless ?? false });
|
||||
const context = await browser.newContext({ permissions: ['clipboard-read'] }); // {{SQL CARBON EDIT}} avoid permissison request
|
||||
try {
|
||||
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
} catch (error) {
|
||||
console.warn(`Failed to start playwright tracing.`); // do not fail the build when this fails
|
||||
}
|
||||
const page = await context.newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
page.on('pageerror', async error => console.error(`Playwright ERROR: page error: ${error}`));
|
||||
page.on('crash', page => console.error('Playwright ERROR: page crash'));
|
||||
page.on('response', async response => {
|
||||
if (response.status() >= 400) {
|
||||
console.error(`Playwright ERROR: HTTP status ${response.status()} for ${response.url()}`);
|
||||
}
|
||||
const page = await context.newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
page.on('pageerror', async error => console.error(`Playwright ERROR: page error: ${error}`));
|
||||
page.on('crash', page => console.error('Playwright ERROR: page crash'));
|
||||
page.on('response', async response => {
|
||||
if (response.status() >= 400) {
|
||||
console.error(`Playwright ERROR: HTTP status ${response.status()} for ${response.url()}`);
|
||||
}
|
||||
});
|
||||
const payloadParam = `[["enableProposedApi",""],["skipWelcome","true"]]`;
|
||||
await page.goto(`${endpoint}&folder=vscode-remote://localhost:9888${URI.file(workspacePath!).path}&payload=${payloadParam}`);
|
||||
const result = {
|
||||
client: {
|
||||
dispose: () => {
|
||||
browser.close();
|
||||
teardown();
|
||||
}
|
||||
},
|
||||
driver: buildDriver(browser, context, page)
|
||||
};
|
||||
c(result);
|
||||
});
|
||||
const payloadParam = `[["enableProposedApi",""],["skipWelcome","true"]]`;
|
||||
await page.goto(`${endpoint}&folder=vscode-remote://localhost:9888${URI.file(workspacePath!).path}&payload=${payloadParam}`);
|
||||
|
||||
return {
|
||||
client: {
|
||||
dispose: () => {
|
||||
browser.close();
|
||||
teardown();
|
||||
}
|
||||
},
|
||||
driver: buildDriver(browser, context, page)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,23 +4,25 @@
|
||||
|
||||
Make sure to run the following commands to compile and install dependencies:
|
||||
|
||||
yarn --cwd test/integration/browser
|
||||
yarn --cwd test/integration/browser compile
|
||||
yarn --cwd test/integration/browser
|
||||
yarn --cwd test/integration/browser compile
|
||||
|
||||
## Run (inside Electron)
|
||||
|
||||
scripts/test-integration.[sh|bat]
|
||||
scripts/test-integration.[sh|bat]
|
||||
|
||||
All integration tests run in an Electron instance. You can specify to run the tests against a real build by setting the environment variables `INTEGRATION_TEST_ELECTRON_PATH` and `VSCODE_REMOTE_SERVER_PATH` (if you want to include remote tests).
|
||||
|
||||
## Run (inside browser)
|
||||
|
||||
resources/server/test/test-web-integration.[sh|bat] --browser [chromium|webkit] [--debug]
|
||||
resources/server/test/test-web-integration.[sh|bat] --browser [chromium|webkit] [--debug]
|
||||
|
||||
All integration tests run in a browser instance as specified by the command line arguments.
|
||||
|
||||
Add the `--debug` flag to see a browser window with the tests running.
|
||||
|
||||
**Note**: you can enable verbose logging of playwright library by setting a `DEBUG` environment variable before running the tests (https://playwright.dev/docs/debug#verbose-api-logs)
|
||||
|
||||
## Debug
|
||||
|
||||
All integration tests can be run and debugged from within VSCode (both Electron and Web) simply by selecting the related launch configuration and running them.
|
||||
|
||||
@@ -45,6 +45,16 @@ async function runTestsInBrowser(browserType: BrowserType, endpoint: url.UrlWith
|
||||
console.error(`Playwright ERROR: HTTP status ${response.status()} for ${response.url()}`);
|
||||
}
|
||||
});
|
||||
page.on('console', async msg => {
|
||||
try {
|
||||
consoleLogFn(msg)(msg.text(), await Promise.all(msg.args().map(async arg => await arg.jsonValue())));
|
||||
} catch (err) {
|
||||
console.error('Error logging console', err);
|
||||
}
|
||||
});
|
||||
page.on('requestfailed', e => {
|
||||
console.error('Request Failed', e.url(), e.failure()?.errorText);
|
||||
});
|
||||
|
||||
const host = endpoint.host;
|
||||
const protocol = 'vscode-remote';
|
||||
@@ -53,7 +63,7 @@ async function runTestsInBrowser(browserType: BrowserType, endpoint: url.UrlWith
|
||||
const testExtensionUri = url.format({ pathname: URI.file(path.resolve(optimist.argv.extensionDevelopmentPath)).path, protocol, host, slashes: true });
|
||||
const testFilesUri = url.format({ pathname: URI.file(path.resolve(optimist.argv.extensionTestsPath)).path, protocol, host, slashes: true });
|
||||
|
||||
const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""],["webviewExternalEndpointCommit","5319757634f77a050b49c10162939bfe60970c29"],["skipWelcome","true"]]`;
|
||||
const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""],["webviewExternalEndpointCommit","dc1a6699060423b8c4d2ced736ad70195378fddf"],["skipWelcome","true"]]`;
|
||||
|
||||
if (path.extname(testWorkspaceUri) === '.code-workspace') {
|
||||
await page.goto(`${endpoint.href}&workspace=${testWorkspaceUri}&payload=${payloadParam}`);
|
||||
@@ -82,6 +92,20 @@ async function runTestsInBrowser(browserType: BrowserType, endpoint: url.UrlWith
|
||||
});
|
||||
}
|
||||
|
||||
function consoleLogFn(msg) {
|
||||
const type = msg.type();
|
||||
const candidate = console[type];
|
||||
if (candidate) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
if (type === 'warning') {
|
||||
return console.warn;
|
||||
}
|
||||
|
||||
return console.log;
|
||||
}
|
||||
|
||||
function pkill(pid: number): Promise<void> {
|
||||
return new Promise((c, e) => {
|
||||
kill(pid, error => error ? e(error) : c());
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.14",
|
||||
"chai": "^4.2.0"
|
||||
"chai": "^4.2.0",
|
||||
"warnings-to-errors-webpack-plugin": "^2.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const path = require('path');
|
||||
const WarningsToErrorsPlugin = require('warnings-to-errors-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
@@ -51,5 +52,8 @@ module.exports = {
|
||||
moduleTrace: true,
|
||||
errorDetails: true,
|
||||
chunks: true
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new WarningsToErrorsPlugin()
|
||||
],
|
||||
};
|
||||
|
||||
@@ -50,3 +50,8 @@ type-detect@^4.0.0, type-detect@^4.0.5:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
||||
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
||||
|
||||
warnings-to-errors-webpack-plugin@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/warnings-to-errors-webpack-plugin/-/warnings-to-errors-webpack-plugin-2.3.0.tgz#5f9a58aaec458feafabe0f7a2b88a492db263a30"
|
||||
integrity sha512-fzOyw+Ctr2MqJ+4UXKobDiOLzMMSBAdvGMWvZ4NRgTBCofAL2mmdfr6/Of3Bqz9Sq6R6xT5dLs6nnLLCtmppeQ==
|
||||
|
||||
@@ -27,7 +27,7 @@ example: yarn smoketest --build /Applications/Visual\ Studio\ Code\ -\ Insiders.
|
||||
# Build (Web - read instructions below)
|
||||
yarn smoketest --build <path to server web build (ends in -web)> --web --browser [chromium|webkit]
|
||||
|
||||
# Remote (Electron)
|
||||
# Remote (Electron - Must be run on distro)
|
||||
yarn smoketest --build <path to latest version> --remote
|
||||
```
|
||||
|
||||
@@ -63,6 +63,8 @@ xattr -d com.apple.quarantine <path to server with web folder zip>
|
||||
- `-f PATTERN` (alias `-g PATTERN`) filters the tests to be run. This is sent to Mocha as the [grep](https://mochajs.org/api/mocha#grep) option, typically you can just use a simple string of the test name to filter down to just that test (e.g. `test -f "My Test Name"`)
|
||||
- `--screenshots SCREENSHOT_DIR` captures screenshots when tests fail.
|
||||
|
||||
**Note**: you can enable verbose logging of playwright library by setting a `DEBUG` environment variable before running the tests (https://playwright.dev/docs/debug#verbose-api-logs)
|
||||
|
||||
### Develop
|
||||
|
||||
```bash
|
||||
@@ -80,7 +82,7 @@ On Windows, check for the folder `C:\Users\<username>\AppData\Local\Temp\t`. If
|
||||
|
||||
- Beware of workbench **state**. The tests within a single suite will share the same state.
|
||||
|
||||
- Beware of **singletons**. This evil can, and will, manifest itself under the form of FS paths, TCP ports, IPC handles. Whenever writing a test, or setting up more smoke test architecture, make sure it can run simultaneously with any other tests and even itself. All test suites should be able to run many times in parallel.
|
||||
- Beware of **singletons**. This evil can, and will, manifest itself under the form of FS paths, TCP ports, IPC handles. Whenever writing a test, or setting up more smoke test architecture, make sure it can run simultaneously with any other tests and even itself. All test suites should be able to run many times in parallel.
|
||||
|
||||
- Beware of **focus**. **Never** depend on DOM elements having focus using `.focused` classes or `:focus` pseudo-classes, since they will lose that state as soon as another window appears on top of the running VS Code window. A safe approach which avoids this problem is to use the `waitForActiveElement` API. Many tests use this whenever they need to wait for a specific element to _have focus_.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as cp from 'child_process';
|
||||
import minimist = require('minimist');
|
||||
import { Application } from '../../../../automation';
|
||||
import { afterSuite, beforeSuite } from '../../utils';
|
||||
import { afterSuite, beforeSuite, retry } from '../../utils';
|
||||
|
||||
export function setup(opts: minimist.ParsedArgs) {
|
||||
// https://github.com/microsoft/vscode/issues/115244
|
||||
@@ -15,8 +15,8 @@ export function setup(opts: minimist.ParsedArgs) {
|
||||
|
||||
after(function () {
|
||||
const app = this.app as Application;
|
||||
cp.execSync('git checkout . --quiet', { cwd: app.workspacePathOrFolder });
|
||||
cp.execSync('git reset --hard HEAD --quiet', { cwd: app.workspacePathOrFolder });
|
||||
retry(async () => cp.execSync('git checkout . --quiet', { cwd: app.workspacePathOrFolder }), 0, 5);
|
||||
retry(async () => cp.execSync('git reset --hard HEAD --quiet', { cwd: app.workspacePathOrFolder }), 0, 5);
|
||||
});
|
||||
|
||||
afterSuite(opts);
|
||||
|
||||
@@ -65,18 +65,6 @@ export function setup(opts: minimist.ParsedArgs) {
|
||||
await app.workbench.problems.waitForProblemsView();
|
||||
});
|
||||
|
||||
it(`checks if 'Go to Line' works if called from the status bar`, async function () {
|
||||
const app = this.app as Application;
|
||||
|
||||
await app.workbench.quickaccess.openFile('app.js');
|
||||
await app.workbench.statusbar.clickOn(StatusBarElement.SELECTION_STATUS);
|
||||
|
||||
await app.workbench.quickinput.waitForQuickInputOpened();
|
||||
|
||||
await app.workbench.quickinput.submit(':15');
|
||||
await app.workbench.editor.waitForHighlightingLine('app.js', 15);
|
||||
});
|
||||
|
||||
it(`verifies if changing EOL is reflected in the status bar`, async function () {
|
||||
const app = this.app as Application;
|
||||
|
||||
|
||||
@@ -48,7 +48,11 @@ export function afterSuite(opts: minimist.ParsedArgs) {
|
||||
|
||||
if (this.currentTest?.state === 'failed' && opts.screenshots) {
|
||||
const name = this.currentTest!.fullTitle().replace(/[^a-z0-9\-]/ig, '_');
|
||||
await app.captureScreenshot(name);
|
||||
try {
|
||||
await app.captureScreenshot(name);
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -68,3 +72,23 @@ export function timeout(i: number) {
|
||||
}, i);
|
||||
});
|
||||
}
|
||||
|
||||
export interface ITask<T> {
|
||||
(): T;
|
||||
}
|
||||
|
||||
export async function retry<T>(task: ITask<Promise<T>>, delay: number, retries: number): Promise<T> {
|
||||
let lastError: Error | undefined;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
try {
|
||||
return await task();
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
|
||||
await timeout(delay);
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
@@ -88,11 +88,15 @@ function deserializeRunnable(runnable) {
|
||||
function deserializeError(err) {
|
||||
const inspect = err.inspect;
|
||||
err.inspect = () => inspect;
|
||||
// Unfortunately, mocha rewrites and formats err.actual/err.expected.
|
||||
// This formatting is hard to reverse, so err.*JSON includes the unformatted value.
|
||||
if (err.actual) {
|
||||
err.actual = JSON.parse(err.actual).value;
|
||||
err.actualJSON = err.actual;
|
||||
}
|
||||
if (err.expected) {
|
||||
err.expected = JSON.parse(err.expected).value;
|
||||
err.expectedJSON = err.expected;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -129,6 +129,12 @@ function createCoverageReport(opts) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
function loadWorkbenchTestingModule() {
|
||||
return new Promise((resolve, reject) => {
|
||||
loader.require(['vs/workbench/test/electron-browser/testing'], resolve, reject);
|
||||
})
|
||||
}
|
||||
|
||||
function loadTestModules(opts) {
|
||||
|
||||
if (opts.run) {
|
||||
@@ -192,20 +198,34 @@ function loadTests(opts) {
|
||||
});
|
||||
});
|
||||
|
||||
return loadTestModules(opts).then(() => {
|
||||
suite('Unexpected Errors & Loader Errors', function () {
|
||||
test('should not have unexpected errors', function () {
|
||||
const errors = _unexpectedErrors.concat(_loaderErrors);
|
||||
if (errors.length) {
|
||||
errors.forEach(function (stack) {
|
||||
console.error('');
|
||||
console.error(stack);
|
||||
});
|
||||
assert.ok(false, errors);
|
||||
}
|
||||
return loadWorkbenchTestingModule().then((workbenchTestingModule) => {
|
||||
const assertCleanState = workbenchTestingModule.assertCleanState;
|
||||
|
||||
suite('Tests are using suiteSetup and setup correctly', () => {
|
||||
test.skip('assertCleanState - check that registries are clean at the start of test running', () => {
|
||||
assertCleanState();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return loadTestModules(opts).then(() => {
|
||||
suite('Unexpected Errors & Loader Errors', function () {
|
||||
test('should not have unexpected errors', function () {
|
||||
const errors = _unexpectedErrors.concat(_loaderErrors);
|
||||
if (errors.length) {
|
||||
errors.forEach(function (stack) {
|
||||
console.error('');
|
||||
console.error(stack);
|
||||
});
|
||||
assert.ok(false, errors);
|
||||
}
|
||||
});
|
||||
|
||||
test.skip('assertCleanState - check that registries are clean and objects are disposed at the end of test running', () => {
|
||||
assertCleanState();
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function serializeSuite(suite) {
|
||||
|
||||
@@ -35,6 +35,8 @@ module.exports = class FullJsonStreamReporter extends BaseRunner {
|
||||
test = clean(test);
|
||||
test.actual = err.actual;
|
||||
test.expected = err.expected;
|
||||
test.actualJSON = err.actualJSON;
|
||||
test.expectedJSON = err.expectedJSON;
|
||||
test.err = err.message;
|
||||
test.stack = err.stack || null;
|
||||
writeEvent(['fail', test]);
|
||||
|
||||
Reference in New Issue
Block a user