Skip to content

Commit

Permalink
chore: enable build caching for playwright tests (#2338)
Browse files Browse the repository at this point in the history
Relates to #2321

- Move build step as precondition for all checks and tests in the
pipeline to create cache and avoid downstream build failures.
- Extracted shared playwright config into `@sit-onyx/shared` package as
`PLAYWRIGHT_BASE_CONFIG` to reduce code duplications.
- Pass playwright shard configuration from `playwright.config.ts` file
instead of using CLI arguments. See beneath for more details:

There was an issue where every shard executed a fresh build of all
packages.
The cause was the `--shard` cli argument that differs for every shard.
Because [turbo
considers](https://turbo.build/repo/docs/crafting-your-repository/caching#task-inputs)
pass-through arguments in their hashing, there was always a hash
mismatch.
Unfortunately, turbo doesn't support changing this behavior.

Luckily, playwright allows setting the sharding configuration via the
`playwright.config.ts` file, where we can use environment variables. And
because turbo can be configured to ignore specific environment
variables, we can use them instead of CLI arguments.
  • Loading branch information
JoCa96 authored Dec 16, 2024
1 parent 01b11ec commit 78ffb9b
Show file tree
Hide file tree
Showing 18 changed files with 135 additions and 144 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,22 @@ env:
TURBO_TOKEN: ${{ secrets.TURBO_REMOTE_CACHE__TURBO_TOKEN }}

jobs:
# We run the build first standalone to ensure everything is cached for all other jobs
build:
name: Build and Cache
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: ./.github/templates/node-setup

- name: 🛠️ Build packages
run: pnpm run build:all

check:
name: Check code quality
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -68,6 +81,7 @@ jobs:
path: apps/docs/src/.vitepress/dist

screenshots:
needs: build
name: Component tests
uses: ./.github/workflows/playwright.yml
secrets: inherit
6 changes: 5 additions & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ jobs:
run: pnpm exec playwright install-deps

- name: 🔎 Run Playwright tests
run: pnpm run test:components:all -- --shard=${{ matrix.shard }}/${{ strategy.job-total }} ${{ inputs.update-snapshots == true && '--update-snapshots' || '' }}
run: pnpm run test:playwright:all
env:
PW_UPDATE_SNAPSHOTS: "${{ inputs.update-snapshots }}"
PW_SHARD: "${{ matrix.shard }}"
PW_TOTAL_SHARDS: "${{ strategy.job-total }}"

# we only want to include actual changed screenshots in the artifact to prevent that old/unchanged screenshots
# override changed screenshots from other shards when creating the pull request
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"type-check": "vue-tsc --noEmit",
"preview": "vitepress preview src",
"storybook": "storybook dev -p 6006 --no-open",
"test:integration": "playwright install && playwright test"
"test:playwright": "playwright install && playwright test"
},
"devDependencies": {
"@playwright/test": "^1.49.1",
Expand Down
28 changes: 3 additions & 25 deletions apps/docs/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
import { defineConfig, devices } from "@playwright/test";
import { defineConfig } from "@playwright/test";
import { PLAYWRIGHT_BASE_CONFIG } from "@sit-onyx/shared/playwright.config.base";

// NOTE: You need to run "pnpm build" before running the tests

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
...PLAYWRIGHT_BASE_CONFIG,
testDir: "./tests",
testMatch: `**/*.ct.{ts,tsx}`,
snapshotDir: "./playwright/snapshots",
// custom snapshotPathTemplate to remove the testFileName folder that we don't want
snapshotPathTemplate: "{snapshotDir}/{testFileDir}/{arg}-{projectName}-{platform}{ext}",
// we don't want to update snapshots on the local machine of each developer.
// if you want to update snapshots for your branch, use the corresponding GitHub action:
// https://github.com/SchwarzIT/onyx/actions/workflows/playwright-screenshots.yml
ignoreSnapshots: !process.env.CI,
updateSnapshots: "none",
expect: { toHaveScreenshot: { maxDiffPixelRatio: 0.01 } },
fullyParallel: true,
forbidOnly: !!process.env.CI, // fail build on CI if we left test.only in the source code
retries: process.env.CI ? 1 : 0, // retry on CI only
/* In the CI pipeline it generates dot (for the stdout) and blob reports, locally only a html report is generated */
reporter: process.env.CI ? [["dot"], ["blob"]] : [["html", { open: "never" }]],
use: {
baseURL: "http://localhost:3200/",
trace: process.env.CI ? "retain-on-failure" : "off",
video: process.env.CI ? "retain-on-failure" : "off",
},
/* Configure projects for major browsers */
projects: [
{ name: "edge", use: { ...devices["Desktop Edge"], channel: "msedge" } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },
],
/* Run your local dev server before starting the tests */
webServer: {
command: "pnpm preview --port 3200 --mode test",
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/principles/contributing/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pnpm format:all # format all files
pnpm dev # run Storybook in dev mode when developing components
pnpm build # build all onyx components
pnpm test # run unit tests
pnpm test:components # run Playwright component tests
pnpm test:playwright # run Playwright component tests
```

```sh [apps/docs]
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/principles/contributing/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ For standalone tests or more complicated setups, [`toHaveScreenshot`](https://pl

### Development

In our monorepo component tests are run non-interactively using the `pnpm test:components` script.
In our monorepo component tests are run non-interactively using the `pnpm test:playwright` script.

To use Playwright interactively run `pnpm exec playwright test --ui` (add the `--headed` flag to open the see the- browsers) in the package directory.

Expand Down
2 changes: 1 addition & 1 deletion apps/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"build": "pnpm run '/type-check|build-only/'",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"test:integration": "playwright install && playwright test"
"test:playwright": "playwright install && playwright test"
},
"dependencies": {
"@sit-onyx/icons": "workspace:^",
Expand Down
18 changes: 3 additions & 15 deletions apps/playground/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@
import { defineConfig, devices } from "@playwright/test";
import { defineConfig } from "@playwright/test";
import { PLAYWRIGHT_BASE_CONFIG } from "@sit-onyx/shared/playwright.config.base";

// NOTE: You need to run "pnpm build" before running the tests

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
...PLAYWRIGHT_BASE_CONFIG,
testDir: "./tests",
fullyParallel: true,
forbidOnly: !!process.env.CI, // fail build on CI if we left test.only in the source code
retries: process.env.CI ? 1 : 0, // retry on CI only
/* In the CI pipeline it generates dot (for the stdout) and blob reports, locally only a html report is generated */
reporter: process.env.CI ? [["dot"], ["blob"]] : [["html", { open: "never" }]],
use: {
trace: process.env.CI ? "retain-on-failure" : "off",
video: process.env.CI ? "retain-on-failure" : "off",
},
/* Configure projects for major browsers */
projects: [
{ name: "edge", use: { ...devices["Desktop Edge"], channel: "msedge" } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },
],
/* Run your local dev server before starting the tests */
webServer: {
command: "pnpm preview --port 3200 --mode test",
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"author": "Schwarz IT KG",
"license": "Apache-2.0",
"scripts": {
"build:all": "turbo build build:storybook",
"test:all": "turbo test:coverage",
"test:components:all": "turbo test:components test:integration --concurrency 1",
"build:all": "turbo run build build:storybook",
"test:all": "turbo run test:coverage",
"test:playwright:all": "turbo run test:playwright --concurrency 1",
"format:all": "prettier --write .",
"format:check:all": "prettier --check .",
"lint:all": "eslint .",
Expand Down
2 changes: 1 addition & 1 deletion packages/chartjs-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"build": "vue-tsc --noEmit",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"test:components": "playwright install && playwright test"
"test:playwright": "playwright install && playwright test"
},
"peerDependencies": {
"chart.js": ">= 4.0.0",
Expand Down
24 changes: 2 additions & 22 deletions packages/chartjs-plugin/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,14 @@
import { defineConfig, devices } from "@playwright/experimental-ct-vue";
import vue from "@vitejs/plugin-vue";
import { PLAYWRIGHT_BASE_CONFIG } from "@sit-onyx/shared/playwright.config.base";

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
...PLAYWRIGHT_BASE_CONFIG,
testDir: "./src",
testMatch: `**/*.ct.tsx`,
snapshotDir: "./playwright/snapshots",
// custom snapshotPathTemplate to remove the testFileName folder that we don't want
snapshotPathTemplate: "{snapshotDir}/{testFileDir}/{arg}-{projectName}-{platform}{ext}",
// we don't want to update snapshots on the local machine of each developer.
// if you want to update snapshots for your branch, use the corresponding GitHub action:
// https://github.com/SchwarzIT/onyx/actions/workflows/playwright-screenshots.yml
ignoreSnapshots: !process.env.CI,
updateSnapshots: "none",
expect: { toHaveScreenshot: { maxDiffPixelRatio: 0.01 } },
fullyParallel: true,
forbidOnly: !!process.env.CI, // fail build on CI if we left test.only in the source code
retries: process.env.CI ? 2 : 0, // retry on CI only
/* In the CI pipeline it generates dot (for the stdout) and blob reports, locally only a html report is generated */
reporter: process.env.CI ? [["dot"], ["blob"]] : [["html", { open: "never" }]],
use: {
trace: process.env.CI ? "retain-on-failure" : "off",
video: process.env.CI ? "retain-on-failure" : "off",
ctPort: 3100,
ctViteConfig: {
plugins: [vue()],
},
},
/* Configure projects for major browsers */
projects: [
// one browser is sufficient for the screenshot tests
Expand Down
3 changes: 2 additions & 1 deletion packages/headless/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@
"scripts": {
"build": "vue-tsc --build --force",
"test": "vitest",
"test:components": "playwright install && playwright test"
"test:playwright": "playwright install && playwright test"
},
"peerDependencies": {
"typescript": ">= 5",
"vue": ">= 3.5.0"
},
"devDependencies": {
"@sit-onyx/shared": "workspace:^",
"@vue/compiler-dom": "catalog:",
"vue": "catalog:"
}
Expand Down
37 changes: 3 additions & 34 deletions packages/headless/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,11 @@
import { defineConfig, devices } from "@playwright/experimental-ct-vue";
import { defineConfig } from "@playwright/experimental-ct-vue";
import { PLAYWRIGHT_BASE_CONFIG } from "@sit-onyx/shared/playwright.config.base";

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
...PLAYWRIGHT_BASE_CONFIG,
testDir: "./",
testMatch: `**/*.ct.tsx`,
/* Maximum time one test can run for. */
timeout: 10 * 1000,
/* 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,
/* In the CI pipeline it generates dot (for the stdout) and blob reports, locally only a html report is generated */
reporter: process.env.CI ? [["dot"], ["blob"]] : [["html", { open: "never" }]],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",

/* Port to use for Playwright component endpoint. */
ctPort: 3100,
},

/* Configure projects for major browsers */
projects: [
{ name: "edge", use: { ...devices["Desktop Edge"], channel: "msedge" } },
{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},
{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},
],
});
84 changes: 84 additions & 0 deletions packages/shared/src/playwright.config.base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { devices, PlaywrightTestConfig } from "@playwright/experimental-ct-vue";
import vue, { Options } from "@vitejs/plugin-vue";

export const vuePluginOptions: Options = {
template: {
compilerOptions: {
// comments can cause issues for components where classes
// are not merged correctly, e.g. when using `<OnyxIcon class="custom-class" />`
comments: false,
},
},
};

/**
* Basic, shared playwright configuration
*
* See https://playwright.dev/docs/test-configuration
*/
export const PLAYWRIGHT_BASE_CONFIG = {
/**
* SCREENSHOTS
*
* See: https://playwright.dev/docs/screenshots
*/
snapshotDir: "./playwright/snapshots",
// custom snapshotPathTemplate to remove the testFileName folder that we don't want
snapshotPathTemplate: "{snapshotDir}/{testFileDir}/{arg}-{projectName}-{platform}{ext}",
// we don't want to update snapshots on the local machine of each developer.
// if you want to update snapshots for your branch, use the corresponding GitHub action:
// https://github.com/SchwarzIT/onyx/actions/workflows/playwright-screenshots.yml
ignoreSnapshots: !process.env.CI,
updateSnapshots: process.env.PW_UPDATE_SNAPSHOTS ? "all" : "none",

/**
* SHARDING
*
* See: https://playwright.dev/docs/test-sharding
*/
fullyParallel: true,
// when (in the pipeline) the sharding environment variables are set, sharding is enabled
shard:
process.env.CI && process.env.PW_SHARD && process.env.PW_TOTAL_SHARDS
? {
current: +process.env.PW_SHARD,
total: +process.env.PW_TOTAL_SHARDS,
}
: null,

/**
* FAILURE HANDLING
*
* See: https://playwright.dev/docs/test-retries
*/
timeout: 20 * 1000,
forbidOnly: !!process.env.CI, // fail build on CI if we left test.only in the source code
retries: process.env.CI ? 1 : 0, // retry on CI only

/**
* REPORTERS
*
* See: https://playwright.dev/docs/test-reporters
*/
/* In the CI pipeline it generates dot (for the stdout) and blob reports, locally only a html report is generated */
reporter: process.env.CI ? [["dot"], ["blob"]] : [["html", { open: "never" }]],
use: {
trace: process.env.CI ? "retain-on-failure" : "off",
video: process.env.CI ? "retain-on-failure" : "off",
ctPort: 3100,
ctViteConfig: {
plugins: [vue(vuePluginOptions)],
},
},

/**
* BROWSERS
*
* See: https://playwright.dev/docs/test-projects
*/
projects: [
{ name: "edge", use: { ...devices["Desktop Edge"], channel: "msedge" } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },
],
} as const satisfies PlaywrightTestConfig;
2 changes: 1 addition & 1 deletion packages/sit-onyx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"preview": "vite serve storybook-static",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"test:components": "playwright install && playwright test"
"test:playwright": "playwright install && playwright test"
},
"peerDependencies": {
"@sit-onyx/icons": "workspace:^",
Expand Down
Loading

0 comments on commit 78ffb9b

Please sign in to comment.