Skip to content

Commit 5c9b4aa

Browse files
committed
feat: start storing keywordLocation on error
1 parent a1a15bc commit 5c9b4aa

File tree

6 files changed

+64
-3
lines changed

6 files changed

+64
-3
lines changed

Sources/Validation/enum.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ func `enum`(context: Context, enum: Any, instance: Any, schema: [String: Any]) -
1414
return AnySequence([
1515
ValidationError(
1616
"'\(instance)' is not a valid enumeration value of '\(`enum`)'",
17-
instanceLocation: context.instanceLocation
17+
instanceLocation: context.instanceLocation,
18+
keywordLocation: context.keywordLocation
1819
)
1920
])
2021
}

Sources/Validation/required.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ func required(context: Context, required: Any, instance: Any, schema: [String: A
1212
guard !instance.keys.contains(key) else { return nil }
1313
return ValidationError(
1414
"Required property '\(key)' is missing",
15-
instanceLocation: context.instanceLocation
15+
instanceLocation: context.instanceLocation,
16+
keywordLocation: context.keywordLocation
1617
)
1718
})
1819
}

Sources/ValidationResult.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
public class ValidationError: Encodable {
22
public let description: String
33

4-
init(_ value: String, instanceLocation: JSONPointer) {
4+
init(_ value: String, instanceLocation: JSONPointer, keywordLocation: JSONPointer? = nil) {
55
self.description = value
66
self.instanceLocation = instanceLocation
7+
self.keywordLocation = keywordLocation
78
}
89

910
enum CodingKeys: String, CodingKey {
@@ -18,6 +19,7 @@ public class ValidationError: Encodable {
1819
}
1920

2021
public let instanceLocation: JSONPointer
22+
public let keywordLocation: JSONPointer?
2123
}
2224

2325

Sources/Validator.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class Context {
55
let validator: Validator
66

77
var instanceLocation = JSONPointer()
8+
var keywordLocation = JSONPointer(path: "#")
89

910
init(resolver: RefResolver, validator: Validator) {
1011
self.resolver = RefResolver(resolver: resolver)
@@ -36,6 +37,8 @@ class Context {
3637

3738
return try AnySequence(validator.validations.compactMap { (key, validation) -> AnySequence<ValidationError> in
3839
if let value = schema[key] {
40+
keywordLocation.push(key)
41+
defer { keywordLocation.pop() }
3942
return try validation(self, value, instance, schema)
4043
}
4144

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import XCTest
2+
@testable import JSONSchema
3+
4+
5+
class EnumTests: XCTestCase {
6+
func testEnumValidationFailure() throws {
7+
let schema: [String: Any] = [
8+
"$schema": "http://json-schema.org/draft-07/schema#",
9+
"enum": ["one"],
10+
]
11+
12+
let result = try validate(["two"], schema: schema)
13+
14+
switch result {
15+
case .valid:
16+
XCTFail("Validation should fail")
17+
case .invalid(let errors):
18+
XCTAssertEqual(errors.count, 1)
19+
let error = errors[0]
20+
21+
//XCTAssertEqual(error.description, "is not a valid enumeration value of '[\"one\"]'")
22+
XCTAssertEqual(error.instanceLocation.path, "")
23+
XCTAssertEqual(error.keywordLocation?.path, "#/enum")
24+
}
25+
}
26+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import XCTest
2+
@testable import JSONSchema
3+
4+
5+
class RequiredTests: XCTestCase {
6+
func testRequiredValidationFailure() throws {
7+
let schema: [String: Any] = [
8+
"$schema": "http://json-schema.org/draft-07/schema#",
9+
"items": [
10+
"required": ["test"],
11+
]
12+
]
13+
14+
let result = try validate([[:]], schema: schema)
15+
16+
switch result {
17+
case .valid:
18+
XCTFail("Validation should fail")
19+
case .invalid(let errors):
20+
XCTAssertEqual(errors.count, 1)
21+
let error = errors[0]
22+
23+
XCTAssertEqual(error.description, "Required property 'test' is missing")
24+
XCTAssertEqual(error.instanceLocation.path, "/0")
25+
XCTAssertEqual(error.keywordLocation?.path, "#/items/required")
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)