Filter $$ref from examples (#4392)
* fix(dev-server): don't open localhost in a browser * tests: refactor model-example enzyme tests to be more isolated * tests: add failing sampleFromSchema tests for $$ref keys * tests: add additional test for user-created $$ref values * fix: create deeplyStripKey; use it to filter $$refs out of examples * tests: add cases for deeplyStripKey
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { objectify, isFunc, normalizeArray } from "core/utils"
|
import { objectify, isFunc, normalizeArray, deeplyStripKey } from "core/utils"
|
||||||
import XML from "xml"
|
import XML from "xml"
|
||||||
import memoizee from "memoizee"
|
import memoizee from "memoizee"
|
||||||
|
|
||||||
@@ -29,13 +29,14 @@ export const sampleFromSchema = (schema, config={}) => {
|
|||||||
let { type, example, properties, additionalProperties, items } = objectify(schema)
|
let { type, example, properties, additionalProperties, items } = objectify(schema)
|
||||||
let { includeReadOnly, includeWriteOnly } = config
|
let { includeReadOnly, includeWriteOnly } = config
|
||||||
|
|
||||||
if(example && example.$$ref) {
|
if(example !== undefined) {
|
||||||
delete example.$$ref
|
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(!type) {
|
||||||
if(properties) {
|
if(properties) {
|
||||||
type = "object"
|
type = "object"
|
||||||
|
|||||||
@@ -712,3 +712,25 @@ export const createDeepLinkPath = (str) => typeof str == "string" || str instanc
|
|||||||
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str) )
|
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str) )
|
||||||
|
|
||||||
export const getExtensions = (defObj) => defObj.filter((v, k) => /^x-/.test(k))
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,11 +6,26 @@ import ModelExample from "components/model-example"
|
|||||||
import ModelComponent from "components/model-wrapper"
|
import ModelComponent from "components/model-wrapper"
|
||||||
|
|
||||||
describe("<ModelExample/>", function(){
|
describe("<ModelExample/>", function(){
|
||||||
// Given
|
let components, props
|
||||||
let components = {
|
|
||||||
|
let exampleSelectedTestInputs = [
|
||||||
|
{ defaultModelRendering: "model", isExecute: true },
|
||||||
|
{ defaultModelRendering: "example", isExecute: true },
|
||||||
|
{ defaultModelRendering: "example", isExecute: false },
|
||||||
|
{ defaultModelRendering: "othervalue", isExecute: true },
|
||||||
|
{ defaultModelRendering: "othervalue", isExecute: false }
|
||||||
|
]
|
||||||
|
|
||||||
|
let modelSelectedTestInputs = [
|
||||||
|
{ defaultModelRendering: "model", isExecute: false }
|
||||||
|
]
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
components = {
|
||||||
ModelWrapper: ModelComponent
|
ModelWrapper: ModelComponent
|
||||||
}
|
}
|
||||||
let props = {
|
|
||||||
|
props = {
|
||||||
getComponent: (c) => {
|
getComponent: (c) => {
|
||||||
return components[c]
|
return components[c]
|
||||||
},
|
},
|
||||||
@@ -23,16 +38,7 @@ describe("<ModelExample/>", function(){
|
|||||||
defaultModelExpandDepth: 1
|
defaultModelExpandDepth: 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let exampleSelectedTestInputs = [
|
})
|
||||||
{ defaultModelRendering: "model", isExecute: true },
|
|
||||||
{ defaultModelRendering: "example", isExecute: true },
|
|
||||||
{ defaultModelRendering: "example", isExecute: false },
|
|
||||||
{ defaultModelRendering: "othervalue", isExecute: true },
|
|
||||||
{ defaultModelRendering: "othervalue", isExecute: false }
|
|
||||||
]
|
|
||||||
let modelSelectedTestInputs = [
|
|
||||||
{ defaultModelRendering: "model", isExecute: false }
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
it("renders model and example tabs", function(){
|
it("renders model and example tabs", function(){
|
||||||
|
|||||||
@@ -100,6 +100,92 @@ describe("sampleFromSchema", function() {
|
|||||||
expect(sampleFromSchema(definition, { includeWriteOnly: true })).toEqual(expected)
|
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() {
|
describe("for array type", function() {
|
||||||
it("returns array with sample of array type", function() {
|
it("returns array with sample of array type", function() {
|
||||||
var definition = {
|
var definition = {
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ import {
|
|||||||
createDeepLinkPath,
|
createDeepLinkPath,
|
||||||
escapeDeepLinkPath,
|
escapeDeepLinkPath,
|
||||||
sanitizeUrl,
|
sanitizeUrl,
|
||||||
extractFileNameFromContentDispositionHeader
|
extractFileNameFromContentDispositionHeader,
|
||||||
|
deeplyStripKey
|
||||||
} from "core/utils"
|
} from "core/utils"
|
||||||
import win from "core/window"
|
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() {
|
describe("parse and serialize search", function() {
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
win.location.search = ""
|
win.location.search = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user