Skip to content

Commit 784a496

Browse files
authored
Add ui tests (#171)
* add ui tests * Execute ui test only on linux * Restore running test against JLab prerelease To many selectors and screenshots are wrong otherwise * Change notebook directory to an empty folder * Force viewport & remove slow motion Pin playwright * Fixe embedme * Close filebrowser before taking screenshot Fix other tests * Add test on server-extension Remove slow down * Ensure homogeneous ui test config * Homogeneous timeout * Fix integration test on server-extension * Fix JSDoc warnings * Fix README * More robust tests * Update README.md
1 parent 1395b09 commit 784a496

File tree

147 files changed

+3940
-71
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

147 files changed

+3940
-71
lines changed

.github/workflows/main.yml

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ jobs:
6464
diff ../hello-world/.eslintignore .eslintignore
6565
diff ../hello-world/.eslintrc.js .eslintrc.js
6666
diff ../hello-world/.gitignore .gitignore
67+
diff ../hello-world/ui-tests/playwright.config.ts ./ui-tests/playwright.config.ts
68+
diff ../hello-world/ui-tests/README.md ./ui-tests/README.md
6769
shell: bash
6870
- name: Install node
6971
if: steps.filter.outputs.extension == 'true'
@@ -103,13 +105,34 @@ jobs:
103105
- name: Build and check by extension
104106
if: steps.filter.outputs.extension == 'true'
105107
run: |
106-
pip install . -vvv
108+
pip install . -v
107109
jupyter labextension list 2>&1 | tee labextension.list
108110
cat labextension.list | grep -ie "@jupyterlab-examples/*.*OK"
109111
python -m jupyterlab.browser_check
110112
pip uninstall -y $(python setup.py --name)
111113
shell: bash
112114

115+
- name: Integration tests
116+
if: steps.filter.outputs.extension == 'true' && startsWith(runner.os, 'Linux')
117+
run: |
118+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env down || true
119+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env pull -q || true
120+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env build
121+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env run --rm e2e
122+
- name: Upload UI Test artifacts
123+
if: steps.filter.outputs.extension == 'true' && startsWith(runner.os, 'Linux') && always()
124+
uses: actions/upload-artifact@v2
125+
with:
126+
name: ui-test-output
127+
path: |
128+
${{ matrix.example }}/ui-tests/test-results
129+
- name: Stop containers
130+
if: steps.filter.outputs.extension == 'true' && startsWith(runner.os, 'Linux') && always()
131+
run: |
132+
# Print jupyterlab logs before removing the containers using the container name set in docker-compose file
133+
docker logs jupyterlab
134+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env down
135+
113136
build_serverextension:
114137
runs-on: ${{ matrix.os }}
115138
strategy:
@@ -147,6 +170,8 @@ jobs:
147170
diff hello-world/tsconfig.json server-extension/tsconfig.json
148171
diff hello-world/.eslintignore server-extension/.eslintignore
149172
diff hello-world/.eslintrc.js server-extension/.eslintrc.js
173+
diff hello-world/ui-tests/playwright.config.ts server-extension/ui-tests/playwright.config.ts
174+
diff hello-world/ui-tests/README.md server-extension/ui-tests/README.md
150175
shell: bash
151176
- name: Install Python
152177
if: steps.filter.outputs.extension == 'true'
@@ -218,6 +243,29 @@ jobs:
218243
cat labextension.list | grep -ie "@jupyterlab-examples/server-extension.*OK"
219244
python -m jupyterlab.browser_check
220245
246+
- name: Integration tests
247+
if: steps.filter.outputs.extension == 'true' && startsWith(runner.os, 'Linux')
248+
run: |
249+
cd server-extension
250+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env down || true
251+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env pull -q || true
252+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env build
253+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env run --rm e2e
254+
- name: Upload UI Test artifacts
255+
if: steps.filter.outputs.extension == 'true' && startsWith(runner.os, 'Linux') && always()
256+
uses: actions/upload-artifact@v2
257+
with:
258+
name: ui-test-output
259+
path: |
260+
server-extension/ui-tests/test-results
261+
- name: Stop containers
262+
if: steps.filter.outputs.extension == 'true' && startsWith(runner.os, 'Linux') && always()
263+
run: |
264+
cd server-extension
265+
# Print jupyterlab logs before removing the containers using the container name set in docker-compose file
266+
docker logs jupyterlab
267+
docker-compose -f ../end-to-end-tests/docker-compose.yml --env-file ./ui-tests/.env down
268+
221269
build_all:
222270
runs-on: ${{ matrix.os }}
223271
strategy:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ __pycache__
1313

1414
static
1515
labextension
16+
**/test-results/

command-palette/.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ node_modules
22
dist
33
coverage
44
**/*.d.ts
5+
ui-tests

command-palette/style/index.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import url('base.css');

command-palette/ui-tests/.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
EXT_FOLDER=command-palette/jupyterlab_examples_command_palette
2+
EXT_NAME=command-palette

command-palette/ui-tests/README.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Test
2+
3+
The test will produce a video to help debugging and check what happened.
4+
5+
To execute integration tests, you can two options:
6+
7+
- use docker-compose (cons: needs to know and use docker) - this is a more reliable solution.
8+
- run tests locally (cons: will interact with your JupyterLab user settings)
9+
10+
## Test on docker
11+
12+
1. Compile the extension:
13+
14+
```
15+
jlpm install
16+
jlpm run build:prod
17+
```
18+
19+
2. Execute the docker stack (`extension-path` needs to be set accordingly):
20+
21+
```
22+
docker-compose -f ./end-to-end-tests/docker-compose.yml --env-file ./extension-path/ui-tests/.env build
23+
docker-compose -f ./end-to-end-tests/docker-compose.yml --env-file ./extension-path/ui-tests/.env run --rm e2e
24+
docker-compose -f ./end-to-end-tests/docker-compose.yml --env-file ./extension-path/ui-tests/.env down
25+
```
26+
27+
## Test locally
28+
29+
1. Compile the extension:
30+
31+
```
32+
jlpm install
33+
jlpm run build:prod
34+
```
35+
36+
2. Start JupyterLab _with the extension installed_ without any token or password
37+
38+
```
39+
jupyter lab --ServerApp.token= --ServerApp.password=
40+
```
41+
42+
3. Execute in another console the [Playwright](https://playwright.dev/docs/test-intro) tests:
43+
44+
```
45+
cd ui-tests
46+
jlpm install
47+
npx playwright test
48+
```
49+
50+
# Create tests
51+
52+
To create tests, the easiest way is to use the code generator tool of playwright:
53+
54+
1. Compile the extension:
55+
56+
```
57+
jlpm install
58+
jlpm run build:prod
59+
```
60+
61+
2. Start JupyterLab _with the extension installed_ without any token or password:
62+
63+
**Using docker**
64+
65+
```
66+
docker-compose -f ./end-to-end-tests/docker-compose.yml --env-file ./extension-path/ui-tests/.env run --rm -p 8888:8888 lab
67+
```
68+
69+
**Using local installation**
70+
71+
```
72+
jupyter lab --ServerApp.token= --ServerApp.password=
73+
```
74+
75+
3. Launch the code generator tool:
76+
77+
```
78+
cd ui-tests
79+
jlpm install
80+
npx playwright codegen localhost:8888
81+
```
82+
83+
# Debug tests
84+
85+
To debug tests, a good way is to use the inspector tool of playwright:
86+
87+
1. Compile the extension:
88+
89+
```
90+
jlpm install
91+
jlpm run build:prod
92+
```
93+
94+
2. Start JupyterLab _with the extension installed_ without any token or password:
95+
96+
**Using docker**
97+
98+
```
99+
docker-compose -f ./end-to-end-tests/docker-compose.yml --env-file ./extension-path/ui-tests/.env run --rm -p 8888:8888 lab
100+
```
101+
102+
**Using local installation**
103+
104+
```
105+
jupyter lab --ServerApp.token= --ServerApp.password=
106+
```
107+
108+
3. Launch the code generator tool:
109+
110+
```
111+
cd ui-tests
112+
jlpm install
113+
PWDEBUG=1 npx playwright test
114+
```

command-palette/ui-tests/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "@jupyterlab-examples/command-palette-tests",
3+
"version": "0.1.0",
4+
"description": "Integration test for command-palette example",
5+
"repository": "https://github.com/jupyterlab/extension-examples",
6+
"author": "Project Jupyter Contributors",
7+
"license": "BSD-3-Clause",
8+
"private": true,
9+
"devDependencies": {
10+
"@playwright/test": "1.12.3",
11+
"typescript": "~4.1.3"
12+
}
13+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { PlaywrightTestConfig } from '@playwright/test';
2+
3+
const config: PlaywrightTestConfig = {
4+
timeout: 60000,
5+
use: {
6+
// Browser options
7+
// headless: false,
8+
// slowMo: 500,
9+
10+
// Context options
11+
viewport: { width: 1280, height: 720 },
12+
13+
// Artifacts
14+
video: 'on',
15+
},
16+
};
17+
18+
export default config;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
const TARGET_URL = process.env.TARGET_URL ?? 'http://localhost:8888';
4+
5+
test('should emit console message when called from palette', async ({
6+
page,
7+
}) => {
8+
const logs: string[] = [];
9+
10+
page.on('console', (message) => {
11+
logs.push(message.text());
12+
});
13+
14+
await page.goto(`${TARGET_URL}/lab`);
15+
await page.waitForSelector('#jupyterlab-splash', { state: 'detached' });
16+
await page.waitForSelector('div[role="main"] >> text=Launcher');
17+
18+
// Click text=View
19+
await page.click('text=View');
20+
// Click text=Activate Command Palette
21+
await page.click('text=Activate Command Palette');
22+
// Fill [aria-label="Command Palette Section"] [placeholder="SEARCH"]
23+
await page.fill(
24+
'[aria-label="Command Palette Section"] [placeholder="SEARCH"]',
25+
'Execute'
26+
);
27+
// Click text=Execute jlab-examples:command-palette Command
28+
await page.click('text=Execute jlab-examples:command-palette Command');
29+
30+
expect(
31+
logs.filter((s) =>
32+
s.startsWith('jlab-examples:command-palette has been called from palette')
33+
)
34+
).toHaveLength(1);
35+
});

commands/.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ node_modules
22
dist
33
coverage
44
**/*.d.ts
5+
ui-tests

0 commit comments

Comments
 (0)