Skip to content

Commit 6ade59b

Browse files
committed
Support mocking of response based on openapi or json schema
1 parent fb35098 commit 6ade59b

File tree

4 files changed

+87
-12
lines changed

4 files changed

+87
-12
lines changed

import_map.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
22

3-
}
3+
}

src/json-mock-from-schema.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import toJsonSchema from 'npm:@openapi-contrib/openapi-schema-to-json-schema@latest'
2+
import jsf from 'npm:json-schema-faker@latest'
3+
// After fix use this one: import jsf from 'npm:json-schema-faker@latest/esm'
4+
5+
jsf.option({
6+
useExamplesValue: true,
7+
random: () => 0.000001
8+
})
9+
10+
export const SchemaType = {
11+
OPENAPI: 'openapi',
12+
JSON: 'json'
13+
}
14+
15+
export function toSchemaType(schema) {
16+
return schema.openapi ? SchemaType.OPENAPI : SchemaType.JSON
17+
}
18+
19+
export function toJsonMock(type, schema) {
20+
if (!schema) {
21+
return undefined
22+
}
23+
24+
switch (type) {
25+
case SchemaType.OPENAPI:
26+
return toJsonMockFromOpenapi(schema)
27+
case SchemaType.JSON:
28+
default:
29+
return toJsonMockFromJsonSchema(schema)
30+
}
31+
}
32+
33+
function toJsonMockFromOpenapi(schema) {
34+
let jsonSchema = toJsonSchema(schema)
35+
36+
if (jsonSchema?.properties) {
37+
jsonSchema.required = Object.entries(jsonSchema?.properties)
38+
.map(([key, value]) => {
39+
if (value?.type === 'array') {
40+
return key
41+
}
42+
return value?.required ? key : undefined
43+
})
44+
.filter(v => v !== undefined)
45+
}
46+
47+
return jsf.generate(jsonSchema)
48+
}
49+
50+
function toJsonMockFromJsonSchema(schema) {
51+
return jsf.generate(schema)
52+
}

src/scenario-algorithm.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import utils from './utils.js'
2-
import * as typeGenerators from './type-generators.js'
2+
import {toRandomFromType} from './type-generators.js'
3+
import {toJsonMock, toSchemaType} from './json-mock-from-schema.js'
34

45
function toTechnology(technology) {
56
return technology || 'HTTP'
@@ -256,16 +257,20 @@ function toHeaders(headerFile, headers, defaultHeaders) {
256257
: utils.openFile(defaultHeaders)
257258
}
258259

259-
function resolveInputData(data) {
260-
const extracted = data?.templateFile
260+
function resolveTemplate(data) {
261+
return data?.templateFile
261262
? utils.openFile(data.templateFile)
262263
: data.template
264+
}
263265

264-
const final = data?.entryName && extracted
265-
? extracted[data?.entryName]
266-
: extracted
266+
function resolveEntry(data, template) {
267+
return data?.entryName
268+
? utils.resolvePathData(data.entryName, template)
269+
: undefined
270+
}
267271

268-
return final || data
272+
function resolveInputData(data) {
273+
return resolveEntry(data, resolveTemplate(data)) || data
269274
}
270275

271276
function toRequest(request) {
@@ -286,7 +291,14 @@ function toResponse(response) {
286291

287292
const {...outResponse} = response
288293

289-
outResponse.body = response.body ? resolveInputData(response.body) : {}
294+
outResponse.body = response.body ? resolveInputData(response.body) : undefined
295+
296+
if (!outResponse.body) {
297+
const template = resolveTemplate(response.schema)
298+
const schema = resolveEntry(response.schema, template)
299+
300+
outResponse.body = toJsonMock(toSchemaType(template), schema)
301+
}
290302

291303
return outResponse
292304
}
@@ -351,7 +363,7 @@ function toGenerateConstants(generateConstants) {
351363
.map(constant => {
352364
return {
353365
...constant,
354-
generated: typeGenerators.toRandomFromType(
366+
generated: toRandomFromType(
355367
constant.type,
356368
constant.min,
357369
constant.max,

src/utils.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {readFileSync} from 'https://deno.land/[email protected]/node/fs.ts'
2+
import {parse} from "https://deno.land/[email protected]/encoding/yaml.ts";
23

34
function randomIban(countryCode, technicalOrgNum) {
45
return countryCode + randomInteger(20, 90) + technicalOrgNum + randomInteger(1000000, 9999999)
@@ -126,7 +127,12 @@ export default {
126127
setWorkingDirectory: dir => workingDirectory = dir || '.',
127128

128129
openFile: fileName => {
129-
return JSON.parse(readFileSync(toPath(fileName)).toString())
130+
const text = readFileSync(toPath(fileName)).toString()
131+
132+
if(fileName.endsWith(".yaml") || fileName.endsWith(".yml")) {
133+
return parse(text)
134+
}
135+
return JSON.parse(text)
130136
},
131137

132138
toReplace: (generate, replace) => {
@@ -140,5 +146,10 @@ export default {
140146
return generateReplace(generate || [], config || {})
141147
},
142148

143-
inputReplacesToJson: csv => inputReplacesToJson(csv)
149+
inputReplacesToJson: csv => inputReplacesToJson(csv),
150+
151+
resolvePathData: (path, obj) => {
152+
return path.split('.')
153+
.reduce((prev, curr) => prev ? prev[curr] : null, obj || self)
154+
}
144155
}

0 commit comments

Comments
 (0)