@postman/postman-plugin 0.5.0 → 0.6.0-rc.0
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.
- package/README.md +2 -2
- package/dist/hosts/factory.js +29 -3
- package/hooks/session-start-context.md +1 -1
- package/mcp.pi.json +2 -2
- package/package.json +1 -1
- package/skills/api-discovery/SKILL.md +7 -2
- package/skills/api-documentation/SKILL.md +2 -3
- package/skills/api-engineer/SKILL.md +13 -15
- package/skills/api-mocking/SKILL.md +4 -2
- package/skills/api-monitoring/SKILL.md +35 -25
- package/skills/api-simulation/SKILL.md +109 -74
- package/skills/api-simulation/reference/context_file.md +183 -149
- package/skills/api-simulation/reference/sim_yaml_schema.md +1 -1
- package/skills/api-testing/SKILL.md +3 -3
- package/skills/application-testing/SKILL.md +2 -2
- package/skills/ci-integration/SKILL.md +7 -5
- package/skills/cli-install/SKILL.md +29 -0
- package/skills/collection-schema-v3/SKILL.md +21 -11
- package/skills/collection-schema-v3/reference/environment.md +2 -0
- package/skills/collection-schema-v3/reference/globals.md +40 -0
- package/skills/collection-schema-v3/reference/http.md +149 -11
- package/skills/collection-schema-v3/reference/other_protocols.md +232 -86
- package/skills/datasets/SKILL.md +6 -5
- package/skills/datasets/reference/schema.md +51 -0
- package/skills/flows/SKILL.md +0 -1
- package/skills/performance-testing/SKILL.md +14 -1
- package/skills/performance-testing/references/gatling-import/README.md +141 -0
- package/skills/performance-testing/references/gatling-import/feeders.md +31 -0
- package/skills/performance-testing/references/gatling-import/injection.md +88 -0
- package/skills/performance-testing/references/gatling-import/mapping.md +91 -0
- package/skills/performance-testing/references/gatling-import/unsupported.md +31 -0
- package/skills/postman-mcp-server/SKILL.md +1 -1
- package/skills/variables/SKILL.md +2 -2
- package/skills/webhook-testing/SKILL.md +1 -1
- package/skills/workspaces/SKILL.md +53 -0
- package/skills/bootstrap/SKILL.md +0 -140
- package/skills/bootstrap/reference/cli_installation.md +0 -59
package/README.md
CHANGED
|
@@ -235,8 +235,8 @@ exercise failure paths.
|
|
|
235
235
|
`postman init` is idempotent and safe to run in any project. Run it before API
|
|
236
236
|
engineering work to create the relevant local directories and make Postman
|
|
237
237
|
skills available to guide the task, even if the project is already initialized.
|
|
238
|
-
See [
|
|
239
|
-
options and
|
|
238
|
+
See [workspaces](https://github.com/postmanlabs/postman-plugin/blob/main/skills/workspaces/SKILL.md) for init's
|
|
239
|
+
workspace options and binding.
|
|
240
240
|
|
|
241
241
|
Work done in a Postman folder produces artifacts: collection runs, lint
|
|
242
242
|
results, request history, mock deployments. When that folder is connected to a
|
package/dist/hosts/factory.js
CHANGED
|
@@ -2,17 +2,43 @@ import { GIT_URL, REPO, isSameRepo, redact } from '../source.js';
|
|
|
2
2
|
import { blocked, guard, mustProbeText, mustRun } from './shared.js';
|
|
3
3
|
import { result } from './types.js';
|
|
4
4
|
const MARKETPLACE = 'postman-plugin', PLUGIN_ID = `postman@${MARKETPLACE}`, SCOPE = 'user', NEXT = 'Restart Droid for the change to take effect.';
|
|
5
|
+
function rowsOfWrappedTable(text) {
|
|
6
|
+
const lines = text.split(/\r?\n/), headerAt = lines.findIndex((line) => /^[A-Z]+(?: [A-Z]+)*(?: {2,}[A-Z]+(?: [A-Z]+)*)+\s*$/.test(line));
|
|
7
|
+
if (headerAt === -1) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const columns = [...lines[headerAt].matchAll(/[A-Z]+(?: [A-Z]+)*/g)].map((match) => ({ name: match[0], start: match.index })), rows = [];
|
|
11
|
+
for (const line of lines.slice(headerAt + 1)) {
|
|
12
|
+
const cells = columns.map(({ start }, i) => line.slice(start, columns[i + 1]?.start).trim()), previous = rows.at(-1), continuesPrevious = !cells[0];
|
|
13
|
+
if (!continuesPrevious) {
|
|
14
|
+
rows.push(Object.fromEntries(columns.map(({ name }, i) => [name, cells[i]])));
|
|
15
|
+
}
|
|
16
|
+
else if (previous) {
|
|
17
|
+
columns.forEach(({ name }, i) => { previous[name] += cells[i]; });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return rows;
|
|
21
|
+
}
|
|
22
|
+
export function installedPlugins(droidPluginList) {
|
|
23
|
+
const bracketedScopes = droidPluginList.split(/\r?\n/)
|
|
24
|
+
.map((line) => /^\s*(\S+@\S+)\s+\[(\w+)\]/.exec(line))
|
|
25
|
+
.filter((match) => match !== null)
|
|
26
|
+
.map(([, plugin, scope]) => `${plugin} [${scope}]`);
|
|
27
|
+
return bracketedScopes.length ?
|
|
28
|
+
bracketedScopes :
|
|
29
|
+
rowsOfWrappedTable(droidPluginList).map((row) => `${row.PLUGIN} [${row.SOURCE}]`);
|
|
30
|
+
}
|
|
5
31
|
function hasInstalledPlugin(text) {
|
|
6
|
-
return text
|
|
32
|
+
return installedPlugins(text).includes(`${PLUGIN_ID} [${SCOPE}]`);
|
|
7
33
|
}
|
|
8
34
|
function marketplaceSource(text) {
|
|
9
|
-
for (const line of text.split(
|
|
35
|
+
for (const line of text.split(/\r?\n/)) {
|
|
10
36
|
const match = /^\s*(\S+)\s+\(\d+ plugins?\)\s+(.+?)(?:\s+"[^"]*")?\s*$/.exec(line);
|
|
11
37
|
if (match && match[1] === MARKETPLACE) {
|
|
12
38
|
return match[2];
|
|
13
39
|
}
|
|
14
40
|
}
|
|
15
|
-
return null;
|
|
41
|
+
return rowsOfWrappedTable(text).find((row) => row.MARKETPLACE === MARKETPLACE)?.SOURCE ?? null;
|
|
16
42
|
}
|
|
17
43
|
function sourceWithoutFactoryPrefix(source) {
|
|
18
44
|
return source.replace(/^(?:github|url):/, '');
|
|
@@ -3,7 +3,7 @@ You have the Postman plugin.
|
|
|
3
3
|
|
|
4
4
|
Before responding to any non-trivial API engineering task — designing, implementing, mocking, testing, monitoring, documenting, or deploying an API or Postman Flow — load the `postman:api-engineer` skill and follow it. It is the default entry point and routes to the specific postman skills from there. Pure questions and trivial one-line edits don't need it.
|
|
5
5
|
|
|
6
|
-
When the intent is already specific, you may enter directly into the relevant skill instead: `postman:
|
|
6
|
+
When the intent is already specific, you may enter directly into the relevant skill instead: `postman:api-mocking`, `postman:api-testing`, `postman:api-monitoring`, `postman:flows`, `postman:ci-integration`, `postman:api-discovery`, `postman:ai-readiness`, `postman:performance-testing`, `postman:api-documentation`, `postman:variables` (where a value or secret belongs and how to reference it).
|
|
7
7
|
|
|
8
8
|
If you were dispatched as a subagent to execute a specific task, ignore this block — `postman:api-engineer` governs the orchestrating session, and it already shaped your dispatch.
|
|
9
9
|
|
package/mcp.pi.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"description": "Postman workspaces, collections, specs, environments, mocks and monitors",
|
|
7
7
|
"headers": {
|
|
8
8
|
"X-Source": "postman-pi-plugin",
|
|
9
|
-
"X-Plugin-Version": "0.
|
|
10
|
-
"User-Agent": "postman-pi-plugin/0.
|
|
9
|
+
"X-Plugin-Version": "0.6.0-rc.0",
|
|
10
|
+
"User-Agent": "postman-pi-plugin/0.6.0-rc.0"
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postman/postman-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-rc.0",
|
|
4
4
|
"description": "Postman's API engineering skills for coding agents: a Pi package, and an npx installer that sets up Claude Code, Codex, Cursor, Kimi Code, Factory Droid, OpenCode and Pi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -10,6 +10,11 @@ must invent. Relationship context broadens investigation beyond the checkout:
|
|
|
10
10
|
passing this service's own tests does not establish that its consumers can
|
|
11
11
|
still use a changed interface.
|
|
12
12
|
|
|
13
|
+
Postman search, the Context Graph and dependency downloads work only for a
|
|
14
|
+
signed-in CLI. Check `postman status` before the first of them and sign in if
|
|
15
|
+
it reports signed out. If signing in isn't possible, don't run them; say which
|
|
16
|
+
sources were skipped.
|
|
17
|
+
|
|
13
18
|
1. Choose the source by the question:
|
|
14
19
|
|
|
15
20
|
| Need | Use |
|
|
@@ -47,8 +52,8 @@ still use a changed interface.
|
|
|
47
52
|
not be present yet. The query uses the authenticated API key's team, not
|
|
48
53
|
the repository's workspace binding; changing that binding cannot fix a
|
|
49
54
|
query against the wrong organization's context.
|
|
50
|
-
5.
|
|
51
|
-
|
|
55
|
+
5. Before importing, tell this repository's owning workspace from a
|
|
56
|
+
dependency. For a dependency, `postman dependency add
|
|
52
57
|
<collection|environment|mock> <name-or-id>` declares and downloads the
|
|
53
58
|
selected resource without rebinding the repository. Prefer the discovered
|
|
54
59
|
ID; `--workspace <id>` disambiguates names. If the graph only identified a
|
|
@@ -14,8 +14,7 @@ with changes reviewable alongside code.
|
|
|
14
14
|
interface for tooling; a Postman collection adds runnable requests,
|
|
15
15
|
examples, and assertions. Maintain both when both uses matter, with an
|
|
16
16
|
explicit direction of generation or synchronization so they do not become
|
|
17
|
-
competing definitions.
|
|
18
|
-
bindings are unresolved.
|
|
17
|
+
competing definitions.
|
|
19
18
|
2. When the spec is authoritative, reuse its operations with
|
|
20
19
|
`postman spec generate collection <spec-path-or-id> -n "<collection-name>"`.
|
|
21
20
|
Inspect the generated result before replacing an existing collection:
|
|
@@ -34,7 +33,7 @@ with changes reviewable alongside code.
|
|
|
34
33
|
to keep credentials out of reusable requests and examples.
|
|
35
34
|
5. Choose delivery by audience. Local artifacts support Git review;
|
|
36
35
|
publishing to the bound workspace makes them available to teammates with
|
|
37
|
-
access
|
|
36
|
+
access. A workspace push does not itself publish a
|
|
38
37
|
public docs page or change permissions. For a public documentation link,
|
|
39
38
|
use **postman-mcp-server**'s documentation workflow and the available
|
|
40
39
|
publishing tool; establish the intended audience before public exposure.
|
|
@@ -16,10 +16,9 @@ guesswork each time work resumes.
|
|
|
16
16
|
regression. Reuse the existing contract; update it where behavior changes.
|
|
17
17
|
Flag design choices that make callers harder to implement or future changes
|
|
18
18
|
harder to adopt, and explain the tradeoff. See **api-documentation**.
|
|
19
|
-
2.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
both purposes matter. See **api-documentation**.
|
|
19
|
+
2. A Postman collection records the contract in a form that runs. The CLI's
|
|
20
|
+
deterministic tools cheaply turn that one source into an OpenAPI spec, a
|
|
21
|
+
mock, an SDK, or a performance suite, so the contract is written once.
|
|
23
22
|
3. Match verification to the behavior at risk. A saved collection can reuse auth,
|
|
24
23
|
variables, payloads, and assertions without reconstructing requests; a one-off
|
|
25
24
|
endpoint check can be smaller. Check the changed behavior and relevant existing
|
|
@@ -40,10 +39,8 @@ guesswork each time work resumes.
|
|
|
40
39
|
your API, publish a mock of it in your service's own workspace, where their
|
|
41
40
|
simulations look first; see **api-mocking**.
|
|
42
41
|
6. Keep specs, collections, environments, and mocks in local files so changes can
|
|
43
|
-
be diffed, reviewed, and reused in Git and CI.
|
|
44
|
-
|
|
45
|
-
current service's existing workspace, or initialize a new project when neither
|
|
46
|
-
exists.
|
|
42
|
+
be diffed, reviewed, and reused in Git and CI. `postman status` shows
|
|
43
|
+
what setup is in place, what is missing, and what closes each gap.
|
|
47
44
|
7. `postman init` gives API engineering work a ready state. It scaffolds local structure: `postman/`
|
|
48
45
|
directories for API artifacts. It installs skills in `postman/skills` folder with guidance on designing, implementing, and validating APIs.
|
|
49
46
|
The command is idempotent and safe to rerun in an initialized project.
|
|
@@ -73,16 +70,17 @@ gap, such as an untested behavior or a consumer affected by an interface change.
|
|
|
73
70
|
Decline unnecessary setup or scope and explain why it would not help the task.
|
|
74
71
|
|
|
75
72
|
Important: If a CLI command says an operation isn't allowed because credits
|
|
76
|
-
or usage are exhausted, or the current plan does not permit it,
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
or usage are exhausted, or the current plan does not permit it, stop
|
|
74
|
+
retrying and tell the user that signing up or upgrading their plan is what
|
|
75
|
+
lifts it.
|
|
79
76
|
|
|
80
77
|
## Verification
|
|
81
78
|
|
|
82
79
|
Report the changed contract or implementation, the checks actually run, and
|
|
83
80
|
the guarantees their results support. Separate local, mocked, and live evidence;
|
|
84
|
-
state any relevant consumer or upstream interaction still unverified.
|
|
81
|
+
state any relevant consumer or upstream interaction still unverified. Run
|
|
82
|
+
`postman status` last to confirm the setup the work relied on is still in place.
|
|
85
83
|
|
|
86
|
-
If actual use exposes a CLI gap or misleading skill,
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
If actual use exposes a CLI gap or misleading skill, report it through the
|
|
85
|
+
CLI's feedback channel after finishing the user's task, with a sanitized
|
|
86
|
+
reproduction and no secrets, user data, or proprietary content.
|
|
@@ -21,8 +21,10 @@ Several APIs at once, for a service, a frontend or a test suite? Use
|
|
|
21
21
|
|
|
22
22
|
When the API belongs to another team, look for their published mock before
|
|
23
23
|
writing one: theirs encodes their contract and their service's state; yours
|
|
24
|
-
encodes a guess.
|
|
25
|
-
|
|
24
|
+
encodes a guess.
|
|
25
|
+
|
|
26
|
+
Every step below needs a signed-in CLI. Check `postman status` first; signed
|
|
27
|
+
out, skip to building one and say the owner search was skipped.
|
|
26
28
|
|
|
27
29
|
1. Find the owner's workspace with `postman search workspaces "<service>" -o json`.
|
|
28
30
|
Name the service plainly, as your code does, not by what it returns: a
|
|
@@ -19,43 +19,53 @@ exercise the guarantees users depend on.
|
|
|
19
19
|
the linked workspace unless one is supplied. Inspect command-specific
|
|
20
20
|
`-h` and available service options for supported schedules and limits.
|
|
21
21
|
Creation starts an immediate run by default; `--no-run-now` avoids that
|
|
22
|
-
when only scheduling was requested.
|
|
23
|
-
|
|
22
|
+
when only scheduling was requested. Pass `--timezone` with the zone the
|
|
23
|
+
user means (for example `America/New_York`); without it the schedule uses
|
|
24
|
+
the zone of the machine running the CLI. Leave the month field as `*`; to
|
|
25
|
+
limit a schedule to certain months, write them as three-letter names such
|
|
26
|
+
as `jan`, not numbers.
|
|
24
27
|
3. Choose a Postman region for a reachable public API. Use a self-hosted
|
|
25
28
|
runner when the target is reachable only inside the user's network;
|
|
26
29
|
running one adds infrastructure to maintain. `postman runner regions`
|
|
27
|
-
provides valid hosted locations and `runner list`
|
|
28
|
-
private
|
|
30
|
+
provides valid hosted locations and `runner list --json` the full IDs of
|
|
31
|
+
registered private runners. `monitor create/update --runner` accepts either;
|
|
29
32
|
multiple locations help distinguish API failures from regional reachability.
|
|
30
|
-
4.
|
|
31
|
-
`monitor update` cannot change
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
4. Update a monitor in place to keep its run history.
|
|
34
|
+
`monitor update` cannot change the collection, and cannot pause or resume
|
|
35
|
+
the monitor: use `monitor pause`/`monitor resume` for that. `update -e`
|
|
36
|
+
swaps the environment and `--clear-environment` removes it. A different
|
|
37
|
+
collection requires a replacement, so plan the handoff before deleting the
|
|
38
|
+
old monitor and its continuity. Permanent deletion needs explicit intent.
|
|
35
39
|
5. Use `postman monitor run <id>` for an immediate verdict, such as after a
|
|
36
40
|
deploy. `--async` returns a job handle when the caller need not wait.
|
|
37
|
-
The CLI timeout caps waiting, not execution
|
|
38
|
-
|
|
39
|
-
6.
|
|
40
|
-
finds jobs, `monitor jobs get <job-id>` shows terminal state
|
|
41
|
-
outcomes, and `monitor runs get <run-id>` shows assertions
|
|
42
|
-
attempt. A failing region, a connection error, and a failed
|
|
43
|
-
imply different fixes.
|
|
41
|
+
The CLI timeout caps waiting, not execution: after a timeout, read the job
|
|
42
|
+
with `monitor jobs get <job-id>`; its state is the verdict.
|
|
43
|
+
6. Answer each failure question at its level. `monitor jobs list
|
|
44
|
+
<monitor-id>` finds jobs, `monitor jobs get <job-id>` shows terminal state
|
|
45
|
+
and regional outcomes, and `monitor runs get <run-id>` shows assertions
|
|
46
|
+
within an attempt. A failing region, a connection error, and a failed
|
|
47
|
+
assertion imply different fixes. For a trend across runs, such as which
|
|
48
|
+
request got slow, use `monitor metrics <monitor-id>`. In a CI gate, run
|
|
49
|
+
`monitor run` without `-x`, so a failed run fails the build.
|
|
44
50
|
|
|
45
|
-
For discovery, `monitor list` supports workspace and collection filters;
|
|
46
|
-
|
|
51
|
+
For discovery, `monitor list` supports workspace and collection filters; to
|
|
52
|
+
page it, pass `--cursor` with the value from the previous page. Its runner filter
|
|
47
53
|
is for a self-hosted ID and cannot be combined with other filters; a page-local
|
|
48
54
|
name filter does not establish absence across all pages.
|
|
49
55
|
|
|
50
|
-
For a private runner, use `runner start` with the
|
|
51
|
-
verify
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
For a private runner, use `runner start` with the ID and key from the runner
|
|
57
|
+
created in Postman, and verify it is reporting in before assigning runs: a
|
|
58
|
+
recent `Last ping` in `runner list` (`lastPingAt` under `--json`; `never`
|
|
59
|
+
means it has not connected). Inspect its help for proxy, private CA,
|
|
60
|
+
residency, and health-metric options only when the network requires them.
|
|
61
|
+
Runner activity is reported by default; `--no-report-events` disables that
|
|
62
|
+
reporting when the task requires it. Pass the runner key at runtime, from the
|
|
63
|
+
user or a secret store (for example `--key "$RUNNER_KEY"`), and keep it out of
|
|
64
|
+
files in the repository. If a `monitor` or `runner list` command fails on
|
|
65
|
+
authentication, sign in.
|
|
56
66
|
|
|
57
67
|
## Verification
|
|
58
68
|
|
|
59
69
|
Report the actual monitor configuration or terminal job/run outcome, including
|
|
60
70
|
where it executed and which checks failed. A created monitor, accepted job,
|
|
61
|
-
or
|
|
71
|
+
or a runner reporting in alone does not prove the API passed its health checks.
|
|
@@ -1,27 +1,50 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: api-simulation
|
|
3
|
-
description: Runs
|
|
3
|
+
description: Runs services, frontends, tests or demos against stand-ins for their HTTP dependencies, served as one environment locally or at a deployed URL. Use when you add or change code that calls other services and need to run it, test it, prove a fix or reproduce an upstream failure (timeouts, 5xx, 409, 429) end to end, locally or in CI, without the real services because they're unreachable, need credentials, cost money, have side effects or don't exist yet. Also answers what happens to a request, or to the data it writes, when a service it calls goes down, is slow or returns errors ("what happens to a booking if the email service is down?"), by exercising relevant failures and observing caller outcomes. Applies even when nobody says mock or simulation, and a `postman/simulations/` directory in the repository is itself a reason to load this before changing code it covers. To give a frontend or another team a stand-in for an API, use api-mocking. Covers `postman simulation`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# API Simulation
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
Simulation lets you control how dependencies behave and explore how your code
|
|
9
|
+
responds to different outcomes. This makes it easier to test assumptions
|
|
10
|
+
repeatedly without real calls changing data, spending money, or notifying
|
|
11
|
+
someone. Simulation context records those assumptions, the evidence supporting
|
|
12
|
+
them, and what remains unknown. As sessions build on this context, it helps
|
|
13
|
+
surface incorrect assumptions and avoid repeated investigation.
|
|
14
|
+
|
|
15
|
+
Together, the simulation and its context provide a place to explore changes
|
|
16
|
+
and identify what still needs validation against the real dependencies.
|
|
17
|
+
|
|
18
|
+
Check whether an existing simulation in `postman/simulations/` covers the
|
|
19
|
+
dependency interactions relevant to the task. Reusing its mocks and wiring
|
|
20
|
+
can avoid rebuilding an environment; extend it only where the behavior you
|
|
21
|
+
need to exercise is missing.
|
|
22
|
+
|
|
23
|
+
The `<name>.context.yaml` beside a simulation records those assumptions, their
|
|
24
|
+
supporting evidence, and unresolved questions so later sessions can build on
|
|
25
|
+
earlier findings. For example, a timeout from `/payments` does not establish
|
|
26
|
+
whether the payment failed or completed before the response arrived. The
|
|
27
|
+
context file will document what has been established about the real provider
|
|
28
|
+
and identify what still needs verification.
|
|
29
|
+
|
|
30
|
+
A simulation serves several mocks as one environment: by default behind a
|
|
31
|
+
proxy that answers for the dependencies' own hostnames, so the code under test
|
|
32
|
+
keeps the base URLs it ships with, or on one local port where each member is
|
|
33
|
+
reached by its routeKey.
|
|
34
|
+
|
|
35
|
+
Simulation adds value when the result depends on real HTTP behavior, such as
|
|
36
|
+
client configuration, serialization, timeouts or retries, and the real
|
|
37
|
+
dependencies are unavailable or unsuitable for the exercise. Stubbing the
|
|
38
|
+
HTTP client can bypass those behaviors. Choose verification that exercises
|
|
39
|
+
what matters to the task: an existing test may already answer a local logic
|
|
40
|
+
question, while a claim about the provider may need its contract or a real
|
|
41
|
+
service check. A simulation's log shows what each stand-in was asked.
|
|
42
|
+
|
|
43
|
+
Define the expected outcome and what observation would distinguish correct
|
|
44
|
+
from incorrect behavior, including side effects when relevant. A request
|
|
45
|
+
through the changed path shows that it ran; its response and resulting state
|
|
46
|
+
determine whether the expectation held. Choose boundary and failure cases
|
|
47
|
+
from the behavior changed and the consequences of getting it wrong.
|
|
25
48
|
|
|
26
49
|
`postman simulation` needs CLI 1.70.0 or later (`postman --version`; an older
|
|
27
50
|
CLI answers `postman simulation -h` with its general help).
|
|
@@ -33,7 +56,9 @@ CLI answers `postman simulation -h` with its general help).
|
|
|
33
56
|
shared code; ask about the repo by its `git remote` name, because a close
|
|
34
57
|
name matches another repo.
|
|
35
58
|
- **Each member needs a mock: see `api-mocking`,** which looks for the owning
|
|
36
|
-
team's published mock before building one.
|
|
59
|
+
team's published mock before building one. Finding and pulling an owner's
|
|
60
|
+
mock needs a signed-in CLI; check `postman status` first, and signed out,
|
|
61
|
+
build each mock and record that the owner search was skipped. For a question, one built from
|
|
37
62
|
the contract will do; one that invents responses can send the caller down a
|
|
38
63
|
path the real service never would. In a mock you build, answer `501` for calls this path
|
|
39
64
|
doesn't make: a `404` reads to the caller like a real "not found".
|
|
@@ -52,45 +77,37 @@ The run is a server that never exits, so a foreground command never returns.
|
|
|
52
77
|
Start it in the background, its log in a file:
|
|
53
78
|
|
|
54
79
|
```bash
|
|
55
|
-
postman simulation run postman/simulations/checkout-dev.sim.yaml --
|
|
80
|
+
postman simulation run postman/simulations/checkout-dev.sim.yaml --proxy --output ndjson > sim.ndjson 2> sim.err &
|
|
56
81
|
```
|
|
57
82
|
|
|
58
|
-
`--
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
83
|
+
`--proxy` is how to run it unless something below rules it out: nothing about
|
|
84
|
+
the code changes for the run — not a base URL, not a config file, not an SDK's
|
|
85
|
+
built-in host — and because nothing the proxy answers for has to resolve, an
|
|
86
|
+
internal hostname with no DNS record works.
|
|
87
|
+
|
|
88
|
+
It's up when `sim.ndjson` has a `listening` event; a start-up error is in
|
|
89
|
+
`sim.err`, a busy proxy port among them. Stop it with
|
|
62
90
|
`pkill -INT -f "simulation run .*<file>.sim.yaml"`. Nothing reloads: restart
|
|
63
91
|
it after a mock edit.
|
|
64
92
|
|
|
65
|
-
Point the caller at it without changing what the code does once deployed.
|
|
66
|
-
Under path routing, swap only the host and keep the path:
|
|
67
|
-
`https://catalog.internal.example.com/v2` becomes
|
|
68
|
-
`http://127.0.0.1:4900/catalog/v2`; a dropped `/v2` is the usual cause of a
|
|
69
|
-
`404`. A hard-coded base URL should read an environment variable with
|
|
70
|
-
today's value as the default. If the code mustn't change at all, run it
|
|
71
|
-
behind the proxy instead, below.
|
|
72
|
-
|
|
73
|
-
## Through a proxy, when no base URL can change
|
|
74
|
-
|
|
75
|
-
`simulation run <file.sim.yaml> --proxy` puts the members behind a local
|
|
76
|
-
forward proxy that answers for the dependencies' own hostnames, so the code
|
|
77
|
-
keeps the base URLs it ships with. Any other host passes through to the real
|
|
78
|
-
service. Reach for it when hostnames are hard-coded, built from config the
|
|
79
|
-
change shouldn't touch, or owned by an SDK — and because nothing it answers
|
|
80
|
-
for has to resolve, an internal hostname with no DNS record works.
|
|
81
|
-
|
|
82
93
|
Read `postman simulation run --help` before driving it. The flags, what the
|
|
83
94
|
caller's own process needs in order to reach the proxy, and what to do about a
|
|
84
95
|
client that ignores it are all there and change with the CLI, so take them
|
|
85
96
|
from the command rather than from here.
|
|
86
97
|
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
What decides whether a proxied run proves anything is `origin:`. A member with
|
|
99
|
+
none in the `.sim.yaml` is never matched, so its traffic reaches the real
|
|
89
100
|
service and a run can come up having intercepted nothing — `simulation create`
|
|
90
101
|
copies that field from the mock's manifest, so editing the manifest alone
|
|
91
102
|
won't fix it ([reference/sim_yaml_schema.md](reference/sim_yaml_schema.md)).
|
|
92
|
-
|
|
93
|
-
|
|
103
|
+
|
|
104
|
+
## Running it on one port instead
|
|
105
|
+
|
|
106
|
+
`--port` puts every member on one local port, each addressable by its routeKey,
|
|
107
|
+
with the code under test pointed at that port. Reach for it when a client has
|
|
108
|
+
no proxy setting to honour, and when you want to address a member yourself —
|
|
109
|
+
each one keeps a stable URL for the whole run, so a mock's control routes and
|
|
110
|
+
its individual responses are a curl away.
|
|
94
111
|
|
|
95
112
|
## Reading the log
|
|
96
113
|
|
|
@@ -98,8 +115,8 @@ A passing test command doesn't show the dependency path ran: read
|
|
|
98
115
|
`sim.ndjson`. A member with no `request` events isn't wired or isn't on this
|
|
99
116
|
path. Some answers come from the simulation itself and mean wiring, not code:
|
|
100
117
|
|
|
101
|
-
- `404 Unknown simulation member
|
|
102
|
-
sent the wrong `x-mock-slug`.
|
|
118
|
+
- `404 Unknown simulation member`, on a one-port run: a base URL lost its
|
|
119
|
+
routeKey, or a client sent the wrong `x-mock-slug`.
|
|
103
120
|
- `501`, or a generated mock's `404 Endpoint not defined`: a call the mock
|
|
104
121
|
doesn't model yet.
|
|
105
122
|
- `502 Proxy error`: the member's process died, usually an async throw in a
|
|
@@ -108,12 +125,20 @@ path. Some answers come from the simulation itself and mean wiring, not code:
|
|
|
108
125
|
|
|
109
126
|
## When a dependency goes down
|
|
110
127
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
128
|
+
Choose failures from the outcome the user needs to understand. A failure
|
|
129
|
+
before a write, a timeout after a write may have completed, and a failure
|
|
130
|
+
during compensation can expose different risks: lost work, duplicate writes
|
|
131
|
+
or unreleased resources. Read the caller to identify relevant paths, then
|
|
132
|
+
exercise the ones whose runtime behavior remains uncertain.
|
|
115
133
|
|
|
116
|
-
|
|
134
|
+
Isolating one failure helps attribute the result. Combine failures or model
|
|
135
|
+
partial completion when the question depends on their interaction. The
|
|
136
|
+
injection must represent the event being investigated: delaying a response
|
|
137
|
+
alone does not establish whether a write completed before the timeout.
|
|
138
|
+
Examples of available techniques:
|
|
139
|
+
|
|
140
|
+
- **Unreachable:** point its base URL at a port nothing listens on. This one
|
|
141
|
+
needs the one-port run, since under `--proxy` the base URLs are the point.
|
|
117
142
|
- **Hanging:** give its member a `latency` condition longer than the
|
|
118
143
|
client's timeout. If the client sets none, that is the finding: Node's
|
|
119
144
|
`fetch` waits about five minutes, so say so rather than wait it out.
|
|
@@ -131,19 +156,24 @@ stock reserved and never released.
|
|
|
131
156
|
|
|
132
157
|
## Its context document
|
|
133
158
|
|
|
134
|
-
Every simulation is created with a `<name>.context.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this is the
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
Every simulation is created with a `<name>.context.yaml` beside it, holding
|
|
160
|
+
what the code is believed to rely on about the dependencies it calls — who the
|
|
161
|
+
caller is taken to be, which plan or permission is assumed, the order calls go
|
|
162
|
+
in, what gets retried, the shape of the data — and what each belief rests on.
|
|
163
|
+
The `.sim.yaml` says what the simulation is, not what the services it stands in
|
|
164
|
+
for do, so this is the record that saves a session the search.
|
|
165
|
+
|
|
166
|
+
Read relevant claims before investigating the dependencies, and assess whether
|
|
167
|
+
their evidence still applies to this task. Write what you established back
|
|
168
|
+
into the document before you finish. Each claim carries a `status`,
|
|
169
|
+
the `reason` the evidence adds up to it, the `verification` that was done and
|
|
170
|
+
what it showed, and a `source` to re-check it against, so the next session can
|
|
171
|
+
tell a claim a contract promises from one a request actually demonstrated.
|
|
172
|
+
Preserve existing claims and their evidence when updating the file, including
|
|
173
|
+
unresolved assumptions and historical findings. Its fixed schema and guidance
|
|
174
|
+
on evidence and reuse are in
|
|
175
|
+
[reference/context_file.md](reference/context_file.md); read that before
|
|
176
|
+
writing to it.
|
|
147
177
|
|
|
148
178
|
## Keeping it
|
|
149
179
|
|
|
@@ -173,16 +203,21 @@ first. It fails on a pulled member, which keeps its owner's `id:`; copy it to
|
|
|
173
203
|
|
|
174
204
|
## Before you say it works
|
|
175
205
|
|
|
176
|
-
Claim
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
206
|
+
Claim a simulation passes only after the code under test ran and you observed
|
|
207
|
+
the expected response or state change. Use its calls in the log to confirm
|
|
208
|
+
the dependency path was exercised; for injected failures, use the caller
|
|
209
|
+
outcomes described above. If startup failed or the relevant path never ran,
|
|
210
|
+
report that limitation. Say what a pass proves,
|
|
180
211
|
your code against these stand-ins rather than the real services, what still
|
|
181
212
|
needs the real service before release, and where each mock came from,
|
|
182
213
|
including when you skipped the owner's.
|
|
183
214
|
|
|
184
|
-
Then write
|
|
185
|
-
where this one ended
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
215
|
+
Then write what you established back into `<name>.context.yaml`, so the next
|
|
216
|
+
session starts where this one ended. Add or update claims that help a later
|
|
217
|
+
session reuse the findings. For each claim the run settled or contradicted,
|
|
218
|
+
update its `status`, the `verification` that was done and the `source` to
|
|
219
|
+
re-check it against. Scope what you claim to what you actually
|
|
220
|
+
exercised — "held in the scenarios run" rather than "works" — since the record
|
|
221
|
+
is read later as evidence, and the two don't mean the same thing.
|
|
222
|
+
[reference/context_file.md](reference/context_file.md) has what each field is
|
|
223
|
+
for.
|