Skip to content

Commit

Permalink
add ui tests
Browse files Browse the repository at this point in the history
  • Loading branch information
trungleduc committed Nov 6, 2023
1 parent 3fa6946 commit f6dd9c3
Show file tree
Hide file tree
Showing 18 changed files with 4,596 additions and 6 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ coverage
# ms IDE stuff
.history/
.vscode/

ui-tests/playwright-report
53 changes: 53 additions & 0 deletions .github/workflows/ui-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: UI Test

on:
push:
branches: [main]
pull_request:
branches: '*'

jobs:
ui-tests:
name: Visual Regression
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Install node
uses: actions/setup-node@v1
with:
node-version: '18.x'

- name: Install Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
architecture: 'x64'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install jupyter_packaging jupyterlab
- name: Install the extension
run: |
python -m pip install ".[test]"
cd ui-tests
jlpm install
- name: Install browser
run: npx playwright install chromium
working-directory: ui-tests

- name: Test
run: jlpm run test
working-directory: ui-tests

- name: Upload Playwright Test assets
if: always()
uses: actions/upload-artifact@v2
with:
name: gridstack-test-assets
path: |
ui-tests/test-results
47 changes: 47 additions & 0 deletions .github/workflows/update_galata_references.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Update UI-tests References

on:
issue_comment:
types: [created, edited]

permissions:
contents: write
pull-requests: write

defaults:
run:
shell: bash -l {0}

jobs:
update-reference-screenshots:
name: Update UI Tests References
if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, 'update playwright snapshots') }}
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Configure git to use https
run: git config --global hub.protocol https

- name: Checkout the branch from the PR that triggered the job
run: hub pr checkout ${{ github.event.issue.number }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Install Micromamba
uses: mamba-org/provision-with-micromamba@main

- name: Install dependencies and build tests
run: |
python -m pip install ".[test]"
cd ui-tests
jlpm install --immutable
- uses: jupyterlab/maintainer-tools/.github/actions/update-snapshots@main
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
test_folder: ui-tests
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,10 @@ dmypy.json
_temp_extension
junit.xml
[uU]ntitled*
.yarn/
.yarn/

ui-tests/playwright-report
ui-tests/test-results
ui-tests/benchmark-results
ui-tests/jlab_root
ui-tests/examples
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ coverage
# ms IDE stuff
.history/
.vscode/

ui-tests/playwright-report
6 changes: 3 additions & 3 deletions examples/iris_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@
}
],
"source": [
"sns.FacetGrid(df, hue=\"Species\", size=5).map(plt.scatter, \"SepalLengthCm\", \"SepalWidthCm\").add_legend();"
"sns.FacetGrid(df, hue=\"Species\").map(plt.scatter, \"SepalLengthCm\", \"SepalWidthCm\").add_legend();"
]
},
{
Expand Down Expand Up @@ -528,7 +528,7 @@
}
},
"kernelspec": {
"display_name": "Python 3",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
Expand All @@ -542,7 +542,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
"version": "3.10.13"
}
},
"nbformat": 4,
Expand Down
15 changes: 14 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,20 @@ dynamic = ["version", "description", "authors", "urls", "keywords"]

[project.optional-dependencies]
dev = ["click", "jupyter_releaser", "hatch", "hatch-nodejs-version"]
test = ["ipykernel", "lxml", "nbconvert>=6.4.5,<8", "pytest", "pytest-tornasync"]
test = [
"ipykernel",
"lxml",
"nbconvert>=6.4.5,<8",
"pytest",
"pytest-tornasync",
"pandas",
"numpy",
"scipy",
"matplotlib",
"seaborn",
"ipywidgets",
"bqplot"
]
docs = ["sphinx", "myst-parser", "pydata-sphinx-theme"]

