Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,9 @@ licences.temp
Thumbs.db

# Cypress
packages/*/cypress/screenshots/
packages/*/cypress/screenshots/

# Playwright
packages/dev/playwright/**/*.png
packages/dev/test-results/*
packages/dev/playwright-report/*
27 changes: 14 additions & 13 deletions packages/dev/licences.txt
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
name license period license type installed version author
---- -------------- ------------ ----------------- ------
fuse.js perpetual Apache-2.0 6.6.2 Kiro Risk kirollos@gmail.com http://kiro.me
react perpetual MIT 19.0.0 n/a
react-dom perpetual MIT 19.0.0 n/a
react-router-dom perpetual MIT 6.28.2 Remix Software <hello@remix.run>
react perpetual MIT 19.2.0 n/a
react-dom perpetual MIT 19.2.0 n/a
react-router-dom perpetual MIT 6.30.1 Remix Software <hello@remix.run>
seedrandom perpetual MIT 3.0.5 David Bau
serve perpetual MIT 14.2.4 n/a
@percy/cli perpetual MIT 1.30.6 n/a
@percy/cypress perpetual MIT 3.1.3 Perceptual Inc.
@pmmmwh/react-refresh-webpack-plugin perpetual MIT 0.5.15 Michael Mok
@types/react perpetual MIT 19.0.7 n/a
@types/react-dom perpetual MIT 19.0.3 n/a
serve perpetual MIT 14.2.5 n/a
@percy/cli perpetual MIT 1.31.4 n/a
@percy/cypress perpetual MIT 3.1.6 Perceptual Inc.
@playwright/test perpetual Apache-2.0 1.56.1 Microsoft Corporation
@pmmmwh/react-refresh-webpack-plugin perpetual MIT 0.5.17 Michael Mok
@types/react perpetual MIT 19.2.2 n/a
@types/react-dom perpetual MIT 19.2.2 n/a
@types/react-router perpetual MIT 5.1.20 n/a
@types/webpack-env perpetual MIT 1.18.5 n/a
@types/webpack-env perpetual MIT 1.18.8 n/a
cypress perpetual MIT 13.17.0 n/a
html-webpack-plugin perpetual MIT 5.6.3 Jan Nicklas <j.nicklas@me.com> (https://github.com/jantimon)
html-webpack-plugin perpetual MIT 5.6.4 Jan Nicklas <j.nicklas@me.com> (https://github.com/jantimon)
react-refresh perpetual MIT 0.14.2 n/a
react-refresh-typescript perpetual MIT 2.0.9 n/a
ts-loader perpetual MIT 9.5.2 John Reilly <johnny_reilly@hotmail.com> (https://johnnyreilly.com)
ts-loader perpetual MIT 9.5.4 John Reilly <johnny_reilly@hotmail.com> (https://johnnyreilly.com)
typescript perpetual Apache-2.0 4.9.5 Microsoft Corp.
typescript-plugin-css-modules perpetual MIT 4.2.3 Brody McKee <mrmckeb@hotmail.com>
webpack perpetual MIT 5.97.1 Tobias Koppers @sokra
webpack perpetual MIT 5.102.1 Tobias Koppers @sokra
webpack-cli perpetual MIT 5.1.4 n/a
webpack-dev-server perpetual MIT 4.15.2 Tobias Koppers @sokra
1,600 changes: 973 additions & 627 deletions packages/dev/package-lock.json

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion packages/dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@
"dev": "webpack-dev-server --host 0.0.0.0",
"serve": "serve dist -s -p 9501",
"check": "tsc --noEmit",
"test": "npx percy exec -- cypress run"
"test": "npx percy exec -- cypress run",
"test:playwright": "playwright test",
"test:playwright:percy": "npx percy exec -- playwright test",
"test:playwright:ui": "playwright test --ui",
"test:playwright:report": "playwright show-report"
},
"devDependencies": {
"@percy/cli": "^1.29.1",
"@percy/cypress": "^3.1.3-beta.0",
"@percy/playwright": "^1.0.6",
"@playwright/test": "^1.48.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@types/react": "^19",
"@types/react-dom": "^19",
Expand Down
84 changes: 84 additions & 0 deletions packages/dev/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { defineConfig, devices } from '@playwright/test'

/**
* @see https://playwright.dev/docs/test-configuration
*/
export default defineConfig({
testDir: './playwright/tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [
['html'],
],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://localhost:9501',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',

/* Take screenshot on failure */
screenshot: 'only-on-failure',

/* Record video on failure */
video: 'retain-on-failure',

/* Timeout for each action */
actionTimeout: 15000,

/* Timeout for navigation actions */
navigationTimeout: 30000,
},

/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
/* Visual tests with specific viewport */
{
name: 'visual-tests',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1800, height: 1200 },
},
testMatch: /.*tooltip\.spec\.ts/,
/* Expect options for visual testing */
expect: {
/* Screenshot comparison options */
toHaveScreenshot: {
threshold: 0.2,
animations: 'disabled',
caret: 'hide',
},
},
},
],

