docs: update to assertions
What/Why/How?
Docs for a desired update to assertions.
- Change
contexttoif. - Change
iflist to conform to assertion object (see the docs --if,message, suggest,severityare ignored when used inside of theiflist. The assertion object in theiflist must contain the subject and at least one assertion (such asdefined: true`). - Add support for 3 additional locator properties:
filterInParentKeys,filterOutParentKeys,matchParentKeys(regex). See the docs for more details. - Remove
undefinedbecause it is the same asdefined: false. - Add support for message placeholders as described in the documentation:
{{assertionName}}, {{subject}}, {{property}}, {{problems}}.
Reference
This would replace various other tickets:
- #855
- #781
- #714
This would influence #780 because a custom function could provide a list of problems (which are added to the problems list used for the placeholders) so the return signature would need to be able to include that.
Testing
This is the docs only.
Coverage report
St.:grey_question: |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🟡 | Statements | 73.04% | 3256/4458 |
| 🟡 | Branches | 64.73% | 1808/2793 |
| 🟡 | Functions | 65.46% | 544/831 |
| 🟡 | Lines | 72.94% | 3024/4146 |
Test suite run success
498 tests passing in 85 suites.
Report generated by 🧪jest coverage report action from 5a8e8fb7e2d0cb44385b2484f500b74f7e1eccf5
In case we have assertion like this (I know it doesn't make much sense but Im interested in implementation behaviour):
assert/put-200-and-201:
subject:
- ResponsesMap
if:
- subject:
- PathsMap
- Operation
filterInParentKeys:
- put
- /path
defined: true
message: Must mutually define 200 and 201 responses for PUT requests.
severity: error
mutuallyRequired:
- '200'
- '201'
Will it apply assertion for ResponsesMap inside PathsMap AND ResponsesMap inside Operation (like 2 separate assertions) ? Or ResponsesMap which is inside of Operation which is inside of PathsMap (I dont like this approach because it requires strong knowledge of types hierarchy and correct order in subject field but on the other side adds possibility to create more specific selectors)?
@roman-sainchuk the first one (like 2 separate assertions).
I'm not sure if we want to support array for subject at all.
I'd say to support array only for top level subject field. As for me its not clear how it supposed to work if we have several items in where list where each of them has multiple subjects
I would just remove this to simplify things.
Add support for 3 additional locator properties:
filterInParentKeys,filterOutParentKeys,matchParentKeys(regex). See the docs for more details.
From my understanding these properties are mutually exclusive along with property locator. Is that correct?
From my understanding these properties are mutually exclusive along with property locator. Is that correct?
No, I don't think so. Let's sync tomorrow.
I agree with simplifying if possible. Flattening the subject may be fine.
Those properties (filterInParentKeys, filterOutParentKeys, matchParentKeys) shouldn't be mutually exclusive, and people should be aware they could create nonsense combinations (as is with most things in life):
filterInParentKeys:
- put
filterOutParentKeys:
- put
We had a small discussion with @ohorbachevskyi about new syntax and ended up with idea to put top level subject, property, new locators and assertion inside do block. So this way users have better visual separation of preconditions and assertion's action itself.
Example:
assert/put-200-and-201:
where:
- subject: Operation
filterInParentKeys:
- put
defined: true
do:
subject: ResponsesMap
mutuallyRequired:
- '200'
- '201'
message: Must mutually define 200 and 201 responses for PUT requests.
severity: error
I think do block can be even a list as well as where block where we can define different assertions or different subjects.
Example:
assert/put-200-and-201:
where:
- subject: Operation
filterInParentKeys:
- put
defined: true
do:
- subject: ResponsesMap
mutuallyRequired:
- '200'
- '201'
- subject: Parameter
property: in
defined: true
message: Must mutually define 200 and 201 responses for PUT requests and define in parameter.
severity: error
I wonder if this:
assert/media-type-map-not-pdf:
subject: MediaTypesMap
disallowed: ['application/pdf']
where:
- subject: Operation
filterOutParentKeys:
- put
could be expressed with the following:
assert/media-type-map-not-pdf:
subject: MediaTypesMap
disallowed: ['application/pdf']
where:
- subject: PathItem
disallowed:
- put
If yes, having filterIn/Out/matchParentKeys sounds redundant.
@adamaltman, @RomanHotsiy what do you think? Am I missing something?
could be expressed with the following:
It can't. The where condition will eliminate the whole PathItem that has put property in it, not only put operation.
Ah, indeed, thanks. I'm constantly forgetting about this 🙂.
I'm not sure about the do word. I feel it is used in combination with while and introduces the same confusion as if without else.
There is a language Gherkin (used for describing behavior) which used the keywords Given, When, Then. I'm not saying this because those keywords make sense in our system (they don't IMO), but I think there are actually 3 parts here:
- subject evaluated (maybe name
subjectand renamesubjecttotype) - additional conditions (
where) - assertions (maybe we call them
assertions? it's the most logical word)
The before:
assert/operation-id-delete:
context:
- type: Operation
matchParentKeys:
- delete
subject: Operation
property: operationId
pattern: /Delete/
casing: PascalCase
The result:
assert/operation-id-delete:
where:
- type: Operation
filterInParentKeys:
- delete
subject:
type: Operation
property: operationId
assertions:
pattern: /Delete/
casing: PascalCase
However, that specific example wouldn't require the where, it could be:
assert/operation-id-delete:
subject:
type: Operation
property: operationId
filterInParentKeys:
- delete
assertions:
pattern: /Delete/
casing: PascalCase
Also, I found a practical use case that requires where (because Webhooks also have PathItem objects):
assert/path-must-be-ref-file:
subject:
type: PathItem
where:
- type: PathsMap
assertions:
ref: /^(.\/paths|paths)\/.*yaml$/
I reworked it more and decided to open it as a separate PR: https://github.com/Redocly/redocly-cli/pull/917