Skip to content

Commit 00652a8

Browse files
jianyexijianyexi
and
jianyexi
authored
fix rule index & support additionalProperties:true (#263)
* fix rule index * fix additional properties boolean * add removed test * fix test * fix test * fix test Co-authored-by: jianyexi <[email protected]>
1 parent 000f1f7 commit 00652a8

File tree

7 files changed

+264
-4
lines changed

7 files changed

+264
-4
lines changed

docs/README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,10 @@
9090

9191
[1045 - AddedOptionalProperty](rules/1045.md)
9292

93-
[1046 - RemovedOptionalParameter](rules/1046.md)
93+
[1046 - RemovedOptionalParameter](rules/1046.md)
94+
95+
[1047 - XmsEnumChanged](rules/1047.md)
96+
97+
[1048 - AddedXmsEnum](rules/1048.md)
98+
99+
[1049 - RemovedXmsEnum](rules/1049.md)

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@azure/oad",
3-
"version": "0.10.3",
3+
"version": "0.10.4",
44
"author": {
55
"name": "Microsoft Corporation",
66
"email": "[email protected]",

src/lib/util/resolveSwagger.ts

+57
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export class ResolveSwagger {
102102
this.unifyXMsPaths()
103103
this.ConvertPathLevelParameter()
104104
this.ExpandDefinitions()
105+
this.ConvertAdditionalProperty()
105106
this.generateNew()
106107
return this.innerSwagger
107108
}
@@ -145,6 +146,62 @@ export class ResolveSwagger {
145146
}
146147
}
147148
}
149+
150+
public ConvertAdditionalProperty() {
151+
if (!this.innerSwagger) {
152+
throw new Error("Null swagger object")
153+
}
154+
const swagger = this.innerSwagger as any
155+
const paths = swagger.paths
156+
if (paths && paths instanceof Object && toArray(sm.keys(paths)).length > 0) {
157+
for (const v of sm.values(paths)) {
158+
for (const [key, o] of sm.entries(v as any)) {
159+
if (key.toLowerCase() !== "parameters") {
160+
const operationParam = (o as any).parameters ? (o as any).parameters : []
161+
operationParam.forEach((v: any) => v.schema && this.transformAdditionalProperty(v.schema))
162+
const responses = (o as any).responses ? sm.values((o as any).responses) : []
163+
responses.forEach((v: any) => v.schema && this.transformAdditionalProperty(v.schema))
164+
} else {
165+
sm.values(o as any).forEach((v: any) => v.schema && this.transformAdditionalProperty(v.schema))
166+
}
167+
}
168+
}
169+
}
170+
if (swagger.definitions) {
171+
for (const o of sm.values(swagger.definitions)) {
172+
this.transformAdditionalProperty(o)
173+
}
174+
}
175+
if (swagger.parameters) {
176+
for (const o of sm.values(swagger.parameters)) {
177+
if ((o as any).schema) {
178+
this.transformAdditionalProperty((o as any).schema)
179+
}
180+
}
181+
}
182+
}
183+
184+
private transformAdditionalProperty(schema: any) {
185+
if (typeof schema?.additionalProperties === "boolean") {
186+
if (!schema?.additionalProperties) {
187+
delete schema.additionalProperties
188+
} else {
189+
schema.additionalProperties = {}
190+
}
191+
}
192+
if (schema.properties) {
193+
for (const v of sm.values(schema.properties)) {
194+
this.transformAdditionalProperty(v)
195+
}
196+
}
197+
198+
if (schema.allOf) {
199+
for (const v of sm.values(schema.allOf)) {
200+
this.transformAdditionalProperty(v)
201+
}
202+
}
203+
}
204+
148205
private ExpandDefinitions() {
149206
if (!this.innerSwagger) {
150207
throw new Error("Null swagger object")
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"swagger": "2.0",
3+
"info": {
4+
"title": "common_parameter_check_04",
5+
"version": "1.0"
6+
},
7+
"parameters": {
8+
"P0": {
9+
"name": "p0",
10+
"in": "query",
11+
"type": "string"
12+
},
13+
"P2": {
14+
"name": "p2",
15+
"in": "body",
16+
"schema": {
17+
"type": "object",
18+
"additionalProperties": true
19+
}
20+
}
21+
},
22+
"host": "localhost:8000",
23+
"schemes": [ "http", "https" ],
24+
"paths": {
25+
"/api/Operations": {
26+
"parameters": [
27+
{
28+
"$ref": "#/parameters/P0"
29+
},
30+
{
31+
"$ref": "#/parameters/P2"
32+
}
33+
],
34+
"get": {
35+
"operationId": "Operations_Get",
36+
"produces": [
37+
"text/plain"
38+
],
39+
"responses": {
40+
"default": {
41+
"description": "Error response describing why the operation failed.",
42+
"schema": {
43+
"additionalProperties": true
44+
}
45+
},
46+
"200": {
47+
"description": "operation successfully .",
48+
"schema": {
49+
"$ref":"#/definitions/Foo"
50+
}
51+
}
52+
}
53+
}
54+
}
55+
},
56+
"definitions": {
57+
"Foo": {
58+
"type":"object",
59+
"properties": {
60+
"bar": {
61+
"type":"object",
62+
"additionalProperties":true
63+
}
64+
}
65+
}
66+
}
67+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"swagger": "2.0",
3+
"info": {
4+
"title": "common_parameter_check_04",
5+
"version": "1.0"
6+
},
7+
"parameters": {
8+
"P0": {
9+
"name": "p0",
10+
"in": "query",
11+
"type": "string"
12+
},
13+
"P2": {
14+
"name": "p2",
15+
"in": "body",
16+
"schema": {
17+
"type": "object",
18+
"additionalProperties": false
19+
}
20+
}
21+
},
22+
"host": "localhost:8000",
23+
"schemes": [ "http", "https" ],
24+
"paths": {
25+
"/api/Operations": {
26+
"parameters": [
27+
{
28+
"$ref": "#/parameters/P0"
29+
},
30+
{
31+
"$ref": "#/parameters/P2"
32+
}
33+
],
34+
"get": {
35+
"operationId": "Operations_Get",
36+
"produces": [
37+
"text/plain"
38+
],
39+
"responses": {
40+
"default": {
41+
"description": "Error response describing why the operation failed.",
42+
"schema": {
43+
"additionalProperties": true
44+
}
45+
},
46+
"200": {
47+
"description": "operation successfully .",
48+
"schema": {
49+
"$ref":"#/definitions/Foo"
50+
}
51+
}
52+
}
53+
}
54+
}
55+
},
56+
"definitions": {
57+
"Foo": {
58+
"type":"object",
59+
"properties": {
60+
"bar": {
61+
"type":"object",
62+
"additionalProperties":true
63+
}
64+
}
65+
}
66+
}
67+
}

src/test/test.ts

+63
Original file line numberDiff line numberDiff line change
@@ -732,4 +732,67 @@ describe("index", () => {
732732
]
733733
assert.deepStrictEqual(result, expected)
734734
})
735+
736+
it("Additional Properties is boolean", async () => {
737+
const diff = new index.OpenApiDiff({})
738+
const oldFile = "src/test/additional-properties/old.json"
739+
const newFile = "src/test/additional-properties/new.json"
740+
const resultStr = await diff.compare(oldFile, newFile)
741+
const result = JSON.parse(resultStr)
742+
const newFilePath = fileUrl(path.resolve(newFile))
743+
const oldFilePath = fileUrl(path.resolve(oldFile))
744+
const expected = [
745+
{
746+
id: "1001",
747+
code: "NoVersionChange",
748+
message: "The versions have not changed.",
749+
old: {
750+
ref: `${oldFilePath}#`,
751+
path: "",
752+
location: `${oldFilePath}:1:1`
753+
},
754+
new: {
755+
ref: `${newFilePath}#`,
756+
path: "",
757+
location: `${newFilePath}:1:1`
758+
},
759+
type: "Info",
760+
docUrl: "https://github.com/Azure/openapi-diff/tree/master/docs/rules/1001.md",
761+
mode: "Update"
762+
},
763+
{
764+
code: "AddedAdditionalProperties",
765+
docUrl: "https://github.com/Azure/openapi-diff/tree/master/docs/rules/1021.md",
766+
id: "1021",
767+
message: "The new version adds an 'additionalProperties' element.",
768+
mode: "Addition",
769+
new: {
770+
location: ``,
771+
path: "paths./api/Operations.get.parameters",
772+
ref: ``
773+
},
774+
old: {},
775+
type: "Error"
776+
},
777+
{
778+
code: "AddedAdditionalProperties",
779+
docUrl: "https://github.com/Azure/openapi-diff/tree/master/docs/rules/1021.md",
780+
id: "1021",
781+
message: "The new version adds an 'additionalProperties' element.",
782+
mode: "Addition",
783+
new: {
784+
location: `${newFilePath}:16:7`,
785+
path: "parameters.P2.schema",
786+
ref: `${newFilePath}#/parameters/P2/schema`
787+
},
788+
old: {
789+
location: `${oldFilePath}:16:7`,
790+
path: "parameters.P2.schema",
791+
ref: `${oldFilePath}#/parameters/P2/schema`
792+
},
793+
type: "Error"
794+
}
795+
]
796+
assert.deepStrictEqual(result, expected)
797+
})
735798
})

0 commit comments

Comments
 (0)