diff --git a/src/core/plugins/samples/fn.js b/src/core/plugins/samples/fn.js
index 30e74132..d7fa8cad 100644
--- a/src/core/plugins/samples/fn.js
+++ b/src/core/plugins/samples/fn.js
@@ -1,4 +1,4 @@
-import { objectify, isFunc, normalizeArray } from "core/utils"
+import { objectify, isFunc, normalizeArray, deeplyStripKey } from "core/utils"
import XML from "xml"
import memoizee from "memoizee"
@@ -29,13 +29,14 @@ export const sampleFromSchema = (schema, config={}) => {
let { type, example, properties, additionalProperties, items } = objectify(schema)
let { includeReadOnly, includeWriteOnly } = config
- if(example && example.$$ref) {
- delete example.$$ref
+ if(example !== undefined) {
+ return deeplyStripKey(example, "$$ref", (val) => {
+ // do a couple of quick sanity tests to ensure the value
+ // looks like a $$ref that swagger-client generates.
+ return typeof val === "string" && val.indexOf("#") > -1
+ })
}
- if(example !== undefined)
- return example
-
if(!type) {
if(properties) {
type = "object"
diff --git a/src/core/utils.js b/src/core/utils.js
index 08450e73..913801ce 100644
--- a/src/core/utils.js
+++ b/src/core/utils.js
@@ -712,3 +712,25 @@ export const createDeepLinkPath = (str) => typeof str == "string" || str instanc
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str) )
export const getExtensions = (defObj) => defObj.filter((v, k) => /^x-/.test(k))
+
+// Deeply strips a specific key from an object.
+//
+// `predicate` can be used to discriminate the stripping further,
+// by preserving the key's place in the object based on its value.
+export function deeplyStripKey(input, keyToStrip, predicate = () => true) {
+ if(typeof input !== "object" || Array.isArray(input) || !keyToStrip) {
+ return input
+ }
+
+ const obj = Object.assign({}, input)
+
+ Object.keys(obj).forEach(k => {
+ if(k === keyToStrip && predicate(obj[k], k)) {
+ delete obj[k]
+ return
+ }
+ obj[k] = deeplyStripKey(obj[k], keyToStrip, predicate)
+ })
+
+ return obj
+}
diff --git a/test/components/model-example.js b/test/components/model-example.js
index f4225c30..eb8c8a27 100644
--- a/test/components/model-example.js
+++ b/test/components/model-example.js
@@ -6,23 +6,8 @@ import ModelExample from "components/model-example"
import ModelComponent from "components/model-wrapper"
describe("", function(){
- // Given
- let components = {
- ModelWrapper: ModelComponent
- }
- let props = {
- getComponent: (c) => {
- return components[c]
- },
- specSelectors: {},
- schema: {},
- example: "{\"example\": \"value\"}",
- isExecute: false,
- getConfigs: () => ({
- defaultModelRendering: "model",
- defaultModelExpandDepth: 1
- })
- }
+ let components, props
+
let exampleSelectedTestInputs = [
{ defaultModelRendering: "model", isExecute: true },
{ defaultModelRendering: "example", isExecute: true },
@@ -30,10 +15,31 @@ describe("", function(){
{ defaultModelRendering: "othervalue", isExecute: true },
{ defaultModelRendering: "othervalue", isExecute: false }
]
+
let modelSelectedTestInputs = [
{ defaultModelRendering: "model", isExecute: false }
]
+ beforeEach(() => {
+ components = {
+ ModelWrapper: ModelComponent
+ }
+
+ props = {
+ getComponent: (c) => {
+ return components[c]
+ },
+ specSelectors: {},
+ schema: {},
+ example: "{\"example\": \"value\"}",
+ isExecute: false,
+ getConfigs: () => ({
+ defaultModelRendering: "model",
+ defaultModelExpandDepth: 1
+ })
+ }
+ })
+
it("renders model and example tabs", function(){
// When
diff --git a/test/core/plugins/samples/fn.js b/test/core/plugins/samples/fn.js
index 5a969d9c..65fdd141 100644
--- a/test/core/plugins/samples/fn.js
+++ b/test/core/plugins/samples/fn.js
@@ -100,6 +100,92 @@ describe("sampleFromSchema", function() {
expect(sampleFromSchema(definition, { includeWriteOnly: true })).toEqual(expected)
})
+ it("returns object without any $$ref fields at the root schema level", function () {
+ var definition = {
+ type: "object",
+ properties: {
+ message: {
+ type: "string"
+ }
+ },
+ example: {
+ value: {
+ message: "Hello, World!"
+ },
+ $$ref: "#/components/examples/WelcomeExample"
+ },
+ $$ref: "#/components/schemas/Welcome"
+ }
+
+ var expected = {
+ "value": {
+ "message": "Hello, World!"
+ }
+ }
+
+ expect(sampleFromSchema(definition, { includeWriteOnly: true })).toEqual(expected)
+ })
+
+ it("returns object without any $$ref fields at nested schema levels", function () {
+ var definition = {
+ type: "object",
+ properties: {
+ message: {
+ type: "string"
+ }
+ },
+ example: {
+ a: {
+ value: {
+ message: "Hello, World!"
+ },
+ $$ref: "#/components/examples/WelcomeExample"
+ }
+ },
+ $$ref: "#/components/schemas/Welcome"
+ }
+
+ var expected = {
+ a: {
+ "value": {
+ "message": "Hello, World!"
+ }
+ }
+ }
+
+ expect(sampleFromSchema(definition, { includeWriteOnly: true })).toEqual(expected)
+ })
+
+ it("returns object with any $$ref fields that appear to be user-created", function () {
+ var definition = {
+ type: "object",
+ properties: {
+ message: {
+ type: "string"
+ }
+ },
+ example: {
+ $$ref: {
+ value: {
+ message: "Hello, World!"
+ },
+ $$ref: "#/components/examples/WelcomeExample"
+ }
+ },
+ $$ref: "#/components/schemas/Welcome"
+ }
+
+ var expected = {
+ $$ref: {
+ "value": {
+ "message": "Hello, World!"
+ }
+ }
+ }
+
+ expect(sampleFromSchema(definition, { includeWriteOnly: true })).toEqual(expected)
+ })
+
describe("for array type", function() {
it("returns array with sample of array type", function() {
var definition = {
@@ -108,12 +194,12 @@ describe("sampleFromSchema", function() {
type: "integer"
}
}
-
+
var expected = [ 0 ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
-
+
it("returns array of examples for array that has example", function() {
var definition = {
type: "array",
@@ -122,9 +208,9 @@ describe("sampleFromSchema", function() {
},
example: "dog"
}
-
+
var expected = [ "dog" ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
@@ -132,16 +218,16 @@ describe("sampleFromSchema", function() {
var definition = {
type: "array",
items: {
- type: "string",
+ type: "string",
},
example: [ "dog", "cat" ]
}
-
+
var expected = [ "dog", "cat" ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
-
+
it("returns array of samples for oneOf type", function() {
var definition = {
type: "array",
@@ -154,9 +240,9 @@ describe("sampleFromSchema", function() {
]
}
}
-
+
var expected = [ 0 ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
@@ -175,9 +261,9 @@ describe("sampleFromSchema", function() {
]
}
}
-
+
var expected = [ "string", 0 ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
@@ -198,12 +284,12 @@ describe("sampleFromSchema", function() {
]
}
}
-
+
var expected = [ "dog", 1 ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
-
+
it("returns array of samples for anyOf type", function() {
var definition = {
type: "array",
@@ -216,9 +302,9 @@ describe("sampleFromSchema", function() {
]
}
}
-
+
var expected = [ 0 ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
@@ -237,9 +323,9 @@ describe("sampleFromSchema", function() {
]
}
}
-
+
var expected = [ "string", 0 ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
@@ -260,9 +346,9 @@ describe("sampleFromSchema", function() {
]
}
}
-
+
var expected = [ "dog", 1 ]
-
+
expect(sampleFromSchema(definition)).toEqual(expected)
})
})
diff --git a/test/core/utils.js b/test/core/utils.js
index 99ee60d4..1c6b2beb 100644
--- a/test/core/utils.js
+++ b/test/core/utils.js
@@ -21,7 +21,8 @@ import {
createDeepLinkPath,
escapeDeepLinkPath,
sanitizeUrl,
- extractFileNameFromContentDispositionHeader
+ extractFileNameFromContentDispositionHeader,
+ deeplyStripKey
} from "core/utils"
import win from "core/window"
@@ -942,6 +943,58 @@ describe("utils", function() {
})
})
+ describe("deeplyStripKey", function() {
+ it("should filter out a specified key", function() {
+ const input = {
+ $$ref: "#/this/is/my/ref",
+ a: {
+ $$ref: "#/this/is/my/other/ref",
+ value: 12345
+ }
+ }
+ const result = deeplyStripKey(input, "$$ref")
+ expect(result).toEqual({
+ a: {
+ value: 12345
+ }
+ })
+ })
+
+ it("should filter out a specified key by predicate", function() {
+ const input = {
+ $$ref: "#/this/is/my/ref",
+ a: {
+ $$ref: "#/keep/this/one",
+ value: 12345
+ }
+ }
+ const result = deeplyStripKey(input, "$$ref", (v) => v !== "#/keep/this/one")
+ expect(result).toEqual({
+ a: {
+ value: 12345,
+ $$ref: "#/keep/this/one"
+ }
+ })
+ })
+
+ it("should only call the predicate when the key matches", function() {
+ const input = {
+ $$ref: "#/this/is/my/ref",
+ a: {
+ $$ref: "#/this/is/my/other/ref",
+ value: 12345
+ }
+ }
+ let count = 0
+
+ const result = deeplyStripKey(input, "$$ref", () => {
+ count++
+ return true
+ })
+ expect(count).toEqual(2)
+ })
+ })
+
describe("parse and serialize search", function() {
afterEach(function() {
win.location.search = ""