Skip to content

test(e2e): add notifications flow suite, opt-in e2e CI and runbook - #158

Open
damispicyGithub wants to merge 5 commits into
TrustUp-app:mainfrom
damispicyGithub:cloud-fixer/TrustUp-API-150-1790375347252
Open

damispicyGithub wants to merge 5 commits into
TrustUp-app:mainfrom
damispicyGithub:cloud-fixer/TrustUp-API-150-1790375347252

Conversation

@damispicyGithub

Copy link
Copy Markdown

Overview

The repository already ships e2e specs for auth, loans, repayment, liquidity, transactions, reputation, webhooks and the loan-default job math, but the notifications leg of the BNPL flow had no end-to-end coverage and the e2e suite was never wired into CI. This PR closes that gap: a self-contained notifications flow spec that runs the reminder job, reads the notification back over HTTP and marks it read; an opt-in GitHub Actions workflow that runs the e2e suite with the services and env vars it needs; and a runbook under docs/setup/.

Related Issue

Closes #150

Changes

Notifications flow E2E

  • [ADD] test/e2e/modules/notifications/notifications.e2e-spec.ts
    • Boots NotificationsModule with Test.createTestingModule + FastifyAdapter and drives it through app.inject(), so routing, guards, the validation pipe, controller and service are all exercised together.
    • Replaces SupabaseService with an in-memory fake that implements only the query shapes NotificationsRepository and LoanPaymentReminderProcessor actually use: eq, gte, in, not('…','is',null), order, range, select({ count, head }), maybeSingle, single, insert, and update().select(). It also resolves the data->>loan_db_id JSONB path the processor de-duplicates on.
    • Overrides JwtAuthGuard with a guard that maps Authorization: Bearer … to a fixed wallet and rejects requests with no token.
    • Job → notification: runs LoanPaymentReminderProcessor.process() against an active loan due in three UTC days and asserts a payment_reminder_3d row is written with the merchant context, then reads it back through GET /notifications.
    • Idempotency: a second job run on the same day creates no duplicate reminder.
    • Mark as read: PATCH /notifications/:id/read returns updatedCount: 1 and clears the unread badge; re-reading an already-read notification returns updatedCount: 0.
    • Bulk read: PATCH /notifications/read-all marks every unread row and returns the affected count.
    • Filtering/pagination: unread=true plus limit/offset behave as documented, and unreadCount still reflects the whole mailbox rather than the filtered page.
    • Negative paths: another user's notification → 403 (NOTIFICATION_FORBIDDEN), unknown id → 404 (NOTIFICATION_NOT_FOUND), missing token → 401, invalid query params → 400.

E2E CI

  • [ADD] .github/workflows/e2e.yml
    • Runs the suite on workflow_dispatch or when the run-e2e label is added to a PR. The default ci.yml is untouched and stays build + unit only, as its own comment documents.
    • Provisions Redis 7 as a service container and supplies JWT/Redis values plus Supabase from the E2E_SUPABASE_URL, E2E_SUPABASE_ANON_KEY and E2E_SUPABASE_SERVICE_ROLE_KEY repository secrets.
    • Skips the suite with a notice when E2E_SUPABASE_URL is not configured, so adding the label can never fail a PR by accident.
    • concurrency cancels superseded runs and timeout-minutes: 20 bounds the job.

Documentation

  • [ADD] docs/setup/e2e-testing.md — prerequisites, isolation rules, single-flow commands, the CI opt-in, and a flow → spec coverage map.
  • [MODIFY] README.md — notes the e2e prerequisites and links the runbook from the testing and documentation sections.
  • [MODIFY] docs/README.md — links the runbook from the setup index and the docs tree.

Verification Results

Changes authored via GitHub Contents/Git API (no local clone or sandbox).
The suite was therefore not executed in this environment. Static verification performed:

✅ The spec mirrors the known-good harness in test/e2e/modules/loans/loan-lifecycle.e2e-spec.ts
   (FastifyAdapter, app.inject, overrideProvider(SupabaseService), overrideGuard(JwtAuthGuard)).
✅ Every query shape used by NotificationsRepository and LoanPaymentReminderProcessor was read
   from src/ at main@57d0f16 and is implemented by the in-memory fake.
✅ All added paths were absent on main before this branch; README.md and docs/README.md received
   additive lines only.
⚠️ `npm run test:e2e` still needs a Supabase project (and Redis for the queue-backed specs) for
   specs that boot modules without fakes — see the new runbook. The notifications spec added here
   needs neither, because it overrides SupabaseService with an in-memory fake.
Acceptance Criteria Status
E2E test: Notifications flow — trigger reminder job → verify notification created → mark as read ✅ test/e2e/modules/notifications/notifications.e2e-spec.ts
E2E tests run in isolation and clean up their own state ✅ State reset in beforeEach, in-memory Supabase, app.close() in afterAll
Use @nestjs/testing createTestingModule with the Fastify adapter ✅ FastifyAdapter + app.inject()
Add a GitHub Actions step to run E2E tests with test environment variables ✅ Opt-in .github/workflows/e2e.yml (Redis service + Supabase secrets, skips when unset)
Document how to run E2E tests locally in docs/setup/ ✅ docs/setup/e2e-testing.md, linked from README.md and docs/README.md
Auth / Loan / Repayment / Liquidity flows ⏭️ Already covered on main (test/e2e/modules/auth, loans, liquidity); not duplicated here

Closes #150

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: add E2E test suite for complete BNPL flow

1 participant