[tool.hatch.version]
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.eslint.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "./tsconfig",
"include": ["src/**/*", "style/**/*"],
"include": ["src/**/*", "style/**/*", "ui-tests/**/*"],
"compilerOptions": {
"types": ["jest"]
}
Expand Down
12 changes: 12 additions & 0 deletions ui-tests/jupyter_server_test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Server configuration for integration tests.
!! Never use this configuration in production because it
opens the server to the world and provide access to JupyterLab
JavaScript objects through the global window variable.
"""
from jupyterlab.galata import configure_jupyter_server

configure_jupyter_server(c) # noqa
c.ServerApp.root_dir = './examples' # noqa
# Uncomment to set server log level to debug level
# c.ServerApp.log_level = "DEBUG"
24 changes: 24 additions & 0 deletions ui-tests/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "voila-gridstack-ui-tests",
"version": "1.0.0",
"description": "Voila gridstack Ui Tests",
"private": true,
"scripts": {
"copy": "rimraf exampes && copyup ../examples/* ui-tests",
"start": "jlpm copy && jupyter lab --config jupyter_server_test_config.py",
"start:detached": "yarn run start&",
"test": "npx playwright test",
"test:debug": "PWDEBUG=1 npx playwright test",
"test:report": "http-server ./playwright-report -a localhost -o",
"test:update": "npx playwright test --update-snapshots"
},
"author": "Project Jupyter",
"license": "BSD-3-Clause",
"dependencies": {
"@jupyterlab/galata": "^5.0.0-beta.0"
},
"devDependencies": {
"copyfiles": "^2.4.1",
"rimraf": "^3.0.2"
}
}
24 changes: 24 additions & 0 deletions ui-tests/playwright.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
timeout: 120000,
reporter: [[process.env.CI ? 'dot' : 'list'], ['html']],
use: {
baseURL: 'http://localhost:8888',
trace: 'on-first-retry',
video: 'retain-on-failure',
},
retries: 0,
expect: {
toMatchSnapshot: {
maxDiffPixelRatio: 0.01,
},
},
webServer: [
{
command: 'yarn start',
url: 'http://localhost:8888/lab',
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
},
],
testDir: './tests',
};
46 changes: 46 additions & 0 deletions ui-tests/tests/extension.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

import { expect, test, APIRequestContext, Page } from '@playwright/test';

async function beforeEach(
page: Page,
request: APIRequestContext
): Promise<void> {
page.setDefaultTimeout(600000);
page.setViewportSize({ width: 1920, height: 1080 });
page.on('console', (message) => {
console.log('CONSOLE MSG ---', message.text());
});
}

test.describe('JupyterLab extension tests', () => {
test.beforeEach(({ page, request }) => void beforeEach(page, request));

test('Render iris_example.ipynb', async ({ page }) => {
const notebookName = 'iris_example';
await page.goto(`/lab/tree/${notebookName}.ipynb?reset`);
// wait for the widgets to load
await page
.getByRole('button', { name: 'Open with Voilà GridStack editor' })
.click();
await page.waitForTimeout(500);
expect(await page.screenshot()).toMatchSnapshot(`${notebookName}.png`);

await page.getByText('File', { exact: true }).click();
await page.locator('#jp-mainmenu-file').getByText('Close All Tabs').click();
});

test('Render scotch_dashboard.ipynb', async ({ page }) => {
const notebookName = 'scotch_dashboard';
await page.goto(`/lab/tree/${notebookName}.ipynb?reset`);
// wait for the widgets to load
await page
.getByRole('button', { name: 'Open with Voilà GridStack editor' })
.click();
await page.waitForTimeout(1500);
expect(await page.screenshot()).toMatchSnapshot(`${notebookName}.png`);
await page.getByText('File', { exact: true }).click();
await page.locator('#jp-mainmenu-file').getByText('Close All Tabs').click();
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions ui-tests/tests/template.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

import { expect, test, APIRequestContext, Page } from '@playwright/test';

async function beforeEach(
page: Page,
request: APIRequestContext
): Promise<void> {
page.setDefaultTimeout(600000);
page.setViewportSize({ width: 1920, height: 1080 });
page.on('console', (message) => {
console.log('CONSOLE MSG ---', message.text());
});
}

test.describe('Template tests', () => {
test.beforeEach(async ({ page, request }) => void beforeEach(page, request));

test('Render iris_example.ipynb', async ({ page }) => {
const notebookName = 'iris_example';
// const page = await context.newPage();
await page.goto(`/voila/render/${notebookName}.ipynb?template=gridstack`),
// wait for the widgets to load
await page.waitForSelector('div.lm-Widget.jp-RenderedImage');
await page.waitForTimeout(500);
expect(await page.screenshot()).toMatchSnapshot(`${notebookName}.png`);
});

test('Render scotch_dashboard.ipynb', async ({ page }) => {
const notebookName = 'scotch_dashboard';
await page.goto(`/voila/render/${notebookName}.ipynb?template=gridstack`);
// wait for the widgets to load
await page.waitForSelector('div.lm-Widget.bqplot.figure.jupyter-widgets');
await page.waitForTimeout(500);
expect(await page.screenshot()).toMatchSnapshot(`${notebookName}.png`);
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit f6dd9c3

Please sign in to comment.