Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@splitpro-db:5432
# https://next-auth.js.org/configuration/options#secret
NEXTAUTH_SECRET="secret"
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_URL_INTERNAL="http://localhost:3000"

# Playwright uses only this disposable database and port.
E2E_DATABASE_URL="postgresql://postgres:strong-password@localhost:5432/splitpro_test"
E2E_BASE_URL="http://127.0.0.1:3176"

# The default /home page is a blog page that may not be suitable for your use case.
# You can change it to /balances or any other URL you want.
Expand Down
11 changes: 11 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,14 @@ library/API documentation. This means you should automatically use the Context7
tools to resolve library id and get library docs without me having to explicitly ask.

Do not generate documentation or tests if not explicitly requested.

## Testing Harness Rules

- Keep fast checks independent from PostgreSQL integration and Chromium E2E jobs.
- Select unit/component tests with `pnpm test`; select database tests with
`pnpm test:integration`; select browser tests with `pnpm exec playwright test --project=chromium`.
- Integration and E2E commands may only use a disposable local database whose name ends in
`_test`. Never run reset, push, or destructive test setup against shared or production data.
- Read `docs/testing-strategy.md` before changing test selection, CI workflows, or database setup.
- When browser tests fail, inspect `test-results/e2e` and `playwright-report` artifacts before
changing application code.
69 changes: 69 additions & 0 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: E2E Tests

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
e2e:
name: Chromium E2E tests
runs-on: ubuntu-latest
env:
DATABASE_URL: postgresql://splitpro:test-password@localhost:5432/splitpro_harness_test
E2E_DATABASE_URL: postgresql://splitpro:test-password@localhost:5432/splitpro_harness_test
SKIP_ENV_VALIDATION: '1'
services:
postgres:
image: ossapps/postgres:18.3-trixie
env:
POSTGRES_USER: splitpro
POSTGRES_PASSWORD: test-password
POSTGRES_DB: splitpro_harness_test
options: >-
--health-cmd "pg_isready -U splitpro -d splitpro_harness_test"
--health-interval 2s
--health-timeout 5s
--health-retries 15
ports:
- 5432:5432

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install pnpm
uses: pnpm/action-setup@v5
with:
run_install: false

- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 22.16.0
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Prepare disposable database
run: pnpm exec prisma migrate deploy

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

- name: Run Chromium E2E tests
run: pnpm test:e2e -- --project=chromium

- name: Upload Playwright artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-artifacts
path: |
test-results/e2e
playwright-report
if-no-files-found: ignore
55 changes: 55 additions & 0 deletions .github/workflows/test-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Integration Tests

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
integration:
name: PostgreSQL integration tests
runs-on: ubuntu-latest
env:
DATABASE_URL: postgresql://splitpro:test-password@localhost:5432/splitpro_harness_test
SKIP_ENV_VALIDATION: '1'
services:
postgres:
image: ossapps/postgres:18.3-trixie
env:
POSTGRES_USER: splitpro
POSTGRES_PASSWORD: test-password
POSTGRES_DB: splitpro_harness_test
options: >-
--health-cmd "pg_isready -U splitpro -d splitpro_harness_test"
--health-interval 2s
--health-timeout 5s
--health-retries 15
ports:
- 5432:5432

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install pnpm
uses: pnpm/action-setup@v5
with:
run_install: false

- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 22.16.0
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Prepare disposable database
run: pnpm exec prisma migrate deploy

- name: Run integration tests
run: pnpm test:integration
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

# testing
/coverage
/test-results
/playwright/.auth

# database
/prisma/db.sqlite
Expand Down Expand Up @@ -60,4 +62,4 @@ SEED_STATISTICS.md

# Agents
.worktrees/
docs/superpowers/
docs/superpowers/
27 changes: 27 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,33 @@ Husky runs on commit:

Override with `git commit --no-verify` if needed.

## Testing Harness Workflow

Keep the fast checks (`pnpm prettier --check .`, `pnpm lint`, `pnpm tsgo --noEmit`,
`pnpm test`, and `pnpm build --no-lint`) independent from the disposable database and
browser jobs. CI runs PostgreSQL integration tests with `pnpm test:integration` and Chromium
E2E tests with `pnpm exec playwright test --project=chromium` in separate jobs.

### Test Selection

- `pnpm test` selects `src/**/*.{test,spec}.{ts,tsx}` and excludes `src/tests/integration/`.
- `pnpm test:integration` selects only `src/tests/integration/**/*.{test,spec}.{ts,tsx}`.
- `pnpm exec playwright test --project=chromium` selects `tests/e2e/` through
`playwright.config.ts`; setup runs before the Chromium project.
- Run one Jest file with `pnpm test src/tests/simplify.test.ts`, one integration file with
`pnpm test:integration src/tests/integration/expense.integration.test.ts`, or one browser
file with `pnpm exec playwright test tests/e2e/group-expense.spec.ts`.

