{"id":48898935,"url":"https://github.com/radekbednarik/playwright-cart","last_synced_at":"2026-04-16T13:01:42.980Z","repository":{"id":350025107,"uuid":"1199498156","full_name":"radekBednarik/playwright-cart","owner":"radekBednarik","description":"Self-hosted dashboard for collecting and viewing Playwright test reports from any CI/CD pipeline.","archived":false,"fork":false,"pushed_at":"2026-04-16T08:26:00.000Z","size":838,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-16T10:10:17.034Z","etag":null,"topics":["dashboard","nodejs","playwright","qa","qa-automation","report","reporting","test-automation","test-reports","testing","typescript"],"latest_commit_sha":null,"homepage":"https://radekbednarik.github.io/playwright-cart/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/radekBednarik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-02T12:10:29.000Z","updated_at":"2026-04-16T08:20:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/radekBednarik/playwright-cart","commit_stats":null,"previous_names":["radekbednarik/playwright-cart"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/radekBednarik/playwright-cart","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekBednarik%2Fplaywright-cart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekBednarik%2Fplaywright-cart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekBednarik%2Fplaywright-cart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekBednarik%2Fplaywright-cart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/radekBednarik","download_url":"https://codeload.github.com/radekBednarik/playwright-cart/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekBednarik%2Fplaywright-cart/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31886937,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T11:36:10.202Z","status":"ssl_error","status_checked_at":"2026-04-16T11:36:09.652Z","response_time":69,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dashboard","nodejs","playwright","qa","qa-automation","report","reporting","test-automation","test-reports","testing","typescript"],"created_at":"2026-04-16T13:01:37.945Z","updated_at":"2026-04-16T13:01:42.972Z","avatar_url":"https://github.com/radekBednarik.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# playwright-cart\n\nA self-hosted dashboard for collecting and viewing Playwright test reports from any CI/CD pipeline.\n\n## What is playwright-cart?\n\nWhen you run Playwright tests across multiple projects, branches, or CI pipelines, results end up scattered in ephemeral job logs and short-lived HTML report artifacts. playwright-cart gives you a permanent, centralized place to collect and browse them.\n\nIt has three parts: a **reporter** npm package you add to your Playwright config, a **server** that receives results during test runs and stores them in PostgreSQL, and a **dashboard** (React SPA) for browsing runs, inspecting individual test results, viewing screenshots and traces, and opening the full Playwright HTML report. Everything is self-hosted — you own your data.\n\n## Quick Start\n\n**Prerequisites:** Docker + Compose plugin\n\n```bash\ngit clone https://github.com/radekBednarik/playwright-cart.git\ncd playwright-cart\ndocker compose up --build\n```\n\nOpen `http://localhost` in your browser. Log in with the default credentials: `admin` / `changeme123`.\n\n\u003e **Change the default password and set a strong `JWT_SECRET` before exposing this instance to a network.** See [Configuration](#configuration).\n\nTo run in the background:\n\n```bash\ndocker compose up --build -d\ndocker compose logs -f   # follow logs\ndocker compose ps        # check health status\n```\n\nTo stop:\n\n```bash\ndocker compose down       # stop containers, preserve data\ndocker compose down -v    # stop containers and delete all data\n```\n\n---\n\n## Reporter Setup\n\nThe reporter is published as a **public** package to GitHub Packages under `@radekbednarik/playwright-cart-reporter` — no auth token required to install.\n\n### 1. Install\n\nAdd the registry scope to `.npmrc` in your **project root** (the project that runs Playwright tests, not this repo):\n\n```ini\n@radekbednarik:registry=https://npm.pkg.github.com\n```\n\nThen install:\n\n```bash\nnpm install --save-dev @radekbednarik/playwright-cart-reporter\n# or\npnpm add -D @radekbednarik/playwright-cart-reporter\n```\n\n### 2. Configure in `playwright.config.ts`\n\nAdd the reporter alongside the HTML reporter:\n\n```ts\nimport { defineConfig } from '@playwright/test'\n\nexport default defineConfig({\n  reporter: [\n    ['html'],\n    ['@radekbednarik/playwright-cart-reporter', {\n      serverUrl: 'http://localhost:3001',              // URL of your playwright-cart server (required)\n      project: 'my-app',                               // logical project name shown in the dashboard (required)\n      branch: process.env.BRANCH,                      // git branch name (optional)\n      commitSha: process.env.COMMIT_SHA,               // git commit SHA (optional)\n      tags: ['@smoke', '@checkout'],                   // tags shown in UI and filterable later (optional)\n      apiKey: process.env.PLAYWRIGHT_CART_API_KEY,     // Bearer token for auth (required)\n      uploadConcurrency: 3,                            // max parallel test uploads, default: 3 (optional)\n      retries: 3,                                      // upload retry attempts per test, default: 3 (optional)\n      retryDelay: 500,                                 // initial retry backoff in ms, doubles each attempt, default: 500 (optional)\n    }],\n  ],\n})\n```\n\nThe reporter streams test results to the server during the run and uploads the zipped Playwright HTML report on completion. Run-level tags from reporter config and test-level tags from Playwright are stored and exposed in the dashboard filters. In deployed setups, reporter uploads should use an API key because all non-public `/api/*` routes require authentication.\n\n---\n\n## Authentication\n\n### First login\n\nOn first startup the server creates an admin account from the `ADMIN_USERNAME` and `ADMIN_PASSWORD` environment variables. Log in at `http://localhost` and change the password immediately.\n\n### Roles\n\n| Role | Capabilities |\n|------|-------------|\n| `admin` | Manage users, create/revoke API keys, configure retention settings, view and delete all runs |\n| `user` | View all runs, update own username/password/theme/runs-per-page setting |\n\n### API keys for CI/CD\n\nFor the reporter and any CI/CD tooling, use an API key instead of a password. Admins can create keys in **Settings → API Keys**. The raw key is shown only once — store it as a secret immediately.\n\nPass the key as a Bearer token:\n\n```\nAuthorization: Bearer \u003ckey\u003e\n```\n\nOr via the reporter config:\n\n```ts\napiKey: process.env.PLAYWRIGHT_CART_API_KEY,\n```\n\nAPI keys are HMAC-SHA256-hashed with `JWT_SECRET` before storage and can be revoked at any time.\n\n---\n\n## Dashboard\n\n### Annotation-based status inversion (`type: fail`)\n\nThe dashboard understands Playwright's [`test.fail()`](https://playwright.dev/docs/api/class-test#test-fail) annotation. When a test carries an annotation with `type: 'fail'`, the dashboard inverts its displayed status:\n\n| Raw status | Annotation | Displayed as | Label |\n|---|---|---|---|\n| `failed` | `type: 'fail'` | **passed** (green) | `expected failure` (purple pill) |\n| `passed` | `type: 'fail'` | **failed** (red) | `unexpected pass` (red pill) |\n\nThis inversion is applied consistently across all views:\n\n- **Test detail page** — status badge and secondary label pill\n- **Suite tree** — icon next to each test row\n- **Suite header** — failure counter (`N failed`)\n- **Run header** — pass-rate bar and stat pills (`N passed` / `N failed`)\n\nThe logic lives in `getTestOutcome()` (`packages/web/src/lib/api.ts`). No server-side changes are involved — the raw status is stored as Playwright reports it; the inversion is display-only.\n\n---\n\n## Configuration\n\nEnvironment variables for the server. When using `docker compose up`, `DATABASE_URL` is set automatically. For local development without Docker, copy `.env.example` to `.env`:\n\n```bash\ncp .env.example .env\n```\n\n| Variable | Default | Description |\n|---|---|---|\n| `PORT` | `3001` | Port the server listens on |\n| `DATABASE_URL` | *(required)* | PostgreSQL connection string |\n| `DATA_DIR` | `./data` | Directory for binary files: attachments and extracted HTML reports. `docker compose` overrides this to `/app/data`. |\n| `ADMIN_USERNAME` | `admin` | Username for the initial admin account |\n| `ADMIN_PASSWORD` | `changeme123` | Password for the initial admin account — **change in production** |\n| `JWT_SECRET` | *(insecure default)* | Secret for signing JWT session tokens. Generate with `openssl rand -hex 32`. **Must be set in production.** |\n| `NODE_ENV` | `development` | Set to `production` to enable secure (HTTPS-only) cookies |\n| `ALLOWED_ORIGIN` | `http://localhost:5173` | CORS allowed origin for `/api/*`. Set to your dashboard URL in production. |\n\n---\n\n## Deployment\n\nFor deploying playwright-cart to a production server with HTTPS, see the [Deployment Guide](docs/deployment.md). It covers provisioning a VPS, installing Coolify as a self-hosted PaaS, and deploying the full stack with automatic SSL.\n\n---\n\n## Developer\n\n### Architecture\n\n```\nplaywright tests\n      │\n      │  @radekbednarik/playwright-cart-reporter (npm package)\n      │  streams results during test run\n      ▼\n┌─────────────┐        ┌─────────────┐\n│   server    │◄───────│     web     │\n│  (Hono API) │  /api  │ (React SPA) │\n│  port 3001  │        │   port 80   │\n└─────────────┘        └─────────────┘\n      │\n  PostgreSQL         data volume\n  (run + test        (attachments,\n   metadata)          report files)\n```\n\nThe **server** stores run and test metadata in PostgreSQL via Drizzle ORM. Binary files — attachments (screenshots, traces) and extracted HTML reports — are stored on disk in `DATA_DIR`. The **web** frontend is a static React SPA served by Nginx; Nginx proxies `/api` and `/reports` to the server. The **reporter** is installed in the project under test, not here.\n\n### Local development\n\n**Prerequisites:** Node.js ≥ 20, pnpm\n\n```bash\npnpm install\npnpm dev        # starts all packages in watch mode\n```\n\nThe web dev server runs on `http://localhost:5173` and proxies `/api` and `/reports` to the server on port 3001.\n\nIndividual packages:\n\n```bash\npnpm --filter @playwright-cart/server dev                        # tsx watch — server on :3001\npnpm --filter @playwright-cart/web dev                           # Vite dev server on :5173\npnpm --filter @radekbednarik/playwright-cart-reporter dev        # tsc watch\n```\n\nBuild, lint, and type-check:\n\n```bash\npnpm build\npnpm lint\npnpm format\npnpm typecheck\n```\n\n### Running tests\n\n```bash\npnpm --filter @radekbednarik/playwright-cart-reporter test\npnpm --filter @radekbednarik/playwright-cart-reporter test:watch\n\npnpm --filter @playwright-cart/server test\npnpm --filter @playwright-cart/server test:watch\n\npnpm --filter @playwright-cart/web test\npnpm --filter @playwright-cart/web test:watch\n```\n\n### E2E testing\n\nA self-contained E2E suite lives in `packages/e2e`. It uses the workspace reporter package directly (no npm publish needed) and runs Playwright tests against a small static demo app, verifying the full reporter → server → dashboard pipeline.\n\n**Prerequisites:** Docker + Compose plugin, Playwright browsers:\n\n```bash\npnpm --filter @playwright-cart/e2e exec playwright install chromium\n```\n\n**Run the suite:**\n\n```bash\n# 1. Start the stack\ndocker compose up --build -d\ndocker compose ps   # wait until server and web show \"healthy\"\n\n# 2. Run the tests (reporter is built automatically via pretest)\npnpm --filter @playwright-cart/e2e test\n\n# 3. Open the dashboard\n# visit http://localhost in your browser\n```\n\nExpect 4 passing tests and 1 intentional failure — the failing test verifies that the dashboard correctly displays error states and attached traces.\n\n| Check | Where |\n|-------|-------|\n| New run with project `e2e-demo` | Runs list |\n| 4 passed, 1 failed | Run summary |\n| Trace attachment on each test | Test detail view |\n| Timeout error on the failing test | Test detail view |\n| Trace viewer opens | Click a trace attachment |\n| HTML report link present | Run detail |\n\n**Tear down:**\n\n```bash\ndocker compose down      # stop containers, preserve data\ndocker compose down -v   # stop containers and delete all data\n```\n\n### Further reading\n\n- [API Reference](docs/api.md) — all REST endpoints with auth requirements\n- [Deployment Guide](docs/deployment.md) — production deployment on Hetzner + Coolify\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradekbednarik%2Fplaywright-cart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fradekbednarik%2Fplaywright-cart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradekbednarik%2Fplaywright-cart/lists"}