Skip to content

Commit 1ba135a

Browse files
author
Oliver Rumbelow
committed
Merge pull request #130 from holidayextras/swagger-fixes
Swagger Improvements
2 parents d92bcf5 + 70ab5b0 commit 1ba135a

File tree

9 files changed

+95
-25
lines changed

9 files changed

+95
-25
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ env:
88
- TEST_STEP=lint
99
- TEST_STEP=flow
1010
- TEST_STEP=test
11+
- TEST_STEP=swagger
1112
notifications:
1213
email: false

lib/swagger/paths.js

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"use strict";
22
var swaggerPaths = module.exports = { };
33
var jsonApi = require("../../");
4+
var _ = {
5+
uniq: require("lodash.uniq")
6+
};
47

58

69
swaggerPaths.getPathDefinitions = function() {
@@ -40,31 +43,36 @@ swaggerPaths._addBasicPaths = function(paths, resourceName, resourceConfig) {
4043
handler: "search",
4144
resourceName: resourceName,
4245
description: "Search for " + resourceName,
43-
parameters: resourceConfig.searchParams
46+
parameters: resourceConfig.searchParams,
47+
hasPathId: false
4448
}),
4549
post: swaggerPaths._getPathOperationObject({
4650
handler: "create",
4751
resourceName: resourceName,
4852
description: "Create a new instance of " + resourceName,
49-
parameters: resourceConfig.attributes
53+
parameters: resourceConfig.attributes,
54+
hasPathId: false
5055
})
5156
};
5257

