Skip to content

Commit 0e54caa

Browse files
authored
Merge pull request #187 from Dataport/feature/e2e-tests-poc
Feature/e2e tests poc
2 parents 1c6f767 + 87e6b22 commit 0e54caa

17 files changed

Lines changed: 340 additions & 4 deletions

.github/workflows/run-tests.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ jobs:
2525
- run: |
2626
npm ci
2727
npm run test
28+
teste2e:
29+
timeout-minutes: 60
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
- uses: actions/setup-node@v4
34+
with:
35+
node-version: 20.16.0
36+
- name: Install dependencies
37+
run: npm ci
38+
- name: Build snowbox (started by playwright by itself)
39+
run: npm run snowbox:build
40+
- name: Install Playwright Browsers
41+
run: npx playwright install --with-deps
42+
- name: Run Playwright tests
43+
run: npm run test:e2e
44+
- uses: actions/upload-artifact@v4
45+
if: ${{ !cancelled() }}
46+
with:
47+
name: playwright-report
48+
path: playwright-report/
49+
retention-days: 30
2850
type-check:
2951
runs-on: ubuntu-latest
3052
steps:

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ logs
1414
/.idea/
1515
/.nx/
1616
**/.parcel-cache
17+
/test-results/
18+
/playwright-report/
19+
/blob-report/
20+
/playwright/.cache/

e2e/draw.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { test, expect } from '@playwright/test'
2+
import { openSnowbox } from './utils/openSnowbox'
3+
4+
const drawTargetId = '#vuex-target-draw-result'
5+
6+
test('clicks to the map produce a fetchable pin coordinate', async ({
7+
page,
8+
}) => {
9+
await openSnowbox(page)
10+
11+
const canvas = await page.locator('canvas')
12+
const boundingBox = await canvas.boundingBox()
13+
if (boundingBox === null) throw new Error('Canvas not found.')
14+
const { width, height } = boundingBox
15+
let { x, y } = boundingBox
16+
17+
x += width / 2
18+
y += height / 2
19+
20+
await page.getByLabel('Draw tools').click()
21+
await page.getByText('Draw and write').click()
22+
await page.getByText('Polygon').click()
23+
24+
const moves: [number, number, string][] = [
25+
[0, 0, 'click'],
26+
[40, -40, 'click'],
27+
[40, 40, 'click'],
28+
[-80, 80, 'click'],
29+
[-80, -80, 'click'],
30+
[40, -40, 'dblclick'],
31+
]
32+
33+
for (const [xMove, yMove, method] of moves) {
34+
await page.mouse[method]((x += xMove), (y += yMove))
35+
}
36+
37+
const drawing = JSON.parse(await page.locator(drawTargetId).innerText())
38+
39+
expect(drawing.type).toBe('FeatureCollection')
40+
expect(drawing.features.length).toBe(1)
41+
expect(drawing.features[0].geometry.coordinates[0].length).toBe(7)
42+
})

e2e/pins.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { test, expect } from '@playwright/test'
2+
import { openSnowbox } from './utils/openSnowbox'
3+
4+
const pinsTargetId = '#vuex-target-pin-coordinate'
5+
6+
test('clicks to the map produce a fetchable pin coordinate', async ({
7+
page,
8+
}) => {
9+
await openSnowbox(page)
10+
11+
const coordinateTarget = page.locator(pinsTargetId)
12+
13+
await expect(coordinateTarget).toBeEmpty()
14+
await page.locator('canvas').click()
15+
await expect(coordinateTarget).toHaveText(/\d+(\.\d+)?,\d+(\.\d+)?/)
16+
})

e2e/toast.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { test, expect } from '@playwright/test'
2+
import { openSnowbox } from './utils/openSnowbox'
3+
import { dispatch } from './utils/vuex'
4+
5+
const locatable = '私が来た'
6+
7+
test('programmatically dispatched toasts are visible in the UI', async ({
8+
page,
9+
}) => {
10+
await openSnowbox(page)
11+
12+
await dispatch(page, 'plugin/toast/addToast', {
13+
type: 'info',
14+
text: locatable,
15+
})
16+
17+
await expect(page.getByText(locatable)).toBeVisible()
18+
})