/* Run your local dev server before starting the tests */
webServer: {
command: 'npm run serve',
url: 'http://localhost:9501',
reuseExistingServer: !process.env.CI,
timeout: 120000,
},
})
34 changes: 34 additions & 0 deletions packages/dev/playwright/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Playwright Testing Setup

This directory contains Playwright end-to-end tests for the Unovis visualization library.

## Structure

- `tests/` - Contains test files
- `utils/` - Helper utilities for tests

## Running Tests

### Prerequisites

Make sure your development server is running:

```bash
npm run serve
```

### Test Commands

```bash
# Run all tests headlessly
npm run test:playwright

# Run tests with UI mode (interactive)
npm run test:playwright:ui

# Run specific test
npx playwright test unovis.spec.ts

# Run tests in specific browser
npx playwright test --project=chromium
```
103 changes: 103 additions & 0 deletions packages/dev/playwright/page-objects/tooltip-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Page, Locator } from '@playwright/test'

export class TooltipPage {
readonly page: Page
readonly scatterPoints: Locator
readonly tooltipContainer: Locator

// Scatter plot selectors
readonly scatterPointCategory0: Locator
readonly scatterPointCategory1: Locator
readonly scatterPointCategory2: Locator
readonly scatterPointCategory3: Locator
readonly scatterTooltip: Locator

constructor (page: Page) {
this.page = page
this.scatterPoints = page.locator('[visScatterPointE2eTestId]')
this.tooltipContainer = page.locator('[visTooltipE2eTestId]')

// Specific category selectors
this.scatterPointCategory0 = page.locator('[visScatterPointE2eTestId="scatter-point-category-0"]')
this.scatterPointCategory1 = page.locator('[visScatterPointE2eTestId="scatter-point-category-1"]')
this.scatterPointCategory2 = page.locator('[visScatterPointE2eTestId="scatter-point-category-2"]')
this.scatterPointCategory3 = page.locator('[visScatterPointE2eTestId="scatter-point-category-3"]')
this.scatterTooltip = page.locator('[visTooltipE2eTestId="scatter-tooltip"]')
}

async navigateToTooltipExample (): Promise<void> {
await this.page.goto('/examples/Tooltip/Tooltip:%20Empty%20Content')
await this.page.waitForTimeout(300)
}

async waitForScatterPointsToLoad (): Promise<void> {
await this.scatterPoints.first().waitFor({ state: 'visible' })
}
}

export class GraphTooltipPage {
readonly page: Page
readonly graphNodes: Locator
readonly graphTooltip: Locator

// Specific node selectors
readonly nodeString: Locator
readonly nodeHex: Locator
readonly nodeShortHex: Locator
readonly nodeRGB: Locator
readonly nodeNone: Locator

constructor (page: Page) {
this.page = page
this.graphNodes = page.locator('[visGraphNodeE2eTestId]')
this.graphTooltip = page.locator('[visGraphNodeTooltipE2eTestId="graph-node-tooltip"]')

// Specific node selectors
this.nodeString = page.locator('[visGraphNodeE2eTestId="node-String"]')
this.nodeHex = page.locator('[visGraphNodeE2eTestId="node-Hex"]')
this.nodeShortHex = page.locator('[visGraphNodeE2eTestId="node-Short hex"]')
this.nodeRGB = page.locator('[visGraphNodeE2eTestId="node-RGB"]')
this.nodeNone = page.locator('[visGraphNodeE2eTestId="node-None"]')
}

async navigateToGraphExample (): Promise<void> {
await this.page.goto('/examples/Graph/Graph:%20Custom%20Node%20Fills%20with%20Tooltip')
await this.page.waitForTimeout(300)
}
}

export class LeafletTooltipPage {
readonly page: Page
readonly leafletPoints: Locator
readonly leafletTooltip: Locator

// Specific point selectors
readonly pointAP0: Locator
readonly pointAP2: Locator
readonly pointAP3: Locator
readonly pointAP4: Locator

constructor (page: Page) {
this.page = page
this.leafletPoints = page.locator('[visLeafletPointE2eTestId]')
this.leafletTooltip = page.locator('[visLeafletMapTooltipE2eTestId="leaflet-map-tooltip"]')

// Specific point selectors
this.pointAP0 = page.locator('[visLeafletPointE2eTestId="leaflet-point-ap-0"]')
this.pointAP2 = page.locator('[visLeafletPointE2eTestId="leaflet-point-ap-2"]')
this.pointAP3 = page.locator('[visLeafletPointE2eTestId="leaflet-point-ap-3"]')
this.pointAP4 = page.locator('[visLeafletPointE2eTestId="leaflet-point-ap-4"]')
}

async navigateToLeafletExample (): Promise<void> {
await this.page.goto('/examples/Leaflet/Color%20Map')
}

async setupMapInterceptions (): Promise<void> {
await this.page.route('https://demotiles.maplibre.org/tiles/tiles.json', route => route.continue())
await this.page.route(/^https:\/\/demotiles\.maplibre\.org\/tiles\/(\d+)\/(\d+)\/(\d+)\.pbf/, route => route.continue())

// Wait for map tiles to load
await this.page.waitForTimeout(1000)
}
}
Loading
Loading