5358
paths["/" + resourceName + "/{id}"] = {
5459
get: swaggerPaths._getPathOperationObject({
5560
handler: "find",
5661
resourceName: resourceName,
57-
description: "Get a specific instance of " + resourceName
62+
description: "Get a specific instance of " + resourceName,
63+
hasPathId: true
5864
}),
5965
delete: swaggerPaths._getPathOperationObject({
6066
handler: "delete",
6167
resourceName: resourceName,
62-
description: "Delete an instance of " + resourceName
68+
description: "Delete an instance of " + resourceName,
69+
hasPathId: true
6370
}),
6471
patch: swaggerPaths._getPathOperationObject({
6572
handler: "update",
6673
resourceName: resourceName,
67-
description: "Update an instance of " + resourceName
74+
description: "Update an instance of " + resourceName,
75+
hasPathId: true
6876
})
6977
};
7078
};
@@ -73,7 +81,8 @@ swaggerPaths._addDeepPaths = function(paths, resourceName, resourceConfig, relat
7381
paths["/" + resourceName + "/{id}/" + relationName] = {
7482
get: swaggerPaths._getPathOperationObject({
7583
handler: "find",
76-
resourceName: relation
84+
resourceName: relation,
85+
hasPathId: true
7786
})
7887
};
7988

@@ -83,25 +92,29 @@ swaggerPaths._addDeepPaths = function(paths, resourceName, resourceConfig, relat
8392
handler: "find",
8493
resourceName: relation,
8594
relationType: relationType,
86-
extraTags: resourceName
95+
extraTags: resourceName,
96+
hasPathId: true
8797
}),
8898
post: swaggerPaths._getPathOperationObject({
8999
handler: "create",
90100
resourceName: relation,
91101
relationType: relationType,
92-
extraTags: resourceName
102+
extraTags: resourceName,
103+
hasPathId: true
93104
}),
94105
patch: swaggerPaths._getPathOperationObject({
95106
handler: "update",
96107
resourceName: relation,
97108
relationType: relationType,
98-
extraTags: resourceName
109+
extraTags: resourceName,
110+
hasPathId: true
99111
}),
100112
delete: swaggerPaths._getPathOperationObject({
101113
handler: "delete",
102114
resourceName: relation,
103115
relationType: relationType,
104-
extraTags: resourceName
116+
extraTags: resourceName,
117+
hasPathId: true
105118
})
106119
};
107120
};
@@ -116,7 +129,7 @@ swaggerPaths._getPathOperationObject = function(options) {
116129
description: options.resourceName + " " + options.handler + " response",
117130
schema: {
118131
type: "object",
119-
required: [ "jsonapi", "meta, links" ],
132+
required: [ "jsonapi", "meta", "links" ],
120133
properties: {
121134
jsonapi: {
122135
type: "object",
@@ -164,6 +177,7 @@ swaggerPaths._getPathOperationObject = function(options) {
164177
};
165178
if (options.extraTags) {
166179
pathDefinition.tags = pathDefinition.tags.concat(options.extraTags);
180+
pathDefinition.tags = _.uniq(pathDefinition.tags);
167181
}
168182

169183
var responseShortcut = pathDefinition.responses["200"].schema.properties;
@@ -180,7 +194,10 @@ swaggerPaths._getPathOperationObject = function(options) {
180194
if (((options.handler === "search") || (options.handler === "find")) && !options.relation) {
181195
pathDefinition.parameters = pathDefinition.parameters.concat(swaggerPaths._optionalJsonApiParameters());
182196
responseShortcut.included = {
183-
type: "array"
197+
type: "array",
198+
items: {
199+
type: "object"
200+
}
184201
};
185202
}
186203

@@ -214,7 +231,7 @@ swaggerPaths._getPathOperationObject = function(options) {
214231
pathDefinition.responses["200"] = undefined;
215232
}
216233

217-
if ((options.handler !== "search") && (options.handler !== "create")) {
234+
if (options.hasPathId) {
218235
pathDefinition.parameters.push({
219236
name: "id",
220237
in: "path",
@@ -258,7 +275,8 @@ swaggerPaths._optionalJsonApiParameters = function() {
258275
{ "$ref": "#/parameters/sort" },
259276
{ "$ref": "#/parameters/include" },
260277
{ "$ref": "#/parameters/filter" },
261-
{ "$ref": "#/parameters/fields" }
278+
{ "$ref": "#/parameters/fields" },
279+
{ "$ref": "#/parameters/page" }
262280
];
263281
};
264282

lib/swagger/resources.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,10 @@ swaggerPaths._getResourceDefinition = function(resourceConfig) {
3030
},
3131
"attributes": {
3232
type: "object",
33-
required: [ ],
3433
properties: { }
3534
},
3635
"relationships": {
3736
type: "object",
38-
required: [ ],
3937
properties: { }
4038
},
4139
"links": {
@@ -74,9 +72,10 @@ swaggerPaths._getResourceDefinition = function(resourceConfig) {
7472
}
7573
attributeShortcut[attribute] = swaggerScheme;
7674

77-
// if ((joiScheme._flags || { }).presence === "required") {
78-
// resourceDefinition.properties.attributes.required.push(attribute);
79-
// }
75+
if ((joiScheme._flags || { }).presence === "required") {
76+
resourceDefinition.properties.attributes.required = resourceDefinition.properties.attributes.required || [ ];
77+
resourceDefinition.properties.attributes.required.push(attribute);
78+
}
8079
} else {
8180
if (joiScheme._settings.as) continue;
8281

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"mocha-performance": "0.1.0",
4646
"node-inspector": "0.12.5",
4747
"plato": "1.5.0",
48+
"swagger-tools": "^0.10.1",
4849
"v8-profiler": "5.5.0"
4950
},
5051
"scripts": {
@@ -56,7 +57,8 @@
5657
"performance": "node --allow-natives-syntax --harmony ./node_modules/mocha/bin/_mocha -S --reporter mocha-performance ./test/*.js",
5758
"lint": "node ./node_modules/eslint/bin/eslint ./example ./lib ./test --quiet && echo '✔ All good!'",
5859
"jscpd": "jscpd --blame -p ./lib/ || echo 'Finished!'",
59-
"flow": "node ./node_modules/flow-bin/cli.js && echo '✔ All good!'"
60+
"flow": "node ./node_modules/flow-bin/cli.js && echo '✔ All good!'",
61+
"swagger": "node ./node_modules/mocha/bin/mocha -S -R spec ./swaggerValidator.js --timeout 60000"
6062
},
6163
"config": {
6264
"blanket": {

swaggerValidator.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"use strict";
2+
var jsonApiTestServer = require("./example/server.js");
3+
var request = require("request");
4+
var assert = require("assert");
5+
6+
describe("Use a tool to validate the generated swagger document", function() {
7+
it("should not contain any errors", function(done) {
8+
var validator = require("swagger-tools").specs.v2;
9+
10+
var uri = "http://localhost:16006/rest/swagger.json";
11+
request(uri, function(meh, res, swaggerObject) {
12+
swaggerObject = JSON.parse(swaggerObject);
13+
14+
validator.validate(swaggerObject, function (err, result) {
15+
assert.ifError(err);
16+
17+
if (!result) {
18+
console.log("Swagger document is valid");
19+
return done();
20+
}
21+
22+
if (result.errors.length > 0) {
23+
console.log("The Swagger document is invalid...");
24+
console.log("");
25+
console.log("Errors");
26+
console.log("------");
27+
console.log(result.errors);
28+
console.log("");
29+
}
30+
31+
if (result.warnings.length > 0) {
32+
console.log("Warnings");
33+
console.log("--------");
34+
console.log(result.warnings);
35+
}
36+
37+
done(new Error("Invalid swagger.json!"));
38+
});
39+
});
40+
});
41+
42+
before(function() {
43+
jsonApiTestServer.start();
44+
});
45+
after(function() {
46+
jsonApiTestServer.close();
47+
});
48+
});

test/get-resource-id.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use strict";
22
var assert = require("assert");
33
var helpers = require("./helpers.js");
4+
var request = require("request");
45
var jsonApiTestServer = require("../example/server.js");
56

67

@@ -38,7 +39,7 @@ describe("Testing jsonapi-server", function() {
3839

3940
it("with fields", function(done) {
4041
var url = "http://localhost:16006/rest/articles/de305d54-75b4-431b-adb2-eb6b9e546014?fields[articles]=title";
41-
helpers.request({
42+
request({
4243
method: "GET",
4344
url: url
4445
}, function(err, res, json) {

test/get-resource.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use strict";
22
var assert = require("assert");
33
var helpers = require("./helpers.js");
4+
var request = require("request");
45
var jsonApiTestServer = require("../example/server.js");
56

67

@@ -365,7 +366,7 @@ describe("Testing jsonapi-server", function() {
365366

366367
it("just title", function(done) {
367368
var url = "http://localhost:16006/rest/articles?fields[articles]=title";
368-
helpers.request({
369+
request({
369370
method: "GET",
370371
url: url
371372
}, function(err, res, json) {
@@ -384,7 +385,7 @@ describe("Testing jsonapi-server", function() {
384385

385386
it("title AND content", function(done) {
386387
var url = "http://localhost:16006/rest/articles?fields[articles]=title,content";
387-
helpers.request({
388+
request({
388389
method: "GET",
389390
url: url
390391
}, function(err, res, json) {

test/patch-resource-id.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ describe("Testing jsonapi-server", function() {
166166
}
167167
})
168168
};
169-
helpers.request(data, function(err, res, json) {
169+
request(data, function(err, res, json) {
170170
assert.equal(err, null);
171171
json = helpers.validateJson(json);
172172

test/post-resource.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe("Testing jsonapi-server", function() {
3636
}
3737
})
3838
};
39-
helpers.request(data, function(err, res, json) {
39+
request(data, function(err, res, json) {
4040
assert.equal(err, null);
4141
json = helpers.validateError(json);
4242
assert.equal(json.errors[0].detail.length, 2, "Expecting several validation errors");

0 commit comments

Comments
 (0)