diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 261a7235af2..f457629d219 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,6 +48,12 @@ To clone and build iTwinUI, you'll need [Git](https://git-scm.com), [Node 18+](h _Before running this command, make sure Docker is running. See [Visual testing](#visual-testing-css) (CSS and React) sections below for more details._ +### To run all tests for a specific component + +`pnpm test [component-name]` e.g. `pnpm test Alert` + +_Please note this command is case sensitive. e.g. `Alert`, not `alert`._ + ### To lint and fix autofixable errors `pnpm lint` @@ -324,8 +330,8 @@ We reuse our stories for visual tests by taking screenshots of the story iframes #### Running visual tests 1. Make sure you have [Docker](https://www.docker.com/get-started) installed and running. -2. From the monorepo root, run `pnpm run test --filter=react-workshop`. This will build react-workshop and run all cypress tests in docker. - - If you only need to run tests for a specific component, you can do so by passing the `--spec` argument to cypress. e.g. for testing `Alert`, you can run `pnpm --filter=react-workshop run test --spec="**/Alert.*"`. But don't forget to build react-workshop first (pnpm run build --filter=react-workshop). +2. From the monorepo root, run `pnpm run test --filter=react-workshop` or `pnpm test:react`. This will build react-workshop and run all cypress tests in docker. + - If you only need to run tests for a specific component, you can do so by passing the `--spec` argument to cypress. e.g. for testing `Alert`, you can run `pnpm test:react --spec="**/Alert.*"`. 3. Once the tests finish running, you can approve any failing test images using `pnpm approve:react`. #### Writing visual tests @@ -368,7 +374,7 @@ We use an automated script to evaluate each component example for accessibility In the terminal: -- Run the command `pnpm run test --filter=a11y` to run automated accessibility tests for all examples. +- Run `pnpm run test --filter=a11y` or `pnpm test:a11y` to run automated accessibility tests for all examples. In the Cypress GUI: @@ -388,7 +394,7 @@ For more information on the Axe rule IDs and their meanings, visit [Deque Univer The `testing/e2e` workspace facilitates testing of complex scenarios in a real browser. This is achieved by running [Playwright](https://playwright.dev/) tests against a [Remix](https://remix.run/) app. -- **To run tests**, use this command: `pnpm run test --filter=e2e`. +- **To run tests**, use `pnpm run test --filter=e2e` or `pnpm test:e2e`. - **To write tests**, add a new [Remix route](https://remix.run/docs/en/main/discussion/routes#conventional-route-folders) and a `.spec.ts` next to it. For more details on how to write a test, see [Playwright docs](https://playwright.dev/docs/writing-tests). diff --git a/package.json b/package.json index 82a4dcb07a6..1056bfa842a 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,12 @@ "scripts": { "build": "turbo run build", "dev": "turbo run dev --concurrency=15", - "test": "turbo run test", + "test": "node scripts/runTests.mjs", + "test:css": "pnpm run build --filter=css-workshop && pnpm --filter=css-workshop run test", + "test:react": "pnpm run build --filter=react-workshop && pnpm --filter=react-workshop run test", + "test:a11y": "pnpm run build --filter=a11y && pnpm --filter=/a11y run test", + "test:e2e": "pnpm run build --filter=e2e && pnpm --filter=e2e run test", + "test:unit": "pnpm --filter=@itwin/itwinui-react run test:unit", "lint": "turbo run lint", "format": "turbo run format", "prepare": "husky install && playwright install", diff --git a/scripts/runTests.mjs b/scripts/runTests.mjs new file mode 100644 index 00000000000..9255bd7d752 --- /dev/null +++ b/scripts/runTests.mjs @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Bentley Systems, Incorporated. All rights reserved. + * See LICENSE.md in the project root for license terms and full copyright notice. + *--------------------------------------------------------------------------------------------*/ +import { spawn } from 'node:child_process'; + +try { + const argument = process.argv[2]; + + if (argument?.includes('filter')) { + spawn(`turbo run test ${argument}`, { + stdio: 'inherit', + shell: true, + }); + } else if (argument) { + spawn( + `conc -g -n "CSS-workshop,Unit,A11y,React-workshop,e2e" -c "#8BCC2F,#D8598C,#539AD0,#D1B52A,white" "pnpm test:css --filter=${argument.toLowerCase()}" "pnpm test:unit ${argument}" "pnpm test:a11y --env componentName=${argument}" "pnpm test:react --spec="**/${argument}.*"" "pnpm run test:e2e -- ${argument}"`, + { + stdio: 'inherit', + shell: true, + }, + ); + } else { + spawn(`turbo run test`, { + stdio: 'inherit', + shell: true, + }); + } +} catch (error) { + console.log(error); +} diff --git a/testing/a11y/src/Component.cy.tsx b/testing/a11y/src/Component.cy.tsx index e219c326e9b..5ded5de2026 100644 --- a/testing/a11y/src/Component.cy.tsx +++ b/testing/a11y/src/Component.cy.tsx @@ -24,7 +24,13 @@ const axeConfigPerExample = (example) => { }; describe('Should have no WCAG violations', () => { - Object.entries(allExamples).forEach(([name, Component]) => { + const componentName = Cypress.env('componentName'); + + const examplesToTest = Object.entries(allExamples).filter( + ([name]) => componentName === undefined || name.includes(componentName), + ); + + examplesToTest.forEach(([name, Component]) => { it(name, () => { cy.mount( diff --git a/testing/e2e/package.json b/testing/e2e/package.json index 4b15fbde6a5..71d141c7414 100644 --- a/testing/e2e/package.json +++ b/testing/e2e/package.json @@ -9,7 +9,7 @@ "dev": "remix vite:dev", "start": "remix-serve ./build/server/index.js", "typecheck": "tsc", - "test": "playwright test" + "test": "playwright test --pass-with-no-tests" }, "dependencies": { "@itwin/itwinui-react": "*", diff --git a/testing/e2e/playwright.config.ts b/testing/e2e/playwright.config.ts index 0d7f70d5794..659587d7920 100644 --- a/testing/e2e/playwright.config.ts +++ b/testing/e2e/playwright.config.ts @@ -5,7 +5,7 @@ import { defineConfig, devices } from '@playwright/test'; */ export default defineConfig({ testMatch: 'app/**/*spec.ts', // Look for test files anywhere in the app - + fullyParallel: true, // Run tests in files in parallel forbidOnly: !!process.env.CI, // Fail CI if you accidentally left test.only retries: process.env.CI ? 2 : 0, // Retry on CI only