Code Health & Janitor
Relevant source files
The following files were used as context for generating this wiki page:
The Code Health and Janitor system provides static analysis, architecture enforcement, and code quality automation for the n8n project, specifically focusing on the Playwright E2E test suite and monorepo standards. Its primary purpose is to catch architectural drift, dead code, and selector duplication before they scale into unmanageable maintenance burdens. Sources: packages/testing/janitor/README.md:1-12, packages/testing/code-health/package.json:5-10
Within the development workflow, the Janitor acts as a guardrail, enforcing a layered architecture and providing tools for TCR (Test && Commit || Revert) workflows. This ensures that only code meeting defined quality standards and passing relevant tests is committed to the repository. Sources: packages/testing/janitor/README.md:12-40, packages/testing/playwright/AGENTS.md:14-25
Architectural Model and Enforcement
The Janitor enforces a strict layered architecture for test suites to prevent leaky abstractions and maintainable selectors. This hierarchy ensures that dependencies flow downward and layers are not skipped during execution.
Layered Architecture
The system enforces the following dependency flow:
- Tests: High-level scenarios using flows.
- Flows / Composables: Business logic orchestrating multiple page objects.
- Page Objects: Encapsulations of UI elements and simple actions.
- Components: Scoped wrappers around UI fragments.
- Playwright API: The underlying engine for DOM interaction.
Sources: packages/testing/janitor/README.md:14-38, packages/testing/playwright/AGENTS.md:54-60
This diagram illustrates the enforced relationship between architectural layers:
Key Principles
- Dependencies flow downward: Upper layers can only import lower layers. Sources: packages/testing/janitor/README.md:40-42
- No layer skipping: Tests should not reach directly into page internals or the Playwright API. Sources: packages/testing/janitor/README.md:42-43
- Selector Purity: Raw locators like
getByTestId()must be encapsulated within Page Objects. Sources: packages/testing/janitor/README.md:140-150, packages/testing/playwright/README.md:275-280
Janitor Rules and Severity
The Janitor utilizes specialized rules to perform static analysis via AST (Abstract Syntax Tree) structural fingerprinting. These rules are categorized into Architecture and Code Quality groups.
Architecture Rules
| Rule | Severity | Description |
|---|---|---|
boundary-protection | Error | Prevents pages from importing other pages directly. Sources: packages/testing/janitor/README.md:104-106 |
scope-lockdown | Error | Ensures locators are scoped to a container or navigation method. Sources: packages/testing/janitor/README.md:118-125 |
selector-purity | Error | Raw Playwright locators must not appear in tests or flows. Sources: packages/testing/janitor/README.md:140-145 |
no-page-in-flow | Warning | Flows should work through page objects rather than page directly. Sources: packages/testing/janitor/README.md:175-180 |
no-raw-editor-navigation | Error | Prevents page.goto() to editor routes; requires n8n.start.* methods. Sources: packages/testing/janitor/README.md:200-210 |
api-purity | Warning | HTTP calls must go through API services, not directly in tests. Sources: packages/testing/janitor/README.md:190-195 |
Code Quality Rules
| Rule | Severity | Description |
|---|---|---|
dead-code | Warning | Detects and can auto-fix unused public methods in page objects. Sources: packages/testing/janitor/README.md:246-252 |
duplicate-logic | Warning | Finds copy-paste patterns across tests and helpers using AST fingerprinting. Sources: packages/testing/janitor/README.md:270-280 |
deduplication | Warning | Ensures every Test ID has exactly one authoritative home. Sources: packages/testing/janitor/README.md:258-262 |
test-data-hygiene | Warning | Detects orphaned workflow files or generic names like test.json. Sources: packages/testing/janitor/README.md:264-268 |
TCR Workflow (Test && Commit || Revert)
The Janitor includes a TcrExecutor for a safety-first development loop. This process automates the verification and commit phase, reverting changes if tests fail. Sources: packages/testing/janitor/README.md:435-445, packages/testing/playwright/AGENTS.md:108-115
TCR Process Flow
The following diagram shows the internal logic of the TcrExecutor:
Impact Analysis
Before executing a TCR run, the system determines the blast radius of changes using:
- File-Level Impact: Identifying which tests use a specific page object.
- Method-Level Impact: Tracking tests that call specific methods via a usage index.
- AST Diff Analysis: Detecting which methods were added, removed, or modified compared to
HEAD.
Sources: packages/testing/janitor/README.md:404-432, packages/testing/playwright/README.md:310-315
Baseline and Incremental Cleanup
For existing repositories with many technical debt violations, the Janitor supports a Baseline mechanism. This allows teams to enable enforcement without being blocked by legacy issues. Sources: packages/testing/janitor/README.md:65-75
.janitor-baseline.json: Tracks pre-existing violations by file and content hash.- Enforcement: The Janitor and TCR only fail on new violations.
- Safeguard: TCR blocks any commits that modify the baseline file, preventing accidental "fixing" of violations by simply updating the snapshot.
Sources: packages/testing/janitor/README.md:75-85, packages/testing/playwright/AGENTS.md:85-95
Workspace Integration
The @n8n/playwright-janitor package provides workspace-level commands that do not require individual configuration files. These are used in CI pipelines to filter affected packages based on git changes. Sources: packages/testing/janitor/README.md:92-100
CI Pipeline Flow
The following sequence diagram describes how the Janitor scopes tests in a CI environment:
Global Triggers
Certain files trigger a full workspace test run (RUN_FULL) because their impact cannot be tracked via static imports. These include:
pnpm-lock.yaml- Root
package.json - Universal sinks in
packages/@n8n/db,packages/workflow, orpackages/core.
Sources: packages/testing/janitor/README.md:112-120
Conclusion
Code Health and Janitor represent a proactive approach to maintaining the n8n codebase. By combining architectural enforcement with automated TCR workflows and intelligent CI scoping, the system reduces the manual overhead of code reviews while ensuring the long-term stability and maintainability of the project's complex test infrastructure.