ANW-20 hurl HTTP contract-test harness
This commit is contained in:
parent
ec650e6c66
commit
b4a33abd71
50 changed files with 415 additions and 2 deletions
13
tests/hurl/notes/folder_index.hurl
Normal file
13
tests/hurl/notes/folder_index.hurl
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Trailing slash is a folder listing -- immediate children only.
|
||||
GET {{host}}/notes/Projects/
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
header "Content-Type" startsWith "application/json"
|
||||
jsonpath "$.path" == "Projects"
|
||||
jsonpath "$.entries" count == 4
|
||||
jsonpath "$.entries[0].name" == "PDR-001-intro.md"
|
||||
jsonpath "$.entries[0].type" == "file"
|
||||
jsonpath "$.entries[0].size" > 0
|
||||
jsonpath "$.entries[1].name" == "PDR-002-followup.md"
|
||||
jsonpath "$.entries[2].name" == "alpha.md"
|
||||
jsonpath "$.entries[3].name" == "anwesen.md"
|
||||
3
tests/hurl/notes/folder_index_not_found.hurl
Normal file
3
tests/hurl/notes/folder_index_not_found.hurl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Missing folder returns 404.
|
||||
GET {{host}}/notes/no-such-folder/
|
||||
HTTP 404
|
||||
11
tests/hurl/notes/folder_index_root.hurl
Normal file
11
tests/hurl/notes/folder_index_root.hurl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# /notes/ is the vault root listing; dot-directories are invisible.
|
||||
GET {{host}}/notes/
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.path" == ""
|
||||
jsonpath "$.entries[*].name" not contains ".obsidian"
|
||||
jsonpath "$.entries[*].name" not contains ".trash"
|
||||
jsonpath "$.entries[*].name" contains "Projects"
|
||||
jsonpath "$.entries[*].name" contains "Projects-old"
|
||||
jsonpath "$.entries[*].name" contains "events"
|
||||
jsonpath "$.entries[*].name" contains "README.md"
|
||||
16
tests/hurl/notes/get_one.hurl
Normal file
16
tests/hurl/notes/get_one.hurl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# GET /notes/<path> returns the documented JSON shape.
|
||||
GET {{host}}/notes/README.md
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
header "Content-Type" startsWith "application/json"
|
||||
header "ETag" exists
|
||||
jsonpath "$.path" == "README.md"
|
||||
jsonpath "$.frontmatter.status" == "published"
|
||||
jsonpath "$.frontmatter.tags" count == 2
|
||||
jsonpath "$.frontmatter.tags[0]" == "demo"
|
||||
jsonpath "$.frontmatter.tags[1]" == "readme"
|
||||
jsonpath "$.frontmatter.date" == "2026-05-01"
|
||||
jsonpath "$.body" contains "Fixture vault README"
|
||||
jsonpath "$.size" > 0
|
||||
jsonpath "$.etag" matches "^\"[0-9a-f]{64}\"$"
|
||||
jsonpath "$.last_modified" matches "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"
|
||||
9
tests/hurl/notes/get_one_accept_markdown.hurl
Normal file
9
tests/hurl/notes/get_one_accept_markdown.hurl
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Accept: text/markdown returns the raw file bytes verbatim.
|
||||
GET {{host}}/notes/README.md
|
||||
Accept: text/markdown
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
header "Content-Type" startsWith "text/markdown"
|
||||
header "ETag" exists
|
||||
body startsWith "---\ntags: [demo, readme]\ndate: 2026-05-01\nstatus: published\n---\n"
|
||||
body contains "Fixture vault README. Used by the hurl contract harness."
|
||||
5
tests/hurl/notes/get_one_dotdot_400.hurl
Normal file
5
tests/hurl/notes/get_one_dotdot_400.hurl
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# .. path segments are rejected with 400. Use percent-encoding to bypass
|
||||
# the HTTP client's URL normalization; curl/hurl collapse a bare ".."
|
||||
# before the request goes out.
|
||||
GET {{host}}/notes/%2E%2E/etc/passwd
|
||||
HTTP 400
|
||||
9
tests/hurl/notes/get_one_etag_304.hurl
Normal file
9
tests/hurl/notes/get_one_etag_304.hurl
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Chain: fetch ETag, then send If-None-Match -> 304.
|
||||
GET {{host}}/notes/README.md
|
||||
HTTP 200
|
||||
[Captures]
|
||||
etag: header "ETag"
|
||||
|
||||
GET {{host}}/notes/README.md
|
||||
If-None-Match: {{etag}}
|
||||
HTTP 304
|
||||
6
tests/hurl/notes/get_one_etag_mismatch.hurl
Normal file
6
tests/hurl/notes/get_one_etag_mismatch.hurl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# A stale ETag returns the full body (not 304).
|
||||
GET {{host}}/notes/README.md
|
||||
If-None-Match: "stale0000000000000000000000000000000000000000000000000000000000"
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.path" == "README.md"
|
||||
8
tests/hurl/notes/get_one_no_frontmatter.hurl
Normal file
8
tests/hurl/notes/get_one_no_frontmatter.hurl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# A note without a frontmatter block still serves; frontmatter is {}.
|
||||
GET {{host}}/notes/no-frontmatter.md
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.path" == "no-frontmatter.md"
|
||||
jsonpath "$.frontmatter" exists
|
||||
jsonpath "$.frontmatter.tags" not exists
|
||||
jsonpath "$.body" contains "no frontmatter block"
|
||||
3
tests/hurl/notes/get_one_not_found.hurl
Normal file
3
tests/hurl/notes/get_one_not_found.hurl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Missing path returns 404.
|
||||
GET {{host}}/notes/does-not-exist.md
|
||||
HTTP 404
|
||||
Loading…
Add table
Add a link
Reference in a new issue