Skip to content

Commit

Permalink
Merge branch 'main' of github.com:andylockran/spectral-aws-apigateway…
Browse files Browse the repository at this point in the history
…-ruleset
  • Loading branch information
andylockran committed Apr 3, 2023
2 parents 1b54130 + 65d487b commit b080a53
Show file tree
Hide file tree
Showing 10 changed files with 3,459 additions and 1,581 deletions.
2 changes: 2 additions & 0 deletions .spectral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extends:
- spectral-aws-apigateway-ruleset
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"search.exclude": {
"**/node_modules": false
}
}
1 change: 1 addition & 0 deletions examples/petstore_aws.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ components:
type: integer
message:
type: string
additionalProperties: false
ArrayOfError:
type: "array"
items:
Expand Down
4,707 changes: 3,236 additions & 1,471 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "aws_important_notes.yml",
"scripts": {
"clean": "rm -rf functions/",
"build": "webpack",
"build": "./node_modules/.bin/esbuild src/draft4.mjs --bundle --outfile=functions/draft4.js --platform=node",
"test": "jest",
"test-build": "cp src/draft4.mjs functions/draft4.js && jest"
},
Expand All @@ -24,17 +24,20 @@
"dependencies": {
"ajv": "^8.5.0",
"ajv-draft-04": "^1.0.0",
"ajv-formats": "^2.1.0"
"ajv-formats": "^2.1.0",
"esbuild": "^0.17.15"
},
"devDependencies": {
"@babel/preset-env": "^7.14.1",
"@stoplight/spectral-core": "^1.16.1",
"@stoplight/spectral-parsers": "^1.0.2",
"@stoplight/spectral-ruleset-bundler": "^1.5.1",
"@stoplight/spectral-runtime": "^1.1.2",
"apigw-model-validator": "^1.1.0",
"babel-jest": "^29.5.0",
"jest": "^29.5.0",
"jest-json-schema": "^6.1.0",
"js-yaml": "^4.1.0",
"webpack": "^5.54.0",
"webpack-cli": "^5.0.1"
"js-yaml": "^4.1.0"
},
"jest": {
"verbose": true,
Expand All @@ -52,6 +55,6 @@
"^.+\\.js$": "babel-jest",
"^.+\\.mjs$": "babel-jest"
},
"testRegex": "((\\.|/*.)(spec))\\.js?$"
"testRegex": "((\\.|/*.)(spec))\\.(mjs|js)?$"
}
}
2 changes: 2 additions & 0 deletions src/__tests__/.spectral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extends:
- spectral-aws-apigateway-ruleset
98 changes: 54 additions & 44 deletions src/__tests__/draft4.spec.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,64 @@
import { doesNotMatch } from "assert";
import draft4 from "../draft4";
const yaml = require('js-yaml');
const fs = require('fs')
const AMV = require('apigw-model-validator')
const yaml = require("js-yaml");
const fs = require("fs");
const AMV = require("apigw-model-validator");

const validator = new AMV()
const validator = new AMV();

describe("JSONSchema Compile All", () => {
test("A schema should compile across all $refs", () => {
const input = yaml.load(fs.readFileSync('examples/petstore_aws.yaml', 'utf8'), {schema: yaml.DEFAULT_SCHEMA});
const output = [];
expect(draft4(input)).toEqual(output);
})
test("A schema should compile across all $refs", () => {
const input = yaml.load(
fs.readFileSync("examples/petstore_aws.yaml", "utf8"),
{ schema: yaml.DEFAULT_SCHEMA }
);
const output = [];
expect(draft4(input)).toEqual(output);
});

test("An object should match the schema", (done) => {
const input = yaml.load(fs.readFileSync('examples/petstore_aws.yaml', 'utf8'), {schema: yaml.DEFAULT_SCHEMA});
const pet = {
'name': 'Django',
'id': 123
}
const result = validator.isPayloadValid({
model: 'Pet',
test("An object should match the schema", (done) => {
const input = yaml.load(
fs.readFileSync("examples/petstore_aws.yaml", "utf8"),
{ schema: yaml.DEFAULT_SCHEMA }
);
const pet = {
name: "Django",
id: 123,
};
const result = validator
.isPayloadValid({
model: "Pet",
payload: pet,
schema: 'examples/petstore_aws.yaml'
}).then(data => {
expect(data).toEqual([])
done()
schema: "examples/petstore_aws.yaml",
})
})

test("An object should not match the schema", (done) => {
const pet = {
'name': 'Django',
'id': 123,
'age': 1
}
const result = validator.isPayloadValid({
model: 'Pets',
.then((data) => {
expect(data).toEqual([]);
done();
});
});

test("An object should not match the schema", (done) => {
const pet = {
name: "Django",
id: 123,
age: 1,
};
const result = validator
.isPayloadValid({
model: "Pets",
payload: pet,
schema: 'examples/petstore_aws.yaml'
}).catch(data => {
schema: "examples/petstore_aws.yaml",
})
.catch((data) => {
expect(data).toEqual([
{
instancePath: '',
schemaPath: '#/type',
keyword: 'type',
params: { type: 'array' },
message: 'must be array'
}
])
done()
})
})})
instancePath: "",
schemaPath: "#/type",
keyword: "type",
params: { type: "array" },
message: "must be array",
},
]);
done();
});
});
});
118 changes: 118 additions & 0 deletions src/__tests__/rules.spec.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
const path = require("path");
const fs = require("fs");
const yaml = require("js-yaml");

