Skip to content

Commit cd787d2

Browse files
authored
Enable intellisense and improve web smoke tests (#9623)
* Enable intellisense and improve web smoke tests * Misc
1 parent 42e3f38 commit cd787d2

15 files changed

+141
-127
lines changed

.github/workflows/build-test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ jobs:
767767
retention-days: 1
768768

769769
- name: Build web parts
770-
run: npm run compile-web
770+
run: npm run compile-web-test
771771
if: always()
772772

773773
- name: Run web smoke test

.vscode/launch.json

+33
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@
4444
"order": 1
4545
}
4646
},
47+
{
48+
"name": "Extension (web with daemon compilation)",
49+
"type": "pwa-extensionHost",
50+
"debugWebWorkerHost": true,
51+
"request": "launch",
52+
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionDevelopmentKind=web"],
53+
"outFiles": ["${workspaceFolder}/out/**/*", "!${workspaceFolder}/**/node_modules**/*"],
54+
"presentation": {
55+
"group": "1_extension",
56+
"order": 1
57+
}
58+
},
4759
{
4860
"name": "Extension (with daemon compilation)",
4961
"type": "extensionHost",
@@ -88,6 +100,27 @@
88100
"order": 3
89101
}
90102
},
103+
{
104+
"name": "Web Tests",
105+
"type": "extensionHost",
106+
"debugWebWorkerHost": true,
107+
"request": "launch",
108+
"args": [
109+
"--extensionDevelopmentPath=${workspaceFolder}",
110+
"--enable-proposed-api",
111+
"--extensionDevelopmentKind=web",
112+
"--extensionTestsPath=${workspaceFolder}/out/extension.web.bundle"
113+
],
114+
"outFiles": [
115+
"${workspaceFolder}/out/**/*.*"
116+
],
117+
"sourceMaps": true,
118+
"preLaunchTask": "compile-web-test",
119+
"presentation": {
120+
"group": "2_tests",
121+
"order": 11
122+
}
123+
},
91124
{
92125
// Note, for the smoke test you want to debug, you may need to copy the file,
93126
// rename it and remove a check for only smoke tests.

.vscode/tasks.json

+11
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@
4040
},
4141
"problemMatcher": ["$ts-webpack-watch"]
4242
},
43+
{
44+
"label": "compile-web-test",
45+
"type": "npm",
46+
"script": "compile-web-test",
47+
"isBackground": true,
48+
"group": {
49+
"kind": "build",
50+
"isDefault": true
51+
},
52+
"problemMatcher": ["$ts-webpack-watch"]
53+
},
4354
{
4455
"label": "Run Unit Tests",
4556
"type": "npm",

build/launchWebTest.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
const path = require('path');
5+
const test_web = require('@vscode/test-web');
6+
async function go() {
7+
try {
8+
const extensionDevelopmentPath = path.resolve(__dirname, '../');
9+
await test_web.runTests({
10+
browserType: 'chromium',
11+
extensionDevelopmentPath,
12+
extensionTestsPath: path.join(extensionDevelopmentPath, 'out', 'extension.web.bundle')
13+
});
14+
} catch (err) {
15+
console.error('Failed to run tests');
16+
process.exit(1);
17+
}
18+
}
19+
void go();

build/webpack/webpack.extension.web.config.js

+13-6
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@ const webpack = require('webpack');
88
const constants = require('../constants');
99
const CleanTerminalPlugin = require('clean-terminal-webpack-plugin');
1010

11+
const prodEntry = {
12+
extension: './src/extension.web.ts',
13+
'test/smoke.test/index': './src/test/web/smoke.test/index.ts' // source of the web extension test runner
14+
};
15+
const testEntry = {
16+
extension: './src/test/web/smoke.test/index.ts' // source of the web extension test runner
17+
};
18+
19+
// When running web tests, the entry point for the tests and extension are the same.
20+
const entry = process.env.VSC_TEST_BUNDLE ? testEntry : prodEntry;
21+
1122
// tslint:disable-next-line:no-var-requires no-require-imports
1223
const configFileName = path.join(constants.ExtensionRootDir, 'tsconfig.extension.web.json');
1324
const config = {
14-
mode: 'none',
25+
mode: process.env.VSC_TEST_BUNDLE ? 'development' : 'none',
1526
target: 'webworker',
16-
entry: {
17-
extension: './src/extension.web.ts',
18-
'test/vscode.test/index': './src/test/web/vscode.test/index.ts', // source of the web extension test runner
19-
'test/smoke.test/index': './src/test/web/smoke.test/index.ts' // source of the web extension test runner
20-
},
27+
entry,
2128
devtool: 'nosources-source-map', // create a source map that points to the original source file
2229
node: {
2330
__dirname: false,

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -2102,6 +2102,8 @@
21022102
"compile-webviews-watch": "webpack --config ./build/webpack/webpack.datascience-ui.config.js --watch",
21032103
"compile-web-watch": "webpack --config ./build/webpack/webpack.extension.web.config.js --stats-error-details --watch",
21042104
"compile-web": "webpack --config ./build/webpack/webpack.extension.web.config.js",
2105+
"compile-web-test": "cross-env VSC_TEST_BUNDLE=true npm run compile-web",
2106+
"compile-web-test-watch": "cross-env VSC_TEST_BUNDLE=true npm run compile-web-watch",
21052107
"compile-webviews-watchd": "deemon npm run compile-webviews-watch",
21062108
"compile-widgetTester": "cross-env NODE_OPTIONS=--max_old_space_size=9096 webpack --config ./build/webpack/webpack.datascience-ui-widgetTester.config.js --watch",
21072109
"kill-compile-webviews-watchd": "deemon --kill npm run compile-webviews-watch",
@@ -2125,7 +2127,7 @@
21252127
"testPerformance": "node ./out/test/testBootstrap.node.js ./out/test/performanceTest.js",
21262128
"testSmoke": "node ./out/test/testBootstrap.node.js ./out/test/smokeTest.node.js",
21272129
"testSmokeLogged": "cross-env VSC_JUPYTER_FORCE_LOGGING=true VSC_JUPYTER_LOG_FILE=smoke-test.log node --no-force-async-hooks-checks ./out/test/testBootstrap.node.js ./out/test/smokeTest.node.js",
2128-
"testSmokeWeb": "node ./out/test/smokeTest.web.js",
2130+
"testSmokeWeb": "node ./build/launchWebTest.js",
21292131
"lint": "eslint -c .eslintrc.js --ext .ts src",
21302132
"prettier-fix": "prettier 'src/**/*.ts*' --write && prettier 'build/**/*.js' --write",
21312133
"clean": "gulp clean",

src/platform/api.ts

-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { INotebookEditorProvider } from '../notebooks/types';
99
import { IDataViewerDataProvider, IDataViewerFactory } from '../webviews/extension-side/dataviewer/types';
1010
import { IExportedKernelService } from './api/extension';
1111
import { IExportedKernelServiceFactory, IPythonApiProvider, PythonApi } from './api/types';
12-
import { IApplicationShell } from './common/application/types';
1312
import { isTestExecution } from './common/constants';
1413
import { IExtensionContext } from './common/types';
1514
import { IServiceContainer, IServiceManager } from './ioc/types';
@@ -102,14 +101,6 @@ export function buildApi(
102101
/* eslint-disable @typescript-eslint/no-explicit-any */
103102
(api as any).serviceContainer = serviceContainer;
104103
(api as any).serviceManager = serviceManager;
105-
(api as any).getSymbol = (symbol: String) => {
106-
// Needed for web tests. Eval for the extension happens in another web worker so
107-
// the symbol objects have different values
108-
switch (symbol) {
109-
case 'IApplicationShell':
110-
return IApplicationShell;
111-
}
112-
};
113104
/* eslint-enable @typescript-eslint/no-explicit-any */
114105
}
115106
return api;

src/test/common.ts

-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22
// Licensed under the MIT License.
33
'use strict';
44

5-
import { interfaces } from 'inversify';
65
import { IExtensionApi } from '../platform/api';
76
import { IServiceContainer, IServiceManager } from '../platform/ioc/types';
87

98
export interface IExtensionTestApi extends IExtensionApi {
109
serviceContainer: IServiceContainer;
1110
serviceManager: IServiceManager;
12-
getSymbol<T>(symbolName: string): interfaces.ServiceIdentifier<T> | undefined;
1311
}

src/test/smokeTest.web.ts

-25
This file was deleted.

src/test/web/smoke.test/index.ts

+58-23
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,64 @@
1-
// imports mocha for the browser, defining the `mocha` global.
2-
require('mocha/mocha');
1+
// Re-export extension entry point, so that the output from this file
2+
// when bundled can be used as entry point for extension as well as tests.
3+
// The same objects/types will be used as the module is only ever loaded once by nodejs.
4+
import * as extension from '../../../extension.web';
5+
import * as vscode from 'vscode';
6+
import type { IExtensionApi } from '../../../platform/api';
7+
import type { IExtensionContext } from '../../../platform/common/types';
8+
import { IExtensionTestApi } from '../../common';
9+
import { JVSC_EXTENSION_ID } from '../../../platform/common/constants';
310

4-
export function run(): Promise<void> {
5-
return new Promise((c, e) => {
6-
mocha.setup({
7-
ui: 'tdd',
8-
reporter: undefined
9-
});
11+
let activatedResponse: undefined | IExtensionApi;
1012

11-
// bundles all files in the current directory matching `*.test`
12-
const importAll = (r: __WebpackModuleApi.RequireContext) => r.keys().forEach(r);
13-
importAll(require.context('.', true, /\.web.test$/));
13+
// Basically this is the entry point for the extension.
14+
export async function activate(context: IExtensionContext): Promise<IExtensionApi> {
15+
if (activatedResponse) {
16+
return activatedResponse;
17+
}
18+
vscode.commands.registerCommand('jupyter.web.runTests', async () => {
19+
// imports mocha for the browser, defining the `mocha` global.
20+
require('mocha/mocha');
1421

15-
try {
16-
// Run the mocha test
17-
mocha.run((failures) => {
18-
if (failures > 0) {
19-
e(new Error(`${failures} tests failed.`));
20-
} else {
21-
c();
22-
}
22+
return new Promise<void>((resolve, reject) => {
23+
mocha.setup({
24+
ui: 'tdd',
25+
reporter: undefined
2326
});
24-
} catch (err) {
25-
console.error(err);
26-
e(err);
27-
}
27+
28+
// bundles all files in the current directory matching `*.test`
29+
const importAll = (r: __WebpackModuleApi.RequireContext) => r.keys().forEach(r);
30+
importAll(require.context('.', true, /\.web.test$/));
31+
32+
try {
33+
// Run the mocha test
34+
mocha.run((failures) => {
35+
if (failures > 0) {
36+
reject(new Error(`${failures} tests failed.`));
37+
} else {
38+
resolve();
39+
}
40+
});
41+
} catch (err) {
42+
console.error(err);
43+
reject(err);
44+
}
45+
});
2846
});
47+
activatedResponse = await extension.activate(context);
48+
return activatedResponse;
49+
}
50+
51+
export async function deactivate(): Promise<void> {
52+
return extension.deactivate();
53+
}
54+
55+
export async function run(): Promise<void> {
56+
// Activate the extension so that the commands are registered.
57+
// Also this will not slow down the suite-setups.
58+
const extension = vscode.extensions.getExtension<IExtensionTestApi>(JVSC_EXTENSION_ID)!;
59+
const api = await extension.activate();
60+
await api.ready;
61+
// Run the tests from within the context of the extension bundle.
62+
// We achieve this by getting the extension to run the tests (then its guaranteed to use the same context as the extension).
63+
await vscode.commands.executeCommand('jupyter.web.runTests');
2964
}

src/test/web/smoke.test/smoke.web.test.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ suite('Web Extension Smoke Test Suite', () => {
1818
});
1919

2020
test('Verify containers', () => {
21-
const appShellSymbol = extensionApi.getSymbol<IApplicationShell>('IApplicationShell');
22-
assert.ok(appShellSymbol, `Cannot get the symbol for IApplicationShell`);
23-
const appShell = extensionApi.serviceManager?.get<IApplicationShell>(appShellSymbol!);
21+
const appShell = extensionApi.serviceManager?.get<IApplicationShell>(IApplicationShell);
2422
assert.ok(appShell, 'Dependency Injection container not initialized in web context');
2523
});
2624
});

src/test/web/vscode.test/extension.web.test.ts

-24
This file was deleted.

src/test/web/vscode.test/index.ts

-29
This file was deleted.

tsconfig.extension.web.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
"compilerOptions": {
44
"paths": {
55
"*": ["types/*"]
6-
},
7-
"types": ["@types/vscode-notebook-renderer/preload", "webpack-env"]
6+
}
87
},
98
"exclude": [
109
"node_modules",

tsconfig.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"resolveJsonModule": true,
2323
"removeComments": true,
2424
"useUnknownInCatchVariables": false,
25-
"types": ["@types/vscode-notebook-renderer/preload"]
25+
"types": ["@types/vscode-notebook-renderer/preload", "webpack-env"]
2626
},
2727
"exclude": [
2828
"node_modules",
@@ -35,7 +35,6 @@
3535
"src/ipywidgets",
3636
"src/smoke",
3737
"src/test/datascience/extensionapi",
38-
"src/test/web",
3938
"build",
4039
"out",
4140
"ipywidgets",

0 commit comments

Comments
 (0)