@postman/postman-plugin 0.4.0 → 0.4.1-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 +14 -1
- package/dist/hosts/codex-hooks.js +68 -0
- package/dist/hosts/codex.js +87 -8
- package/dist/json-rpc.js +113 -0
- package/dist/system.js +40 -3
- package/mcp.pi.json +2 -2
- package/package.json +1 -1
- package/skills/performance-testing/SKILL.md +6 -6
- package/skills/performance-testing/references/jmeter-import/README.md +35 -66
- package/skills/performance-testing/references/jmeter-import/import-report.md +2 -2
- package/skills/performance-testing/references/jmeter-import/mapping-table.md +73 -75
- package/skills/performance-testing/references/jmeter-import/postman-perf-capabilities.md +3 -3
- package/skills/performance-testing/references/jmeter-import/script-translation.md +8 -9
- package/skills/performance-testing/references/jmeter-import/scripts/groovy_to_js.py +0 -83
- package/skills/performance-testing/references/jmeter-import/scripts/jmx_to_postman.py +0 -1433
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Import Report — <TEST PLAN NAME>
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> Fill in every section from the import. Once the manual tasks are resolved, update the
|
|
4
|
+
> "Needs manual work" list and the summary counts to match the collection you hand off.
|
|
5
5
|
|
|
6
6
|
## Summary
|
|
7
7
|
|
|
@@ -1,97 +1,95 @@
|
|
|
1
1
|
# JMeter → Postman mapping table
|
|
2
2
|
|
|
3
|
-
Fidelity: **exact** (behaviour preserved) · **approx** (closest supported equivalent, reported) · **manual** (needs the
|
|
4
|
-
Owner: **script** (deterministic Python) · **model** (judgment call).
|
|
3
|
+
Fidelity: **exact** (behaviour preserved) · **approx** (closest supported equivalent, reported) · **manual** (needs a judgment call, often with the user) · **unsupported** (dropped, reported).
|
|
5
4
|
|
|
6
5
|
## Structure
|
|
7
6
|
|
|
8
|
-
| JMeter element | XML tag | Postman | Fidelity |
|
|
9
|
-
|
|
10
|
-
| Test Plan | `TestPlan` | Collection (`info` + `item`) | exact |
|
|
11
|
-
| Thread Group | `ThreadGroup` | load config (VUs/duration/profile) + folder when >1 | approx |
|
|
12
|
-
| setUp/tearDown Thread Group | `SetupThreadGroup`/`PostThreadGroup` | folder; suggest `--setup-collection`/`--teardown-collection` | approx |
|
|
13
|
-
| Concurrency Thread Group | `...ConcurrencyThreadGroup` | VUs=`TargetLevel`, duration=`RampUp`+`Hold`, `ramp-up` | approx |
|
|
14
|
-
| Stepping Thread Group | `kg.apc...SteppingThreadGroup` | VUs=`num_threads`, duration=`flighttime`, `ramp-up` | approx |
|
|
15
|
-
| Ultimate Thread Group | `kg.apc...UltimateThreadGroup` | VUs=max row concurrency, duration=sum of row times | approx |
|
|
16
|
-
| Arrivals Thread Group | `...ArrivalsThreadGroup` | treated like concurrency | approx |
|
|
17
|
-
| Transaction Controller | `TransactionController` | folder | exact |
|
|
18
|
-
| Simple/Generic Controller | `GenericController`/`SimpleController` | folder | exact |
|
|
19
|
-
| Loop Controller | `LoopController` | flattened; loop count → duration | approx |
|
|
20
|
-
| If Controller | `IfController` | each enclosed request gets a pre-request skip guard (`pm.execution.skipRequest`); `${var}` → `pm.variables.get(...)` | approx |
|
|
21
|
-
| While Controller | `WhileController` | flattened, requests run unconditionally; restore looping with `pm.execution.setNextRequest` | approx |
|
|
22
|
-
| Recording Controller | `RecordingController` | transparent (children recursed) | exact |
|
|
23
|
-
| Module / Include Controller | `ModuleController`/`IncludeController` | flattened children if inline; external refs reported | manual |
|
|
7
|
+
| JMeter element | XML tag | Postman | Fidelity |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| Test Plan | `TestPlan` | Collection (`info` + `item`) | exact |
|
|
10
|
+
| Thread Group | `ThreadGroup` | load config (VUs/duration/profile) + folder when >1 | approx |
|
|
11
|
+
| setUp/tearDown Thread Group | `SetupThreadGroup`/`PostThreadGroup` | folder; suggest `--setup-collection`/`--teardown-collection` | approx |
|
|
12
|
+
| Concurrency Thread Group | `...ConcurrencyThreadGroup` | VUs=`TargetLevel`, duration=`RampUp`+`Hold`, `ramp-up` | approx |
|
|
13
|
+
| Stepping Thread Group | `kg.apc...SteppingThreadGroup` | VUs=`num_threads`, duration=`flighttime`, `ramp-up` | approx |
|
|
14
|
+
| Ultimate Thread Group | `kg.apc...UltimateThreadGroup` | VUs=max row concurrency, duration=sum of row times | approx |
|
|
15
|
+
| Arrivals Thread Group | `...ArrivalsThreadGroup` | treated like concurrency | approx |
|
|
16
|
+
| Transaction Controller | `TransactionController` | folder | exact |
|
|
17
|
+
| Simple/Generic Controller | `GenericController`/`SimpleController` | folder | exact |
|
|
18
|
+
| Loop Controller | `LoopController` | flattened; loop count → duration | approx |
|
|
19
|
+
| If Controller | `IfController` | each enclosed request gets a pre-request skip guard (`pm.execution.skipRequest`); `${var}` → `pm.variables.get(...)` | approx |
|
|
20
|
+
| While Controller | `WhileController` | flattened, requests run unconditionally; restore looping with `pm.execution.setNextRequest` | approx |
|
|
21
|
+
| Recording Controller | `RecordingController` | transparent (children recursed) | exact |
|
|
22
|
+
| Module / Include Controller | `ModuleController`/`IncludeController` | flattened children if inline; external refs reported | manual |
|
|
24
23
|
|
|
25
24
|
## Requests
|
|
26
25
|
|
|
27
|
-
| JMeter | XML | Postman | Fidelity |
|
|
28
|
-
|
|
29
|
-
| HTTP Request | `HTTPSamplerProxy` | request item | exact |
|
|
30
|
-
| method / path / domain / port / protocol | `HTTPSampler.*` | `request.method` + `url` (blank protocol → `http`) | exact |
|
|
31
|
-
| Query/body params | `Arguments`/`HTTPArgument` | query (GET) / urlencoded (POST/PUT/PATCH) / formdata (multipart) | exact |
|
|
32
|
-
| Raw body | `postBodyRaw=true` | `body.mode=raw` | exact |
|
|
33
|
-
| Header Manager | `HeaderManager` | `request.header` (merged by scope, later wins) | exact |
|
|
34
|
-
| HTTP Request Defaults | `ConfigTestElement`/`HttpDefaultsGui` | fallback for blank domain/port/protocol/path | exact |
|
|
35
|
-
| Auth Manager Basic/Digest | `AuthManager` | `request.auth` basic/digest (first entry; multiples reported) | exact |
|
|
36
|
-
| Auth Manager Kerberos/NTLM | `AuthManager` mechanism | — | unsupported |
|
|
37
|
-
| Cookie / Cache / DNS Manager | `CookieManager`/... | auto per-VU cookies; presets not transferred | unsupported |
|
|
38
|
-
| Non-HTTP samplers | `JDBC/FTP/LDAP/Java/TCP/Debug/Dummy...Sampler` | — | unsupported |
|
|
26
|
+
| JMeter | XML | Postman | Fidelity |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| HTTP Request | `HTTPSamplerProxy` | request item | exact |
|
|
29
|
+
| method / path / domain / port / protocol | `HTTPSampler.*` | `request.method` + `url` (blank protocol → `http`) | exact |
|
|
30
|
+
| Query/body params | `Arguments`/`HTTPArgument` | query (GET) / urlencoded (POST/PUT/PATCH) / formdata (multipart) | exact |
|
|
31
|
+
| Raw body | `postBodyRaw=true` | `body.mode=raw` | exact |
|
|
32
|
+
| Header Manager | `HeaderManager` | `request.header` (merged by scope, later wins) | exact |
|
|
33
|
+
| HTTP Request Defaults | `ConfigTestElement`/`HttpDefaultsGui` | fallback for blank domain/port/protocol/path | exact |
|
|
34
|
+
| Auth Manager Basic/Digest | `AuthManager` | `request.auth` basic/digest (first entry; multiples reported) | exact |
|
|
35
|
+
| Auth Manager Kerberos/NTLM | `AuthManager` mechanism | — | unsupported |
|
|
36
|
+
| Cookie / Cache / DNS Manager | `CookieManager`/... | auto per-VU cookies; presets not transferred | unsupported |
|
|
37
|
+
| Non-HTTP samplers | `JDBC/FTP/LDAP/Java/TCP/Debug/Dummy...Sampler` | — | unsupported |
|
|
39
38
|
|
|
40
39
|
## Extractors (post-response → test script `pm.collectionVariables.set`)
|
|
41
40
|
|
|
42
|
-
| JMeter | XML | Fidelity |
|
|
43
|
-
|
|
44
|
-
| Regular Expression Extractor | `RegexExtractor` | exact (via `new RegExp`, group from `$n$` template) |
|
|
45
|
-
| Boundary Extractor | `BoundaryExtractor` | exact (left/right → non-greedy regex) |
|
|
46
|
-
| JSON Extractor (native) | `JSONPostProcessor` | exact for dot/index paths; complex → manual |
|
|
47
|
-
| JSON Path Extractor (plugin) | `...JSONPathExtractor` | exact for simple paths |
|
|
48
|
-
| XPath / XPath2 Extractor | `XPathExtractor`/`XPath2Extractor` | manual (no sandbox XPath) |
|
|
49
|
-
| CSS/HTML Extractor | `HtmlExtractor` | manual (no sandbox CSS) |
|
|
41
|
+
| JMeter | XML | Fidelity |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| Regular Expression Extractor | `RegexExtractor` | exact (via `new RegExp`, group from `$n$` template) |
|
|
44
|
+
| Boundary Extractor | `BoundaryExtractor` | exact (left/right → non-greedy regex) |
|
|
45
|
+
| JSON Extractor (native) | `JSONPostProcessor` | exact for dot/index paths; complex → manual |
|
|
46
|
+
| JSON Path Extractor (plugin) | `...JSONPathExtractor` | exact for simple paths |
|
|
47
|
+
| XPath / XPath2 Extractor | `XPathExtractor`/`XPath2Extractor` | manual (no sandbox XPath) |
|
|
48
|
+
| CSS/HTML Extractor | `HtmlExtractor` | manual (no sandbox CSS) |
|
|
50
49
|
|
|
51
50
|
## Assertions (→ `pm.test`)
|
|
52
51
|
|
|
53
|
-
| JMeter | XML | Maps to | Fidelity |
|
|
54
|
-
|
|
55
|
-
| Response Assertion | `ResponseAssertion` | status / contains / equals / matches, honouring `test_type` bitmask + NOT | exact |
|
|
56
|
-
| — test_field response_code | | `pm.response.code` | exact |
|
|
57
|
-
| — test_field response_data | | `pm.response.text()` | exact |
|
|
58
|
-
| — test_field headers/message | | `pm.response.headers`/`.status` | exact |
|
|
59
|
-
| Duration Assertion | `DurationAssertion` | `pm.test` responseTime + `--pass-if less_than(p95, ms)` hint | exact |
|
|
60
|
-
| Size Assertion | `SizeAssertion` | `pm.test` on `responseSize` | approx |
|
|
61
|
-
| JSON Assertion | `JSONPathAssertion` | `pm.test` on simple path | approx |
|
|
52
|
+
| JMeter | XML | Maps to | Fidelity |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| Response Assertion | `ResponseAssertion` | status / contains / equals / matches, honouring `test_type` bitmask + NOT | exact |
|
|
55
|
+
| — test_field response_code | | `pm.response.code` | exact |
|
|
56
|
+
| — test_field response_data | | `pm.response.text()` | exact |
|
|
57
|
+
| — test_field headers/message | | `pm.response.headers`/`.status` | exact |
|
|
58
|
+
| Duration Assertion | `DurationAssertion` | `pm.test` responseTime + `--pass-if less_than(p95, ms)` hint | exact |
|
|
59
|
+
| Size Assertion | `SizeAssertion` | `pm.test` on `responseSize` | approx |
|
|
60
|
+
| JSON Assertion | `JSONPathAssertion` | `pm.test` on simple path | approx |
|
|
62
61
|
|
|
63
62
|
`ResponseAssertion.test_type` bits: `MATCH=1, CONTAINS=2, NOT=4, EQUALS=8, SUBSTRING=16, OR=32`.
|
|
64
63
|
|
|
65
64
|
## Variables & data
|
|
66
65
|
|
|
67
|
-
| JMeter | XML | Postman | Fidelity |
|
|
68
|
-
|
|
69
|
-
| User Defined Variables | `Arguments` under TestPlan/scope | collection `variable[]` | exact |
|
|
70
|
-
| `${var}` references | inline | `{{var}}` | exact |
|
|
71
|
-
| `${__UUID}` / `${__time}` | function | `{{$guid}}` / `{{$timestamp}}` | exact |
|
|
72
|
-
| `${__Random(...)}` and other `__fn` | function | `{{$randomInt}}` or flagged reference | approx/manual |
|
|
73
|
-
| CSV Data Set Config | `CSVDataSet` | `--data-file` + column list | approx (one file/run; naive CSV) |
|
|
74
|
-
| Counter / Random Variable | `CounterConfig`/`RandomVariableConfig` | pre-request script or `{{$randomInt}}` | manual |
|
|
66
|
+
| JMeter | XML | Postman | Fidelity |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| User Defined Variables | `Arguments` under TestPlan/scope | collection `variable[]` | exact |
|
|
69
|
+
| `${var}` references | inline | `{{var}}` | exact |
|
|
70
|
+
| `${__UUID}` / `${__time}` | function | `{{$guid}}` / `{{$timestamp}}` | exact |
|
|
71
|
+
| `${__Random(...)}` and other `__fn` | function | `{{$randomInt}}` or flagged reference | approx/manual |
|
|
72
|
+
| CSV Data Set Config | `CSVDataSet` | `--data-file` + column list | approx (one file/run; naive CSV) |
|
|
73
|
+
| Counter / Random Variable | `CounterConfig`/`RandomVariableConfig` | pre-request script or `{{$randomInt}}` | manual |
|
|
75
74
|
|
|
76
75
|
## Scripting
|
|
77
76
|
|
|
78
|
-
| JMeter | XML | Postman | Fidelity |
|
|
79
|
-
|
|
80
|
-
| JSR223 PreProcessor | `JSR223PreProcessor` | prerequest script (JS, IIFE-wrapped) |
|
|
81
|
-
| JSR223 PostProcessor | `JSR223PostProcessor` | test script |
|
|
82
|
-
| BeanShell Pre/PostProcessor | `BeanShell*Processor` | pre/test script |
|
|
83
|
-
| JSR223 / BeanShell Sampler | `JSR223Sampler`/`BeanShellSampler` | script-only stub (no HTTP) | manual |
|
|
84
|
-
|
|
85
|
-
## Timing / pacing —
|
|
86
|
-
|
|
87
|
-
Postman
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
| JMeter | XML |
|
|
91
|
-
|
|
92
|
-
| Constant
|
|
93
|
-
| Constant
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
97
|
-
| Test Action (pause/stop) | `TestAction` | dropped; reported |
|
|
77
|
+
| JMeter | XML | Postman | Fidelity |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| JSR223 PreProcessor | `JSR223PreProcessor` | prerequest script (JS, IIFE-wrapped) | manual |
|
|
80
|
+
| JSR223 PostProcessor | `JSR223PostProcessor` | test script | manual |
|
|
81
|
+
| BeanShell Pre/PostProcessor | `BeanShell*Processor` | pre/test script | manual |
|
|
82
|
+
| JSR223 / BeanShell Sampler | `JSR223Sampler`/`BeanShellSampler` | script-only stub (no HTTP) | manual |
|
|
83
|
+
|
|
84
|
+
## Timing / pacing — not supported, always reported
|
|
85
|
+
|
|
86
|
+
Postman performance runs have no think time and no flag for one. Every timer is
|
|
87
|
+
dropped and listed in the report; none is reproduced.
|
|
88
|
+
|
|
89
|
+
| JMeter | XML |
|
|
90
|
+
|---|---|
|
|
91
|
+
| Constant / Uniform / Gaussian / Poisson Timer | `ConstantTimer`/`UniformRandomTimer`/... |
|
|
92
|
+
| Constant Throughput Timer | `ConstantThroughputTimer` |
|
|
93
|
+
| Throughput Shaping Timer | plugin |
|
|
94
|
+
| Synchronizing Timer | `SyncTimer` |
|
|
95
|
+
| Test Action (pause/stop) | `TestAction` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# What Postman performance testing supports (the import target)
|
|
2
2
|
|
|
3
|
-
Grounded in the `postman-cli`, `performance-test-api`, and `postman-performance-test` source — not the marketing docs. This is the ceiling
|
|
3
|
+
Grounded in the `postman-cli`, `performance-test-api`, and `postman-performance-test` source — not the marketing docs. This is the ceiling an import maps onto. When JMeter asks for something not here, it is reported, never faked.
|
|
4
4
|
|
|
5
5
|
## `postman performance run` CLI flags that matter for import
|
|
6
6
|
|
|
@@ -26,7 +26,7 @@ Four named shapes only, each derived from `(vu-count, duration)`:
|
|
|
26
26
|
- `spike` — low baseline, one spike to full mid-run, back down.
|
|
27
27
|
- `peak` — baseline, ramp up, hold, ramp down.
|
|
28
28
|
|
|
29
|
-
JMeter custom ramp curves, stepping schedules, and arrival-rate shapes **cannot be reproduced**. Pick the closest of the four and report the approximation. Rule
|
|
29
|
+
JMeter custom ramp curves, stepping schedules, and arrival-rate shapes **cannot be reproduced**. Pick the closest of the four and report the approximation. Rule: any ramp/stepping/concurrency/ultimate/arrivals group → `ramp-up`; a flat group with zero ramp → `fixed`.
|
|
30
30
|
|
|
31
31
|
## `--pass-if` metrics and operators
|
|
32
32
|
|
|
@@ -52,5 +52,5 @@ JMeter custom ramp curves, stepping schedules, and arrival-rate shapes **cannot
|
|
|
52
52
|
1. One collection, repeated across VUs. **No concurrent thread groups.**
|
|
53
53
|
2. Time-based, not iteration-based. **Loop counts → duration.**
|
|
54
54
|
3. One `--pass-if`.
|
|
55
|
-
4. **No
|
|
55
|
+
4. **No think time** — timers are not reproduced; each one is reported.
|
|
56
56
|
5. **HTTP(S) only.**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Translating JSR223 / BeanShell scripts to Postman JavaScript
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Every JSR223/BeanShell script is translated by hand and treated as a manual task until it's checked. Wrap each translation in an IIFE (`(function () { ... })();`) so a leftover `return` stays legal.
|
|
4
4
|
|
|
5
5
|
## Execution-context map
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ JMeter runs these inside a sampler's processor. Postman runs them as a request's
|
|
|
23
23
|
| `UUID.randomUUID().toString()` | `require('uuid').v4()` | both |
|
|
24
24
|
| `Integer.parseInt(x)` | `parseInt(x)` | both |
|
|
25
25
|
|
|
26
|
-
## What
|
|
26
|
+
## What doesn't map line by line
|
|
27
27
|
|
|
28
28
|
- **BeanShell implicit result vars** (`ResponseCode`, `ResponseMessage`, `IsSuccess`, `bsh.args`, `Parameters`). No pm.* equivalent in a processor. For a sampler that sets `IsSuccess=false`, express it as a `pm.test(...)` that fails. For `return X`, delete the return (the IIFE makes it legal, but it's a no-op).
|
|
29
29
|
- **Groovy closures / collection methods** (`.each {}`, `.collect {}`, `->`). Rewrite as `for...of` / `.map()` / arrow functions.
|
|
@@ -33,11 +33,10 @@ JMeter runs these inside a sampler's processor. Postman runs them as a request's
|
|
|
33
33
|
|
|
34
34
|
## Procedure
|
|
35
35
|
|
|
36
|
-
1. Read the
|
|
37
|
-
2.
|
|
38
|
-
3.
|
|
39
|
-
4.
|
|
40
|
-
5. Re-run the node syntax gate from `SKILL.md` step 3.
|
|
36
|
+
1. Read the original `<script>` text in the `.jmx` (note the element's name, so the report can point at it).
|
|
37
|
+
2. Rewrite line by line using the table. Preserve variable names so `{{var}}` references elsewhere still resolve.
|
|
38
|
+
3. Mark anything you're unsure of with a `// REVIEW` comment, and remove it once the logic is confirmed.
|
|
39
|
+
4. Run the syntax check from `README.md` step 4.
|
|
41
40
|
|
|
42
41
|
## Example
|
|
43
42
|
|
|
@@ -57,9 +56,9 @@ pm.collectionVariables.set("authToken", token);
|
|
|
57
56
|
console.log("got " + token);
|
|
58
57
|
```
|
|
59
58
|
|
|
60
|
-
## Canonical JS templates
|
|
59
|
+
## Canonical JS templates
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
Emit exactly these so every import produces the same code. `<default>` empty-string if JMeter has none. Source is `pm.response.text()` normally, or `pm.response.headers.toString()` when the extractor's `useHeaders` is true.
|
|
63
62
|
|
|
64
63
|
**Regex extractor** (`$n$` template → group `n`):
|
|
65
64
|
```javascript
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
"""Best-effort, deterministic Groovy / BeanShell -> JavaScript translation.
|
|
2
|
-
|
|
3
|
-
This handles the common mechanical rewrites so the model only has to review and
|
|
4
|
-
fix the genuinely ambiguous parts. Every script that passes through here is ALSO
|
|
5
|
-
flagged as a manual task, because no regex pass can guarantee semantic fidelity
|
|
6
|
-
for arbitrary JSR223/BeanShell code.
|
|
7
|
-
|
|
8
|
-
Keep the rules ordered from most specific to least specific. The model may extend
|
|
9
|
-
this table; see references/script-translation.md for the patterns and rationale.
|
|
10
|
-
"""
|
|
11
|
-
import re
|
|
12
|
-
|
|
13
|
-
# (pattern, replacement) applied in order. Patterns are plain regex on source text.
|
|
14
|
-
RULES = [
|
|
15
|
-
# --- JMeter bound variables -> pm equivalents ---
|
|
16
|
-
# vars["x"] / vars['x'] -> pm.variables.get("x") (bracket form, must precede .get/.put rules)
|
|
17
|
-
(r'\bvars\[\s*([\'"][^\'"]*[\'"])\s*\]', r'pm.variables.get(\1)'),
|
|
18
|
-
(r'\bprops\[\s*([\'"][^\'"]*[\'"])\s*\]', r'pm.variables.get(\1)'),
|
|
19
|
-
(r'\bvars\.get\(', 'pm.variables.get('),
|
|
20
|
-
(r'\bvars\.put\(', 'pm.variables.set('),
|
|
21
|
-
(r'\bvars\.getObject\(', 'pm.variables.get('),
|
|
22
|
-
(r'\bvars\.putObject\(', 'pm.variables.set('),
|
|
23
|
-
(r'\bprops\.get\(', 'pm.variables.get('),
|
|
24
|
-
(r'\bprops\.put\(', 'pm.variables.set('),
|
|
25
|
-
|
|
26
|
-
# --- logging ---
|
|
27
|
-
(r'\blog\.info\(', 'console.log('),
|
|
28
|
-
(r'\blog\.warn\(', 'console.warn('),
|
|
29
|
-
(r'\blog\.error\(', 'console.error('),
|
|
30
|
-
(r'\blog\.debug\(', 'console.log('),
|
|
31
|
-
|
|
32
|
-
# --- previous-sample result accessors (post-processor context) ---
|
|
33
|
-
(r'\bprev\.getResponseDataAsString\(\)', 'pm.response.text()'),
|
|
34
|
-
(r'\bprev\.getResponseCode\(\)', 'String(pm.response.code)'),
|
|
35
|
-
(r'\bprev\.getResponseMessage\(\)', 'pm.response.status'),
|
|
36
|
-
(r'\bprev\.getResponseHeaders\(\)', 'pm.response.headers.toString()'),
|
|
37
|
-
(r'\bprev\.getTime\(\)', 'pm.response.responseTime'),
|
|
38
|
-
(r'\bctx\.getPreviousResult\(\)', 'pm.response'),
|
|
39
|
-
|
|
40
|
-
# --- sampler mutation (pre-processor context) ---
|
|
41
|
-
(r'\bsampler\.getUrl\(\)', 'pm.request.url.toString()'),
|
|
42
|
-
(r'\bsampler\.addArgument\(', '// [manual] sampler.addArgument -> set a query/body param; '),
|
|
43
|
-
|
|
44
|
-
# --- JDK calls that have JS equivalents ---
|
|
45
|
-
(r'\bSystem\.currentTimeMillis\(\)', 'Date.now()'),
|
|
46
|
-
(r'\bUUID\.randomUUID\(\)\.toString\(\)', 'require("uuid").v4()'),
|
|
47
|
-
(r'\bInteger\.parseInt\(', 'parseInt('),
|
|
48
|
-
(r'\bLong\.parseLong\(', 'parseInt('),
|
|
49
|
-
(r'\bDouble\.parseDouble\(', 'parseFloat('),
|
|
50
|
-
(r'\bString\.valueOf\(', 'String('),
|
|
51
|
-
(r'\bMath\.', 'Math.'), # identity, keeps it explicit
|
|
52
|
-
|
|
53
|
-
# --- declarations: Groovy def / typed decls -> let ---
|
|
54
|
-
(r'\bdef\s+', 'let '),
|
|
55
|
-
(r'\b(?:String|int|long|double|float|boolean|Object|var)\s+(\w+\s*=)', r'let \1'),
|
|
56
|
-
|
|
57
|
-
# --- Groovy GString interpolation "${x}" stays valid-ish; leave for model ---
|
|
58
|
-
]
|
|
59
|
-
|
|
60
|
-
# Tokens that, if present after translation, almost certainly need human review.
|
|
61
|
-
REVIEW_MARKERS = [
|
|
62
|
-
'import ', 'new ', 'class ', '.each', '.collect', '->', 'bsh.', 'ctx.',
|
|
63
|
-
'OUT.', 'SampleResult', 'Thread.sleep', 'try {', 'catch', '@', '::',
|
|
64
|
-
]
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def translate(source: str, lang: str = 'groovy') -> dict:
|
|
68
|
-
"""Return {'js': <translated>, 'needs_review': bool, 'reasons': [...]}."""
|
|
69
|
-
if source is None:
|
|
70
|
-
return {'js': '', 'needs_review': False, 'reasons': []}
|
|
71
|
-
js = source
|
|
72
|
-
for pat, repl in RULES:
|
|
73
|
-
js = re.sub(pat, repl, js)
|
|
74
|
-
|
|
75
|
-
# BeanShell implicit result vars have no clean pm.* mapping.
|
|
76
|
-
reasons = []
|
|
77
|
-
if lang and 'beanshell' in lang.lower():
|
|
78
|
-
reasons.append('BeanShell script: implicit vars (ResponseCode, IsSuccess, bsh.args) have no pm.* equivalent')
|
|
79
|
-
for marker in REVIEW_MARKERS:
|
|
80
|
-
if marker in js:
|
|
81
|
-
reasons.append(f'contains "{marker.strip()}" which needs manual translation')
|
|
82
|
-
needs_review = True # always true: no mechanical pass is trustworthy for scripts
|
|
83
|
-
return {'js': js, 'needs_review': needs_review, 'reasons': sorted(set(reasons))}
|