const { Spectral } = require("@stoplight/spectral-core");
const { fetch } = require("@stoplight/spectral-runtime"); // can also use isomorphic-fetch, etc.. If you ruleset does not reference any external assets, you can provide some stub instead.
const {
bundleAndLoadRuleset,
} = require("@stoplight/spectral-ruleset-bundler/with-loader");
const {
commonjs,
} = require("@stoplight/spectral-ruleset-bundler/plugins/commonjs"); // needed if you want to use CommonJS

expect.extend({
toFailWithRule(received, argument) {
const pass = this.equals(
received,
expect.arrayContaining([expect.objectContaining(argument)])
);

if (pass) {
return {
message: () =>
`expected ${this.utils.printReceived(
received
)} not to contain object ${this.utils.printExpected(argument)}`,
pass: true,
};
} else {
return {
message: () =>
`expected ${this.utils.printReceived(
received
)} to contain object ${this.utils.printExpected(argument)}`,
pass: false,
};
}
},
});

const spectral = new Spectral({});

let mutableTemplate;

beforeAll(async () => {
const rulesetFilepath = path.join(__dirname, ".spectral.yaml");
mutableTemplate = yaml.load(
fs.readFileSync("examples/petstore_aws.yaml", "utf8"),
{ schema: yaml.DEFAULT_SCHEMA }
);
spectral.setRuleset(
await bundleAndLoadRuleset(rulesetFilepath, { fs, fetch }, [commonjs()])
);
return spectral;
});

// beforeEach(async () => {
// mutableTemplate = undefined;
// });

describe("Testing each rule against example documents", () => {
test("aws-openapi-version should fail if the openapi version is set to 3.1.1", async () => {
let badDocument = mutableTemplate;
badDocument.openapi = "3.1.1";
// we lint our document using the ruleset we passed to the Spectral object
spectral.run(badDocument).then((spectralResultArray) => {
expect(spectralResultArray).toFailWithRule({
code: "aws-openapi-version",
});
});
});

test("aws-path-segments should fail if the path contains spaces", async () => {
let pathSegments = mutableTemplate;
pathSegments.paths = {
"this should not work as it has spaces": {
post: {
tags: ["pet"],
summary: "uploads an image",
description: "",
operationId: "uploadFile",
consumes: ["multipart/form-data"],
produces: ["application/json"],
},
},
};

// we lint our document using the ruleset we passed to the Spectral object
spectral.run(pathSegments).then((spectralResultArray) => {
expect(spectralResultArray).toFailWithRule({
code: "aws-path-segments",
});
});
});

test("aws-path-segments should not fail if the path is just a /", async () => {
let pathSegments = mutableTemplate;
pathSegments.paths = {
"/": {
post: {
tags: ["pet"],
summary: "uploads an image",
description: "",
operationId: "uploadFile",
consumes: ["multipart/form-data"],
produces: ["application/json"],
},
},
};

// we lint our document using the ruleset we passed to the Spectral object
spectral.run(pathSegments).then((spectralResultArray) => {
expect(spectralResultArray).not.toFailWithRule({
code: "aws-path-segments",
});
});
});
});
64 changes: 32 additions & 32 deletions src/draft4.mjs
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
import Ajv from "ajv-draft-04"
import Ajv from "ajv-draft-04";

const ajv = new Ajv({
"strict": true,
"validateFormats": false
strict: true,
validateFormats: false,
});

// Removed the checking of formats, as AWS API Gateway has additional formats, and
// will delegate to specific rules to make easier to spot compatible/incompatible formats.
//addFormats(ajv, ["date-time","email","hostname","ipv4","ipv6","uri"])

ajv.addKeyword("example"); // Added 'example' keyword as picked up by `aws-example-tag` rule.

// function validate_json() {

// };

module.exports = (targetVal, _opts, context) => {
let openapi = JSON.parse(JSON.stringify(targetVal))
const results = []
// };

const schemaList = openapi.components.schemas
var draft4 = (targetVal, _opts, context) => {
let openapi = JSON.parse(JSON.stringify(targetVal));
const results = [];
if (openapi.components.schemas) {
const schemaList = openapi.components.schemas;
for (const property in schemaList) {
if (Object.prototype.hasOwnProperty.call(schemaList, property)) {
const schema_model = schemaList[property]
schema_model.id = `#/components/schemas/${property}`
try {
let schema = schemaList[property]
ajv.addSchema(schema)
}
catch (error) {
console.log(`${property} failed to add due to ${error}`)
}

if (Object.prototype.hasOwnProperty.call(schemaList, property)) {
const schema_model = schemaList[property];
schema_model.id = `#/components/schemas/${property}`;
try {
let schema = schemaList[property];
ajv.addSchema(schema);
} catch (error) {
console.log(`${property} failed to add due to ${error}`);
}
}
}
for (const property in schemaList) {
try {
ajv.compile(schemaList[property])
}
catch (error) {
results.push({
"message": `${error}`,
"path": ['components', 'schemas', property]
})
}
try {
ajv.compile(schemaList[property]);
} catch (error) {
results.push({
message: `${error}`,
path: ["components", "schemas", property],
});
}
}
return results
}
}
return results;
};

export default draft4;
Loading

0 comments on commit b080a53

Please sign in to comment.