FilesystemAdapter
Writes test results to JSON files on the local filesystem.
Installation
import { FilesystemAdapter } from '@lytics/playwright-adapters/filesystem';Overview
The FilesystemAdapter is useful for:
- Local development — Debug test results without external services
- CI artifacts — Store results for later analysis
- Offline usage — No network dependencies
Configuration
interface FilesystemAdapterConfig {
/** Directory to write test results to (required) */
outputDir: string;
/** Whether to pretty-print JSON (default: true) */
pretty?: boolean;
}Usage
Basic Usage
Create a reporter file:
// reporter.ts
import { CoreReporter } from '@lytics/playwright-reporter';
import { FilesystemAdapter } from '@lytics/playwright-adapters/filesystem';
class CustomReporter extends CoreReporter {
constructor() {
super({
adapters: [
new FilesystemAdapter({
outputDir: './test-results',
}),
],
});
}
}
export default CustomReporter;Reference it in your config:
// playwright.config.ts
export default {
reporter: [['list'], ['./reporter.ts']],
};With Options
new FilesystemAdapter({
outputDir: './test-results',
pretty: true, // Pretty-print JSON (default: true)
})Compact JSON
For smaller file sizes:
new FilesystemAdapter({
outputDir: './test-results',
pretty: false, // Minified JSON
})Output Structure
The adapter creates an organized directory structure:
test-results/
├── test-results/
│ ├── ACCOUNT_SECURITY_VIEW-TOKENS_VALID-2024-01-01T00-00-00.000Z.json
│ ├── ACCOUNT_SECURITY_VIEW-TOKENS_EMPTY-2024-01-01T00-00-01.000Z.json
│ └── USER_MANAGEMENT_CREATE-USER_VALID-2024-01-01T00-00-02.000Z.json
└── test-runs/
├── test-run-run-123-2024-01-01T00-00-00.000Z.json
├── test-run-run-456-2024-01-01T01-00-00.000Z.json
└── latest.jsontest-results/
Individual test result files, named by testCaseId and timestamp:
{
"testCaseId": "ACCOUNT_SECURITY_VIEW-TOKENS_VALID",
"journeyId": "ACCOUNT_SECURITY_VIEW-TOKENS",
"title": "user can view access tokens",
"status": "passed",
"projectName": "chromium",
"durationMs": 1234,
"timestamp": "2024-01-01T00:00:00.000Z",
"buildId": "run-123",
"annotations": {
"testSuiteName": "ACCOUNT_SECURITY",
"journeyId": "ACCOUNT_SECURITY_VIEW-TOKENS",
"testCaseId": "ACCOUNT_SECURITY_VIEW-TOKENS_VALID"
}
}test-runs/
Test run summary files:
{
"runId": "run-123",
"timestamp": "2024-01-01T00:00:00.000Z",
"overallStatus": "passed",
"totalTests": 10,
"totalExecutions": 12,
"passed": 9,
"failed": 1,
"skipped": 0,
"durationMs": 45000,
"passRate": 0.9,
"averageTestDuration": 4500,
"slowestTestDuration": 12000,
"flakyTests": 2,
"environment": {
"branch": "main",
"commit": "abc123"
}
}latest.json
A symlink/copy of the most recent test run for easy access:
# Quick access to latest results
cat test-results/test-runs/latest.json | jq '.passRate'Features
Automatic Directory Creation
The adapter automatically creates the output directory and subdirectories if they don’t exist.
Pretty-Printed JSON
By default, JSON is pretty-printed for readability. Set pretty: false for minified output.
Non-Blocking Errors
File write errors are logged but don’t throw, allowing other adapters to continue.
CI/CD Integration
GitHub Actions
- name: Run tests
run: npx playwright test
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: test-results/
retention-days: 30GitLab CI
test:
script:
- npx playwright test
artifacts:
when: always
paths:
- test-results/
expire_in: 30 daysExample Output
Test Result (passed)
{
"testCaseId": "ACCOUNT_SECURITY_VIEW-TOKENS_VALID",
"journeyId": "ACCOUNT_SECURITY_VIEW-TOKENS",
"title": "user can view access tokens",
"status": "passed",
"projectName": "chromium",
"durationMs": 2341,
"timestamp": "2024-01-15T10:30:00.000Z",
"buildId": "github-run-12345",
"reportLink": "https://artifacts.example.com/run-12345/report.html",
"annotations": {
"testSuiteName": "ACCOUNT_SECURITY",
"journeyId": "ACCOUNT_SECURITY_VIEW-TOKENS",
"testCaseId": "ACCOUNT_SECURITY_VIEW-TOKENS_VALID"
}
}Test Result (failed)
{
"testCaseId": "ACCOUNT_SECURITY_VIEW-TOKENS_EMPTY",
"journeyId": "ACCOUNT_SECURITY_VIEW-TOKENS",
"title": "shows empty state when no tokens exist",
"status": "failed",
"projectName": "chromium",
"durationMs": 5123,
"timestamp": "2024-01-15T10:30:05.000Z",
"buildId": "github-run-12345",
"error": {
"matcher": "toBeVisible",
"expected": "visible",
"actual": "hidden",
"locator": "getByText('No tokens found')",
"location": {
"file": "tests/account-security.spec.ts",
"line": 42,
"column": 5
},
"message": "Expected element to be visible",
"snippet": [
" test('shows empty state', async ({ page }) => {",
" await page.goto('/settings/tokens');",
" await expect(page.getByText('No tokens found')).toBeVisible();",
" });"
]
},
"annotations": {
"testSuiteName": "ACCOUNT_SECURITY",
"journeyId": "ACCOUNT_SECURITY_VIEW-TOKENS",
"testCaseId": "ACCOUNT_SECURITY_VIEW-TOKENS_EMPTY"
}
}Troubleshooting
Permission denied errors
Cause: The process doesn’t have write permissions to the output directory.
Solution: Ensure the directory is writable or use a different path.
Files not appearing
Cause: Tests don’t have required annotations.
Solution: Add journeyId and testCaseId annotations to all tests. Unannotated tests are skipped.
The FilesystemAdapter is included in @lytics/playwright-adapters — no additional dependencies required.