Skip to content

Commit ccd5c00

Browse files
OpenAPI: split import into URL and file commands with e2e tests (#6)
# TLDR; Split the single OpenAPI import button into two: cloud icon for URL import (downloads spec via HTTPS) and file icon for local file import. Added context menu commands, response/request headers in panels, and e2e tests with real network calls. # Details - **Two import commands**: `napper.importOpenApiUrl` (cloud icon) downloads an OpenAPI spec from a URL; `napper.importOpenApiFile` (file icon) picks a local spec file - **URL download**: HTTPS with redirect following, error handling for 4xx responses - **Context menus**: add-to-playlist, duplicate, delete, copy path, enrich with AI - **Response panel**: now shows request headers alongside response headers - **Playlist panel**: shows request/response headers per step - **Report generator**: includes request/response headers in HTML reports - **F# Output.fs**: additional output formatting - **E2e tests**: real network calls to petstore swagger URL, 404 error handling, redirect following, temp file creation # How do the tests prove the change works - `downloadSpec fetches valid OpenAPI from petstore URL` — makes a real HTTPS call to petstore3.swagger.io, parses the JSON, asserts it has `openapi` version field and `paths` with entries - `downloadSpec returns error for 404 URL` — hits httpbin.org/status/404, asserts the result is an error with the correct prefix - `downloadSpec follows redirects` — uses httpbin.org redirect-to endpoint, verifies the final response is valid OpenAPI - `saveTempSpec writes file and returns path` — writes to a real temp dir, reads back, asserts content matches - `saveTempSpec overwrites existing file` — writes twice, asserts second content wins - Command registration tests verify both `napper.importOpenApiUrl` and `napper.importOpenApiFile` are registered ---------
1 parent 4cdb6e6 commit ccd5c00

57 files changed

Lines changed: 5372 additions & 1824 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/pr.yml

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,19 @@ jobs:
3131
- name: Build CLI, compile extension & tests
3232
run: npm run pretest
3333

34-
- name: Unit tests
34+
- name: Unit tests with coverage
3535
run: npm run test:unit
3636

3737
- name: E2E tests
3838
run: xvfb-run --auto-servernum npm test
3939

40+
- name: Upload TypeScript coverage
41+
if: always()
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: typescript-coverage
45+
path: coverage/typescript/report/
46+
4047
test-fsharp:
4148
name: F# Build & Tests
4249
runs-on: ubuntu-latest
@@ -47,14 +54,24 @@ jobs:
4754
with:
4855
dotnet-version: "10.0.x"
4956

57+
- name: Install ReportGenerator
58+
run: dotnet tool install --global dotnet-reportgenerator-globaltool
59+
5060
- name: Install dotnet-script
5161
run: dotnet tool install -g dotnet-script
5262

5363
- name: Build
5464
run: dotnet build --nologo
5565

56-
- name: Test
57-
run: dotnet test --nologo --verbosity normal
66+
- name: Test with coverage
67+
run: bash scripts/test-fsharp.sh
68+
69+
- name: Upload F# coverage
70+
if: always()
71+
uses: actions/upload-artifact@v4
72+
with:
73+
name: fsharp-coverage
74+
path: coverage/fsharp/report/
5875

5976
build-website:
6077
name: Website Build

.gitignore

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,38 @@
1-
.too_many_cooks/
2-
.commandtree/
1+
# OS
2+
.DS_Store
33

4+
# .NET build output
45
bin/
56
obj/
67
publish/
78

9+
# Node / TypeScript build output
10+
node_modules/
11+
dist/
12+
out/
13+
814
# VSCode extension
915
src/Nap.VsCode/node_modules/
1016
src/Nap.VsCode/dist/
17+
src/Nap.VsCode/out/
1118
src/Nap.VsCode/*.vsix
19+
src/Nap.VsCode/.vscode-test/
1220

13-
# Environment secrets
14-
.napenv.local
15-
16-
# VSCode workspace settings
21+
# IDE settings
1722
.vscode/
1823

19-
node_modules/
20-
dist/
21-
src/Nap.VsCode/.vscode-test/
22-
out/
23-
src/Nap.VsCode/out/
24+
# Secrets
25+
.napenv.local
2426

25-
.DS_Store
27+
# Test output
28+
coverage/
29+
TestResults/
2630

31+
# Tools
32+
.too_many_cooks/
33+
.commandtree/
2734
.playwright-mcp/
2835

36+
# Generated files
2937
website/_site/
38+
examples/httpbin/advanced-report.html

Claude.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ You are working with many other agents. Make sure there is effective cooperation
2828

2929
### F#
3030
- **Idiomatic F#**
31+
- **Standard F# result types** - Use the standard F# built-in result types
32+
- **Turn on F# analyzers** - Strict rules to enforce F# best practice
3133

3234
## Testing
3335

examples/petstore/openapi.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

scripts/test-fsharp.sh

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33
cd "$(dirname "$0")/.."
4-
echo "==> Running F# tests..."
5-
dotnet test tests/Nap.Core.Tests --nologo
4+
5+
COVERAGE_DIR="coverage/fsharp"
6+
rm -rf "$COVERAGE_DIR"
7+
mkdir -p "$COVERAGE_DIR"
8+
9+
echo "==> Running F# tests with coverage..."
10+
dotnet test tests/Nap.Core.Tests --nologo \
11+
--settings tests/Nap.Core.Tests/coverage.runsettings \
12+
--results-directory "$COVERAGE_DIR/raw"
13+
14+
echo "==> Generating coverage report..."
15+
reportgenerator \
16+
-reports:"$COVERAGE_DIR/raw/*/coverage.cobertura.xml" \
17+
-targetdir:"$COVERAGE_DIR/report" \
18+
-reporttypes:"Html;TextSummary;Cobertura;lcov"
19+
20+
echo ""
21+
echo "=== F# Coverage Summary ==="
22+
cat "$COVERAGE_DIR/report/Summary.txt"

scripts/test.sh

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,24 @@ cd "$(dirname "$0")/.."
44

55
bash scripts/build-cli.sh
66

7-
echo "==> Compiling test TypeScript..."
7+
COVERAGE_DIR="coverage/typescript"
8+
rm -rf "$COVERAGE_DIR"
9+
mkdir -p "$COVERAGE_DIR"
10+
11+
echo "==> Compiling TypeScript..."
812
cd src/Nap.VsCode
913
npm run compile
1014
npm run compile:tests
1115

16+
echo "==> Running unit tests with coverage..."
17+
npx c8 \
18+
--temp-directory "../../$COVERAGE_DIR/tmp" \
19+
--report-dir "../../$COVERAGE_DIR/report" \
20+
mocha out/test/unit/**/*.test.js --ui tdd --timeout 5000
21+
1222
echo "==> Running e2e tests..."
1323
npx vscode-test
24+
25+
echo ""
26+
echo "=== TypeScript Coverage Summary ==="
27+
echo "Report: $COVERAGE_DIR/report/index.html"

NAP_SPEC.md renamed to specs/Napper.md

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -667,55 +667,6 @@ nap/
667667

668668
---
669669

670-
## OpenAPI / Swagger Test Generation (Phase 6+)
670+
## OpenAPI / Swagger Test Generation
671671

672-
Nap will support generating `.nap` files and `.naplist` playlists from OpenAPI 3.x specs.
673-
674-
```sh
675-
# Generate a collection from an OpenAPI spec
676-
nap generate openapi ./petstore.yaml --output ./petstore/
677-
678-
# Generate from a URL
679-
nap generate openapi https://api.example.com/openapi.json --output ./generated/
680-
681-
# Generate only for specific tags or paths
682-
nap generate openapi ./petstore.yaml --tag users --output ./users/
683-
```
684-
685-
### What gets generated
686-
687-
For each operation in the spec:
688-
- A `.nap` file with the correct method, URL template, and required headers.
689-
- Example request bodies derived from the spec's `example` / `examples` fields or schema defaults.
690-
- Basic `[assert]` blocks asserting the documented success status code and response shape.
691-
- Placeholder `{{variables}}` for path params, query params, and auth headers.
692-
693-
```nap
694-
# Generated from GET /users/{userId}
695-
[meta]
696-
name = "Get user by ID"
697-
description = "Auto-generated from petstore.yaml — operation: getUserById"
698-
tags = ["users", "generated"]
699-
700-
[vars]
701-
userId = "REPLACE_ME"
702-
703-
[request]
704-
method = GET
705-
url = {{baseUrl}}/users/{{userId}}
706-
707-
[request.headers]
708-
Authorization = Bearer {{token}}
709-
710-
[assert]
711-
status = 200
712-
body.id exists
713-
body.name exists
714-
```
715-
716-
### Design notes
717-
718-
- Generated files are **starting points**, not final tests. The user edits and extends them.
719-
- Re-running `nap generate` over an existing collection offers a `--diff` mode that shows what changed in the spec without overwriting custom assertions.
720-
- A `[meta] generated = true` flag marks auto-generated files so tooling can identify them.
721-
- Generation is a separate `Nap.OpenApi` library/package, keeping the core runtime free of OpenAPI dependencies.
672+
See [OpenAPI Generation Specification](./OpenApiGeneration.md) for the full specification covering one-click test suite generation from OpenAPI specs, including AI-assisted enrichment via GitHub Copilot.

0 commit comments

Comments
 (0)