Class: SpecGuard::RSpec::ViolationRenderer
- Inherits:
-
Object
- Object
- SpecGuard::RSpec::ViolationRenderer
- Defined in:
- lib/specguard/rspec/violation_renderer.rb
Overview
Renders json_schemer's structured validation errors in the grammar and
the order used by open-test-intent's bin/validate-intent.
Why not just print json_schemer's own message?
Because the protocol repo ships a validator, and "client and platform
agree on what's valid" is worth very little if the two tools say
different things about the same annotation. The verdicts already agree:
the v1 schema uses only type / enum / required /
additionalProperties / properties / items / minLength, all of
which both implementations support. The messages do not agree at all:
reference layer: value 'e2e' is not one of ['unit', 'integration', ...]
json_schemer value at `/layer` is not one of: ["unit", "integration", ...]
So the text is rebuilt here. It is rebuilt from the structured fields
of each error (type, data_pointer, schema, details.missing_keys)
and never by string-munging error["error"]: that sentence is
gem-version-dependent, so a json_schemer bump would silently drift the
output away from the reference. Structured fields are the gem's API;
the sentence is not.
Three divergences that are not wording
-
Order. json_schemer emits in its own traversal order —
additionalPropertiesbeforerequired,minLengthbeforerequired. The reference walks the document deliberately (seevalidateatbin/validate-intent:150-210): per node,type, thenenum, then every missingrequiredkey in schema order, then each instance property in insertion order (recursing, or reporting the disallowed additional property), then array, string and number keywords. #render reproduces that traversal as a sort key rather than re-walking the document, so the two tools list the same violations in the same sequence. -
Cardinality. Two missing required keys are one json_schemer error carrying
details.missing_keys = ["action", "layer"]; the reference prints one line per key (its loop atbin/validate-intent:163-165). The batch is fanned back out here. -
additionalPropertiesdoes not have the type you would guess. It arrives astype: "schema"(schema_pointer/additionalProperties,schemaliterallyfalse) withdata_pointeron the offending property —/entiity, not the object that disallowed it. A renderer dispatching on a guessed"additionalProperties"would render nothing for this case, silently. The error is re-attributed to the parent object here, which is what makes the reference's<root>: additional property 'entiity' is not allowedcome out.
A fourth, smaller one: the reference returns as soon as a node's type
is wrong ("a type mismatch makes the remaining keywords moot"), while
json_schemer reports the type failure and every other keyword at that
node — a non-string layer yields both a type and an enum error. See
#drop_shadowed_by_type_mismatch.
Defined Under Namespace
Classes: Entry
Constant Summary collapse
- ROOT =
What the reference calls the document root in a message.
"<root>"- RANK_TYPE =
Keyword ranks within one node, in the reference's evaluation order. Children start at CHILD_BASE so every keyword of a node sorts before any of its descendants — which is exactly what
required-before- property-iteration means. 0- RANK_ENUM =
1- RANK_REQUIRED =
2- RANK_MIN =
minItems / minLength / minimum — instance types are disjoint
3- RANK_MAX =
maxItems / maxLength / maximum
4- RANK_PATTERN =
5- RANK_UNKNOWN =
9- CHILD_BASE =
10- JSON_TYPE_NAMES =
typevalues json_schemer uses for a failedtypekeyword. A union ("type": ["string", "null"]) reports the literal"type"instead. %w[object array string integer number boolean null].freeze
- TYPE_KEYWORD =
"type"- REQUIRED_KEYWORD =
"required"- SUBSCHEMA_KEYWORD =
json_schemer's error
typefor a subschema that rejected the instance without a more specific keyword to blame.additionalProperties: falseis one such subschema — and the only one the v1 schema contains — but a literalfalseschema or an unmatchednotreports identically. The name is deliberately the general one; #additional_properties? is what narrows it, so a schema revision that grows anotrenders json_schemer's sentence instead of a nonsense "additional property" line about a property that was declared. "schema"- ADDITIONAL_PROPERTIES_POINTER =
"/additionalProperties"
Instance Method Summary collapse
-
#render(errors, instance) ⇒ Array<String>
Reason lines, reference grammar, reference order.
Instance Method Details
#render(errors, instance) ⇒ Array<String>
Returns reason lines, reference grammar, reference order.
105 106 107 108 109 |
# File 'lib/specguard/rspec/violation_renderer.rb', line 105 def render(errors, instance) entries = errors.each_with_index.flat_map { |error, seq| entries_for(error, instance, seq) } drop_shadowed_by_type_mismatch(entries).sort_by(&:sort_key).map(&:message) end |