zuplo 7.4.4 → 7.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/docs/articles/ci-cd-azure/local-testing.mdx +22 -4
  2. package/docs/articles/ci-cd-bitbucket/local-testing.mdx +22 -4
  3. package/docs/articles/ci-cd-circleci/local-testing.mdx +21 -4
  4. package/docs/articles/ci-cd-github/deploy-and-test.mdx +28 -13
  5. package/docs/articles/ci-cd-github/local-testing.mdx +36 -16
  6. package/docs/articles/ci-cd-gitlab/local-testing.mdx +22 -4
  7. package/docs/articles/github-deployment-testing.mdx +118 -31
  8. package/docs/articles/testing-getting-started.mdx +220 -0
  9. package/docs/articles/testing-preview-environments.mdx +148 -0
  10. package/docs/articles/testing-recipes.mdx +429 -0
  11. package/docs/articles/testing.mdx +138 -408
  12. package/docs/mcp-gateway/auth/configuring-auth0.mdx +6 -5
  13. package/docs/mcp-gateway/auth/configuring-clerk.mdx +4 -4
  14. package/docs/mcp-gateway/auth/configuring-cognito.mdx +5 -4
  15. package/docs/mcp-gateway/auth/configuring-entra.mdx +5 -4
  16. package/docs/mcp-gateway/auth/configuring-generic-oidc.mdx +8 -8
  17. package/docs/mcp-gateway/auth/configuring-google.mdx +4 -4
  18. package/docs/mcp-gateway/auth/configuring-keycloak.mdx +4 -3
  19. package/docs/mcp-gateway/auth/configuring-logto.mdx +4 -4
  20. package/docs/mcp-gateway/auth/configuring-okta.mdx +3 -3
  21. package/docs/mcp-gateway/auth/configuring-onelogin.mdx +3 -3
  22. package/docs/mcp-gateway/auth/configuring-ping.mdx +3 -3
  23. package/docs/mcp-gateway/auth/configuring-workos.mdx +5 -4
  24. package/docs/mcp-gateway/auth/manual-oauth-testing.mdx +8 -8
  25. package/docs/mcp-gateway/auth/overview.mdx +17 -17
  26. package/docs/mcp-gateway/auth/upstream-oauth.mdx +5 -5
  27. package/docs/mcp-gateway/code-config/local-development.mdx +14 -12
  28. package/docs/mcp-gateway/code-config/overview.mdx +9 -4
  29. package/docs/mcp-gateway/connect-clients/chatgpt.mdx +114 -56
  30. package/docs/mcp-gateway/how-it-works.mdx +11 -9
  31. package/docs/mcp-gateway/introduction.mdx +3 -1
  32. package/docs/mcp-gateway/quickstart-local.mdx +7 -7
  33. package/docs/mcp-gateway/reference.mdx +58 -25
  34. package/docs/mcp-gateway/server-registry.mdx +179 -0
  35. package/docs/mcp-gateway/test-clients.mdx +2 -2
  36. package/docs/mcp-server/custom-tools.mdx +32 -0
  37. package/docs/programmable-api/mcp-gateway-plugin.mdx +137 -0
  38. package/docs/programmable-api/mcp-sdk.mdx +240 -0
  39. package/docs/self-hosted/overview.md +2 -0
  40. package/package.json +5 -5
