Skip to content

Commit

Permalink
feat: error for parameter without schema or content
Browse files Browse the repository at this point in the history
Purpose:
- OAS3 schema requires that either a schema or a content object must be defined for any parameter. Tooling based on OAS3 will expect parameters to have a schema or content.

Changes:
- Add check that a schema is provided in content objects for parameters.
- Check that schema or content object provided for all parameters.

Test:
- Add test to ensure that error returned for parameter with no schema and no content objects.
- Add test to ensure a warning given for a content object in a parameter with no schema object.

Docs:
- Document the parameter-contains-schema rule.
  • Loading branch information
Barrett Schonefeld authored and barrett-schonefeld committed Apr 21, 2021
1 parent 6e9d3a9 commit 8b6e8bd
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 17 deletions.
26 changes: 26 additions & 0 deletions docs/spectral-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,32 @@ Validates that every path contains a path segment for the API major version, of

**Default Severity**: warn

## parameter-schema-or-content

Parameters must provide either a schema or content object.

**Bad Example**

```yaml
parameters:
- name: param1
in: query
description: query param
```

**Good Example**

```yaml
parameters:
- name: param1
in: query
description: query param
schema:
type: string
```

**Default Severity**: error

## response-example-provided

Response examples are used to generate documentation. To improve the generated documentation, response examples should be provided in the schema object or "next to" the schema object.
Expand Down
15 changes: 13 additions & 2 deletions src/spectral/rulesets/.defaultsForSpectral.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ functions:
- check-major-version
- error-response-schema
- response-example-provided
- schema-or-content-provided
rules:

# Original list created from Spectral with:
Expand Down Expand Up @@ -112,10 +113,10 @@ rules:
function: truthy
# custom Spectral rule to ensure content object contains schema
content-entry-contains-schema:
description: Content entries in request and response bodies must specify a schema
description: Content entries must specify a schema
given:
- $.paths[*].[post,put,patch].requestBody.content[*]
- $.paths[*].[get,post,put,patch,delete].responses[*].content[*]
- $.paths[*].[get,post,put,patch,delete].[parameters,responses][*].content[*]
severity: warn
resolved: true
then:
Expand Down Expand Up @@ -147,3 +148,13 @@ rules:
severity: warn
then:
function: check-major-version
# ensure parameter contains schema
parameter-schema-or-content:
description: 'Parameter must provide either a schema or content'
message: "{{error}}"
severity: error
formats: ["oas3"]
resolved: true
given: $.paths[*][*].parameters[*]
then:
function: schema-or-content-provided
9 changes: 9 additions & 0 deletions src/spectral/rulesets/ibm-oas/schema-or-content-provided.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = function(obj) {
if (!obj.schema && !obj.content) {
return [
{
message: 'Parameter must provide either a schema or content'
}
];
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ describe('spectral - test validation that schema provided in content object', fu

const res = await inCodeValidator(spec, true);
const expectedWarnings = res.warnings.filter(
warn =>
warn.message ===
'Content entries in request and response bodies must specify a schema'
warn => warn.message === 'Content entries must specify a schema'
);
expect(expectedWarnings.length).toBe(0);
});
Expand Down Expand Up @@ -67,9 +65,7 @@ describe('spectral - test validation that schema provided in content object', fu

const res = await inCodeValidator(spec, true);
const expectedWarnings = res.warnings.filter(
warn =>
warn.message ===
'Content entries in request and response bodies must specify a schema'
warn => warn.message === 'Content entries must specify a schema'
);
expect(expectedWarnings.length).toBe(1);
});
Expand Down Expand Up @@ -103,9 +99,7 @@ describe('spectral - test validation that schema provided in content object', fu

const res = await inCodeValidator(spec, true);
const expectedWarnings = res.warnings.filter(
warn =>
warn.message ===
'Content entries in request and response bodies must specify a schema'
warn => warn.message === 'Content entries must specify a schema'
);
expect(expectedWarnings.length).toBe(1);
});
Expand Down Expand Up @@ -140,9 +134,7 @@ describe('spectral - test validation that schema provided in content object', fu

const res = await inCodeValidator(spec, true);
const expectedWarnings = res.warnings.filter(
warn =>
warn.message ===
'Content entries in request and response bodies must specify a schema'
warn => warn.message === 'Content entries must specify a schema'
);
expect(expectedWarnings.length).toBe(2);
});
Expand All @@ -168,10 +160,49 @@ describe('spectral - test validation that schema provided in content object', fu

const res = await inCodeValidator(spec, true);
const expectedWarnings = res.warnings.filter(
warn =>
warn.message ===
'Content entries in request and response bodies must specify a schema'
warn => warn.message === 'Content entries must specify a schema'
);
expect(expectedWarnings.length).toBe(1);
});

it('should error when the content object does not contain a schema in a parameter', async () => {
const spec = {
openapi: '3.0.0',
paths: {
createPet: {
post: {
operationId: 'addPet',
parameters: [
{
name: 'exampleParam1',
description: 'example param 1',
in: 'query',
content: {
'application/json': {
// no schema provided
}
}
},
{
name: 'exampleParam2',
description: 'example param 2',
in: 'query',
content: {
'application/json': {
// no schema provided
}
}
}
]
}
}
}
};

const res = await inCodeValidator(spec, true);
const expectedWarnings = res.warnings.filter(
warn => warn.message === 'Content entries must specify a schema'
);
expect(expectedWarnings.length).toBe(2);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const inCodeValidator = require('../../../../src/lib');

describe('spectral - test validation that schema provided in content object', function() {
it('should error only when parameter does not provide a schema or content', async () => {
const spec = {
openapi: '3.0.0',
paths: {
createPet: {
post: {
operationId: 'addPet',
parameters: [
{
name: 'exampleParam1',
description: 'example param 1',
in: 'query'
// no schema or content object
}
]
}
},
createOwner: {
post: {
operationId: 'addOwner',
parameters: [
{
name: 'exampleParam1',
description: 'example param 1',
in: 'query',
schema: {
type: 'string'
}
},
{
name: 'exampleParam2',
description: 'example param 2',
in: 'query',
content: {
'application/json': {
schema: {
type: 'string'
}
}
}
}
]
}
}
}
};

const res = await inCodeValidator(spec, true);
const expectedErrors = res.errors.filter(
err => err.message === 'Parameter must provide either a schema or content'
);
expect(expectedErrors.length).toBe(1);
});
});

0 comments on commit 8b6e8bd

Please sign in to comment.