Skip to content

Commit

Permalink
test: storybook test-runner visual tests (#96)
Browse files Browse the repository at this point in the history
* test: add screenshot test runner

* test: fix jest typing

* ci: update docker compose npm scripts

* test: add Dockerfile for playwright testing image

* test: added storybook snapshots

* test: update snapshots

* ci: update github workflow

* ci: install docker-compose

* ci: run apt-get with sudo

* test: run storybook tests with ci flag

* ci: make /app dir writable in docker

* ci: change working dir

* ci: test as root on github

* ci: add maptiler key environment variable for tests

* ci: fix docker compose syntax

* ci: set maptiler key on storybook container

* ci: increase visual test poll interval

* docs: add npm keywords

* refactor: apply lint conditions

* test: increase test timeout to 60 s

* test: use run command for docker-compose tests

* test: increase story test timeout

* test: skip Hill Layer tests

* test: disable GpxSatteliteTerrain story visual tests

* test: disable visual tests for TripLayer

* test: disable some more visual tests

* test: delete stale visual test snapshots

* test: update snapshots

* test: disable more visual tests
  • Loading branch information
hkfb authored Nov 2, 2024
1 parent 1de37a8 commit 01357b9
Show file tree
Hide file tree
Showing 40 changed files with 417 additions and 886 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ README.md
dist
storybook-static
package-lock.json
__snapshots__
37 changes: 22 additions & 15 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,6 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Build Storybook
run: npm run build-storybook

- name: Install Playwright browsers
run: npx playwright install

- name: Run smoke tests
env:
PORT: 8080
HOST: 127.0.0.1
run: |
npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
"npx http-server storybook-static --port $PORT -a $HOST" \
"npx wait-on http://$HOST:$PORT/ && npm run test:storybook -- --ci --url http://$HOST:$PORT/"
- name: Build package
if: ${{ github.ref == 'refs/heads/main' }}
run: npm run build
Expand All @@ -49,3 +34,25 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release

test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v4

- name: Install docker compose
run: sudo apt-get -y install docker-compose

- name: Install dependencies
run: npm ci

- name: Storybook visual tests
env:
VITE_MAPTILER_API_KEY: ${{ secrets.MAPTILER_API_KEY }}
run: npm run docker:compose:test:github

13 changes: 13 additions & 0 deletions .storybook/test-runner-jest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { getJestConfig } = require("@storybook/test-runner");

// The default Jest configuration comes from @storybook/test-runner
const testRunnerConfig = getJestConfig();

/**
* @type {import('@jest/types').Config.InitialOptions}
*/
module.exports = {
...testRunnerConfig,
testTimeout: 120000,
maxWorkers: process.env.CI ? 4 : 8,
};
54 changes: 54 additions & 0 deletions .storybook/test-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { toMatchImageSnapshot } from "jest-image-snapshot";

import { getStoryContext, type TestRunnerConfig } from "@storybook/test-runner";

const customSnapshotsDir = `${process.cwd()}/__snapshots__`;

const screenshotTest = async (page, context) => {
let previousScreenshot: Buffer = Buffer.from("");

let stable = false;

const pollInterval = 20000;

while (!stable) {
const currentScreenshot = await page.screenshot();
if (currentScreenshot.equals(previousScreenshot)) {
stable = true;
} else {
previousScreenshot = currentScreenshot;
}

if (!stable) {
await page.waitForTimeout(pollInterval);
}
}

// @ts-expect-error TS2551
expect(previousScreenshot).toMatchImageSnapshot({
customSnapshotsDir,
customSnapshotIdentifier: context.id,
});
};

const config: TestRunnerConfig = {
setup() {
jest.retryTimes(3);

expect.extend({ toMatchImageSnapshot });
},

async postVisit(page, context) {
const storyContext = await getStoryContext(page, context);

if (storyContext.tags.includes("no-test")) {
return;
}

if (!storyContext.tags.includes("no-visual-test")) {
await screenshotTest(page, context);
}
},
};

export default config;
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Velo.gl

Map components and [Deck.gl](https://deck.gl/) layers for rendering GPX tracks.
Library for interactive 3D visualization of GPX activities.

![GpxLayer](https://github.com/hkfb/velo.gl/raw/main/sample/velo.gl.webp)

## Features
* Deck.gl layers
* [Deck.gl](https://deck.gl/) layers
* GPX Layer - renders the trace of a GPX file
* Trip GPX Layer - renders the position along a GPX trace at a given time
* Profile Layer - renders paths extruded vertically from sea level, from a set of 3D polylines
Expand Down Expand Up @@ -48,23 +48,27 @@ npm run storybook

### Using npm & docker:
```sh
npm ci
npm run docker:storybook
```

### Using npm & docker-compose:
```sh
npm ci
npm run docker:compose:storybook
```

## Testing

### Using npm with local storybook running:
### Run visual tests
```sh
npm run test:storybook
npm ci
npm run docker:compose:test
```

### Using npm & docker-compose:
### Update visual test snapshots
```sh
npm run docker:compose:test
npm ci
npm run docker:compose:test:update
```

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
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
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.
Binary file added __snapshots__/gpx-map--annotation-layer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __snapshots__/gpx-map--default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __snapshots__/gpx-map--el-teide.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __snapshots__/gpx-map--gpx-map-text.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
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __snapshots__/gpx-street-map--el-teide.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
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __snapshots__/hill-layer--hill-layer-camera.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __snapshots__/hill-layer--hill-layer-default.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
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.
Binary file added __snapshots__/layers-gpx-layer--gpx-wms.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
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
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions config/test-storybook/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM mcr.microsoft.com/playwright:v1.48.2-noble

RUN mkdir /app
WORKDIR /app

24 changes: 0 additions & 24 deletions docker-compose.test.yml

This file was deleted.

49 changes: 48 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,56 @@
version: "3"
services:
storybook:
image: velo.gl
image: velo.gl-storybook
build: .
environment:
- MAPTILER_API_KEY
volumes:
- ".:/app:rw"
ports:
- "6006:6006"
healthcheck:
test: curl --fail http://localhost:6006/
command: >
sh -c "npm run storybook -- --no-open"
test-storybook:
image: velo.gl-test-storybook
build: ./config/test-storybook
volumes:
- ".:/app:ro"
- "./__snapshots__:/app/__snapshots__:rw"
working_dir: /app
user: ubuntu
depends_on:
storybook:
condition: service_healthy
command: >
sh -c "npm run test:storybook -- --ci --url http://storybook:6006/"
test-storybook-update:
image: velo.gl-test-storybook
build: ./config/test-storybook
volumes:
- ".:/app:ro"
- "./__snapshots__:/app/__snapshots__:rw"
working_dir: /app
user: ubuntu
depends_on:
storybook:
condition: service_healthy
command: >
sh -c "npm run test:storybook -- --updateSnapshot --url http://storybook:6006/"
test-storybook-github:
image: velo.gl-test-storybook
build: ./config/test-storybook
volumes:
- ".:/app:rw"
working_dir: /app
user: root
depends_on:
storybook:
condition: service_healthy
command: >
sh -c "npm run test:storybook -- --ci --url http://storybook:6006/"
Loading

0 comments on commit 01357b9

Please sign in to comment.