### Database Safety

Integration and E2E databases must be local/disposable and end in `_test`. The integration
harness refuses non-local or non-test URLs; never point these commands at development,
staging, or production data. CI creates a fresh PostgreSQL service and may use
`prisma db push --accept-data-loss` because that database is disposable. Local worktrees
must use a separate PostgreSQL container, database name, and host port.

See `docs/testing-strategy.md` for the complete command matrix and agent workflow.

<!-- context7 -->

Use the `ctx7` CLI to fetch current documentation whenever the user asks about a library, framework, SDK, API, CLI tool, or cloud service -- even well-known ones like React, Next.js, Prisma, Express, Tailwind, Django, or Spring Boot. This includes API syntax, configuration, version migration, library-specific debugging, setup instructions, and CLI tool usage. Use even when you think you know the answer -- your training data may not reflect recent changes. Prefer this over web search for library docs.
Expand Down
22 changes: 22 additions & 0 deletions docker/test/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: split-pro-test

services:
postgres:
image: ossapps/postgres:18.3-trixie
container_name: splitpro-testing-harness-db
environment:
POSTGRES_USER: splitpro
POSTGRES_PASSWORD: test-password
POSTGRES_DB: splitpro_harness_test
command: >-
postgres
-c shared_preload_libraries=pg_cron
-c cron.database_name=splitpro_harness_test
-c cron.timezone=UTC
ports:
- '55439:5432'
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U splitpro -d splitpro_harness_test']
interval: 2s
timeout: 5s
retries: 15
51 changes: 51 additions & 0 deletions docs/testing-strategy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Testing strategy

SplitPro has three deliberately independent test surfaces. Fast checks fail quickly without
requiring PostgreSQL; database and browser checks each provision their own disposable service.

## Command matrix

| Purpose | Exact command | Selection |
| -------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| Formatting | `pnpm prettier --check .` | All supported files |
| Lint | `pnpm lint` | Oxlint project sources |
| Types | `pnpm tsgo --noEmit` | TypeScript project |
| Unit/component tests | `pnpm test` | `src/**/*.{test,spec}.{ts,tsx}`, excluding `src/tests/integration/` |
| One unit file | `pnpm test src/tests/simplify.test.ts` | The named file |
| Integration tests | `pnpm test:integration` | `src/tests/integration/**/*.{test,spec}.{ts,tsx}` |
| One integration file | `pnpm test:integration src/tests/integration/expense.integration.test.ts` | The named file |
| Chromium E2E | `pnpm test:e2e -- --project=chromium` | `tests/e2e/`, including setup dependency |
| One E2E file | `pnpm test:e2e -- tests/e2e/group-expense.spec.ts` | The named file |
| Production build | `pnpm build --no-lint` | Next.js production build |

The pull-request `Check` workflow runs formatting, lint, types, unit/component tests, and the
build. `Integration Tests` and `E2E Tests` are separate jobs and do not depend on `Check` or on
each other. E2E failures upload `test-results/e2e` and `playwright-report`.

## Database safety

Integration and E2E tests are destructive by design: they create, update, and delete records.
Use only a local disposable PostgreSQL database whose database name ends in `_test`. The
integration harness also requires a local host (`localhost`, `127.0.0.1`, or `::1`) and refuses
other URLs before tests run. CI creates a new `splitpro_harness_test` service for each job and
prepares it with:

```bash
pnpm exec prisma migrate deploy
```

For local work, copy `.env.example`, use a dedicated container/database/port per worktree, and
set `DATABASE_URL` (and `E2E_DATABASE_URL` for Playwright) to that `_test` database. Do not use
`pnpm db:push`, reset, seed, or these test commands against development, staging, or production.
When the disposable container is no longer needed, stop it with the project’s test-container
workflow; never clean it by deleting data from a shared server.

## Agent workflow

1. Read this document and the existing harness/configuration before changing tests.
2. Make the smallest change in the owning packet; keep application, Prisma, Jest, manifest, and
lockfile changes out of CI/documentation work.
3. Run the narrowest affected command first, then `pnpm prettier --check .` and any available
fast checks. Run integration/E2E only with a disposable `_test` database.
4. For E2E failures, preserve and inspect Playwright traces, screenshots, videos, and reports.
5. Report exact commands and failures; do not weaken selection or database guards to make CI pass.
Loading
Loading