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
6
tests/hurl/query/all.hurl
Normal file
6
tests/hurl/query/all.hurl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# __all: array contains all listed values.
|
||||
GET {{host}}/query?tags__all=anwesen,project
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 1
|
||||
jsonpath "$.results[0].path" == "Projects/anwesen.md"
|
||||
7
tests/hurl/query/anw_limit.hurl
Normal file
7
tests/hurl/query/anw_limit.hurl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# __anw-limit caps results; total still reflects the full match count.
|
||||
GET {{host}}/query?__anw-limit=1&__anw-path=Projects
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.results" count == 1
|
||||
jsonpath "$.total" == 4
|
||||
jsonpath "$.truncated" == true
|
||||
8
tests/hurl/query/anw_path_segment_boundary.hurl
Normal file
8
tests/hurl/query/anw_path_segment_boundary.hurl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# __anw-path=Projects must NOT match Projects-old/legacy.md -- segment-
|
||||
# boundary anchoring per the ANW-22 fix.
|
||||
GET {{host}}/query?__anw-path=Projects
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.results[*].path" contains "Projects/anwesen.md"
|
||||
jsonpath "$.results[*].path" contains "Projects/alpha.md"
|
||||
jsonpath "$.results[*].path" not contains "Projects-old/legacy.md"
|
||||
10
tests/hurl/query/anw_recursive_false.hurl
Normal file
10
tests/hurl/query/anw_recursive_false.hurl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# __anw-recursive=false restricts to direct children of __anw-path.
|
||||
GET {{host}}/query?__anw-path=Projects&__anw-recursive=false
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
# Four notes live directly under Projects/; none under deeper folders here.
|
||||
jsonpath "$.total" == 4
|
||||
jsonpath "$.results[*].path" contains "Projects/anwesen.md"
|
||||
jsonpath "$.results[*].path" contains "Projects/alpha.md"
|
||||
jsonpath "$.results[*].path" contains "Projects/PDR-001-intro.md"
|
||||
jsonpath "$.results[*].path" contains "Projects/PDR-002-followup.md"
|
||||
3
tests/hurl/query/bad_exists_400.hurl
Normal file
3
tests/hurl/query/bad_exists_400.hurl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# __exists value that isn't a bool is rejected with 400.
|
||||
GET {{host}}/query?deprecated__exists=maybe
|
||||
HTTP 400
|
||||
3
tests/hurl/query/bad_regex_400.hurl
Normal file
3
tests/hurl/query/bad_regex_400.hurl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Malformed regex value is rejected with 400 at parse time.
|
||||
GET {{host}}/query?title__regex=(unclosed
|
||||
HTTP 400
|
||||
6
tests/hurl/query/comma_escape.hurl
Normal file
6
tests/hurl/query/comma_escape.hurl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# A literal comma inside an __in value goes in percent-encoded as %2C.
|
||||
# Smoke: confirm the request shape is accepted (no match is fine).
|
||||
GET {{host}}/query?title__in=PDR-001%2CIntro
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 0
|
||||
8
tests/hurl/query/eq_bare_unifies_scalar_and_list.hurl
Normal file
8
tests/hurl/query/eq_bare_unifies_scalar_and_list.hurl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Bare-Eq scalar/list unification per ADR-005: tag=python matches both
|
||||
# `tag: python` and `tag: [python, go]`.
|
||||
GET {{host}}/query?tag=python
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 2
|
||||
jsonpath "$.results[*].path" contains "drift/scalar-tag.md"
|
||||
jsonpath "$.results[*].path" contains "drift/list-tag.md"
|
||||
10
tests/hurl/query/eq_scalar.hurl
Normal file
10
tests/hurl/query/eq_scalar.hurl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Bare equality on a scalar value.
|
||||
GET {{host}}/query?status=active
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.results" count == 1
|
||||
jsonpath "$.results[0].path" == "Projects/anwesen.md"
|
||||
jsonpath "$.results[0].frontmatter.status" == "active"
|
||||
jsonpath "$.results[0].body" not exists
|
||||
jsonpath "$.total" == 1
|
||||
jsonpath "$.truncated" == false
|
||||
7
tests/hurl/query/exists_false.hurl
Normal file
7
tests/hurl/query/exists_false.hurl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# __exists=false: matches every note that lacks the key.
|
||||
GET {{host}}/query?deprecated__exists=false&kind__exists=false&author__exists=false&date__exists=false&purpose__exists=false&tag__exists=false&when__exists=false&tags__exists=false&title__exists=false&status__exists=false
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
# no-frontmatter.md is the only note with no keys at all.
|
||||
jsonpath "$.total" == 1
|
||||
jsonpath "$.results[0].path" == "no-frontmatter.md"
|
||||
7
tests/hurl/query/exists_true.hurl
Normal file
7
tests/hurl/query/exists_true.hurl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# __exists=true: matches every note that defines the key.
|
||||
GET {{host}}/query?deprecated__exists=true
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 2
|
||||
jsonpath "$.results[*].path" contains "Projects/anwesen.md"
|
||||
jsonpath "$.results[*].path" contains "Projects/alpha.md"
|
||||
7
tests/hurl/query/in.hurl
Normal file
7
tests/hurl/query/in.hurl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# __in: one-of, against a list field.
|
||||
GET {{host}}/query?tags__in=alpha,anwesen
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 2
|
||||
jsonpath "$.results[*].path" contains "Projects/anwesen.md"
|
||||
jsonpath "$.results[*].path" contains "Projects/alpha.md"
|
||||
8
tests/hurl/query/nested_dotted_key.hurl
Normal file
8
tests/hurl/query/nested_dotted_key.hurl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Nested key addressed via dotted path: author.name=brn.
|
||||
GET {{host}}/query?author.name=brn
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 1
|
||||
jsonpath "$.results[0].path" == "nested/author-info.md"
|
||||
jsonpath "$.results[0].frontmatter.author.name" == "brn"
|
||||
jsonpath "$.results[0].frontmatter.author.role" == "engineer"
|
||||
6
tests/hurl/query/not.hurl
Normal file
6
tests/hurl/query/not.hurl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# __not: negation on a scalar.
|
||||
GET {{host}}/query?status__not=draft&kind__exists=false
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.results[*].path" contains "Projects/anwesen.md"
|
||||
jsonpath "$.results[*].path" not contains "Projects/alpha.md"
|
||||
6
tests/hurl/query/prefix.hurl
Normal file
6
tests/hurl/query/prefix.hurl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# __prefix: string prefix match on a scalar.
|
||||
GET {{host}}/query?title__prefix=PDR-001
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 1
|
||||
jsonpath "$.results[0].path" == "Projects/PDR-001-intro.md"
|
||||
6
tests/hurl/query/range_dates.hurl
Normal file
6
tests/hurl/query/range_dates.hurl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# __gte / __lte against ISO-8601 dates.
|
||||
GET {{host}}/query?date__gte=2026-02-01&date__lte=2026-04-01
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 1
|
||||
jsonpath "$.results[0].path" == "events/b.md"
|
||||
7
tests/hurl/query/range_datetime.hurl
Normal file
7
tests/hurl/query/range_datetime.hurl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# __gt against an RFC 3339 datetime; verifies coerced typed-date comparison.
|
||||
GET {{host}}/query?when__gt=2026-05-14T00:00:00Z
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 1
|
||||
jsonpath "$.results[0].path" == "events/c.md"
|
||||
jsonpath "$.results[0].frontmatter.when" == "2026-05-14T10:14:22Z"
|
||||
7
tests/hurl/query/regex.hurl
Normal file
7
tests/hurl/query/regex.hurl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# __regex: anchored pattern on a scalar.
|
||||
GET {{host}}/query?title__regex=^PDR-%5Cd%2B
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.total" == 2
|
||||
jsonpath "$.results[*].path" contains "Projects/PDR-001-intro.md"
|
||||
jsonpath "$.results[*].path" contains "Projects/PDR-002-followup.md"
|
||||
3
tests/hurl/query/unknown_control_param_400.hurl
Normal file
3
tests/hurl/query/unknown_control_param_400.hurl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Unknown __anw- control parameter is rejected with 400.
|
||||
GET {{host}}/query?__anw-bogus=1
|
||||
HTTP 400
|
||||
3
tests/hurl/query/unknown_operator_400.hurl
Normal file
3
tests/hurl/query/unknown_operator_400.hurl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Unknown operator suffix is rejected with 400 (not silently ignored).
|
||||
GET {{host}}/query?title__contians=foo
|
||||
HTTP 400
|
||||
Loading…
Add table
Add a link
Reference in a new issue