e2e/utils/clickTimes.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Page } from '@playwright/test'
2+
3+
export const clickTimes = async ({
4+
page,
5+
value,
6+
times,
7+
method = 'getByLabel',
8+
}: {
9+
page: Page
10+
value: string
11+
times: number
12+
method?: string
13+
}) => {
14+
for (let i = 0; i < times; i++) {
15+
await page[method](value).click()
16+
}
17+
}

e2e/utils/openSnowbox.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Page } from '@playwright/test'
2+
3+
export const openSnowbox = async (page: Page) => {
4+
// @ts-expect-error | it's manually added in snowbox client
5+
const watchReadiness = page.waitForFunction(() => Boolean(window.mapInstance))
6+
await page.goto('./dist/index.html')
7+
await watchReadiness
8+
}

e2e/utils/vuex.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Page } from '@playwright/test'
2+
3+
const execute = async (
4+
page: Page,
5+
command: string,
6+
path: string,
7+
payload: unknown,
8+
params?: object
9+
) => {
10+
const evaluatable = `window.mapInstance.$store.${command}('${path}'${
11+
typeof payload !== 'undefined'
12+
? `, ${JSON.stringify(payload)}`
13+
: typeof params !== 'undefined'
14+
? JSON.stringify(null)
15+
: ''
16+
}${typeof params !== 'undefined' ? `, ${JSON.stringify(params)}` : ''})`
17+
console.error(evaluatable)
18+
await page.evaluate(evaluatable)
19+
}
20+
21+
export const dispatch = async (
22+
page: Page,
23+
path: string,
24+
payload: unknown,
25+
params?: object
26+
) => await execute(page, 'dispatch', path, payload, params)
27+
28+
export const commit = async (
29+
page: Page,
30+
path: string,
31+
payload: unknown,
32+
params?: object
33+
) => await execute(page, 'commit', path, payload, params)

e2e/zoom.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { test, expect } from '@playwright/test'
2+
import { openSnowbox } from './utils/openSnowbox'
3+
import { clickTimes } from './utils/clickTimes'
4+
5+
const zoomTargetId = '#vuex-target-zoom'
6+
7+
test('zoom in button zooms in until max zoom', async ({ page }) => {
8+
const zoomInLabel = 'Zoom in'
9+
await openSnowbox(page)
10+
11+
const zoomTarget = page.locator(zoomTargetId)
12+
await expect(zoomTarget).toHaveText('2')
13+
await clickTimes({ page, value: zoomInLabel, times: 7 })
14+
await expect(zoomTarget).toHaveText('9')
15+
await expect(page.getByLabel(zoomInLabel)).toBeDisabled()
16+
})
17+
18+
test('zoom out button zooms out until min zoom', async ({ page }) => {
19+
const zoomOutLabel = 'Zoom out'
20+
await openSnowbox(page)
21+
22+
const zoomTarget = page.locator(zoomTargetId)
23+
await expect(zoomTarget).toHaveText('2')
24+
await clickTimes({ page, value: zoomOutLabel, times: 2 })
25+
await expect(zoomTarget).toHaveText('0')
26+
await expect(page.getByLabel(zoomOutLabel)).toBeDisabled()
27+
})

jest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const config: Config.InitialOptions = {
55
'**/*.{js,ts,vue}',
66
'!**/(node_modules|build|dist|dist-test|.cache|coverage|docs|tests_output)/**',
77
],
8-
modulePathIgnorePatterns: ['<rootDir>/mpapi/'],
8+
modulePathIgnorePatterns: ['<rootDir>/mpapi/', '<rootDir>/e2e/'],
99
moduleFileExtensions: ['js', 'ts', 'json', 'vue'],
1010
moduleNameMapper: {
1111
'vuetify/lib': '<rootDir>/node_modules/vuetify/es5',

0 commit comments

Comments
 (0)