Skip to content

Commit

Permalink
Feat: Complete initial set of test cases and refine JSONPath expressi…
Browse files Browse the repository at this point in the history
…ons for JSON:API rules

This commit marks the completion of detailed test cases for several JSON:API error object rulesets, including:
- errors-error-objects-array-structure
- errors-error-objects-object-structure
- errors-error-objects-object-structure-length
- errors-error-objects-items-id-type
- errors-error-objects-items-links-type
- errors-error-objects-items-links
- errors-error-objects-items-links-structure-length
- errors-error-objects-items-links-about-type
- errors-error-objects-items-links-about-format
- errors-error-objects-items-links-type-type
- errors-error-objects-items-links-type-format

Significant changes have been made to the JSONPath expressions and functions within these rulesets to enhance accuracy and efficiency. Notably, an issue with the 'errors-error-objects-array-structure' rule has been resolved by switching from a custom function to the 'enumeration' predefined function, simplifying the validation process and adhering to the prerequisite of using only predefined functions.

Remaining tasks include completing test cases for the following rulesets:
- errors-error-objects-items-status-type
- errors-error-objects-items-code-type
- errors-error-objects-items-title-type
- errors-error-objects-items-detail-type
- errors-error-objects-items-source-type
- errors-error-objects-items-source
- errors-error-objects-items-source-pointer-type
- errors-error-objects-items-source-parameter-type
- errors-error-objects-items-source-header-type
- errors-error-objects-items-source-structure-length
- errors-error-objects-items-items-type

These updates significantly improve the robustness and reliability of the JSON:API error object validation process.
  • Loading branch information
ezenity committed Nov 29, 2023
1 parent 77d0564 commit 8fd5837
Show file tree
Hide file tree
Showing 16 changed files with 3,120 additions and 623 deletions.
268 changes: 109 additions & 159 deletions rules/jsonapi-errors-error-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

// All rules in the file MUST have corresponding tests

import { enumeration, length, schema } from '@stoplight/spectral-functions';
import validatePropertiesWithCriteria from '../functions/validatePropertyType.js';
import { enumeration, length, schema, truthy } from '@stoplight/spectral-functions';

export default {
documentationUrl: 'https://jsonapi.org/format/#error-objects',
Expand Down Expand Up @@ -42,82 +41,16 @@ export default {
description: 'Error objects must be returned in an array under `errors` key.',
message: '{{path}} - {{error}}',
severity: 'error',
// given: "$.paths.*.*.responses.[?(@property >= '400' && @property <= '599')].content.*.schema.properties",
// given: "$.paths.*.*.responses.['400'].content.*.schema.properties",
// given: "$.paths.*.*.responses.['400'].content.*.schema.properties.errors",
// given: "$.paths.*.*.responses.*[?(@property === 'errors')]",
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property ==='properties')]",
// given: "$..[?(@property === '400')]..[*[?(@property ==='properties')]",
// given: "$.components.schemas.JsonApiError.properties.errors",
then: [
// {
// function: schema,
// functionOptions: {

// // schema: {
// // type: 'object',
// // not: {
// // properties: {
// // type: {
// // const: 'object'
// // }
// // }
// // },
// // properties: {
// // errors: {
// // const: 'array'
// // // items: { type: 'object' }
// // }
// // }
// // // ,
// // // required: ['errors']
// // }

// // schema: {
// // type: 'array',
// // items: {
// // type: 'object',
// // properties: {
// // // Error Object Properties here
// // }
// // // constraints here if needed
// // }
// // }

// schema: {
// type: 'array'
// }

// }
// }


{
function: validatePropertiesWithCriteria,
functionOptions: {
propertyName: 'errors',
propertyType: 'array'
}
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]]",
then: {
field: 'type',
function: enumeration,
functionOptions: {
values: [
'array'
]
}

// {
// function: schema,
// functionOptions: {
// schema: {
// type: 'object',
// properties: {
// type: {
// type: 'string',
// enum: ['array']
// },
// items: {
// type: 'object'
// }
// }
// }
// }
// }
]
}
},

