@ksz54213/specbridge 0.1.0 → 0.2.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 +10 -1
- package/index.js +12 -1
- package/package.json +1 -1
- package/src/runner.js +2 -1
package/README.md
CHANGED
|
@@ -23,13 +23,22 @@ npm install -g @ksz54213/specbridge
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
25
|
```
|
|
26
|
-
specbridge verify -f <path-to-feature> -u <base-url>
|
|
26
|
+
specbridge verify -f <path-to-feature> -u <base-url> [-H "Key: Value"]
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
| Option | Alias | Required | Description |
|
|
30
30
|
|---|---|---|---|
|
|
31
31
|
| `--file` | `-f` | ✅ | Path to the `.feature` contract file |
|
|
32
32
|
| `--url` | `-u` | ✅ | Base URL of the service to test (e.g. `http://localhost:3000`) |
|
|
33
|
+
| `--header` | `-H` | ❌ | HTTP header to include in every request (repeatable) |
|
|
34
|
+
|
|
35
|
+
Multiple headers are supported by repeating the flag:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
specbridge verify -f contract.feature -u http://localhost:3000 \
|
|
39
|
+
-H "Authorization: Bearer <token>" \
|
|
40
|
+
-H "X-Api-Key: abc123"
|
|
41
|
+
```
|
|
33
42
|
|
|
34
43
|
---
|
|
35
44
|
|
package/index.js
CHANGED
|
@@ -16,6 +16,7 @@ program
|
|
|
16
16
|
.description('Verify a contract defined in a Gherkin feature file')
|
|
17
17
|
.requiredOption('-f, --file <path>', 'Path to the .feature file')
|
|
18
18
|
.requiredOption('-u, --url <url>', 'Base URL of the service to test')
|
|
19
|
+
.option('-H, --header <header...>', 'HTTP header(s) to include (format: "Key: Value")')
|
|
19
20
|
.action(async (opts) => {
|
|
20
21
|
if (!existsSync(opts.file)) {
|
|
21
22
|
console.error(`\x1b[31mError: Feature File not found: ${opts.file}\x1b[0m`)
|
|
@@ -35,6 +36,16 @@ program
|
|
|
35
36
|
process.exit(0)
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
const globalHeaders = {}
|
|
40
|
+
for (const raw of (opts.header ?? [])) {
|
|
41
|
+
const sep = raw.indexOf(':')
|
|
42
|
+
if (sep === -1) {
|
|
43
|
+
console.error(`\x1b[31mError: Invalid header format (expected "Key: Value"): ${raw}\x1b[0m`)
|
|
44
|
+
process.exit(1)
|
|
45
|
+
}
|
|
46
|
+
globalHeaders[raw.slice(0, sep).trim()] = raw.slice(sep + 1).trim()
|
|
47
|
+
}
|
|
48
|
+
|
|
38
49
|
let passed = 0
|
|
39
50
|
let failed = 0
|
|
40
51
|
|
|
@@ -45,7 +56,7 @@ program
|
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
const endpoint = buildEndpoint(opts.url, scenario.path)
|
|
48
|
-
const result = await runScenario(scenario, opts.url)
|
|
59
|
+
const result = await runScenario(scenario, opts.url, globalHeaders)
|
|
49
60
|
reportScenario(scenario.name, endpoint, result)
|
|
50
61
|
|
|
51
62
|
if (result.pass) passed++
|
package/package.json
CHANGED
package/src/runner.js
CHANGED
|
@@ -2,7 +2,7 @@ import axios from 'axios'
|
|
|
2
2
|
import { buildEndpoint } from './endpoint.js'
|
|
3
3
|
import { assertStatusCode, assertBodyExact, assertBodyField } from './assertions.js'
|
|
4
4
|
|
|
5
|
-
export async function runScenario(scenario, baseUrl) {
|
|
5
|
+
export async function runScenario(scenario, baseUrl, globalHeaders = {}) {
|
|
6
6
|
const endpoint = buildEndpoint(baseUrl, scenario.path)
|
|
7
7
|
const messages = []
|
|
8
8
|
|
|
@@ -10,6 +10,7 @@ export async function runScenario(scenario, baseUrl) {
|
|
|
10
10
|
const response = await axios({
|
|
11
11
|
method: scenario.method,
|
|
12
12
|
url: endpoint,
|
|
13
|
+
headers: { ...globalHeaders, ...(scenario.headers ?? {}) },
|
|
13
14
|
data: scenario.requestBody ?? undefined,
|
|
14
15
|
timeout: 30_000,
|
|
15
16
|
validateStatus: () => true,
|