This guide provides a comprehensive overview of the testing commands, structure, and best practices for the HRM application.
These are the most frequently used commands for testing and code quality checks.
| Command | Description |
|---|---|
pnpm run test:visual |
Runs the core visual regression test suite in a headless browser. Use this before committing any UI changes. |
pnpm run test:visual:update |
Updates the visual snapshots after intentional UI changes have been made. |
pnpm run test:unit |
Executes the Jest unit test suite for testing individual components and business logic. |
pnpm run lint |
Runs ESLint to check for code quality and style issues. |
pnpm run format |
Formats the entire codebase using Prettier to ensure consistent styling. |
pnpm run test:visual: Runs the main visual regression test suite.pnpm run test:visual:headed: Runs the visual tests with a visible browser for debugging.pnpm run test:visual:update: Updates the visual test snapshots.pnpm run test:comprehensive: Runs a longer, more detailed E2E test suite covering full user journeys.pnpm run test:visual:report: Opens a detailed web report of the last Playwright test run.
pnpm run test:unit: Runs all Jest unit tests.pnpm run test:unit:coverage: Runs unit tests and generates a code coverage report.
pnpm run test:clean: Shuts down any running server instances, starts a fresh server, and runs the visual tests.pnpm run kill-all: A utility script to find and kill all running Node.js processes related to the application, useful for clearing a stuck server.pnpm run pm2:logs: Displays the logs from the PM2 process manager when the application is running in production mode.
pnpm run lint: Lints the codebase.pnpm run lint:fix: Automatically fixes fixable linting errors.pnpm run format: Formats all code with Prettier.pnpm run format:check: Checks for formatting issues without modifying files.
The project uses a combination of Jest for unit tests and Playwright for end-to-end (E2E) and visual regression testing.
- Purpose: To test individual functions, components, and services in isolation.
- Framework: Jest with
@testing-library/react. - Location:
tests/unit/ - Configuration:
jest.config.cjs
- Purpose: To verify complete user workflows and ensure the UI remains consistent.
- Framework: Playwright.
- Location:
tests/playwright/ - Key Files:
visual-regression.spec.ts: The primary suite for screenshot-based testing of core UI components.comprehensive-assessment.spec.ts: Tests longer, more complex user journeys.mobile-assessment.spec.ts: Contains tests specifically for mobile viewports.
- Snapshots: Visual snapshots are stored in a
*-snapshotsdirectory alongside the test file.
Visual Regression Testing is a critical part of our quality assurance process. It helps us prevent unintended UI changes from reaching production.
To run the visual regression tests, use the following command:
pnpm run test:visualThis command will run Playwright in headless mode and compare the latest screenshots with the snapshots stored in the repository. If there are any visual differences, the tests will fail.
If you've made intentional changes to the UI, you'll need to update the snapshots. To do this, run the following command:
pnpm run test:visual:updateThis will generate new snapshots. Be sure to review the changes in the generated diffs to ensure they are intended.
To ensure that our tests are resilient to code refactoring and style changes, we use data-testid attributes to target elements in our tests.
- Use
data-testidfor elements that are not uniquely identifiable by other means: For example, buttons, icons, and other interactive elements. - Be specific and consistent with naming: Use a consistent naming convention for
data-testidattributes. For example,[component-name]-[element-name]. - Avoid using
data-testidfor everything: If an element can be uniquely identified by its text content, role, or other accessible attributes, use those instead.
In our GitHub Actions workflows, we use pnpm install --frozen-lockfile to ensure that the exact versions of dependencies specified in pnpm-lock.yaml are installed. This guarantees a consistent and reproducible build environment for all test runs.
To prevent flaky tests, especially in a real-time application like this, our Playwright test suite needs to reliably wait for the WebSocket connection to be established before proceeding with assertions or screenshots.
- Purpose: The
window.__TEST_WEBSOCKET_READY__flag is a global browser variable used exclusively for this synchronization. - Implementation:
- The flag is set to
trueinside theonopenevent handler of the WebSocket connection incontext/WebSocketContext.tsx. - It is set to
falsein theonclosehandler.
- The flag is set to
- Usage in Tests:
- In Playwright tests, particularly in
visual-regression.spec.ts, we usepage.waitForFunction()to pause the test's execution until this flag becomestrue. - Example:
await dashboardPage.waitForFunction(() => window.__TEST_WEBSOCKET_READY__ === true)
- In Playwright tests, particularly in
- Benefit: This mechanism provides a deterministic way to ensure that the application's client-side state has been hydrated with data from the server before any visual validation occurs, significantly improving the stability of the test suite.
The current test suite has some redundancy and opportunities for optimization. The following plan is in place to improve the test suite's efficiency and maintainability.
- Goal: Reduce the number of redundant tests and screenshots.
- Action: Create a single
core-functionality.spec.tsthat covers the most critical UI components and workflows, reducing the total number of tests from ~29 to ~12. - Benefit: Faster execution time, lower maintenance overhead, and clearer test focus.
- Goal: Eliminate flaky tests caused by timing issues.
- Action: Replace fixed delays (
waitForTimeout) with more resilient waiting strategies, such as waiting for specific network responses, DOM elements to be visible, or WebSocket connection statuses. - Benefit: More reliable test runs and fewer false positives.
- Goal: Reduce the overall test execution time.
- Action: Enable parallel test execution in
playwright.config.tsand reduce the number of screenshots to only the most essential views. - Benefit: Faster feedback loops for developers and in the CI/CD pipeline.