@schmock/openapi 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crud-detector.d.ts.map +1 -1
- package/dist/crud-detector.js +3 -2
- package/dist/generators.d.ts.map +1 -1
- package/dist/generators.js +3 -6
- package/dist/index.js +156 -156
- package/dist/normalizer.d.ts.map +1 -1
- package/dist/normalizer.js +1 -9
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +1 -3
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -4
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +14 -2
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +6 -0
- package/package.json +3 -3
- package/src/crud-detector.ts +3 -2
- package/src/generators.ts +6 -7
- package/src/normalizer.ts +1 -11
- package/src/parser.ts +1 -4
- package/src/plugin.ts +2 -5
- package/src/seed.ts +19 -2
- package/src/steps/openapi-seed.steps.ts +53 -0
- package/src/utils.ts +9 -0
package/dist/normalizer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizer.d.ts","sourceRoot":"","sources":["../src/normalizer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"normalizer.d.ts","sourceRoot":"","sources":["../src/normalizer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,SAAS,EAAE,SAAS,GAAG,UAAU,GAChC,WAAW,CAEb"}
|
package/dist/normalizer.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
/// <reference path="../../../types/schmock.d.ts" />
|
|
2
|
-
|
|
3
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
-
}
|
|
5
|
-
function toJsonSchema(node) {
|
|
6
|
-
// Object.assign merges unknown-keyed properties into JSONSchema7.
|
|
7
|
-
// This is safe because the normalizer has already ensured the shape
|
|
8
|
-
// is valid JSON Schema 7 before calling this function.
|
|
9
|
-
return Object.assign({}, node);
|
|
10
|
-
}
|
|
2
|
+
import { isRecord, toJsonSchema } from "./utils.js";
|
|
11
3
|
/**
|
|
12
4
|
* Normalize an OpenAPI schema to pure JSON Schema 7 that json-schema-faker understands.
|
|
13
5
|
*
|
package/dist/parser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA8CD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAuH5E"}
|
package/dist/parser.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
3
3
|
import { toHttpMethod } from "@schmock/core";
|
|
4
4
|
import { normalizeSchema } from "./normalizer.js";
|
|
5
|
+
import { isRecord } from "./utils.js";
|
|
5
6
|
const HTTP_METHOD_KEYS = new Set([
|
|
6
7
|
"get",
|
|
7
8
|
"post",
|
|
@@ -11,9 +12,6 @@ const HTTP_METHOD_KEYS = new Set([
|
|
|
11
12
|
"head",
|
|
12
13
|
"options",
|
|
13
14
|
]);
|
|
14
|
-
function isRecord(value) {
|
|
15
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16
|
-
}
|
|
17
15
|
function isOpenApiDocument(value) {
|
|
18
16
|
return isRecord(value) && ("swagger" in value || "openapi" in value);
|
|
19
17
|
}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAIxD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,sCAAsC;IACtC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wCAAwC;IACxC,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;CACH;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAwCzB"}
|
package/dist/plugin.js
CHANGED
|
@@ -3,9 +3,7 @@ import { detectCrudResources } from "./crud-detector.js";
|
|
|
3
3
|
import { createCreateGenerator, createDeleteGenerator, createListGenerator, createReadGenerator, createStaticGenerator, createUpdateGenerator, } from "./generators.js";
|
|
4
4
|
import { parseSpec } from "./parser.js";
|
|
5
5
|
import { loadSeed } from "./seed.js";
|
|
6
|
-
|
|
7
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
-
}
|
|
6
|
+
import { isRecord } from "./utils.js";
|
|
9
7
|
/**
|
|
10
8
|
* Create an OpenAPI plugin that auto-registers CRUD routes from a spec.
|
|
11
9
|
*
|
|
@@ -26,7 +24,7 @@ export async function openapi(options) {
|
|
|
26
24
|
: new Map();
|
|
27
25
|
return {
|
|
28
26
|
name: "@schmock/openapi",
|
|
29
|
-
version: "1.
|
|
27
|
+
version: "1.1.1",
|
|
30
28
|
install(instance) {
|
|
31
29
|
// Seed initial state — we need state to be initialized before registering routes
|
|
32
30
|
// The state is populated via generator context.state on first request,
|
package/dist/seed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEpD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,YAAY,EAAE,GACxB,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEpD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,YAAY,EAAE,GACxB,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAyDxB"}
|
package/dist/seed.js
CHANGED
|
@@ -20,7 +20,13 @@ export function loadSeed(config, resources) {
|
|
|
20
20
|
else if (typeof source === "string") {
|
|
21
21
|
// File path
|
|
22
22
|
const content = readFileSync(source, "utf-8");
|
|
23
|
-
|
|
23
|
+
let parsed;
|
|
24
|
+
try {
|
|
25
|
+
parsed = JSON.parse(content);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`Seed file "${source}" for resource "${resourceName}" contains invalid JSON`);
|
|
29
|
+
}
|
|
24
30
|
if (!Array.isArray(parsed)) {
|
|
25
31
|
throw new Error(`Seed file "${source}" for resource "${resourceName}" must contain a JSON array`);
|
|
26
32
|
}
|
|
@@ -30,10 +36,16 @@ export function loadSeed(config, resources) {
|
|
|
30
36
|
source !== null &&
|
|
31
37
|
"count" in source) {
|
|
32
38
|
// Auto-generate from schema
|
|
39
|
+
const rawCount = source.count;
|
|
40
|
+
if (typeof rawCount !== "number" ||
|
|
41
|
+
!Number.isInteger(rawCount) ||
|
|
42
|
+
rawCount < 0) {
|
|
43
|
+
throw new Error(`Seed count for "${resourceName}" must be a non-negative integer, got: ${String(rawCount)}`);
|
|
44
|
+
}
|
|
33
45
|
if (!resource?.schema) {
|
|
34
46
|
throw new Error(`Cannot auto-generate seed for "${resourceName}": no schema found in spec`);
|
|
35
47
|
}
|
|
36
|
-
const items = generateSeedItems(resource.schema,
|
|
48
|
+
const items = generateSeedItems(resource.schema, rawCount, resource.idParam);
|
|
37
49
|
result.set(resourceName, items);
|
|
38
50
|
}
|
|
39
51
|
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAEvE"}
|
package/dist/utils.js
ADDED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schmock/openapi",
|
|
3
3
|
"description": "OpenAPI/Swagger spec-driven auto-registration plugin for Schmock",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@amiceli/vitest-cucumber": "^6.2.0",
|
|
40
40
|
"@types/json-schema": "^7.0.15",
|
|
41
|
-
"@types/node": "^25.1
|
|
41
|
+
"@types/node": "^25.2.1",
|
|
42
42
|
"openapi-types": "^12.1.3",
|
|
43
|
-
"vitest": "^4.0.
|
|
43
|
+
"vitest": "^4.0.18"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/crud-detector.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { JSONSchema7 } from "json-schema";
|
|
4
4
|
import type { ParsedPath } from "./parser.js";
|
|
5
|
+
import { isRecord, toJsonSchema } from "./utils.js";
|
|
5
6
|
|
|
6
7
|
export type CrudOperation = "list" | "create" | "read" | "update" | "delete";
|
|
7
8
|
|
|
@@ -110,8 +111,8 @@ function buildResource(
|
|
|
110
111
|
const items = Array.isArray(listSchema.items)
|
|
111
112
|
? listSchema.items[0]
|
|
112
113
|
: listSchema.items;
|
|
113
|
-
if (
|
|
114
|
-
schema = schema ?? (items
|
|
114
|
+
if (isRecord(items)) {
|
|
115
|
+
schema = schema ?? toJsonSchema(items);
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
} else if (p.method === "POST") {
|
package/src/generators.ts
CHANGED
|
@@ -4,13 +4,10 @@ import { generateFromSchema } from "@schmock/schema";
|
|
|
4
4
|
import type { JSONSchema7 } from "json-schema";
|
|
5
5
|
import type { CrudResource } from "./crud-detector.js";
|
|
6
6
|
import type { ParsedPath } from "./parser.js";
|
|
7
|
+
import { isRecord } from "./utils.js";
|
|
7
8
|
|
|
8
9
|
const COLLECTION_STATE_PREFIX = "openapi:collections:";
|
|
9
10
|
|
|
10
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
11
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
11
|
function toTuple(status: number, body: unknown): [number, unknown] {
|
|
15
12
|
return [status, body];
|
|
16
13
|
}
|
|
@@ -159,9 +156,11 @@ export function createStaticGenerator(
|
|
|
159
156
|
if (responseSchema) {
|
|
160
157
|
try {
|
|
161
158
|
return generateFromSchema({ schema: responseSchema });
|
|
162
|
-
} catch {
|
|
163
|
-
|
|
164
|
-
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.warn(
|
|
161
|
+
`[@schmock/openapi] Schema generation failed for ${parsedPath.method} ${parsedPath.path}:`,
|
|
162
|
+
error instanceof Error ? error.message : error,
|
|
163
|
+
);
|
|
165
164
|
return {};
|
|
166
165
|
}
|
|
167
166
|
}
|
package/src/normalizer.ts
CHANGED
|
@@ -1,17 +1,7 @@
|
|
|
1
1
|
/// <reference path="../../../types/schmock.d.ts" />
|
|
2
2
|
|
|
3
3
|
import type { JSONSchema7 } from "json-schema";
|
|
4
|
-
|
|
5
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
6
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function toJsonSchema(node: Record<string, unknown>): JSONSchema7 {
|
|
10
|
-
// Object.assign merges unknown-keyed properties into JSONSchema7.
|
|
11
|
-
// This is safe because the normalizer has already ensured the shape
|
|
12
|
-
// is valid JSON Schema 7 before calling this function.
|
|
13
|
-
return Object.assign<JSONSchema7, Record<string, unknown>>({}, node);
|
|
14
|
-
}
|
|
4
|
+
import { isRecord, toJsonSchema } from "./utils.js";
|
|
15
5
|
|
|
16
6
|
/**
|
|
17
7
|
* Normalize an OpenAPI schema to pure JSON Schema 7 that json-schema-faker understands.
|
package/src/parser.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { toHttpMethod } from "@schmock/core";
|
|
|
5
5
|
import type { JSONSchema7 } from "json-schema";
|
|
6
6
|
import type { OpenAPI } from "openapi-types";
|
|
7
7
|
import { normalizeSchema } from "./normalizer.js";
|
|
8
|
+
import { isRecord } from "./utils.js";
|
|
8
9
|
|
|
9
10
|
export interface ParsedSpec {
|
|
10
11
|
title: string;
|
|
@@ -41,10 +42,6 @@ const HTTP_METHOD_KEYS = new Set([
|
|
|
41
42
|
"options",
|
|
42
43
|
]);
|
|
43
44
|
|
|
44
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
45
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
45
|
function isOpenApiDocument(value: unknown): value is OpenAPI.Document {
|
|
49
46
|
return isRecord(value) && ("swagger" in value || "openapi" in value);
|
|
50
47
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -13,13 +13,10 @@ import {
|
|
|
13
13
|
import { parseSpec } from "./parser.js";
|
|
14
14
|
import type { SeedConfig, SeedSource } from "./seed.js";
|
|
15
15
|
import { loadSeed } from "./seed.js";
|
|
16
|
+
import { isRecord } from "./utils.js";
|
|
16
17
|
|
|
17
18
|
export type { SeedConfig, SeedSource };
|
|
18
19
|
|
|
19
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
20
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
20
|
export interface OpenApiOptions {
|
|
24
21
|
/** File path or inline spec object */
|
|
25
22
|
spec: string | object;
|
|
@@ -60,7 +57,7 @@ export async function openapi(
|
|
|
60
57
|
|
|
61
58
|
return {
|
|
62
59
|
name: "@schmock/openapi",
|
|
63
|
-
version: "1.
|
|
60
|
+
version: "1.1.1",
|
|
64
61
|
|
|
65
62
|
install(instance: Schmock.CallableMockInstance) {
|
|
66
63
|
// Seed initial state — we need state to be initialized before registering routes
|
package/src/seed.ts
CHANGED
|
@@ -31,7 +31,14 @@ export function loadSeed(
|
|
|
31
31
|
} else if (typeof source === "string") {
|
|
32
32
|
// File path
|
|
33
33
|
const content = readFileSync(source, "utf-8");
|
|
34
|
-
|
|
34
|
+
let parsed: unknown;
|
|
35
|
+
try {
|
|
36
|
+
parsed = JSON.parse(content);
|
|
37
|
+
} catch {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Seed file "${source}" for resource "${resourceName}" contains invalid JSON`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
35
42
|
if (!Array.isArray(parsed)) {
|
|
36
43
|
throw new Error(
|
|
37
44
|
`Seed file "${source}" for resource "${resourceName}" must contain a JSON array`,
|
|
@@ -44,6 +51,16 @@ export function loadSeed(
|
|
|
44
51
|
"count" in source
|
|
45
52
|
) {
|
|
46
53
|
// Auto-generate from schema
|
|
54
|
+
const rawCount = source.count;
|
|
55
|
+
if (
|
|
56
|
+
typeof rawCount !== "number" ||
|
|
57
|
+
!Number.isInteger(rawCount) ||
|
|
58
|
+
rawCount < 0
|
|
59
|
+
) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Seed count for "${resourceName}" must be a non-negative integer, got: ${String(rawCount)}`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
47
64
|
if (!resource?.schema) {
|
|
48
65
|
throw new Error(
|
|
49
66
|
`Cannot auto-generate seed for "${resourceName}": no schema found in spec`,
|
|
@@ -51,7 +68,7 @@ export function loadSeed(
|
|
|
51
68
|
}
|
|
52
69
|
const items = generateSeedItems(
|
|
53
70
|
resource.schema,
|
|
54
|
-
|
|
71
|
+
rawCount,
|
|
55
72
|
resource.idParam,
|
|
56
73
|
);
|
|
57
74
|
result.set(resourceName, items);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
+
import { writeFileSync } from "node:fs";
|
|
2
3
|
import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
|
|
3
4
|
import { schmock } from "@schmock/core";
|
|
4
5
|
import { expect } from "vitest";
|
|
@@ -7,9 +8,12 @@ import { openapi } from "../plugin";
|
|
|
7
8
|
const feature = await loadFeature("../../features/openapi-seed.feature");
|
|
8
9
|
const fixturesDir = resolve(import.meta.dirname, "../__fixtures__");
|
|
9
10
|
|
|
11
|
+
const scratchDir = resolve(import.meta.dirname, "../__fixtures__");
|
|
12
|
+
|
|
10
13
|
describeFeature(feature, ({ Scenario }) => {
|
|
11
14
|
let mock: Schmock.CallableMockInstance;
|
|
12
15
|
let response: Schmock.Response;
|
|
16
|
+
let specPath: string;
|
|
13
17
|
|
|
14
18
|
Scenario("Seed with inline objects", ({ Given, When, Then }) => {
|
|
15
19
|
Given("a mock with Petstore spec and inline seed data", async () => {
|
|
@@ -91,4 +95,53 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
91
95
|
});
|
|
92
96
|
},
|
|
93
97
|
);
|
|
98
|
+
|
|
99
|
+
Scenario(
|
|
100
|
+
"Invalid seed count produces descriptive error",
|
|
101
|
+
({ Given, Then }) => {
|
|
102
|
+
Given("a Petstore spec path", () => {
|
|
103
|
+
specPath = `${fixturesDir}/petstore-swagger2.json`;
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
Then(
|
|
107
|
+
'creating a mock with seed count "abc" should throw about non-negative integer',
|
|
108
|
+
async () => {
|
|
109
|
+
await expect(
|
|
110
|
+
openapi({
|
|
111
|
+
spec: specPath,
|
|
112
|
+
seed: { pets: { count: "abc" as any } },
|
|
113
|
+
}),
|
|
114
|
+
).rejects.toThrow("non-negative integer");
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
},
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
Scenario(
|
|
121
|
+
"Malformed seed file produces descriptive error",
|
|
122
|
+
({ Given, Then }) => {
|
|
123
|
+
Given("a Petstore spec path", () => {
|
|
124
|
+
specPath = `${fixturesDir}/petstore-swagger2.json`;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
Then(
|
|
128
|
+
"creating a mock with malformed seed file should throw about invalid JSON",
|
|
129
|
+
async () => {
|
|
130
|
+
const badFile = resolve(scratchDir, "__bad-seed-temp.json");
|
|
131
|
+
writeFileSync(badFile, "NOT VALID JSON{{{");
|
|
132
|
+
try {
|
|
133
|
+
await expect(
|
|
134
|
+
openapi({
|
|
135
|
+
spec: specPath,
|
|
136
|
+
seed: { pets: badFile },
|
|
137
|
+
}),
|
|
138
|
+
).rejects.toThrow("invalid JSON");
|
|
139
|
+
} finally {
|
|
140
|
+
const { unlinkSync } = await import("node:fs");
|
|
141
|
+
unlinkSync(badFile);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
);
|
|
94
147
|
});
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JSONSchema7 } from "json-schema";
|
|
2
|
+
|
|
3
|
+
export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function toJsonSchema(node: Record<string, unknown>): JSONSchema7 {
|
|
8
|
+
return Object.assign<JSONSchema7, Record<string, unknown>>({}, node);
|
|
9
|
+
}
|