@@ -0,0 +1,220 @@
1
+ ---
2
+ title: Get started with zuplo test
3
+ sidebar_label: Get started
4
+ description:
5
+ Take a Zuplo project from no tests to a green run against a local dev server
6
+ in three steps. Covers test file location, the TestHelper API, and CLI flags
7
+ for filtering and skipping tests.
8
+ ---
9
+
10
+ This guide takes a Zuplo project from no tests to a green test run against a
11
+ local dev server, in three steps. It covers where test files live, what
12
+ `TestHelper` gives you, and the CLI flags worth knowing. The only install is one
13
+ assertion library.
14
+
15
+ Every test `zuplo test` runs is an integration test: it makes a real HTTP
16
+ request to a real running gateway and asserts on the real response. The endpoint
17
+ is a command-line flag, so the same files run against local dev, a preview
18
+ deployment, or production.
19
+
20
+ <Stepper>
21
+
22
+ 1. **Install an assertion library**
23
+
24
+ `describe`, `it`, the lifecycle hooks, and `TestHelper` come from
25
+ `@zuplo/test`, which arrives transitively with the `zuplo` package. The CLI
26
+ requires Node.js 24.0.0 or later, which every sample here assumes.
27
+
28
+ Assertions in these docs use [`expect`](https://www.chaijs.com/api/bdd/) from
29
+ chai. Chai is **not** included in a new Zuplo project, so install it
30
+ yourself:
31
+
32
+ ```bash
33
+ npm install --save-dev chai @types/chai
34
+ ```
35
+
36
+ The CLI marks `chai` as external when it compiles your tests, so it resolves
37
+ from `node_modules` at run time. Skip the install step and the compiler fails
38
+ with `Cannot find package 'chai'` before any test runs.
39
+
40
+ :::tip
41
+
42
+ Prefer no dependencies? Node's built-in
43
+ [`node:assert/strict`](https://nodejs.org/api/assert.html#strict-assertion-mode)
44
+ works instead and needs nothing installed. The strict form compares with
45
+ `===`, so `assert.equal(200, "200")` fails instead of quietly passing.
46
+
47
+ :::
48
+
49
+ 2. **Write the first test**
50
+
51
+ Test files go in a `tests` folder at the root of your project and must end in
52
+ `.test.ts`. Nested folders are fine.
53
+
54
+ ```ts title="/tests/health.test.ts"
55
+ import { describe, it, TestHelper } from "@zuplo/test";
56
+ import { expect } from "chai";
57
+
58
+ describe("gateway", () => {
59
+ it("serves the root route", async () => {
60
+ const response = await fetch(TestHelper.TEST_URL);
61
+ expect(response.status).to.equal(200);
62
+ });
63
+ });
64
+ ```
65
+
66
+ `TestHelper.TEST_URL` is whatever you passed to `--endpoint`. Build request
67
+ URLs from it rather than hard-coding a host — that is the single change that
68
+ lets one suite serve every environment:
69
+
70
+ ```ts
71
+ const url = (path: string) => new URL(path, TestHelper.TEST_URL).toString();
72
+
73
+ const response = await fetch(url("/v1/orders"));
74
+ ```
75
+
76
+ 3. **Run it**
77
+
78
+ Start the dev server in one terminal:
79
+
80
+ ```bash
81
+ npx zuplo dev
82
+ ```
83
+
84
+ Run the suite in another:
85
+
86
+ ```bash
87
+ npx zuplo test --endpoint http://localhost:9000
88
+ ```
89
+
90
+ The CLI discovers every `tests/**/*.test.ts` file, compiles them into
91
+ `.zuplo/__tests__`, and runs them. `.zuplo` is generated output — leave it
92
+ out of source control.
93
+
94
+ :::tip
95
+
96
+ Add the endpoint you use most to a script so the common case is one word:
97
+
98
+ ```json title="package.json"
99
+ {
100
+ "scripts": {
101
+ "test": "zuplo test --endpoint http://localhost:9000"
102
+ }
103
+ }
104
+ ```
105
+
106
+ :::
107
+
108
+ </Stepper>
109
+
110
+ ## TestHelper reference
111
+
112
+ `TestHelper` has two static members.
113
+
114
+ | Member | Type | Description |
115
+ | ------------------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
116
+ | `TestHelper.TEST_URL` | `string` | The value passed to `--endpoint`. Throws if `zuplo test` was not given one. |
117
+ | `TestHelper.environment` | `Record<string, string>` | The test process environment. This is `process.env` — the two are interchangeable, including anything from `.env`. |
118
+
119
+ `TestHelper.environment` reads the environment of the **test process**, not the
120
+ environment variables configured on your Zuplo project. Those belong to the
121
+ gateway; these belong to the test process. Fixture tokens, API keys, and seed
122
+ data come in this way:
123
+
124
+ ```bash
125
+ TENANT_A_JWT=eyJhbGciOi... npx zuplo test --endpoint http://localhost:9000
126
+ ```
127
+
128
+ ```ts title="/tests/auth.test.ts"
129
+ import { describe, it, TestHelper } from "@zuplo/test";
130
+ import { expect } from "chai";
131
+
132
+ describe("auth", () => {
133
+ it("accepts a valid token", async () => {
134
+ const response = await fetch(`${TestHelper.TEST_URL}/v1/orders`, {
135
+ headers: {
136
+ Authorization: `Bearer ${TestHelper.environment.TENANT_A_JWT}`,
137
+ },
138
+ });
139
+ expect(response.status).to.equal(200);
140
+ });
141
+ });
142
+ ```
143
+
144
+ The CLI also loads a `.env` file from the directory you run it in, so local
145
+ fixture values can live there instead of on the command line.
146
+
147
+ :::warning
148
+
149
+ Never commit fixture credentials. Keep them in `.env` (gitignored) locally and
150
+ in your CI provider's secret store in the pipeline.
151
+
152
+ :::
153
+
154
+ ## Select which tests run
155
+
156
+ Two flags select tests by name. Both match against the full test name, which is
157
+ the `describe` label and the `it` label joined together, so a test named
158
+ `smoke: orders route answers` is selected by `--filter smoke` even when its
159
+ enclosing `describe` does not match.
160
+
161
+ ```bash
162
+ # Only tests whose name contains "auth"
163
+ npx zuplo test --endpoint http://localhost:9000 --filter "auth"
164
+
165
+ # Regex form — wrap the pattern in slashes
166
+ npx zuplo test --endpoint http://localhost:9000 --filter "/#label[Aa]/"
167
+
168
+ # Everything except tests tagged [slow] in their name
169
+ npx zuplo test --endpoint http://localhost:9000 --skip-filter "\[slow\]"
170
+ ```
171
+
172
+ `--skip-filter` is applied after `--filter`, so the two compose. This is the
173
+ mechanism behind production smoke checks: name the read-only subset
174
+ consistently, then run only that subset against production.
175
+
176
+ ## Skip a test in code
177
+
178
+ Prefix a suite or test with `.skip` (or its alias `.ignore`) to declare it
179
+ without running it:
180
+
181
+ ```ts title="/tests/skip.test.ts"
182
+ import { describe, it } from "@zuplo/test";
183
+ import { expect } from "chai";
184
+
185
+ describe("arithmetic", () => {
186
+ it.skip("this test is declared but not run", () => {
187
+ expect(1 + 4).to.equal(6);
188
+ });
189
+
190
+ it("this test runs", () => {
191
+ expect(1 + 4).to.equal(5);
192
+ });
193
+ });
194
+ ```
195
+
196
+ :::caution
197
+
198
+ `.only` takes effect only when the run is started with `--only`. Without the
199
+ flag, `zuplo test` runs the marked test **and every other test** — silently the
200
+ opposite of what you wanted, and it looks like it worked.
201
+
202
+ ```bash
203
+ npx zuplo test --endpoint http://localhost:9000 --only
204
+ ```
205
+
206
+ With the flag, only the marked tests and suites execute. If your CLI does not
207
+ recognize `--only`, upgrade the `zuplo` package — or use `--filter` to narrow
208
+ the run by test name, which works on every version.
209
+
210
+ :::
211
+
212
+ ## Next steps
213
+
214
+ - [Gateway test recipes](./testing-recipes.mdx) — what to assert at a gateway,
215
+ as copy-pasteable files
216
+ - [Testing preview environments](./testing-preview-environments.mdx) — run the
217
+ same suite against the real deployment of your branch
218
+ - [Testing GitHub deployments](./github-deployment-testing.mdx) — make a failing
219
+ gateway test block the merge
220
+ - [Testing overview](./testing.mdx) — when to run what, and why
@@ -0,0 +1,148 @@
1
+ ---
2
+ title: Test preview environments
3
+ sidebar_label: Preview environments
4
+ description:
5
+ Run the same test suite against a real per-branch Zuplo deployment before
6
+ merging. Covers getting the preview URL into your tests, waiting for
7
+ readiness, per-environment secrets, and scoping what runs where.
8
+ ---
9
+
10
+ A preview environment is a full Zuplo deployment of a branch, on the same edge
11
+ network as production, at its own URL. That makes it the highest-fidelity place
12
+ to run your test suite before a change merges — closer to production than any
13
+ local server, and without the queueing and drift of a shared staging
14
+ environment.
15
+
16
+ Because `zuplo test` takes the target as a flag, the files you run against
17
+ `http://localhost:9000` are the files you run against the preview URL. Nothing
18
+ in the suite changes.
19
+
20
+ ## How branches become environments
21
+
22
+ Push a branch to a connected repository and Zuplo deploys it:
23
+
24
+ - The repository's default branch deploys to **Production**.
25
+ - Every other branch deploys to a **Preview** environment with its own URL.
26
+
27
+ For the full mapping, see
28
+ [branch-based deployments](./branch-based-deployments.mdx). For how preview
29
+ environments differ from working copies, see [environments](./environments.mdx).
30
+
31
+ ## Get the URL into your tests
32
+
33
+ Preview URLs are derived from the branch name and project, so hard-coding one is
34
+ a maintenance problem. Read the URL from the environment instead.
35
+
36
+ ### From the Zuplo GitHub integration
37
+
38
+ The integration reports a GitHub Deployment for each build, and the deployment
39
+ status carries the environment URL. In a workflow triggered by the
40
+ `deployment_status` event, that value is
41
+ `github.event.deployment_status.environment_url`. This is the mechanism used in
42
+ [testing GitHub deployments](./github-deployment-testing.mdx), and it is the
43
+ approach to prefer: no URL construction, and the tests cannot start before the
44
+ deployment exists.
45
+
46
+ ### From your own pipeline
47
+
48
+ If you deploy from your own CI with `zuplo deploy`, capture the URL from the
49
+ deploy command's output and pass it through:
50
+
51
+ ```bash
52
+ OUTPUT=$(npx zuplo deploy --api-key "$ZUPLO_API_KEY" --environment "$BRANCH" 2>&1)
53
+ echo "$OUTPUT"
54
+ DEPLOY_URL=$(echo "$OUTPUT" | grep -oP 'Deployed to \K(https://[^ ]+)')
55
+
56
+ npx zuplo test --endpoint "$DEPLOY_URL"
57
+ ```
58
+
59
+ For the complete workflow, see
60
+ [GitHub Actions: deploy and test](./ci-cd-github/deploy-and-test.mdx). For
61
+ pipeline patterns for other providers, see [custom CI/CD](./custom-ci-cd.mdx).
62
+
63
+ ## Wait for the environment before testing
64
+
65
+ A deployment reporting success is not the same as a gateway serving traffic, and
66
+ the gap between the two is the single most common cause of "flaky" gateway
67
+ tests. The first few requests fail, the run is retried, and the real problem — a
68
+ race in the pipeline — is filed as test flakiness.
69
+
70
+ Poll a cheap unauthenticated route with a hard deadline instead of sleeping:
71
+
72
+ ```bash
73
+ deadline=$((SECONDS + 120))
74
+ until curl --fail --silent --output /dev/null "$API_URL/health"; do
75
+ if ((SECONDS >= deadline)); then
76
+ echo "Gateway at $API_URL not ready after 120s" >&2
77
+ exit 1
78
+ fi
79
+ sleep 2
80
+ done
81
+
82
+ npx zuplo test --endpoint "$API_URL"
83
+ ```
84
+
85
+ If your gateway has no health route, add one. See
86
+ [health checks](./health-checks.mdx).
87
+
88
+ ## Per-environment services and secrets
89
+
90
+ Preview environments have their own configuration, and a test that passes
91
+ locally can fail on a preview for reasons that have nothing to do with your
92
+ change:
93
+
94
+ - **Environment variables.** Values are set per environment in the Zuplo Portal.
95
+ A variable that exists in production but not on the preview is a real defect
96
+ the preview run catches — but assert on the behavior, not on the variable.
97
+ - **API key buckets.** API key authentication is backed by a bucket tied to the
98
+ environment. Keys minted for one environment do not authenticate against
99
+ another, so CI needs a fixture key for the environment it is testing.
100
+ - **Rate limit buckets.** Rate limit state is per environment too. This works in
101
+ your favor: a preview environment's limits are not being consumed by
102
+ production traffic, which is part of what makes the rate limit recipe
103
+ deterministic.
104
+
105
+ Keep fixture credentials in your CI provider's secret store and pass them to
106
+ `zuplo test` as environment variables. Inside the test they are available on
107
+ `TestHelper.environment`:
108
+
109
+ ```bash
110
+ TENANT_A_JWT="$PREVIEW_TENANT_A_JWT" npx zuplo test --endpoint "$API_URL"
111
+ ```
112
+
113
+ ## Scope what runs where
114
+
115
+ The same files can run everywhere, but that does not mean every test runs
116
+ everywhere:
117
+
118
+ | Target | What to run |
119
+ | ----------------------- | --------------------------------------------------------- |
120
+ | `http://localhost:9000` | Everything. Fast feedback while editing. |
121
+ | Preview deployment | Everything. This is the run that gates the merge. |
122
+ | Production | A small, read-only smoke subset selected with `--filter`. |
123
+
124
+ Name the production-safe tests consistently — a `smoke:` prefix works well — and
125
+ select them by name:
126
+
127
+ ```bash
128
+ npx zuplo test --endpoint https://api.example.com --filter "smoke"
129
+ ```
130
+
131
+ Nothing with side effects belongs in that subset. See
132
+ [gateway test recipes](./testing-recipes.mdx) for the test data hygiene rules
133
+ that make this safe.
134
+
135
+ ## Clean up preview environments
136
+
137
+ Preview environments outlive the branch unless something removes them. Delete
138
+ the branch and the environment goes with it when you use the GitHub integration.
139
+ If you deploy from your own pipeline, add an explicit cleanup step on branch
140
+ delete. See
141
+ [cleanup on branch delete](./ci-cd-github/cleanup-on-branch-delete.mdx).
142
+
143
+ ## Related
144
+
145
+ - [Get started with zuplo test](./testing-getting-started.mdx)
146
+ - [Gateway test recipes](./testing-recipes.mdx)
147
+ - [Testing GitHub deployments](./github-deployment-testing.mdx)
148
+ - [Environments](./environments.mdx)