diff --git a/lib/resolve-external.js b/lib/resolve-external.js index c7238fbd..4f92c4e5 100644 --- a/lib/resolve-external.js +++ b/lib/resolve-external.js @@ -58,17 +58,15 @@ function crawl (obj, path, $refs, options) { if ($Ref.isExternal$Ref(obj)) { promises.push(resolve$Ref(obj, path, $refs, options)); } - else { - for (let key of Object.keys(obj)) { - let keyPath = Pointer.join(path, key); - let value = obj[key]; - - if ($Ref.isExternal$Ref(value)) { - promises.push(resolve$Ref(value, keyPath, $refs, options)); - } - else { - promises = promises.concat(crawl(value, keyPath, $refs, options)); - } + for (let key of Object.keys(obj)) { + let keyPath = Pointer.join(path, key); + let value = obj[key]; + + if ($Ref.isExternal$Ref(value)) { + promises.push(resolve$Ref(value, keyPath, $refs, options)); + } + else { + promises = promises.concat(crawl(value, keyPath, $refs, options)); } } } diff --git a/test/specs/external-root/bundled.js b/test/specs/external-root/bundled.js new file mode 100644 index 00000000..2642c17b --- /dev/null +++ b/test/specs/external-root/bundled.js @@ -0,0 +1,10 @@ +"use strict"; + +module.exports = { + external2: { + $ref: "definitions-other.yaml#/external2" + }, + thing: { + type: "string" + } +}; diff --git a/test/specs/external-root/definitions-other.yaml b/test/specs/external-root/definitions-other.yaml new file mode 100644 index 00000000..4c283411 --- /dev/null +++ b/test/specs/external-root/definitions-other.yaml @@ -0,0 +1,3 @@ +external2: + thing: + type: string diff --git a/test/specs/external-root/definitions.yaml b/test/specs/external-root/definitions.yaml new file mode 100644 index 00000000..b94d0dde --- /dev/null +++ b/test/specs/external-root/definitions.yaml @@ -0,0 +1,3 @@ +external1: + thing: + type: string diff --git a/test/specs/external-root/dereferenced.js b/test/specs/external-root/dereferenced.js new file mode 100644 index 00000000..118327bd --- /dev/null +++ b/test/specs/external-root/dereferenced.js @@ -0,0 +1,13 @@ +"use strict"; + +module.exports = +{ + thing: { + type: "string" + }, + external2: { + thing: { + type: "string" + } + } +}; diff --git a/test/specs/external-root/external-root.spec.js b/test/specs/external-root/external-root.spec.js new file mode 100644 index 00000000..d0b5221f --- /dev/null +++ b/test/specs/external-root/external-root.spec.js @@ -0,0 +1,62 @@ +"use strict"; + +const { expect } = require("chai"); +const $RefParser = require("../../../lib"); +const helper = require("../../utils/helper"); +const path = require("../../utils/path"); +const parsedSchema = require("./parsed"); +const dereferencedSchema = require("./dereferenced"); +const bundledSchema = require("./bundled"); + +/** + * This test is from PR # + * https://github.com/APIDevTools/json-schema-ref-parser/pull/62 + */ +describe("Schema with external root refs", () => { + it("should parse successfully from an absolute path", async () => { + let parser = new $RefParser(); + const schema = await parser.parse(path.abs("specs/external-root/external-root.yaml")); + expect(schema).to.equal(parser.schema); + expect(schema).to.deep.equal(parsedSchema.schema); + expect(parser.$refs.paths()).to.deep.equal([path.abs("specs/external-root/external-root.yaml")]); + }); + + it("should parse successfully from a relative path", async () => { + let parser = new $RefParser(); + const schema = await parser.parse(path.rel("specs/external-root/external-root.yaml")); + expect(schema).to.equal(parser.schema); + expect(schema).to.deep.equal(parsedSchema.schema); + expect(parser.$refs.paths()).to.deep.equal([path.abs("specs/external-root/external-root.yaml")]); + }); + + it("should parse successfully from a url", async () => { + let parser = new $RefParser(); + const schema = await parser.parse(path.url("specs/external-root/external-root.yaml")); + expect(schema).to.equal(parser.schema); + expect(schema).to.deep.equal(parsedSchema.schema); + expect(parser.$refs.paths()).to.deep.equal([path.url("specs/external-root/external-root.yaml")]); + }); + + it("should resolve successfully", helper.testResolve( + path.abs("specs/external-root/external-root.yaml"), + path.abs("specs/external-root/external-root.yaml"), parsedSchema.schema, + path.abs("specs/external-root/definitions.yaml"), parsedSchema.definitions, + path.abs("specs/external-root/definitions-other.yaml"), parsedSchema.definitionsOther + )); + + it("should dereference successfully", async () => { + let parser = new $RefParser(); + const schema = await parser.dereference(path.rel("specs/external-root/external-root.yaml")); + expect(schema).to.equal(parser.schema); + expect(schema).to.deep.equal(dereferencedSchema); + // The "circular" flag should NOT be set + expect(parser.$refs.circular).to.equal(false); + }); + + it("should bundle successfully", async () => { + let parser = new $RefParser(); + const schema = await parser.bundle(path.rel("specs/external-root/external-root.yaml")); + expect(schema).to.equal(parser.schema); + expect(schema).to.deep.equal(bundledSchema); + }); +}); diff --git a/test/specs/external-root/external-root.yaml b/test/specs/external-root/external-root.yaml new file mode 100644 index 00000000..7a8a772f --- /dev/null +++ b/test/specs/external-root/external-root.yaml @@ -0,0 +1,3 @@ +$ref: 'definitions.yaml#/external1' +external2: + $ref: 'definitions-other.yaml#/external2' diff --git a/test/specs/external-root/parsed.js b/test/specs/external-root/parsed.js new file mode 100644 index 00000000..34e41ee6 --- /dev/null +++ b/test/specs/external-root/parsed.js @@ -0,0 +1,27 @@ +"use strict"; + +module.exports = +{ + schema: { + $ref: "definitions.yaml#/external1", + external2: { + $ref: "definitions-other.yaml#/external2" + }, + }, + + definitions: { + external1: { + thing: { + type: "string" + } + } + }, + + definitionsOther: { + external2: { + thing: { + type: "string" + } + } + } +};