test(improve-setup): sharding configuration, allow accessing cornerstone methods and events in tests, and add types (#4255)

This commit is contained in:
Ibrahim 2024-06-25 10:16:51 -04:00 committed by GitHub
parent 2bcdb52db9
commit c9cc372581
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 113 additions and 26 deletions

View File

@ -5,23 +5,59 @@ on:
pull_request: pull_request:
branches: [main, master] branches: [main, master]
jobs: jobs:
test: playwright-tests:
timeout-minutes: 120 timeout-minutes: 60
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4, 5]
shardTotal: [5]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: export NODE_OPTIONS="--max_old_space_size=8192" && npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- name: Upload blob report to GitHub Actions Artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: blob-report-${{ matrix.shardIndex }}
path: blob-report
retention-days: 1
merge-reports:
if: ${{ !cancelled() }}
needs: [playwright-tests]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: lts/* node-version: 18
- name: Install dependencies - name: Install dependencies
run: npm install -g yarn && yarn run: yarn install --frozen-lockfile
- name: Install Playwright Browsers
run: yarn playwright install --with-deps - name: Download blob reports from GitHub Actions Artifacts
- name: Run Playwright tests uses: actions/download-artifact@v4
run: yarn test:e2e:ci
- uses: actions/upload-artifact@v4
if: always()
with: with:
name: playwright-report path: all-blob-reports
path: tests/playwright-report pattern: blob-report-*
retention-days: 30 merge-multiple: true
- name: Merge into HTML Report
run: npx playwright merge-reports --reporter html ./all-blob-reports
- name: Upload HTML report
uses: actions/upload-artifact@v4
with:
name: html-report--attempt-${{ github.run_attempt }}
path: playwright-report
retention-days: 14

View File

@ -6,6 +6,8 @@ import SyncGroupServiceType from '../services/SyncGroupService';
import ToolGroupServiceType from '../services/ToolGroupService'; import ToolGroupServiceType from '../services/ToolGroupService';
import ViewportActionCornersServiceType from '../services/ViewportActionCornersService/ViewportActionCornersService'; import ViewportActionCornersServiceType from '../services/ViewportActionCornersService/ViewportActionCornersService';
import ColorbarServiceType from '../services/ColorbarService'; import ColorbarServiceType from '../services/ColorbarService';
import * as cornerstone from '@cornerstonejs/core';
import * as cornerstoneTools from '@cornerstonejs/tools';
declare global { declare global {
namespace AppTypes { namespace AppTypes {
@ -25,5 +27,11 @@ declare global {
viewportActionCornersService?: ViewportActionCornersServiceType; viewportActionCornersService?: ViewportActionCornersServiceType;
colorbarService?: ColorbarServiceType; colorbarService?: ColorbarServiceType;
} }
export interface Test {
services?: Services;
cornerstone?: typeof cornerstone;
cornerstoneTools?: typeof cornerstoneTools;
}
} }
} }

View File

@ -49,6 +49,7 @@
"test:unit:ci": "lerna run test:unit:ci --parallel --stream", "test:unit:ci": "lerna run test:unit:ci --parallel --stream",
"test:e2e": "lerna run test:e2e --stream", "test:e2e": "lerna run test:e2e --stream",
"test:e2e:ci": "npx playwright test", "test:e2e:ci": "npx playwright test",
"test:e2e:ui": "npx playwright test --ui",
"test:e2e:headed": "npx playwright test --headed", "test:e2e:headed": "npx playwright test --headed",
"test:e2e:dist": "lerna run test:e2e:dist --stream", "test:e2e:dist": "lerna run test:e2e:dist --stream",
"test:e2e:serve": "yarn test:data && lerna run test:e2e:serve --stream", "test:e2e:serve": "yarn test:data && lerna run test:e2e:serve --stream",

View File

@ -120,6 +120,13 @@ declare global {
dataSources?: any; dataSources?: any;
oidc?: any; oidc?: any;
} }
export interface Test {
services?: Services;
commandsManager?: CommandsManager;
extensionManager?: ExtensionManager;
config?: Config;
}
} }
export type withAppTypes<T = object> = T & export type withAppTypes<T = object> = T &

View File

@ -128,6 +128,21 @@ yarn playwright show-report tests/playwright-report
By default, when you run the tests, it will call the `yarn start` command to serve the viewer first, then run the tests, if you would like to serve the viewer manually, you can use the same command. The viewer will be available at `http://localhost:3000`. This could speed up your development process since playwright will skip this step and use the existing server on port 3000. By default, when you run the tests, it will call the `yarn start` command to serve the viewer first, then run the tests, if you would like to serve the viewer manually, you can use the same command. The viewer will be available at `http://localhost:3000`. This could speed up your development process since playwright will skip this step and use the existing server on port 3000.
## Accessing services, managers, configs and cornerstone in your tests
If you would like to access the cornerstone3D, services, or command managers in your tests, you can use the `page.evaluate` function to access them. For example, if you would like to access the `services` so you can show a UI notifcation using the uiNotifcationService, you can use the following code snippet:
```ts
await page.evaluate(({ services }: AppTypes.Test) => {
const { uiNotificationService } = services;
uiNotificationService.show({
title: 'Test',
message: 'This is a test',
type: 'info',
});
}, await page.evaluateHandle('window'));
```
## Playwright VSCode Extension and Recording Tests ## Playwright VSCode Extension and Recording Tests
If you are using VSCode, you can use the Playwright extension to help you write your tests. The extension provides a test runner and many great features such as picking a locator using your mouse, recording a new test, and more. You can install the extension by searching for `Playwright` in the extensions tab in VSCode or by visiting the [Playwright extension page](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright). If you are using VSCode, you can use the Playwright extension to help you write your tests. The extension provides a test runner and many great features such as picking a locator using your mouse, recording a new test, and more. You can install the extension by searching for `Playwright` in the extensions tab in VSCode or by visiting the [Playwright extension page](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright).

View File

@ -8,7 +8,12 @@ export default defineConfig({
workers: process.env.CI ? 1 : undefined, workers: process.env.CI ? 1 : undefined,
snapshotPathTemplate: './tests/screenshots{/projectName}/{testFilePath}/{arg}{ext}', snapshotPathTemplate: './tests/screenshots{/projectName}/{testFilePath}/{arg}{ext}',
outputDir: './tests/test-results', outputDir: './tests/test-results',
reporter: [['html', { outputFolder: './tests/playwright-report' }]], reporter: [
[
process.env.CI ? 'blob' : 'html',
{ outputFolder: './tests/playwright-report' },
],
],
timeout: 720 * 1000, timeout: 720 * 1000,
use: { use: {
baseURL: 'http://localhost:3000', baseURL: 'http://localhost:3000',

View File

@ -1,8 +1,8 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils';
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
const mode = 'Basic Viewer'; const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode, 2000); await visitStudy(page, studyInstanceUID, mode, 2000);
}); });
@ -15,6 +15,7 @@ test.describe('3D four up Test', async () => {
.filter({ hasText: /^3D four up$/ }) .filter({ hasText: /^3D four up$/ })
.first() .first()
.click(); .click();
await reduce3DViewportSize(page);
await checkForScreenshot( await checkForScreenshot(
page, page,
page, page,

View File

@ -1,8 +1,8 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils';
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
const mode = 'Basic Viewer'; const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode, 2000); await visitStudy(page, studyInstanceUID, mode, 2000);
}); });
@ -15,6 +15,7 @@ test.describe('3D main Test', async () => {
.filter({ hasText: /^3D main$/ }) .filter({ hasText: /^3D main$/ })
.first() .first()
.click(); .click();
await reduce3DViewportSize(page);
await checkForScreenshot( await checkForScreenshot(
page, page,
page, page,

View File

@ -1,8 +1,8 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils';
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
const mode = 'Basic Viewer'; const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode, 2000); await visitStudy(page, studyInstanceUID, mode, 2000);
}); });
@ -15,6 +15,7 @@ test.describe('3D only Test', async () => {
.filter({ hasText: /^3D only$/ }) .filter({ hasText: /^3D only$/ })
.first() .first()
.click(); .click();
await reduce3DViewportSize(page);
await checkForScreenshot( await checkForScreenshot(
page, page,
page, page,

View File

@ -1,8 +1,8 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils';
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
const mode = 'Basic Viewer'; const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode, 2000); await visitStudy(page, studyInstanceUID, mode, 2000);
}); });
@ -16,6 +16,7 @@ test.describe('3D primary Test', async () => {
.first() .first()
.click(); .click();
await reduce3DViewportSize(page);
await checkForScreenshot( await checkForScreenshot(
page, page,
page, page,

View File

@ -2,7 +2,7 @@ import { test } from '@playwright/test';
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; import { visitStudy, checkForScreenshot, screenShotPaths } from './utils';
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
const mode = 'Basic Viewer'; const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode, 2000); await visitStudy(page, studyInstanceUID, mode, 2000);
}); });

View File

@ -2,7 +2,7 @@ import { test } from '@playwright/test';
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils/index'; import { visitStudy, checkForScreenshot, screenShotPaths } from './utils/index';
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
const mode = 'Basic Viewer'; const mode = 'Basic Viewer';
await visitStudy(page, studyInstanceUID, mode, 2000); await visitStudy(page, studyInstanceUID, mode, 2000);
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 KiB

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 KiB

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 KiB

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 660 KiB

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 KiB

After

Width:  |  Height:  |  Size: 340 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -2,5 +2,7 @@ import { visitStudy } from './visitStudy';
import { checkForScreenshot } from './checkForScreenshot'; import { checkForScreenshot } from './checkForScreenshot';
import { screenShotPaths } from './screenShotPaths'; import { screenShotPaths } from './screenShotPaths';
import { simulateClicksOnElement } from './simulateClicksOnElement'; import { simulateClicksOnElement } from './simulateClicksOnElement';
import { reduce3DViewportSize } from './reduce3DviewportSize';
export { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement };
export { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement, reduce3DViewportSize };

View File

@ -0,0 +1,9 @@
export const reduce3DViewportSize = async (page: any) => {
await page.evaluate(({ cornerstone }: AppTypes.Test) => {
const enabledElement = cornerstone.getEnabledElements().filter(element => element.viewport.type === 'volume3d')[0]
const { viewport } = enabledElement;
viewport.setZoom(0.5);
viewport.render()
}, await page.evaluateHandle('window'));
}

View File

@ -25,7 +25,7 @@
"platform/**/public/**/*", "platform/**/public/**/*",
"extensions/**/src/**/*", "extensions/**/src/**/*",
"modes/**/src/**/*", "modes/**/src/**/*",
"custom.d.ts" "tests/**/*",
], ],
"exclude": ["node_modules", "dist"] "exclude": ["node_modules", "dist"]
} }