///|
test "parser accepts minimal object" {
  assert_int_eq(unwrap_parse("{}").diagnostics().length(), 0)
}

///|
test "parser rejects malformed json" {
  assert_true(expect_error("{").kind() == InvalidJson)
}

///|
test "parser rejects a root array" {
  assert_true(expect_error("[]").kind() == RootNotObject)
}

///|
test "parser rejects a root string" {
  assert_true(expect_error("\"x\"").kind() == RootNotObject)
}

///|
test "wrong type title is ignored with diagnostic" {
  let r = unwrap_parse("{\"title\":123}")
  assert_true(r.problem().title() is None)
  assert_int_eq(r.diagnostics().length(), 1)
  assert_str_eq(r.diagnostics()[0].member_name(), "title")
  assert_str_eq(r.diagnostics()[0].actual(), "number")
}

///|
test "wrong type status string is ignored" {
  let r = unwrap_parse("{\"status\":\"403\"}")
  assert_true(r.problem().status() is None)
  assert_str_eq(r.diagnostics()[0].expected(), "integer number")
}

///|
test "fractional status is ignored" {
  assert_true(unwrap_problem("{\"status\":4.5}").status() is None)
}

///|
test "wrong type detail array is ignored" {
  assert_true(unwrap_problem("{\"detail\":[\"x\"]}").detail() is None)
}

///|
test "wrong types do not prevent extensions parsing" {
  let r = unwrap_parse("{\"title\":1,\"x\":true}")
  assert_true(r.problem().has_extension("x"))
}

///|
test "diagnostics are deterministically ordered by member name" {
  let r = unwrap_parse("{\"title\":1,\"status\":\"x\"}")
  assert_str_eq(r.diagnostics()[0].member_name(), "status")
  assert_str_eq(r.diagnostics()[1].member_name(), "title")
}

///|
test "unicode text parses losslessly" {
  assert_str_eq(
    unwrap_problem("{\"title\":\"ι”™θ―― πŸ˜€\"}").title().unwrap(),
    "ι”™θ―― πŸ˜€",
  )
}

///|
test "byte parser accepts valid utf8" {
  assert_true(
    parse_problem_json_bytes(@utf8.encode("{\"title\":\"δΈ­\"}")) is Ok(_),
  )
}

///|
test "byte parser rejects malformed utf8" {
  assert_true(
    parse_problem_json_bytes(Bytes::from_array([(0xFF).to_byte()])) is Err(_),
  )
}

///|
test "parse problem convenience preserves structured error" {
  assert_true(parse_problem("[]") is Err(_))
}