@mojaloop/ml-testing-toolkit-shared-lib 14.0.5 → 14.1.0
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/.grype.yaml +13 -0
- package/.nvmrc +1 -1
- package/CHANGELOG.md +7 -0
- package/package.json +10 -8
- package/src/lib/openApiMockGenerator.js +97 -793
- package/.husky/commit-msg +0 -4
- package/.husky/post-commit +0 -4
- package/.husky/pre-commit +0 -1
package/.grype.yaml
ADDED
package/.nvmrc
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
22.15.
|
|
1
|
+
22.15.1
|
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
# Changelog: [mojaloop/als-consent-oracle](https://github.com/mojaloop/als-consent-oracle)
|
|
2
|
+
## [14.1.0](https://github.com/mojaloop/ml-testing-toolkit-shared-lib/compare/v14.0.5...v14.1.0) (2025-06-03)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* bump up the node version to v22.15.1 ([#23](https://github.com/mojaloop/ml-testing-toolkit-shared-lib/issues/23)) ([ccd59bd](https://github.com/mojaloop/ml-testing-toolkit-shared-lib/commit/ccd59bdc348ab1b9bce1cb2ee69f6553fb7021a5))
|
|
8
|
+
|
|
2
9
|
### [14.0.5](https://github.com/mojaloop/ml-testing-toolkit-shared-lib/compare/v14.0.4...v14.0.5) (2025-05-16)
|
|
3
10
|
|
|
4
11
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/ml-testing-toolkit-shared-lib",
|
|
3
|
-
"version": "14.0
|
|
3
|
+
"version": "14.1.0",
|
|
4
4
|
"description": "Shared library for ml-testing-toolkit re-usable functions",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"contributors": [
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
"homepage": "https://github.com/mojaloop/ml-testing-toolkit-shared-lib#readme",
|
|
21
21
|
"pre-commit": [
|
|
22
22
|
"lint",
|
|
23
|
-
"dep:check"
|
|
23
|
+
"dep:check",
|
|
24
|
+
"audit:check",
|
|
25
|
+
"test"
|
|
24
26
|
],
|
|
25
27
|
"scripts": {
|
|
26
28
|
"start": "node src/index.js",
|
|
@@ -30,25 +32,26 @@
|
|
|
30
32
|
"lint:fix": "npm run standard:fix",
|
|
31
33
|
"test": "npm run test:unit",
|
|
32
34
|
"test:unit": "jest --testMatch '**/test/unit/**/*.test.js'",
|
|
35
|
+
"test:xunit": "npm run test:unit",
|
|
33
36
|
"test:int": "jest --reporters=default --reporters=jest-junit --testMatch '**/test/integration/**/*.test.js'",
|
|
34
37
|
"test:coverage": "jest --coverage --coverageThreshold='{}' --testMatch '**/test/unit/**/*.test.js'",
|
|
35
38
|
"test:coverage-check": "jest --coverage --testMatch '**/test/unit/**/*.test.js'",
|
|
36
39
|
"test:junit": "jest --reporters=default --reporters=jest-junit --testMatch '**/test/unit/**/*.test.js'",
|
|
37
|
-
"test:integration": "
|
|
40
|
+
"test:integration": "echo 'No integration tests defined'",
|
|
41
|
+
"test:functional": "echo 'No functional tests defined'",
|
|
38
42
|
"cover": "npx nyc --all report --reporter=lcov npm run test",
|
|
39
43
|
"audit:check": "npx audit-ci --config ./audit-ci.jsonc",
|
|
40
44
|
"audit:fix": "npm audit fix",
|
|
41
45
|
"dep:check": "npx ncu -e 2",
|
|
42
46
|
"dep:update": "npx ncu -u",
|
|
43
|
-
"prepare": "husky || true",
|
|
44
47
|
"release": "npx standard-version --no-verify --releaseCommitMessageFormat 'chore(release): {{currentTag}} [skip ci]'",
|
|
45
48
|
"snapshot": "npx standard-version --no-verify --skip.changelog --prerelease snapshot --releaseCommitMessageFormat 'chore(snapshot): {{currentTag}}'"
|
|
46
49
|
},
|
|
47
50
|
"dependencies": {
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
51
|
+
"@apidevtools/json-schema-ref-parser": "12.0.2",
|
|
52
|
+
"@faker-js/faker": "9.8.0",
|
|
50
53
|
"ajv": "8.17.1",
|
|
51
|
-
"json-schema-
|
|
54
|
+
"json-schema-faker": "0.5.9",
|
|
52
55
|
"lodash": "4.17.21",
|
|
53
56
|
"node-dir": "0.1.17"
|
|
54
57
|
},
|
|
@@ -57,7 +60,6 @@
|
|
|
57
60
|
"@commitlint/config-conventional": "^19.8.1",
|
|
58
61
|
"@types/jest": "29.5.14",
|
|
59
62
|
"audit-ci": "^7.1.0",
|
|
60
|
-
"husky": "^9.1.7",
|
|
61
63
|
"jest": "29.7.0",
|
|
62
64
|
"jest-junit": "16.0.0",
|
|
63
65
|
"npm-check-updates": "18.0.1",
|
|
@@ -32,203 +32,18 @@ const _ = require('lodash')
|
|
|
32
32
|
// const jref = require('json-ref-lite')
|
|
33
33
|
// const yaml = require('js-yaml')
|
|
34
34
|
const { faker } = require('@faker-js/faker')
|
|
35
|
-
const
|
|
36
|
-
const $RefParser = require('json-schema-ref-parser')
|
|
35
|
+
const jsf = require('json-schema-faker')
|
|
36
|
+
const $RefParser = require('@apidevtools/json-schema-ref-parser')
|
|
37
37
|
const Ajv = require('ajv')
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
const samplerOptions = {
|
|
41
|
-
skipNonRequired: false,
|
|
42
|
-
quiet: true,
|
|
43
|
-
maxSampleDepth: 5,
|
|
44
|
-
maxItems: 2,
|
|
45
|
-
ignoreMissingRefs: true,
|
|
46
|
-
formatHandlers: {
|
|
47
|
-
byte: () => Buffer.alloc(faker.lorem.sentence(12)).toString('base64'),
|
|
48
|
-
date: () => faker.date.anytime().toISOString().split('T')[0],
|
|
49
|
-
'date-time': () => faker.date.anytime().toISOString(),
|
|
50
|
-
email: () => faker.internet.email(),
|
|
51
|
-
uri: () => faker.internet.url(),
|
|
52
|
-
uuid: () => faker.string.uuid(),
|
|
53
|
-
phone: () => faker.phone.number('+###########'),
|
|
54
|
-
'geo-latitude': () => {
|
|
55
|
-
const val = faker.location.latitude().toFixed(4)
|
|
56
|
-
return (parseFloat(val) >= 0 ? '+' : '') + val
|
|
57
|
-
},
|
|
58
|
-
'geo-longitude': () => {
|
|
59
|
-
const val = faker.location.longitude().toFixed(4)
|
|
60
|
-
return (parseFloat(val) >= 0 ? '+' : '') + val
|
|
61
|
-
},
|
|
62
|
-
'fsp-id': () => generateFspId(),
|
|
63
|
-
currency: () => faker.helpers.arrayElement(['USD', 'EUR', 'GBP', 'JPY', 'AUD', 'CAD', 'CHF', 'CNY', 'INR', 'BRL']),
|
|
64
|
-
'sub-scenario': () => faker.helpers.fromRegExp(/^[A-Z_]{1,32}$/),
|
|
65
|
-
name: () => `${faker.person.firstName()} ${faker.person.lastName()}`,
|
|
66
|
-
'complex-name': () => ({
|
|
67
|
-
firstName: faker.person.firstName(),
|
|
68
|
-
middleName: faker.helpers.maybe(() => faker.person.middleName(), { probability: 0.3 }),
|
|
69
|
-
lastName: faker.person.lastName()
|
|
70
|
-
}),
|
|
71
|
-
'party-identifier': () => faker.phone.number('##########'),
|
|
72
|
-
amount: () => faker.number.float({ min: 0.01, max: 1000, precision: 0.01 }).toFixed(2),
|
|
73
|
-
'transaction-scenario': () => faker.helpers.arrayElement(['DEPOSIT', 'WITHDRAWAL', 'TRANSFER', 'PAYMENT', 'REFUND']),
|
|
74
|
-
'transaction-initiator': () => faker.helpers.arrayElement(['PAYER', 'PAYEE']),
|
|
75
|
-
'transaction-initiator-type': () => faker.helpers.arrayElement(['CONSUMER', 'AGENT', 'BUSINESS', 'DEVICE']),
|
|
76
|
-
'transfer-state': () => faker.helpers.arrayElement(['RECEIVED', 'RESERVED', 'COMMITTED', 'ABORTED'])
|
|
77
|
-
},
|
|
78
|
-
typeHandlers: {
|
|
79
|
-
string: (schema) => {
|
|
80
|
-
const key = (schema.key || '').toLowerCase()
|
|
81
|
-
const parentKey = (schema.parentKey || '').toLowerCase()
|
|
82
|
-
|
|
83
|
-
// Handle patterns
|
|
84
|
-
if (schema.pattern) {
|
|
85
|
-
if (schema.pattern === 'Created|Closed') {
|
|
86
|
-
return faker.helpers.arrayElement(['Created', 'Closed'])
|
|
87
|
-
}
|
|
88
|
-
if (schema.pattern === 'PERSONAL_ID|BUSINESS_ID') {
|
|
89
|
-
return faker.helpers.arrayElement(['PERSONAL_ID', 'BUSINESS_ID'])
|
|
90
|
-
}
|
|
91
|
-
if (schema.pattern === '123') {
|
|
92
|
-
return '123'
|
|
93
|
-
}
|
|
94
|
-
if (schema.pattern === '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$') {
|
|
95
|
-
return faker.internet.email()
|
|
96
|
-
}
|
|
97
|
-
if (schema.pattern === '^[A-Z0-9]{1,32}$') {
|
|
98
|
-
return generateFspId()
|
|
99
|
-
}
|
|
100
|
-
if (schema.pattern === '^\\d{10,15}$') {
|
|
101
|
-
// Always generate a string of 10-15 digits
|
|
102
|
-
return generateDigitsPhoneNumber(faker.number.int({ min: 10, max: 15 }))
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Handle Content-Length
|
|
107
|
-
if (key === 'content-length' || key === 'contentlength') {
|
|
108
|
-
return '123'
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Handle state, reason, status
|
|
112
|
-
if (key === 'state' || key === 'reason' || key === 'status') {
|
|
113
|
-
return faker.helpers.arrayElement(['Created', 'Closed'])
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Handle partyIdType
|
|
117
|
-
if (key === 'partyidtype' || (parentKey === 'partyidinfo' && key === 'partyidtype')) {
|
|
118
|
-
return faker.helpers.arrayElement(['PERSONAL_ID', 'BUSINESS_ID'])
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Handle transferState
|
|
122
|
-
if (key === 'transferstate') {
|
|
123
|
-
return faker.helpers.arrayElement(['RECEIVED', 'RESERVED', 'COMMITTED', 'ABORTED'])
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Handle FSP ID fields (fspid, payerfsp, payeefsp)
|
|
127
|
-
if (key === 'fspid' || key === 'payerfsp' || key === 'payeefsp' || (parentKey === 'partyidinfo' && key === 'fspid')) {
|
|
128
|
-
return generateFspId()
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Handle currency
|
|
132
|
-
if (key === 'currency' || (parentKey === 'amount' && key === 'currency')) {
|
|
133
|
-
const currency = faker.helpers.arrayElement(['USD', 'EUR', 'GBP', 'JPY', 'AUD', 'CAD', 'CHF', 'CNY', 'INR', 'BRL'])
|
|
134
|
-
if (schema.parentKey === 'amount') {
|
|
135
|
-
schema._currency = currency
|
|
136
|
-
}
|
|
137
|
-
return currency
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Handle amount (including nested amount.amount)
|
|
141
|
-
if (key === 'amount') {
|
|
142
|
-
return faker.number.float({ min: 0.01, max: 1000, precision: 0.01 }).toFixed(2)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Handle partyIdentifier (digits only)
|
|
146
|
-
if (key === 'partyidentifier' || (parentKey === 'partyidinfo' && key === 'partyidentifier')) {
|
|
147
|
-
return generateDigitsPhoneNumber(faker.number.int({ min: 10, max: 15 }))
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Handle geo coordinates
|
|
151
|
-
if (key === 'latitude') {
|
|
152
|
-
const val = faker.location.latitude().toFixed(4)
|
|
153
|
-
return (parseFloat(val) >= 0 ? '+' : '') + val
|
|
154
|
-
}
|
|
155
|
-
if (key === 'longitude') {
|
|
156
|
-
const val = faker.location.longitude().toFixed(4)
|
|
157
|
-
return (parseFloat(val) >= 0 ? '+' : '') + val
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Handle UUIDs for IDs
|
|
161
|
-
if (key === 'bulkquoteid' || key === 'bulktransferid' || key === 'quoteid' || key === 'transferid' || key === 'id') {
|
|
162
|
-
return faker.string.uuid()
|
|
163
|
-
}
|
|
39
|
+
jsf.format('byte', () => Buffer.alloc(faker.lorem.sentence({ min: 12, max: 12 })).toString('base64'))
|
|
164
40
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
if (key === 'initiatortype' || (parentKey === 'transactiontype' && key === 'initiatortype')) {
|
|
173
|
-
return faker.helpers.arrayElement(['CONSUMER', 'AGENT', 'BUSINESS', 'DEVICE'])
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Handle firstName and lastName fields (single name, capitalized, strictly alphabetic)
|
|
177
|
-
if (key === 'firstname') {
|
|
178
|
-
let first
|
|
179
|
-
do {
|
|
180
|
-
first = faker.person.firstName()
|
|
181
|
-
first = `${first.charAt(0).toUpperCase()}${first.slice(1)}`
|
|
182
|
-
} while (!/^[A-Z][a-z]+$/.test(first))
|
|
183
|
-
return first
|
|
184
|
-
}
|
|
185
|
-
if (key === 'lastname') {
|
|
186
|
-
let last
|
|
187
|
-
do {
|
|
188
|
-
last = faker.person.lastName()
|
|
189
|
-
last = `${last.charAt(0).toUpperCase()}${last.slice(1)}`
|
|
190
|
-
} while (!/^[A-Z][a-z]+$/.test(last))
|
|
191
|
-
return last
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Handle name field (full name)
|
|
195
|
-
if (key === 'name') {
|
|
196
|
-
const first = faker.person.firstName()
|
|
197
|
-
const last = faker.person.lastName()
|
|
198
|
-
return `${first.charAt(0).toUpperCase()}${first.slice(1)} ${last.charAt(0).toUpperCase()}${last.slice(1)}`
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Handle complexName (string) to always return a full name (Firstname Lastname)
|
|
202
|
-
if (key === 'complexname' && schema.type === 'string') {
|
|
203
|
-
const first = faker.person.firstName()
|
|
204
|
-
const last = faker.person.lastName()
|
|
205
|
-
return `${first.charAt(0).toUpperCase()}${first.slice(1)} ${last.charAt(0).toUpperCase()}${last.slice(1)}`
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// For any other key ending with 'name' (but not 'name', 'firstname', 'lastname', or 'complexname'), generate a single capitalized name.
|
|
209
|
-
if (/name$/i.test(key) && key !== 'name' && key !== 'firstname' && key !== 'lastname' && key !== 'complexname') {
|
|
210
|
-
const single = faker.person.firstName()
|
|
211
|
-
return `${single.charAt(0).toUpperCase()}${single.slice(1)}`
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Fallback to customTypeHandler for any other string field
|
|
215
|
-
const custom = customTypeHandler(schema)
|
|
216
|
-
if (custom !== undefined) return custom
|
|
217
|
-
|
|
218
|
-
// Default fallback
|
|
219
|
-
return faker.lorem.sentence()
|
|
220
|
-
},
|
|
221
|
-
number: (schema) => {
|
|
222
|
-
const key = (schema.key || '').toLowerCase()
|
|
223
|
-
if (key === 'amount' || /amount$/i.test(key)) {
|
|
224
|
-
return faker.number.float({ min: 0.01, max: 1000, precision: 0.01 }).toFixed(2)
|
|
225
|
-
}
|
|
226
|
-
return faker.number.float({ min: 1, max: 1000, precision: 0.01 })
|
|
227
|
-
},
|
|
228
|
-
integer: () => faker.number.int({ min: 1, max: 1000 }),
|
|
229
|
-
boolean: () => faker.datatype.boolean()
|
|
230
|
-
}
|
|
231
|
-
}
|
|
41
|
+
jsf.option({
|
|
42
|
+
alwaysFakeOptionals: true,
|
|
43
|
+
ignoreMissingRefs: true,
|
|
44
|
+
maxItems: 2
|
|
45
|
+
})
|
|
46
|
+
jsf.extend('faker', () => require('@faker-js/faker').faker)
|
|
232
47
|
|
|
233
48
|
const ajv = new Ajv({
|
|
234
49
|
strict: false,
|
|
@@ -322,574 +137,124 @@ const findRequestSchema = (r) => {
|
|
|
322
137
|
return _.find(content).schema
|
|
323
138
|
}
|
|
324
139
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const
|
|
329
|
-
return names.some(name => keyLower === name.toLowerCase() || keyLower.endsWith(name.toLowerCase()))
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Fix date-time format handler to always generate a valid ISO string with milliseconds
|
|
333
|
-
const customFormatHandlers = {
|
|
334
|
-
name: () => {
|
|
335
|
-
const firstNames = ['John', 'Jane', 'Michael', 'Sarah', 'David', 'Emma']
|
|
336
|
-
const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia']
|
|
337
|
-
return `${firstNames[Math.floor(Math.random() * firstNames.length)]} ${lastNames[Math.floor(Math.random() * lastNames.length)]}`
|
|
338
|
-
},
|
|
339
|
-
amount: () => {
|
|
340
|
-
return (Math.random() * 1000).toFixed(2)
|
|
341
|
-
},
|
|
342
|
-
phone: () => {
|
|
343
|
-
return Math.floor(Math.random() * 9000000000 + 1000000000).toString()
|
|
344
|
-
},
|
|
345
|
-
'geo-latitude': () => {
|
|
346
|
-
const val = (Math.random() * 180 - 90).toFixed(4)
|
|
347
|
-
return (val >= 0 ? '+' : '') + val
|
|
348
|
-
},
|
|
349
|
-
'geo-longitude': () => {
|
|
350
|
-
const val = (Math.random() * 360 - 180).toFixed(4)
|
|
351
|
-
return (val >= 0 ? '+' : '') + val
|
|
352
|
-
},
|
|
353
|
-
uuid: () => {
|
|
354
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
355
|
-
const r = Math.random() * 16 | 0
|
|
356
|
-
const v = c === 'x' ? r : (r & 0x3 | 0x8)
|
|
357
|
-
return v.toString(16)
|
|
358
|
-
})
|
|
359
|
-
},
|
|
360
|
-
'date-time': () => {
|
|
361
|
-
// Always use toISOString() which includes milliseconds
|
|
362
|
-
return new Date().toISOString()
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Custom type handler for the sampler
|
|
367
|
-
const customTypeHandler = (schema) => {
|
|
368
|
-
if (!schema || typeof schema !== 'object') return undefined
|
|
369
|
-
|
|
370
|
-
const key = schema.key || ''
|
|
371
|
-
|
|
372
|
-
// Always handle state, reason, status fields
|
|
373
|
-
if (matchesField(key, 'state', 'status', 'reason')) {
|
|
374
|
-
return ['Created', 'Closed'][Math.floor(Math.random() * 2)]
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Always handle party ID type fields
|
|
378
|
-
if (matchesField(key, 'partyIdType', 'idType')) {
|
|
379
|
-
return ['PERSONAL_ID', 'BUSINESS_ID'][Math.floor(Math.random() * 2)]
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Always handle content length
|
|
383
|
-
if (matchesField(key, 'contentLength', 'content-length')) {
|
|
384
|
-
return '123'
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Handle email fields
|
|
388
|
-
if (matchesField(key, 'email', 'emailAddress')) {
|
|
389
|
-
const domains = ['example.com', 'test.com', 'domain.com']
|
|
390
|
-
const name = Math.random().toString(36).substring(2, 8)
|
|
391
|
-
return `${name}@${domains[Math.floor(Math.random() * domains.length)]}`
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// Handle date-time fields
|
|
395
|
-
if (matchesField(key, 'expiration', 'dateTime', 'datetime', 'timestamp')) {
|
|
396
|
-
return customFormatHandlers['date-time']()
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// Handle date fields
|
|
400
|
-
if (matchesField(key, 'dateOfBirth', 'date')) {
|
|
401
|
-
const date = new Date()
|
|
402
|
-
return date.toISOString().split('T')[0]
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// Use format handlers for other fields
|
|
406
|
-
if (schema.format && customFormatHandlers[schema.format]) {
|
|
407
|
-
return customFormatHandlers[schema.format]()
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
return undefined
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Preprocess schema to inject default values for known fields
|
|
414
|
-
function preprocessSchema (schema, parentKey = null) {
|
|
415
|
-
if (!schema || typeof schema !== 'object') return schema
|
|
416
|
-
|
|
417
|
-
const processed = JSON.parse(JSON.stringify(schema))
|
|
418
|
-
processed.parentKey = parentKey
|
|
419
|
-
|
|
420
|
-
// Process properties recursively
|
|
421
|
-
if (processed.properties) {
|
|
422
|
-
Object.keys(processed.properties).forEach(key => {
|
|
423
|
-
processed.properties[key] = preprocessSchema(processed.properties[key], key)
|
|
424
|
-
})
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Process items for arrays
|
|
428
|
-
if (processed.items) {
|
|
429
|
-
processed.items = preprocessSchema(processed.items, parentKey)
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Handle specific field types
|
|
433
|
-
if (processed.type === 'string') {
|
|
434
|
-
const key = processed.key || ''
|
|
435
|
-
// Handle state and reason fields
|
|
436
|
-
if (matchesField(key, 'state', 'status', 'reason')) {
|
|
437
|
-
processed.format = 'transaction-state'
|
|
438
|
-
return processed
|
|
439
|
-
}
|
|
440
|
-
// Handle party ID type fields
|
|
441
|
-
if (matchesField(key, 'partyIdType', 'idType')) {
|
|
442
|
-
processed.format = 'party-id-type'
|
|
443
|
-
return processed
|
|
444
|
-
}
|
|
445
|
-
// Handle FSP ID fields
|
|
446
|
-
if (matchesField(key, 'fspId', 'fspid')) {
|
|
447
|
-
processed.format = 'fsp-id'
|
|
448
|
-
return processed
|
|
449
|
-
}
|
|
450
|
-
// Handle currency fields
|
|
451
|
-
if (matchesField(key, 'currency')) {
|
|
452
|
-
processed.format = 'currency'
|
|
453
|
-
return processed
|
|
454
|
-
}
|
|
455
|
-
// Handle date-time fields
|
|
456
|
-
if (matchesField(key, 'expiration', 'datetime', 'timestamp')) {
|
|
457
|
-
processed.format = 'date-time'
|
|
458
|
-
return processed
|
|
459
|
-
}
|
|
460
|
-
// Handle date fields
|
|
461
|
-
if (matchesField(key, 'dateOfBirth', 'date')) {
|
|
462
|
-
processed.format = 'date'
|
|
463
|
-
return processed
|
|
464
|
-
}
|
|
465
|
-
// Handle party identifier fields
|
|
466
|
-
if (matchesField(key, 'partyIdentifier')) {
|
|
467
|
-
processed.format = 'party-identifier'
|
|
468
|
-
return processed
|
|
469
|
-
}
|
|
470
|
-
// Handle transaction type fields
|
|
471
|
-
if (matchesField(key, 'scenario')) {
|
|
472
|
-
processed.format = 'transaction-scenario'
|
|
473
|
-
return processed
|
|
474
|
-
}
|
|
475
|
-
if (matchesField(key, 'initiator')) {
|
|
476
|
-
processed.format = 'transaction-initiator'
|
|
477
|
-
return processed
|
|
478
|
-
}
|
|
479
|
-
if (matchesField(key, 'initiatorType')) {
|
|
480
|
-
processed.format = 'transaction-initiator-type'
|
|
481
|
-
return processed
|
|
482
|
-
}
|
|
483
|
-
// Handle transfer state fields
|
|
484
|
-
if (matchesField(key, 'transferState')) {
|
|
485
|
-
processed.format = 'transfer-state'
|
|
486
|
-
return processed
|
|
487
|
-
}
|
|
488
|
-
// Handle subScenario fields
|
|
489
|
-
if (matchesField(key, 'subScenario')) {
|
|
490
|
-
processed.format = 'sub-scenario'
|
|
491
|
-
return processed
|
|
492
|
-
}
|
|
493
|
-
// Handle complex name fields
|
|
494
|
-
if (matchesField(key, 'complexName')) {
|
|
495
|
-
processed.type = 'object'
|
|
496
|
-
processed.properties = {
|
|
497
|
-
firstName: { type: 'string', format: 'name' },
|
|
498
|
-
middleName: { type: 'string', format: 'name' },
|
|
499
|
-
lastName: { type: 'string', format: 'name' }
|
|
500
|
-
}
|
|
501
|
-
return processed
|
|
502
|
-
}
|
|
503
|
-
// Handle bulk operation IDs
|
|
504
|
-
if (matchesField(key, 'bulkQuoteId', 'bulkTransferId', 'quoteId', 'transferId', 'id')) {
|
|
505
|
-
processed.format = 'uuid'
|
|
506
|
-
return processed
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
return processed
|
|
510
|
-
}
|
|
140
|
+
const generateMockResponseBody = async (method, name, data, jsfRefs) => {
|
|
141
|
+
const responseSchema = findResponseSchema(data.responses)
|
|
142
|
+
// Create a new copy of object without copying by references
|
|
143
|
+
const newResponseSchema = JSON.parse(JSON.stringify(responseSchema))
|
|
511
144
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
// Preprocess schema even if no jsfRefs
|
|
515
|
-
return preprocessSchema(schema)
|
|
145
|
+
if (!newResponseSchema) {
|
|
146
|
+
return {}
|
|
516
147
|
}
|
|
517
|
-
|
|
518
|
-
const newSchema = JSON.parse(JSON.stringify(schema))
|
|
519
|
-
|
|
520
|
-
// Process each reference
|
|
521
148
|
jsfRefs.forEach(ref => {
|
|
522
|
-
|
|
523
|
-
const path = ref.id.split('.').map(part => {
|
|
524
|
-
// Escape special characters in JSON pointer
|
|
525
|
-
return part.replace(/~/g, '~0').replace(/\//g, '~1')
|
|
526
|
-
}).join('/')
|
|
149
|
+
const convertedId = ref.id.replace(/\.(?!items)/g, '.properties.')
|
|
527
150
|
|
|
528
|
-
|
|
529
|
-
const processSchemaObject = (targetObject) => {
|
|
530
|
-
if (!targetObject) return
|
|
151
|
+
const targetObject = _.get(newResponseSchema.type === 'array' ? newResponseSchema.items.properties : newResponseSchema.properties, convertedId)
|
|
531
152
|
|
|
532
|
-
|
|
153
|
+
if (targetObject) {
|
|
154
|
+
targetObject.$ref = ref.id
|
|
533
155
|
if (ref.pattern) {
|
|
534
|
-
// For pattern-based fields, ensure we have a string type
|
|
535
|
-
targetObject.type = 'string'
|
|
536
|
-
targetObject.enum = ['Created', 'Closed'] // Use enum instead of pattern
|
|
537
|
-
delete targetObject.pattern
|
|
538
|
-
delete targetObject.format
|
|
539
|
-
} else if (ref.id === 'Content-Length') {
|
|
540
|
-
// Special handling for Content-Length
|
|
541
|
-
targetObject.type = 'string'
|
|
542
|
-
targetObject.enum = ['123']
|
|
543
|
-
delete targetObject.pattern
|
|
544
|
-
delete targetObject.format
|
|
545
|
-
} else if (ref.id === 'partyIdType') {
|
|
546
|
-
// Special handling for partyIdType
|
|
547
|
-
targetObject.type = 'string'
|
|
548
|
-
targetObject.enum = ['PERSONAL_ID', 'BUSINESS_ID']
|
|
549
156
|
delete targetObject.pattern
|
|
550
|
-
delete targetObject.
|
|
157
|
+
delete targetObject.enum
|
|
551
158
|
}
|
|
552
159
|
}
|
|
553
|
-
|
|
554
|
-
// Handle array items
|
|
555
|
-
if (newSchema.type === 'array' && newSchema.items) {
|
|
556
|
-
if (newSchema.items.properties) {
|
|
557
|
-
const targetObject = _.get(newSchema.items.properties, path)
|
|
558
|
-
processSchemaObject(targetObject)
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Handle object properties
|
|
563
|
-
if (newSchema.properties) {
|
|
564
|
-
const targetObject = _.get(newSchema.properties, path)
|
|
565
|
-
processSchemaObject(targetObject)
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// Handle nested objects
|
|
569
|
-
const processNestedObjects = (obj) => {
|
|
570
|
-
if (!obj || typeof obj !== 'object') return
|
|
571
|
-
|
|
572
|
-
if (obj.properties) {
|
|
573
|
-
Object.keys(obj.properties).forEach(key => {
|
|
574
|
-
if (key === ref.id) {
|
|
575
|
-
processSchemaObject(obj.properties[key])
|
|
576
|
-
} else {
|
|
577
|
-
processNestedObjects(obj.properties[key])
|
|
578
|
-
}
|
|
579
|
-
})
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
if (obj.items) {
|
|
583
|
-
processNestedObjects(obj.items)
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
processNestedObjects(newSchema)
|
|
588
160
|
})
|
|
589
161
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
let num = ''
|
|
597
|
-
while (num.length < length) {
|
|
598
|
-
num += faker.number.int({ min: 0, max: 9 }).toString()
|
|
599
|
-
}
|
|
600
|
-
return num.slice(0, length)
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
// Helper to generate a random uppercase alphanumeric string of length 1-32
|
|
604
|
-
function generateFspId () {
|
|
605
|
-
const length = faker.number.int({ min: 1, max: 32 })
|
|
606
|
-
let result = ''
|
|
607
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
|
608
|
-
for (let i = 0; i < length; i++) {
|
|
609
|
-
result += chars.charAt(faker.number.int({ min: 0, max: chars.length - 1 }))
|
|
610
|
-
}
|
|
611
|
-
return result
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// Deep schema walk to generate mock data
|
|
615
|
-
function deepSchemaWalk (schema, key = null, jsfRefs = [], parentKey = null) {
|
|
616
|
-
if (!schema || typeof schema !== 'object') return undefined
|
|
617
|
-
|
|
618
|
-
// Add parent key context
|
|
619
|
-
schema.parentKey = parentKey
|
|
620
|
-
|
|
621
|
-
// Handle arrays
|
|
622
|
-
if (schema.type === 'array') {
|
|
623
|
-
const maxItems = schema.maxItems || 2
|
|
624
|
-
const minItems = schema.minItems || 0
|
|
625
|
-
let count = Math.min(maxItems, Math.max(minItems, 1))
|
|
626
|
-
|
|
627
|
-
// For bulk operations, ensure at least one item
|
|
628
|
-
if (parentKey === 'individualQuotes' || parentKey === 'individualTransfers') {
|
|
629
|
-
count = Math.max(1, count)
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
const items = []
|
|
633
|
-
for (let i = 0; i < count; i++) {
|
|
634
|
-
const item = deepSchemaWalk(schema.items, null, jsfRefs, key)
|
|
635
|
-
if (item !== undefined) {
|
|
636
|
-
items.push(item)
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
return items
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// Handle objects
|
|
643
|
-
if (schema.type === 'object' || schema.properties) {
|
|
644
|
-
const result = {}
|
|
645
|
-
const properties = schema.properties || {}
|
|
646
|
-
const required = schema.required || []
|
|
647
|
-
|
|
648
|
-
// Always process required fields
|
|
649
|
-
for (const propKey of required) {
|
|
650
|
-
const propSchema = properties[propKey]
|
|
651
|
-
const value = deepSchemaWalk(propSchema, propKey, jsfRefs, propKey)
|
|
652
|
-
if (value !== undefined) {
|
|
653
|
-
result[propKey] = value
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// Process optional fields based on skipNonRequired setting
|
|
658
|
-
if (!samplerOptions.skipNonRequired) {
|
|
659
|
-
for (const propKey in properties) {
|
|
660
|
-
if (!required.includes(propKey)) {
|
|
661
|
-
const propSchema = properties[propKey]
|
|
662
|
-
const value = deepSchemaWalk(propSchema, propKey, jsfRefs, propKey)
|
|
663
|
-
if (value !== undefined) {
|
|
664
|
-
result[propKey] = value
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// Handle currency matching for fees
|
|
671
|
-
if (result.amount && result.amount.currency && result.fees) {
|
|
672
|
-
result.fees.currency = result.amount.currency
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
return result
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
// Handle primitive types
|
|
679
|
-
if (schema.type) {
|
|
680
|
-
const typeHandler = samplerOptions.typeHandlers[schema.type]
|
|
681
|
-
if (typeHandler) {
|
|
682
|
-
return typeHandler({ ...schema, key, parentKey })
|
|
162
|
+
const fakedResponse = {}
|
|
163
|
+
fakedResponse.body = await jsf.resolve(newResponseSchema, jsfRefs)
|
|
164
|
+
for (const key in data.responses) {
|
|
165
|
+
fakedResponse.status = key
|
|
166
|
+
if (key >= 200 && key <= 299) {
|
|
167
|
+
break
|
|
683
168
|
}
|
|
684
169
|
}
|
|
685
|
-
|
|
686
|
-
return undefined
|
|
170
|
+
return fakedResponse
|
|
687
171
|
}
|
|
688
172
|
|
|
689
|
-
// Modify postProcessMock to use deepSchemaWalk
|
|
690
|
-
function postProcessMock (obj, schema, key = null, jsfRefs = []) {
|
|
691
|
-
// If schema is missing, try to infer type from obj
|
|
692
|
-
if (!schema || typeof schema !== 'object') {
|
|
693
|
-
if (obj === 'string' && key) {
|
|
694
|
-
const fake = customTypeHandler({ key, type: 'string' })
|
|
695
|
-
return fake !== undefined ? fake : 'string'
|
|
696
|
-
}
|
|
697
|
-
return obj
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
// Use deepSchemaWalk to generate a complete mock object
|
|
701
|
-
const generated = deepSchemaWalk(schema, key, jsfRefs)
|
|
702
|
-
|
|
703
|
-
// If deepSchemaWalk generated something, use it
|
|
704
|
-
if (generated !== undefined && typeof generated === 'object' && !Array.isArray(generated)) {
|
|
705
|
-
// Add missing top-level fields if required by tests
|
|
706
|
-
// 1. state, reason, partyIdType
|
|
707
|
-
if (schema.properties) {
|
|
708
|
-
if (schema.properties.state && generated.state === undefined) {
|
|
709
|
-
generated.state = faker.helpers.arrayElement(['Created', 'Closed'])
|
|
710
|
-
}
|
|
711
|
-
if (schema.properties.reason && generated.reason === undefined) {
|
|
712
|
-
generated.reason = faker.helpers.arrayElement(['Created', 'Closed'])
|
|
713
|
-
}
|
|
714
|
-
if (schema.properties.partyIdType && generated.partyIdType === undefined) {
|
|
715
|
-
generated.partyIdType = faker.helpers.arrayElement(['PERSONAL_ID', 'BUSINESS_ID'])
|
|
716
|
-
}
|
|
717
|
-
if (schema.properties.transferState && generated.transferState === undefined) {
|
|
718
|
-
generated.transferState = faker.helpers.arrayElement(['RECEIVED', 'RESERVED', 'COMMITTED', 'ABORTED'])
|
|
719
|
-
}
|
|
720
|
-
if (schema.properties.bulkQuoteId && generated.bulkQuoteId === undefined) {
|
|
721
|
-
generated.bulkQuoteId = faker.string.uuid()
|
|
722
|
-
}
|
|
723
|
-
if (schema.properties.bulkTransferId && generated.bulkTransferId === undefined) {
|
|
724
|
-
generated.bulkTransferId = faker.string.uuid()
|
|
725
|
-
}
|
|
726
|
-
if (schema.properties.subScenario && generated.subScenario === undefined) {
|
|
727
|
-
generated.subScenario = faker.helpers.fromRegExp(/^[A-Z_]{1,32}$/)
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
// Patch for nested FSP ID and name fields
|
|
731
|
-
function patchNested (obj) {
|
|
732
|
-
if (!obj || typeof obj !== 'object') return
|
|
733
|
-
for (const k in obj) {
|
|
734
|
-
if (k.toLowerCase() === 'fspid' && (typeof obj[k] !== 'string' || !/^[A-Z0-9]{1,32}$/.test(obj[k]))) {
|
|
735
|
-
obj[k] = generateFspId()
|
|
736
|
-
}
|
|
737
|
-
// Only apply full name fallback to 'name' field, not firstName, lastName, or complexName
|
|
738
|
-
if (
|
|
739
|
-
k.toLowerCase() === 'name' &&
|
|
740
|
-
(typeof obj[k] !== 'string' || !/^[A-Z][a-z]+ [A-Z][a-z]+$/.test(obj[k]))
|
|
741
|
-
) {
|
|
742
|
-
const first = faker.person.firstName()
|
|
743
|
-
const last = faker.person.lastName()
|
|
744
|
-
obj[k] = `${first.charAt(0).toUpperCase()}${first.slice(1)} ${last.charAt(0).toUpperCase()}${last.slice(1)}`
|
|
745
|
-
}
|
|
746
|
-
if (typeof obj[k] === 'object') patchNested(obj[k])
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
patchNested(generated)
|
|
750
|
-
return generated
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
// Fallback to original object if deepSchemaWalk didn't generate anything
|
|
754
|
-
if (typeof obj === 'object' && !Array.isArray(obj)) {
|
|
755
|
-
const result = {}
|
|
756
|
-
for (const k in obj) {
|
|
757
|
-
if (schema.properties && schema.properties[k]) {
|
|
758
|
-
result[k] = postProcessMock(obj[k], schema.properties[k], k, jsfRefs)
|
|
759
|
-
} else {
|
|
760
|
-
result[k] = obj[k]
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
return result
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
return obj
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
// Update generateMockOperation to pass jsfRefs to postProcessMock
|
|
770
173
|
const generateMockOperation = async (method, name, data, jsfRefs) => {
|
|
771
|
-
if (!data || !data.requestBody) {
|
|
772
|
-
return {}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
174
|
const requestSchema = findRequestSchema(data.requestBody)
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
console.error(`Error generating mock operation for ${method} ${name}:`, error)
|
|
787
|
-
return {}
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
// Update other generateMock functions similarly
|
|
792
|
-
const generateMockResponseBody = async (method, name, data, jsfRefs) => {
|
|
793
|
-
if (OpenApiRequestGenerator._testForceError === 'generateMockResponseBody') throw new Error('Forced error for test')
|
|
794
|
-
if (!data || !data.responses) {
|
|
795
|
-
return {}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
const responseSchema = findResponseSchema(data.responses)
|
|
799
|
-
if (!responseSchema) {
|
|
800
|
-
return {}
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
try {
|
|
804
|
-
const processedSchema = processRefs(responseSchema, jsfRefs)
|
|
805
|
-
const fakedResponse = {}
|
|
806
|
-
let sampled = JSONSchemaSampler.sample(processedSchema, samplerOptions)
|
|
807
|
-
sampled = postProcessMock(sampled, processedSchema, null, jsfRefs)
|
|
808
|
-
fakedResponse.body = sampled
|
|
809
|
-
|
|
810
|
-
for (const key in data.responses) {
|
|
811
|
-
fakedResponse.status = key
|
|
812
|
-
if (key >= 200 && key <= 299) {
|
|
813
|
-
break
|
|
175
|
+
// Create a new copy of object without copying by references
|
|
176
|
+
const newRequestSchema = JSON.parse(JSON.stringify(requestSchema))
|
|
177
|
+
jsfRefs.forEach(ref => {
|
|
178
|
+
const convertedId = ref.id.replace(/\./g, '.properties.')
|
|
179
|
+
const targetObject = _.get(newRequestSchema.properties, convertedId)
|
|
180
|
+
if (targetObject) {
|
|
181
|
+
targetObject.$ref = ref.id
|
|
182
|
+
if (ref.pattern) {
|
|
183
|
+
delete targetObject.pattern
|
|
184
|
+
delete targetObject.enum
|
|
814
185
|
}
|
|
815
186
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
const fakedResponse = await jsf.resolve(newRequestSchema, jsfRefs)
|
|
190
|
+
|
|
191
|
+
return fakedResponse
|
|
821
192
|
}
|
|
822
193
|
|
|
823
194
|
const generateMockHeaders = async (method, name, data, jsfRefs) => {
|
|
824
|
-
|
|
825
|
-
if (!data || !Array.isArray(data.parameters)) {
|
|
826
|
-
return {}
|
|
827
|
-
}
|
|
828
|
-
const properties = {}
|
|
195
|
+
const headers = {}
|
|
829
196
|
data.parameters.forEach(param => {
|
|
830
197
|
if (param.in === 'header') {
|
|
831
|
-
|
|
198
|
+
headers[param.name] = (param.schema && param.schema.type) ? { type: param.schema.type } : {}
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
jsfRefs.forEach(ref => {
|
|
202
|
+
if (headers[ref.id]) {
|
|
203
|
+
headers[ref.id] = { $ref: ref.id }
|
|
832
204
|
}
|
|
833
205
|
})
|
|
834
206
|
|
|
835
|
-
if (Object.keys(
|
|
207
|
+
if (Object.keys(headers).length === 0) {
|
|
836
208
|
return {}
|
|
837
209
|
}
|
|
838
210
|
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
sampled = postProcessMock(sampled, processedSchema, null, jsfRefs)
|
|
843
|
-
if (sampled === null) sampled = {}
|
|
844
|
-
return sampled
|
|
211
|
+
const fakedResponse = await jsf.resolve(headers, jsfRefs)
|
|
212
|
+
|
|
213
|
+
return fakedResponse
|
|
845
214
|
}
|
|
846
215
|
|
|
847
216
|
const generateMockQueryParams = async (method, name, data, jsfRefs) => {
|
|
848
|
-
|
|
849
|
-
if (!data || !Array.isArray(data.parameters)) {
|
|
850
|
-
return {}
|
|
851
|
-
}
|
|
852
|
-
const properties = {}
|
|
217
|
+
const queryParams = {}
|
|
853
218
|
data.parameters.forEach(param => {
|
|
854
219
|
if (param.in === 'query') {
|
|
855
|
-
|
|
220
|
+
queryParams[param.name] = (param.schema) ? { ...param.schema } : {}
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
jsfRefs.forEach(ref => {
|
|
224
|
+
if (queryParams[ref.id]) {
|
|
225
|
+
queryParams[ref.id] = { $ref: ref.id }
|
|
856
226
|
}
|
|
857
227
|
})
|
|
858
228
|
|
|
859
|
-
if (Object.keys(
|
|
229
|
+
if (Object.keys(queryParams).length === 0) {
|
|
860
230
|
return {}
|
|
861
231
|
}
|
|
862
232
|
|
|
863
|
-
const
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
sampled = postProcessMock(sampled, processedSchema, null, jsfRefs)
|
|
867
|
-
if (sampled === null) sampled = {}
|
|
868
|
-
return sampled
|
|
233
|
+
const fakedResponse = await jsf.resolve(queryParams, jsfRefs)
|
|
234
|
+
|
|
235
|
+
return fakedResponse
|
|
869
236
|
}
|
|
870
237
|
|
|
871
238
|
const generateMockPathParams = async (method, name, data, jsfRefs) => {
|
|
872
|
-
|
|
873
|
-
if (!data || !Array.isArray(data.parameters)) {
|
|
874
|
-
return {}
|
|
875
|
-
}
|
|
876
|
-
const properties = {}
|
|
239
|
+
const pathParams = {}
|
|
877
240
|
data.parameters.forEach(param => {
|
|
878
241
|
if (param.in === 'path') {
|
|
879
|
-
|
|
242
|
+
pathParams[param.name] = (param.schema) ? { ...param.schema } : {}
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
jsfRefs.forEach(ref => {
|
|
246
|
+
if (pathParams[ref.id]) {
|
|
247
|
+
pathParams[ref.id] = { $ref: ref.id }
|
|
880
248
|
}
|
|
881
249
|
})
|
|
882
250
|
|
|
883
|
-
if (Object.keys(
|
|
251
|
+
if (Object.keys(pathParams).length === 0) {
|
|
884
252
|
return {}
|
|
885
253
|
}
|
|
886
254
|
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
sampled = postProcessMock(sampled, processedSchema, null, jsfRefs)
|
|
891
|
-
if (sampled === null) sampled = {}
|
|
892
|
-
return sampled
|
|
255
|
+
const fakedResponse = await jsf.resolve(pathParams, jsfRefs)
|
|
256
|
+
|
|
257
|
+
return fakedResponse
|
|
893
258
|
}
|
|
894
259
|
|
|
895
260
|
class OpenApiRequestGenerator {
|
|
@@ -898,105 +263,44 @@ class OpenApiRequestGenerator {
|
|
|
898
263
|
}
|
|
899
264
|
|
|
900
265
|
async load (schemaPath) {
|
|
901
|
-
|
|
902
|
-
this.schema = await loadYamlFile(schemaPath)
|
|
903
|
-
} catch (error) {
|
|
904
|
-
console.error('Error loading schema:', error)
|
|
905
|
-
this.schema = {}
|
|
906
|
-
}
|
|
266
|
+
this.schema = await loadYamlFile(schemaPath)
|
|
907
267
|
}
|
|
908
268
|
|
|
909
269
|
async generateRequestBody (path, httpMethod, jsfRefs = []) {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
}
|
|
915
|
-
const operation = pathValue[httpMethod]
|
|
916
|
-
if (!operation) {
|
|
917
|
-
return {}
|
|
918
|
-
}
|
|
919
|
-
const id = operation.operationId || operation.summary
|
|
920
|
-
return generateMockOperation(httpMethod, id, operation, jsfRefs)
|
|
921
|
-
} catch (error) {
|
|
922
|
-
console.error(`Error generating request body for ${path} ${httpMethod}:`, error)
|
|
923
|
-
return {}
|
|
924
|
-
}
|
|
270
|
+
const pathValue = this.schema.paths[path]
|
|
271
|
+
const operation = pathValue[httpMethod]
|
|
272
|
+
const id = operation.operationId || operation.summary
|
|
273
|
+
return generateMockOperation(httpMethod, id, operation, jsfRefs)
|
|
925
274
|
}
|
|
926
275
|
|
|
927
276
|
async generateRequestHeaders (path, httpMethod, jsfRefs = []) {
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
}
|
|
933
|
-
const operation = pathValue[httpMethod]
|
|
934
|
-
if (!operation) {
|
|
935
|
-
return {}
|
|
936
|
-
}
|
|
937
|
-
const id = operation.operationId || operation.summary
|
|
938
|
-
return generateMockHeaders(httpMethod, id, operation, jsfRefs)
|
|
939
|
-
} catch (error) {
|
|
940
|
-
console.error(`Error generating request headers for ${path} ${httpMethod}:`, error)
|
|
941
|
-
return {}
|
|
942
|
-
}
|
|
277
|
+
const pathValue = this.schema.paths[path]
|
|
278
|
+
const operation = pathValue[httpMethod]
|
|
279
|
+
const id = operation.operationId || operation.summary
|
|
280
|
+
return generateMockHeaders(httpMethod, id, operation, jsfRefs)
|
|
943
281
|
}
|
|
944
282
|
|
|
945
283
|
async generateRequestQueryParams (path, httpMethod, jsfRefs = []) {
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
}
|
|
951
|
-
const operation = pathValue[httpMethod]
|
|
952
|
-
if (!operation) {
|
|
953
|
-
return {}
|
|
954
|
-
}
|
|
955
|
-
const id = operation.operationId || operation.summary
|
|
956
|
-
return generateMockQueryParams(httpMethod, id, operation, jsfRefs)
|
|
957
|
-
} catch (error) {
|
|
958
|
-
console.error(`Error generating query params for ${path} ${httpMethod}:`, error)
|
|
959
|
-
return {}
|
|
960
|
-
}
|
|
284
|
+
const pathValue = this.schema.paths[path]
|
|
285
|
+
const operation = pathValue[httpMethod]
|
|
286
|
+
const id = operation.operationId || operation.summary
|
|
287
|
+
return generateMockQueryParams(httpMethod, id, operation, jsfRefs)
|
|
961
288
|
}
|
|
962
289
|
|
|
963
290
|
async generateRequestPathParams (path, httpMethod, jsfRefs = []) {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
}
|
|
969
|
-
const operation = pathValue[httpMethod]
|
|
970
|
-
if (!operation) {
|
|
971
|
-
return {}
|
|
972
|
-
}
|
|
973
|
-
const id = operation.operationId || operation.summary
|
|
974
|
-
return generateMockPathParams(httpMethod, id, operation, jsfRefs)
|
|
975
|
-
} catch (error) {
|
|
976
|
-
console.error(`Error generating path params for ${path} ${httpMethod}:`, error)
|
|
977
|
-
return {}
|
|
978
|
-
}
|
|
291
|
+
const pathValue = this.schema.paths[path]
|
|
292
|
+
const operation = pathValue[httpMethod]
|
|
293
|
+
const id = operation.operationId || operation.summary
|
|
294
|
+
return generateMockPathParams(httpMethod, id, operation, jsfRefs)
|
|
979
295
|
}
|
|
980
296
|
|
|
981
297
|
async generateResponseBody (path, httpMethod, jsfRefs = []) {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const operation = pathValue[httpMethod]
|
|
988
|
-
if (!operation) {
|
|
989
|
-
return {}
|
|
990
|
-
}
|
|
991
|
-
const id = operation.operationId || operation.summary
|
|
992
|
-
return generateMockResponseBody(httpMethod, id, operation, jsfRefs)
|
|
993
|
-
} catch (error) {
|
|
994
|
-
console.error(`Error generating response body for ${path} ${httpMethod}:`, error)
|
|
995
|
-
return {}
|
|
996
|
-
}
|
|
298
|
+
const pathValue = this.schema.paths[path]
|
|
299
|
+
const operation = pathValue[httpMethod]
|
|
300
|
+
const id = operation.operationId || operation.summary
|
|
301
|
+
|
|
302
|
+
return generateMockResponseBody(httpMethod, id, operation, jsfRefs)
|
|
997
303
|
}
|
|
998
304
|
}
|
|
999
305
|
|
|
1000
|
-
OpenApiRequestGenerator._testForceError = null
|
|
1001
|
-
|
|
1002
306
|
module.exports = OpenApiRequestGenerator
|
package/.husky/commit-msg
DELETED
package/.husky/post-commit
DELETED
package/.husky/pre-commit
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
npm run lint; npm run dep:check; npm run test:unit
|