Skip to content

Commit a7e228d

Browse files
Sets up E2E tests with playwright and adds tests (#17917)
* init playwright set up * Remove unneeded files * Configure playwright & clean up tests * Correct gulp set up * Fix playwright config * Sets up playwright test boilerplate * Clean up playwright config file * Fix timeout issue with init setup * Add first test * Rename first test file * Clean up test * Clean up * Adds connection test * Changes directory name to e2e * Disconnect from SQL server * Clean up * Minor clean up * Minor adjustment to test hooks * Add e2e test readme * Fix formatting in README * Rename utility file * Capture screenshots on error * Read vsCodeVersionName from .env * Uses env variables to load test conn values * Adds instructions to .env file * Adds query execution tests * Corrects instructions in example .env * Update E2E test readme. * Add user name, and password env vars
1 parent deac5f4 commit a7e228d

16 files changed

+541
-11
lines changed

.gitignore

+6-1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ test-reports
1919
.vscode-test
2020
localization/i18n/
2121
src/constants/localizedConstants.ts
22-
package.nls.*.json
22+
package.nls.*.json
23+
/test-results/
24+
/playwright-report/
25+
/blob-report/
26+
/playwright/.cache/
27+
.env

gulpfile.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ gulp.task('ext:lint', () => {
7474
return gulp.src([
7575
config.paths.project.root + '/src/**/*.ts',
7676
'!' + config.paths.project.root + '/src/views/htmlcontent/**/*',
77-
config.paths.project.root + '/test/unit/**/*.ts'
77+
config.paths.project.root + '/test/**/*.ts'
7878
])
7979
.pipe(gulpESLintNew({
8080
quiet: true
@@ -359,7 +359,7 @@ gulp.task('ext:copy-dependencies', (done) => {
359359
// Compile tests
360360
gulp.task('ext:compile-tests', (done) => {
361361
return gulp.src([
362-
config.paths.project.root + '/test/unit/**/*.ts',
362+
config.paths.project.root + '/test/**/*.ts',
363363
config.paths.project.root + '/typings/**/*.ts'])
364364
.pipe(srcmap.init())
365365
.pipe(tsProject())
@@ -369,8 +369,8 @@ gulp.task('ext:compile-tests', (done) => {
369369
process.exit(1);
370370
}
371371
})
372-
.pipe(srcmap.write('.', { includeContent: false, sourceRoot: '../test/unit' }))
373-
.pipe(gulp.dest('out/test/unit/'));
372+
.pipe(srcmap.write('.', { includeContent: false, sourceRoot: '../test' }))
373+
.pipe(gulp.dest('out/test/'));
374374

375375
});
376376

@@ -432,7 +432,7 @@ gulp.task('watch-src', function () {
432432
});
433433

434434
gulp.task('watch-tests', function () {
435-
return gulp.watch('./test/unit/**/*.ts', gulp.series('ext:compile-tests'))
435+
return gulp.watch('./test/**/*.ts', gulp.series('ext:compile-tests'))
436436
});
437437

438438
gulp.task('watch-reactviews', function () {

images/editor-view-with-tests.png

101 KB
Loading

images/test-explorer-view.png

36.9 KB
Loading

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"@angular/upgrade": "~2.1.2",
6767
"@eslint/compat": "^1.1.0",
6868
"@eslint/js": "^9.5.0",
69+
"@playwright/test": "^1.45.0",
6970
"@jgoz/esbuild-plugin-typecheck": "^4.0.0",
7071
"@types/azdata": "^1.44.0",
7172
"@types/ejs": "^3.1.0",
@@ -143,6 +144,7 @@
143144
"axios": "^1.6.0",
144145
"core-js": "^2.4.1",
145146
"decompress-zip": "^0.2.2",
147+
"dotenv": "^16.4.5",
146148
"ejs": "^3.1.7",
147149
"error-ex": "^1.3.0",
148150
"figures": "^1.4.0",

playwright.config.ts

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import dotenv from 'dotenv';
7+
import { defineConfig } from '@playwright/test';
8+
9+
dotenv.config({ path: './test/e2e/.env' })
10+
11+
/**
12+
* Read environment variables from file.
13+
* https://github.com/motdotla/dotenv
14+
*/
15+
// import dotenv from 'dotenv';
16+
// dotenv.config({ path: path.resolve(__dirname, '.env') });
17+
18+
/**
19+
* See https://playwright.dev/docs/test-configuration.
20+
*/
21+
export default defineConfig({
22+
testDir: './test/e2e',
23+
/* Run tests in files in parallel */
24+
fullyParallel: false,
25+
/* Fail the build on CI if you accidentally left test.only in the source code. */
26+
forbidOnly: !!process.env.CI,
27+
/* Retry on CI only */
28+
retries: process.env.CI ? 2 : 0,
29+
/* Opt out of parallel tests on CI. */
30+
workers: 1,
31+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
32+
reporter: 'html',
33+
/* Set timeout to 5 minutes */
34+
timeout: 5 * 60 * 1000,
35+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
36+
use: {
37+
/* Base URL to use in actions like `await page.goto('/')`. */
38+
// baseURL: 'http://127.0.0.1:3000',
39+
40+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
41+
trace: 'on-first-retry',
42+
},
43+
});

test/e2e/.env.example

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# To run tests locally, create a .env file next to this file and set the environment variables
2+
# as desired to establish a connection with a database.
3+
4+
# The name of the VS Code version name.
5+
# Options are: "stable", "insiders"
6+
VS_CODE_VERSION_NAME=stable
7+
8+
# The name of the database server to connect to.
9+
# This value is the name of the server that will be used by the tests.
10+
SERVER_NAME=(localdb)\MSSqlLocalDb
11+
12+
# The name of the database to connect to.
13+
# This value is optional and can be left empty.
14+
DATABASE_NAME=
15+
16+
# The authentication type to use to connect to the server.
17+
# Options are: "SQL Login", "Integrated", "Microsoft Entra Id - Universal w/ MFA Support"
18+
AUTHENTICATION_TYPE=SQL Login
19+
20+
# The username to log in to the database.
21+
USER_NAME=test-user
22+
23+
# The password to log in to the database.
24+
PASSWORD=
25+
26+
# Indicates whether to save the login password for future logins.
27+
# Options are: "Yes", "No"
28+
SAVE_PASSWORD=No
29+
30+
# The profile name is the name that will appear for the connection profile.
31+
# This value is optional and can be left empty.
32+
PROFILE_NAME=test-server

test/e2e/README.md

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# MSSQL for VSCode Extension - E2E Tests
2+
3+
## Get started
4+
5+
### Limitations
6+
7+
If running extension tests from CLI, the VS Code version the tests run with cannot be running already. As a workaround, VS Code Insiders should be used for test development, so that tests may run in VS Code Stable.
8+
9+
For more information regarding this limitation, refer to [using insiders version for extension development.](https://code.visualstudio.com/api/working-with-extensions/testing-extension#using-insiders-version-for-extension-development)
10+
11+
### Prerequisites
12+
13+
- [Node.js](https://nodejs.org/en/) v18 or higher
14+
- [yarn](https://yarnpkg.com/) v1.22.0 or higher, `npm install -g yarn`
15+
16+
---
17+
18+
### Setup
19+
20+
Tests are currently only setup to run locally.
21+
22+
1. Install root dependencies
23+
24+
From the root of the repo, install all of the build dependencies:
25+
26+
```shell
27+
[sudo] yarn
28+
```
29+
30+
2. Compile the extension and tests by running:
31+
32+
```shell
33+
gulp build
34+
```
35+
36+
or watch for changes in the tests by running:
37+
38+
```shell
39+
gulp watch-tests
40+
```
41+
42+
### Running tests
43+
44+
To run tests, the following options can be used:
45+
46+
1. Using Playwright Test for VSCode:
47+
- Install the `Playwright Test for VSCode` extension in VS code.
48+
- [Run tests with a single click](https://github.com/microsoft/playwright-vscode/blob/main/README.md#run-tests-with-a-single-click)
49+
50+
> Note: If you don't see any tests appearing in the **Test Explorer** view, like in the image, then you'll need to run them from the terminal first to get them to appear. Please refer to option 2.
51+
52+
![Playwright Test for VSCode Test Explorer](../../images/test-explorer-view.png).
53+
54+
2. Setup environment variables in the `test\e2e` folder
55+
- Create a `.env` file
56+
- Add the variables that you want based on the .env.example
57+
- Example:
58+
```env
59+
VS_CODE_VERSION_NAME=stable
60+
SERVER_NAME=(localdb)\MSSqlLocalDb
61+
AUTHENTICATION_TYPE=Integrated
62+
PROFILE_NAME=test-server
63+
```
64+
65+
3. To run tests from the command line execute the following command from the root:
66+
67+
```shell
68+
npx playwright test
69+
```
70+
71+
The tests will automatically appear in the **Test Explorer** view after running them once, and green run icons will appear to the left of line numbers in the editor, like this:
72+
73+
![Run buttons to the left of line numbers in editor](../../images/editor-view-with-tests.png)

test/e2e/activityBar.spec.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { ElectronApplication, Page, test, expect } from '@playwright/test';
7+
import { launchVsCodeWithMssqlExtension } from './utils/launchVscodeWithMsSqlExt';
8+
import { screenshotOnFailure } from './utils/screenshotOnError';
9+
10+
test.describe('MSSQL Extension - Activity Bar', async () => {
11+
let vsCodeApp: ElectronApplication;
12+
let vsCodePage: Page;
13+
14+
test.beforeAll(async () => {
15+
const { electronApp, page } = await launchVsCodeWithMssqlExtension();
16+
vsCodeApp = electronApp;
17+
vsCodePage = page;
18+
});
19+
20+
test('MSSQL button is present in activity bar', async () => {
21+
await vsCodePage.click('a[aria-label="SQL Server (Ctrl+Alt+D)"]');
22+
const count = await vsCodePage.locator('a[aria-label="SQL Server (Ctrl+Alt+D)"]').count();
23+
expect(count).toEqual(1);
24+
});
25+
26+
test.afterEach(async ({ }, testInfo) => {
27+
await screenshotOnFailure(vsCodePage, testInfo);
28+
});
29+
30+
test.afterAll(async () => {
31+
await vsCodeApp.close();
32+
});
33+
});

test/e2e/connection.spec.ts

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { ElectronApplication, Page, Locator, test, expect } from '@playwright/test';
7+
import { launchVsCodeWithMssqlExtension } from './utils/launchVscodeWithMsSqlExt';
8+
import { screenshotOnFailure } from './utils/screenshotOnError';
9+
import { getServerName, getDatabaseName, getAuthenticationType, getUserName, getPassword, getProfileName, getSavePassword } from './utils/envConfigReader';
10+
import { addDatabaseConnection } from './utils/testHelpers';
11+
12+
test.describe('MSSQL Extension - Database Connection', async () => {
13+
let vsCodeApp: ElectronApplication;
14+
let vsCodePage: Page;
15+
16+
test.beforeAll(async () => {
17+
const { electronApp, page } = await launchVsCodeWithMssqlExtension();
18+
vsCodeApp = electronApp;
19+
vsCodePage = page;
20+
});
21+
22+
test('Connect to local SQL Database, and disconnect', async () => {
23+
const serverName = getServerName();
24+
const databaseName = getDatabaseName();
25+
const authType = getAuthenticationType();
26+
const userName = getUserName();
27+
const password = getPassword();
28+
const savePassword = getSavePassword();
29+
const profileName = getProfileName();
30+
await addDatabaseConnection(vsCodePage, serverName, databaseName, authType, userName, password, savePassword, profileName);
31+
32+
let addedSqlConnection: Locator;
33+
if (profileName) {
34+
addedSqlConnection = await vsCodePage.locator(`div[aria-label="${profileName}"]`);
35+
}
36+
else {
37+
addedSqlConnection = await vsCodePage.getByText(`${serverName}`);
38+
}
39+
40+
await expect(addedSqlConnection).toBeVisible({ timeout: 20 * 1000 });
41+
42+
await addedSqlConnection.click({ button: 'right' });
43+
const disconnectOption = await vsCodePage.locator('span[aria-label="Disconnect"]');
44+
await disconnectOption.click();
45+
const isDiconnectOptionVisible = await disconnectOption.isVisible()
46+
if (isDiconnectOptionVisible) {
47+
await disconnectOption.click();
48+
}
49+
50+
await addedSqlConnection.click({ button: 'right' });
51+
await expect(disconnectOption).toBeHidden({ timeout: 10000 });
52+
});
53+
54+
test.afterEach(async ({ }, testInfo) => {
55+
await screenshotOnFailure(vsCodePage, testInfo);
56+
});
57+
58+
test.afterAll(async () => {
59+
await vsCodeApp.close();
60+
});
61+
});

0 commit comments

Comments
 (0)