/**
Expand All @@ -130,60 +63,22 @@ export default {
message: '{{path}} - {{description}}',
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties",
// given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items",
// given: "$..paths.*.*.responses.*.content.*.schema.properties.errors[*]",
// given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property ==='errors')]",
then:
// {
// // field: "",
// function: schema,
// functionOptions: {
// schema: {
// // Original type: 'object'
// // type: 'string',
// // properties: {
// // id: { type: 'string' },
// // links: { type: 'object' },
// // status: { type: 'string' },
// // code: { type: 'string' },
// // title: { type: 'string' },
// // detail: { type: 'string' },
// // source: { type: 'object' },
// // meta: { type: 'object' }
// // },
// // minProperties: 1

// // Only check members
// properties: {
// id,
// links,
// status,
// code,
// title,
// detail,
// source,
// meta
// },
// }
// }
// }

{
field: '@key',
function: enumeration,
functionOptions: {
values: [
'id',
'links',
'status',
'code',
'title',
'detail',
'source',
'meta'
]
}
then: {
field: '@key',
function: enumeration,
functionOptions: {
values: [
'id',
'links',
'status',
'code',
'title',
'detail',
'source',
'meta'
]
}
}
},

/**
Expand Down Expand Up @@ -211,17 +106,17 @@ export default {
* This rule is crucial for maintaining consistency in error object identifiers.
*/
'errors-error-objects-items-id-type': {
description: 'Id member in "errors" array must by of type "string".',
description: 'Id member in `errors` array must by of type `string`.',
message: '{{path}} - {{description}}',
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.id",
then: {
function: schema,
field: 'type',
function: enumeration,
functionOptions: {
schema: {
// Original type: 'string'
type: 'string'
}
values: [
'string'
]
}
}
},
Expand All @@ -236,11 +131,12 @@ export default {
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links",
then: {
function: schema,
field: 'type',
function: enumeration,
functionOptions: {
schema: {
type: 'object'
}
values: [
'object'
]
}
}
},
Expand Down Expand Up @@ -271,7 +167,7 @@ export default {
* Ensures that each 'links' object contains only one or two specified members.
*/
'errors-error-objects-items-links-structure-length': {
description: 'Links objects must only contain the specified members.',
description: 'Links objects must only contain the specified members and not be empty.',
message: '{{path}} - {{description}}',
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links",
Expand All @@ -286,43 +182,97 @@ export default {
},

/**
* Checks that the 'about' member in 'links' objects is a well-formed URI string.
* Checks that the 'about' member in 'links' objects is a the correct type, string.
* This rule is essential for ensuring that reference URLs in error objects are valid.
*/
'errors-error-objects-items-links-about-type': {
description: 'About member in the Links object must be of type "string" in the format of an "URI".',
description: '`About` member in the Links object must be of type `string`.',
message: '{{path}} - {{description}}',
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links.about",
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links.properties.about",
then: {
function: schema,
field: 'type',
function: enumeration,
functionOptions: {
schema: {
type: 'string',
format: 'uri'
}
values: [
'string'
]
}
}
},

/**
* Checks that the 'about' member in 'links' objects is a well-formed URI string.
* This rule is essential for ensuring that reference URLs in error objects are valid.
*/
'errors-error-objects-items-links-about-format': {
description: '`About` member in the Links object must be in the format of an `URI`.',
message: '{{path}} - {{description}}',
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links.properties.about",
then: [
{
field: 'format',
function: truthy
},
{
field: 'format',
function: enumeration,
functionOptions: {
values: [
'uri'
]
}
}
]
},

/**
* Validates te structure of the 'type' member in 'links' objects within error arrays.
* Ensures that it is a string formatted as a URI, aligning with JSON:API specifications.
* Ensures that it is a string, aligning with JSON:API specifications.
*/
'errors-error-objects-items-links-type-type': {
description: 'Type member in the Links object must be of type "string" in the format of an "URI".',
description: '`Type` member in the Links object must be of type "string".',
message: '{{path}} - {{description}}',
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links.type",
then: {
function: schema,
functionOptions: {
schema: {
type: 'string',
format: 'uri'
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links.properties.type",
then: [
{
field: 'type',
function: enumeration,
functionOptions: {
values: [
'string'
]
}
}
}
]
},

/**
* Validates te structure of the 'type' member in 'links' objects within error arrays.
* Ensures that it is a string formatted as a URI, aligning with JSON:API specifications.
*/
'errors-error-objects-items-links-type-format': {
description: '`Type` member in the Links object must have format of an "URI".',
message: '{{path}} - {{description}}',
severity: 'error',
given: "$..[?(@property >= '400' && @property <= '599')]..[*[?(@property === 'errors')]].items.properties.links.properties.type",
then: [
{
field: 'format',
function: truthy
},
{
field: 'format',
function: enumeration,
functionOptions: {
values: [
'uri'
]
}
}
]
},

/**
Expand Down
Loading

0 comments on commit 8fd5837

Please sign in to comment.