|
| 1 | +# Jobs Testing Guide |
| 2 | + |
| 3 | +This document describes how to test the jobs stack end‑to‑end, and how the existing tests are layered across the repositories. |
| 4 | + |
| 5 | +The jobs stack consists of: |
| 6 | + |
| 7 | +- Postgres + `launchql-ext-jobs` (via `@pgpm/database-jobs`) |
| 8 | +- `@launchql/knative-job-worker` + `@launchql/job-*` utilities |
| 9 | +- Jobs runtime (`knative-job-service`) |
| 10 | +- Example function: `functions/simple-email` |
| 11 | + |
| 12 | +All three runtime components (`launchql-server`, `simple-email`, `knative-job-service`) currently use the same Docker image: |
| 13 | + |
| 14 | +```text |
| 15 | +ghcr.io/constructive-io/launchql:b88e3d1 |
| 16 | +``` |
| 17 | + |
| 18 | +They differ only by **entrypoint/command**, so they are already running from the same Dockerfile / image. |
| 19 | + |
| 20 | +--- |
| 21 | + |
| 22 | +## 1. Database‑level tests (`@pgpm/database-jobs`) |
| 23 | + |
| 24 | +**Location** |
| 25 | + |
| 26 | +- `constructive-db/extensions/@pgpm/database-jobs/__tests__/jobs.test.ts` |
| 27 | + |
| 28 | +**What they cover** |
| 29 | + |
| 30 | +- Schema and function behavior for: |
| 31 | + - `app_jobs.jobs` |
| 32 | + - `app_jobs.scheduled_jobs` |
| 33 | + - `app_jobs.add_job(...)` |
| 34 | + - `app_jobs.add_scheduled_job(...)` |
| 35 | + - `app_jobs.run_scheduled_job(...)` |
| 36 | +- Snapshotting of scheduled job rows and key behavior (e.g. `job_key` conflicts). |
| 37 | + |
| 38 | +**How to run** |
| 39 | + |
| 40 | +From `constructive-db/`: |
| 41 | + |
| 42 | +```sh |
| 43 | +cd constructive-db/extensions/@pgpm/database-jobs |
| 44 | +pnpm test |
| 45 | +``` |
| 46 | + |
| 47 | +These tests use `pgsql-test` to provision an isolated Postgres instance per run, so they do not depend on Docker. |
| 48 | + |
| 49 | +--- |
| 50 | + |
| 51 | +## 2. Worker‑level tests (`@launchql/knative-job-worker`) |
| 52 | + |
| 53 | +**Location** |
| 54 | + |
| 55 | +- `constructive/jobs/knative-job-worker/__tests__/req.test.ts` |
| 56 | +- `constructive/jobs/knative-job-worker/__tests__/worker.integration.test.ts` |
| 57 | + |
| 58 | +**What they cover** |
| 59 | + |
| 60 | +- `req.test.ts` |
| 61 | + - Request construction to Knative / gateway: |
| 62 | + - `KNATIVE_SERVICE_URL` |
| 63 | + - `INTERNAL_GATEWAY_URL` |
| 64 | + - `INTERNAL_GATEWAY_DEVELOPMENT_MAP` |
| 65 | + - Headers and body (`X-Worker-Id`, `X-Job-Id`, `X-Database-Id`, `X-Callback-Url`). |
| 66 | + - Error behavior when no base URL envs are set. |
| 67 | +- `worker.integration.test.ts` |
| 68 | + - Integration with `app_jobs.add_job(...)` via `pgsql-test` seed: |
| 69 | + - Inserts jobs into `app_jobs.jobs`. |
| 70 | + - Uses `jobUtils.getJob(...)` to fetch work. |
| 71 | + - Calls `worker.doWork(job)` and asserts it posts to the expected Knative URL. |
| 72 | + - Verifies error propagation when the underlying HTTP request fails. |
| 73 | + |
| 74 | +**How to run** |
| 75 | + |
| 76 | +From `constructive/`: |
| 77 | + |
| 78 | +```sh |
| 79 | +cd constructive/jobs/knative-job-worker |
| 80 | +pnpm test |
| 81 | +``` |
| 82 | + |
| 83 | +These tests also rely on `pgsql-test` and run entirely in‑process (no Docker needed). |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +## 3. HTTP function tests (`functions/simple-email`) |
| 88 | + |
| 89 | +**Location** |
| 90 | + |
| 91 | +- `constructive/functions/simple-email/src/index.ts` |
| 92 | + |
| 93 | +**Goal** |
| 94 | + |
| 95 | +Add focused tests for the `simple-email` function to ensure: |
| 96 | + |
| 97 | +- Payload validation works as expected (required `to`, `subject`, and at least one of `html`/`text`). |
| 98 | +- `MAILGUN_FROM` and optional `from`/`replyTo` are handled correctly. |
| 99 | +- `@launchql/postmaster.send` is invoked with the correct arguments. |
| 100 | + |
| 101 | +**Suggested test approach (no code yet)** |
| 102 | + |
| 103 | +- Use an HTTP testing library (e.g. `supertest`) against the exported `app`. |
| 104 | +- Mock `@launchql/postmaster`: |
| 105 | + - Assert it is called with the expected `to`, `subject`, `html`/`text`, `from`, and `replyTo`. |
| 106 | +- Cover at least: |
| 107 | + - Happy path with `html` only. |
| 108 | + - Happy path with `text` only. |
| 109 | + - Missing required fields (`to`, `subject`). |
| 110 | + - Missing both `html` and `text`. |
| 111 | + - Overriding `MAILGUN_FROM` via payload `from`. |
| 112 | + |
| 113 | +These tests would live alongside the function, e.g.: |
| 114 | + |
| 115 | +- `constructive/functions/simple-email/__tests__/simple-email.test.ts` |
| 116 | + |
| 117 | +and run with whatever test runner is already used in this workspace (`pnpm test` at the workspace or package level). |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +## 4. In‑process end‑to‑end pipeline tests (optional) |
| 122 | + |
| 123 | +To exercise the full pipeline without Docker: |
| 124 | + |
| 125 | +- Use `pgsql-test` to spin up a database with: |
| 126 | + - `launchql-ext-jobs` (via the same seed pattern used in `worker.integration.test.ts`). |
| 127 | +- In a Jest test: |
| 128 | + - Start the `simple-email` HTTP app listening on an ephemeral port. |
| 129 | + - Start a `Worker` instance from `@launchql/knative-job-worker` with `tasks: ['simple-email']`. |
| 130 | + - Set env vars to match dev: |
| 131 | + - `PG*`, `JOBS_SCHEMA` |
| 132 | + - `KNATIVE_SERVICE_URL` or `INTERNAL_GATEWAY_DEVELOPMENT_MAP` pointing to the local `simple-email` server. |
| 133 | + - Enqueue a job via `app_jobs.add_job(...)`. |
| 134 | + - Call `jobUtils.getJob(...)` + `worker.doWork(job)` and assert: |
| 135 | + - The job is processed successfully. |
| 136 | + - `simple-email` (via a mocked `sendEmail`) sees the correct payload. |
| 137 | + |
| 138 | +These tests would sit either: |
| 139 | + |
| 140 | +- in a new integration suite under `constructive/jobs/knative-job-worker`, or |
| 141 | +- in a dedicated `constructive/jobs/knative-job-service` test directory. |
| 142 | + |
| 143 | +They give you a high‑confidence pipeline test without needing Docker‑compose. |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## 5. Docker‑based manual and smoke testing |
| 148 | + |
| 149 | +For real Docker runs and manual verification, use the existing jobs dev guide: |
| 150 | + |
| 151 | +- `constructive/DEVELOPMENT_JOBS.md` |
| 152 | + |
| 153 | +That guide covers: |
| 154 | + |
| 155 | +- Starting Postgres + Minio via `docker compose`. |
| 156 | +- Initializing the database with `pgpm` (including jobs packages). |
| 157 | +- Bringing up the jobs stack via `docker-compose.jobs.yml`. |
| 158 | +- Enqueuing a test job with: |
| 159 | + |
| 160 | + ```sh |
| 161 | + docker exec -it postgres \ |
| 162 | + psql -U postgres -d launchql -c " |
| 163 | + SELECT app_jobs.add_job( |
| 164 | + '00000000-0000-0000-0000-000000000001'::uuid, |
| 165 | + 'simple-email', |
| 166 | + json_build_object( |
| 167 | + |
| 168 | + 'subject', 'Hello from LaunchQL jobs', |
| 169 | + 'html', '<p>Hi from simple-email (dry run)</p>' |
| 170 | + )::json |
| 171 | + ); |
| 172 | + " |
| 173 | + ``` |
| 174 | + |
| 175 | +This is ideal for: |
| 176 | + |
| 177 | +- Local debugging. |
| 178 | +- Verifying new Docker images (e.g. switching from `ghcr.io/constructive-io/launchql:b88e3d1` to a local build). |
| 179 | +- High‑level smoke tests around deployment changes. |
| 180 | + |
0 commit comments