Skip to content

Latest commit

 

History

History
148 lines (97 loc) · 7.6 KB

File metadata and controls

148 lines (97 loc) · 7.6 KB

HRM Testing Guide

This guide provides a comprehensive overview of the testing commands, structure, and best practices for the HRM application.

Primary Test Commands

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.

All Test Commands

Visual & E2E Testing

  • 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.

Unit Testing

  • pnpm run test:unit: Runs all Jest unit tests.
  • pnpm run test:unit:coverage: Runs unit tests and generates a code coverage report.

Server & Process Management

  • 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.

Code Quality

  • 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.

Test Structure

The project uses a combination of Jest for unit tests and Playwright for end-to-end (E2E) and visual regression testing.

Unit Tests (tests/unit)

  • Purpose: To test individual functions, components, and services in isolation.
  • Framework: Jest with @testing-library/react.
  • Location: tests/unit/
  • Configuration: jest.config.cjs

E2E and Visual Tests (tests/playwright)

  • 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 *-snapshots directory alongside the test file.

Visual Regression Testing (VRT) Workflow

Visual Regression Testing is a critical part of our quality assurance process. It helps us prevent unintended UI changes from reaching production.

Running VRT

To run the visual regression tests, use the following command:

pnpm run test:visual

This 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.

Updating Snapshots

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:update

This will generate new snapshots. Be sure to review the changes in the generated diffs to ensure they are intended.

data-testid Usage Guidelines

To ensure that our tests are resilient to code refactoring and style changes, we use data-testid attributes to target elements in our tests.

Best Practices

  • Use data-testid for 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-testid attributes. For example, [component-name]-[element-name].
  • Avoid using data-testid for everything: If an element can be uniquely identified by its text content, role, or other accessible attributes, use those instead.

CI/CD Integration

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.


Advanced Test Synchronization

The __TEST_WEBSOCKET_READY__ Flag

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 true inside the onopen event handler of the WebSocket connection in context/WebSocketContext.tsx.
    • It is set to false in the onclose handler.
  • Usage in Tests:
    • In Playwright tests, particularly in visual-regression.spec.ts, we use page.waitForFunction() to pause the test's execution until this flag becomes true.
    • Example: await dashboardPage.waitForFunction(() => window.__TEST_WEBSOCKET_READY__ === true)
  • 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.

Future Improvements & Test Consolidation Plan

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.

1. Consolidate Core Tests

  • Goal: Reduce the number of redundant tests and screenshots.
  • Action: Create a single core-functionality.spec.ts that 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.

2. Stabilize Unstable Tests

  • 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.

3. Optimize Test Performance

  • Goal: Reduce the overall test execution time.
  • Action: Enable parallel test execution in playwright.config.ts and reduce the number of screenshots to only the most essential views.
  • Benefit: Faster feedback loops for developers and in the CI/CD pipeline.