@api-client/core 0.14.9 → 0.15.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.
Files changed (110) hide show
  1. package/RELEASE.md +163 -0
  2. package/RELEASE_SETUP.md +235 -0
  3. package/build/src/events/authorization/AuthorizationEvents.d.ts +1 -1
  4. package/build/src/events/authorization/AuthorizationEvents.d.ts.map +1 -1
  5. package/build/src/events/authorization/AuthorizationEvents.js +1 -1
  6. package/build/src/events/authorization/AuthorizationEvents.js.map +1 -1
  7. package/build/src/events/cookies/CookieEvents.d.ts +1 -1
  8. package/build/src/events/cookies/CookieEvents.d.ts.map +1 -1
  9. package/build/src/events/cookies/CookieEvents.js +1 -1
  10. package/build/src/events/cookies/CookieEvents.js.map +1 -1
  11. package/build/src/modeling/DataDomain.d.ts +45 -3
  12. package/build/src/modeling/DataDomain.d.ts.map +1 -1
  13. package/build/src/modeling/DataDomain.js +81 -3
  14. package/build/src/modeling/DataDomain.js.map +1 -1
  15. package/build/src/modeling/DomainElement.d.ts +7 -0
  16. package/build/src/modeling/DomainElement.d.ts.map +1 -1
  17. package/build/src/modeling/DomainElement.js +14 -0
  18. package/build/src/modeling/DomainElement.js.map +1 -1
  19. package/build/src/modeling/DomainImpactAnalysis.d.ts +22 -119
  20. package/build/src/modeling/DomainImpactAnalysis.d.ts.map +1 -1
  21. package/build/src/modeling/DomainImpactAnalysis.js +49 -155
  22. package/build/src/modeling/DomainImpactAnalysis.js.map +1 -1
  23. package/build/src/modeling/DomainValidation.d.ts +8 -0
  24. package/build/src/modeling/DomainValidation.d.ts.map +1 -0
  25. package/build/src/modeling/DomainValidation.js +99 -0
  26. package/build/src/modeling/DomainValidation.js.map +1 -0
  27. package/build/src/modeling/types.d.ts +70 -0
  28. package/build/src/modeling/types.d.ts.map +1 -1
  29. package/build/src/modeling/types.js.map +1 -1
  30. package/build/src/modeling/validation/entity_validation.js +1 -1
  31. package/build/src/modeling/validation/entity_validation.js.map +1 -1
  32. package/build/src/modeling/validation/rules.d.ts +2 -3
  33. package/build/src/modeling/validation/rules.d.ts.map +1 -1
  34. package/build/src/modeling/validation/rules.js.map +1 -1
  35. package/build/src/modeling/validation/semantic_validation.d.ts +31 -0
  36. package/build/src/modeling/validation/semantic_validation.d.ts.map +1 -0
  37. package/build/src/modeling/validation/semantic_validation.js +126 -0
  38. package/build/src/modeling/validation/semantic_validation.js.map +1 -0
  39. package/build/tsconfig.tsbuildinfo +1 -1
  40. package/data/models/example-generator-api.json +12 -12
  41. package/noop.ts +3 -0
  42. package/package.json +9 -4
  43. package/src/events/authorization/AuthorizationEvents.ts +1 -1
  44. package/src/events/cookies/CookieEvents.ts +1 -1
  45. package/src/modeling/DataDomain.ts +84 -3
  46. package/src/modeling/DomainElement.ts +16 -0
  47. package/src/modeling/DomainImpactAnalysis.ts +54 -239
  48. package/src/modeling/DomainValidation.ts +105 -0
  49. package/src/modeling/types.ts +86 -0
  50. package/src/modeling/validation/entity_validation.ts +1 -1
  51. package/src/modeling/validation/rules.ts +2 -4
  52. package/src/modeling/validation/semantic_validation.ts +145 -0
  53. package/tests/unit/events/EventsTestHelpers.ts +16 -0
  54. package/tests/unit/events/amf.spec.ts +151 -0
  55. package/tests/unit/events/authorization.spec.ts +150 -0
  56. package/tests/unit/events/cookie.spec.ts +274 -0
  57. package/tests/unit/events/encryption.spec.ts +108 -0
  58. package/tests/unit/events/events_polyfills.ts +77 -0
  59. package/tests/unit/events/process.spec.ts +120 -0
  60. package/tests/unit/events/reporting.spec.ts +82 -0
  61. package/tests/unit/events/telemetry.spec.ts +224 -0
  62. package/tests/unit/events/transport.spec.ts +139 -0
  63. package/tests/unit/modeling/data_domain_foreign.spec.ts +244 -0
  64. package/tests/unit/modeling/domain_impact_analysis.spec.ts +0 -110
  65. package/tests/unit/modeling/domain_validation.spec.ts +94 -0
  66. package/tests/unit/modeling/validation/semantic_validation.spec.ts +91 -0
  67. package/tests/unit/models/environment.spec.ts +574 -0
  68. package/tests/unit/models/error_response.spec.ts +183 -0
  69. package/tests/unit/models/headers_array.spec.ts +86 -0
  70. package/tests/unit/models/http-actions/assertion/equal_assertion.spec.ts +103 -0
  71. package/tests/unit/models/http-actions/assertion/greater_than_assertion.spec.ts +91 -0
  72. package/tests/unit/models/http-actions/assertion/includes_assertion.spec.ts +71 -0
  73. package/tests/unit/models/http-actions/assertion/less_than_assertion.spec.ts +91 -0
  74. package/tests/unit/models/http-actions/assertion/matches_assertion.spec.ts +71 -0
  75. package/tests/unit/models/http-actions/assertion/matches_schema_assertion.spec.ts +117 -0
  76. package/tests/unit/models/http-actions/assertion/not_equal_assertion.spec.ts +103 -0
  77. package/tests/unit/models/http-actions/assertion/not_includes_assertion.spec.ts +71 -0
  78. package/tests/unit/models/http-actions/assertion/not_ok_assertion.spec.ts +47 -0
  79. package/tests/unit/models/http-actions/assertion/not_to_be_assertion.spec.ts +72 -0
  80. package/tests/unit/models/http-actions/assertion/ok_assertion.spec.ts +44 -0
  81. package/tests/unit/models/http-actions/assertion/to_be_assertion.spec.ts +71 -0
  82. package/tests/unit/models/http-actions/transformation/as_lower_case_step.spec.ts +47 -0
  83. package/tests/unit/models/http-actions/transformation/as_number_step.spec.ts +47 -0
  84. package/tests/unit/models/http-actions/transformation/as_upper_case_step.spec.ts +47 -0
  85. package/tests/unit/models/http-actions/transformation/round_step.spec.ts +69 -0
  86. package/tests/unit/models/http-actions/transformation/substring_step.spec.ts +85 -0
  87. package/tests/unit/models/http-actions/transformation/trim_step.spec.ts +44 -0
  88. package/tests/unit/models/http_cookie.spec.ts +516 -0
  89. package/tests/unit/models/http_history.spec.ts +443 -0
  90. package/tests/unit/models/project_folder.spec.ts +926 -0
  91. package/tests/unit/models/project_item.spec.ts +137 -0
  92. package/tests/unit/models/project_request.spec.ts +1047 -0
  93. package/tests/unit/models/project_schema.spec.ts +236 -0
  94. package/tests/unit/models/property.spec.ts +625 -0
  95. package/tests/unit/models/provider.spec.ts +102 -0
  96. package/tests/unit/models/request.spec.ts +1206 -0
  97. package/tests/unit/models/request_log.spec.ts +308 -0
  98. package/tests/unit/models/request_time.spec.ts +138 -0
  99. package/tests/unit/models/response_redirect.spec.ts +303 -0
  100. package/tests/unit/models/sent_request.spec.ts +206 -0
  101. package/tests/unit/models/server.spec.ts +195 -0
  102. package/tests/unit/models/thing.spec.ts +154 -0
  103. package/build/oauth-popup.html +0 -33
  104. /package/tests/unit/models/{Certificate.spec.ts → certificate.spec.ts} +0 -0
  105. /package/tests/unit/models/{HostRule.spec.ts → host_rule.spec.ts} +0 -0
  106. /package/tests/unit/models/{HttpProject.spec.ts → http_project.spec.ts} +0 -0
  107. /package/tests/unit/models/{HttpRequest.spec.ts → http_request.spec.ts} +0 -0
  108. /package/tests/unit/models/{HttpResponse.spec.ts → http_response.spec.ts} +0 -0
  109. /package/tests/unit/models/{License.spec.ts → license.spec.ts} +0 -0
  110. /package/tests/unit/models/{Response.spec.ts → response.spec.ts} +0 -0
@@ -0,0 +1,926 @@
1
+ import { test } from '@japa/runner'
2
+ import sinon from 'sinon'
3
+ import { HttpProject } from '../../../src/models/HttpProject.js'
4
+ import { ProjectFolder, DefaultFolderName, IProjectFolder } from '../../../src/models/ProjectFolder.js'
5
+ import { ProjectItem } from '../../../src/models/ProjectItem.js'
6
+ import { Environment, Kind as EnvironmentKind } from '../../../src/models/Environment.js'
7
+ import { ProjectRequest } from '../../../src/models/ProjectRequest.js'
8
+ import { ProjectFolderKind, ThingKind } from '../../../src/models/kinds.js'
9
+
10
+ test.group('Models > ProjectFolder > Initialization', (group) => {
11
+ let project: HttpProject
12
+ group.each.setup(() => {
13
+ project = new HttpProject()
14
+ })
15
+
16
+ test('initializes a default folder', ({ assert }) => {
17
+ const result = new ProjectFolder(project)
18
+ assert.equal(result.kind, ProjectFolderKind, 'sets the kind property')
19
+ assert.deepEqual(result.items, [], 'sets the items property')
20
+ assert.typeOf(result.updated, 'number', 'sets the updated property')
21
+ assert.typeOf(result.created, 'number', 'sets the created property')
22
+
23
+ const { info } = result
24
+ assert.typeOf(info, 'EventTarget', 'sets the default info property')
25
+ assert.equal(info.kind, ThingKind, 'sets the info.kind property')
26
+ assert.equal(info.name, DefaultFolderName, 'sets the info.name property')
27
+ })
28
+ })
29
+
30
+ test.group('Models > ProjectFolder > From schema initialization', (group) => {
31
+ let project: HttpProject
32
+ let base: IProjectFolder
33
+ group.each.setup(() => {
34
+ project = new HttpProject()
35
+ base = {
36
+ kind: ProjectFolderKind,
37
+ items: [],
38
+ updated: 123,
39
+ created: 456,
40
+ key: 'test1234',
41
+ info: {
42
+ kind: ThingKind,
43
+ name: '',
44
+ },
45
+ }
46
+ })
47
+
48
+ test('sets the info', ({ assert }) => {
49
+ const init: IProjectFolder = {
50
+ ...base,
51
+ ...{
52
+ info: {
53
+ kind: ThingKind,
54
+ name: 'Test project',
55
+ description: 'Project description',
56
+ version: '1.2.3',
57
+ },
58
+ },
59
+ }
60
+ const result = new ProjectFolder(project, init)
61
+ const { info } = result
62
+ assert.equal(info.kind, ThingKind, 'sets the info.kind property')
63
+ assert.equal(info.name, 'Test project', 'sets the info.name property')
64
+ assert.equal(info.description, 'Project description', 'sets the info.description property')
65
+ assert.equal(info.version, '1.2.3', 'sets the info.version property')
66
+ })
67
+
68
+ test('sets the created/updated', ({ assert }) => {
69
+ const result = new ProjectFolder(project, base)
70
+ assert.equal(result.created, 456)
71
+ assert.equal(result.updated, 123)
72
+ })
73
+
74
+ test('sets the passed key', ({ assert }) => {
75
+ const result = new ProjectFolder(project, base)
76
+ assert.equal(result.key, 'test1234')
77
+ })
78
+
79
+ test('sets a new key when the passed key is missing', ({ assert }) => {
80
+ // @ts-expect-error Used in testing
81
+ delete base.key
82
+ const result = new ProjectFolder(project, base)
83
+ assert.typeOf(result.key, 'string')
84
+ })
85
+
86
+ test('creates the default items', ({ assert }) => {
87
+ // @ts-expect-error Used in testing
88
+ delete base.items
89
+ const result = new ProjectFolder(project, base)
90
+ assert.deepEqual(result.items, [])
91
+ })
92
+
93
+ test('sets the stored items', ({ assert }) => {
94
+ base.items = [ProjectItem.projectFolder(project, 'a-key')]
95
+ const serialized = JSON.stringify(base)
96
+ const result = new ProjectFolder(project, serialized)
97
+ assert.lengthOf(result.items, 1, 'has a single item')
98
+ assert.equal(result.items[0].key, 'a-key', 'has the serialized item')
99
+ })
100
+ })
101
+
102
+ test.group('Models > ProjectFolder > From JSON string initialization', () => {
103
+ test('restores project data from JSON string', ({ assert }) => {
104
+ const project = new HttpProject()
105
+ const folder = project.addFolder('a folder')
106
+ const str = JSON.stringify(folder)
107
+
108
+ const result = new ProjectFolder(project, str)
109
+
110
+ assert.equal(result.key, folder.key, 'restores the key')
111
+ assert.equal(result.info.name, 'a folder', 'restores the info object')
112
+ })
113
+
114
+ test('throws when invalid folder object', ({ assert }) => {
115
+ const project = new HttpProject()
116
+ const folder = project.addFolder('a folder')
117
+ const schema = folder.toJSON()
118
+ // @ts-expect-error Used in testing
119
+ delete schema.kind
120
+ const str = JSON.stringify(schema)
121
+
122
+ assert.throws(() => {
123
+ new ProjectFolder(project, str)
124
+ })
125
+ })
126
+ })
127
+
128
+ test.group('Models > ProjectFolder > toJSON()', (group) => {
129
+ let project: HttpProject
130
+ let base: IProjectFolder
131
+ group.each.setup(() => {
132
+ project = new HttpProject()
133
+ base = {
134
+ kind: ProjectFolderKind,
135
+ items: [],
136
+ updated: 123,
137
+ created: 456,
138
+ key: 'test1234',
139
+ info: {
140
+ kind: ThingKind,
141
+ name: '',
142
+ },
143
+ }
144
+ })
145
+
146
+ test('serializes the info object', ({ assert }) => {
147
+ const init: IProjectFolder = {
148
+ ...base,
149
+ ...{
150
+ info: {
151
+ kind: ThingKind,
152
+ name: 'Test project',
153
+ description: 'Project description',
154
+ version: '1.2.3',
155
+ },
156
+ },
157
+ }
158
+ const folder = new ProjectFolder(project, init)
159
+ const result = folder.toJSON()
160
+ assert.equal(result.info.kind, ThingKind, 'has the kind')
161
+ assert.equal(result.info.name, 'Test project', 'has the name')
162
+ assert.equal(result.info.description, 'Project description', 'has the description')
163
+ assert.equal(result.info.version, '1.2.3', 'has the version')
164
+ })
165
+
166
+ test('serializes the key', ({ assert }) => {
167
+ const init: IProjectFolder = { ...base }
168
+ const folder = new ProjectFolder(project, init)
169
+ const result = folder.toJSON()
170
+ assert.equal(result.key, init.key)
171
+ })
172
+
173
+ test('serializes the created/updated', ({ assert }) => {
174
+ const init: IProjectFolder = { ...base }
175
+ const folder = new ProjectFolder(project, init)
176
+ const result = folder.toJSON()
177
+ assert.equal(result.created, init.created)
178
+ assert.equal(result.updated, init.updated)
179
+ })
180
+
181
+ test('serializes the items', ({ assert }) => {
182
+ const init: IProjectFolder = { ...base, ...{ items: [ProjectItem.projectFolder(project, 'a-key')] } }
183
+ const folder = new ProjectFolder(project, init)
184
+ const result = folder.toJSON()
185
+ assert.lengthOf(result.items, 1)
186
+ })
187
+ })
188
+
189
+ test.group('Models > ProjectFolder > ProjectFolder.fromName()', (group) => {
190
+ let project: HttpProject
191
+ group.each.setup(() => {
192
+ project = new HttpProject()
193
+ })
194
+
195
+ test('sets the name', ({ assert }) => {
196
+ const result = ProjectFolder.fromName(project, 'a name')
197
+ assert.equal(result.info.name, 'a name')
198
+ })
199
+
200
+ test('uses the default name', ({ assert }) => {
201
+ const result = ProjectFolder.fromName(project)
202
+ assert.equal(result.info.name, DefaultFolderName)
203
+ })
204
+
205
+ test('generates the key', ({ assert }) => {
206
+ const result = ProjectFolder.fromName(project, 'a name')
207
+ assert.typeOf(result.key, 'string')
208
+ })
209
+
210
+ test('generates the created/updated', ({ assert }) => {
211
+ const result = ProjectFolder.fromName(project, 'a name')
212
+ assert.closeTo(result.updated, Date.now(), 100)
213
+ assert.closeTo(result.created, Date.now(), 100)
214
+ })
215
+
216
+ test('adds empty items', ({ assert }) => {
217
+ const result = ProjectFolder.fromName(project, 'a name')
218
+ assert.deepEqual(result.items, [])
219
+ })
220
+
221
+ test('sets the kind', ({ assert }) => {
222
+ const result = ProjectFolder.fromName(project, 'a name')
223
+ assert.equal(result.kind, ProjectFolderKind)
224
+ })
225
+ })
226
+
227
+ test.group('Models > ProjectFolder > new()', () => {
228
+ test('restores a folder definition', ({ assert }) => {
229
+ const project = new HttpProject()
230
+ const folder = project.addFolder('a folder')
231
+ const time = 12345
232
+ folder.new({
233
+ created: time,
234
+ updated: time,
235
+ info: {
236
+ kind: ThingKind,
237
+ name: 'test',
238
+ },
239
+ items: [],
240
+ key: 'abc',
241
+ kind: ProjectFolderKind,
242
+ })
243
+ assert.equal(folder.created, time, 'updates the created')
244
+ assert.equal(folder.updated, time, 'updates the updated') // Corrected from 'updates the created'
245
+ assert.equal(folder.key, 'abc', 'updates the key')
246
+ assert.equal(folder.info.name, 'test', 'updates the info')
247
+ })
248
+
249
+ test('restores items', ({ assert }) => {
250
+ const project = new HttpProject()
251
+ const folder = project.addFolder('a folder')
252
+ const time = 12345
253
+ const def: IProjectFolder = {
254
+ created: time,
255
+ updated: time,
256
+ info: {
257
+ kind: ThingKind,
258
+ name: 'test',
259
+ },
260
+ items: [], // Assuming items should be processed by .new() if present in schema
261
+ key: 'abc',
262
+ kind: ProjectFolderKind,
263
+ }
264
+ folder.new(def)
265
+ assert.equal(folder.created, time, 'updates the created')
266
+ assert.equal(folder.updated, time, 'updates the updated') // Corrected
267
+ assert.equal(folder.key, 'abc', 'updates the key')
268
+ assert.equal(folder.info.name, 'test', 'updates the info')
269
+ // Add assertion for items if .new() is expected to process them
270
+ assert.deepEqual(folder.items, [], 'updates the items')
271
+ })
272
+
273
+ test('adds the default info object', ({ assert }) => {
274
+ const project = new HttpProject()
275
+ const folder = project.addFolder('a folder')
276
+ const time = 12345
277
+ const def: IProjectFolder = {
278
+ created: time,
279
+ updated: time,
280
+ info: {
281
+ // This info will be deleted before calling new()
282
+ kind: ThingKind,
283
+ name: 'test',
284
+ },
285
+ items: [],
286
+ key: 'abc',
287
+ kind: ProjectFolderKind,
288
+ }
289
+ // @ts-expect-error Used in testing
290
+ delete def.info
291
+ folder.new(def)
292
+ assert.equal(folder.info.name, DefaultFolderName)
293
+ })
294
+ })
295
+
296
+ test.group('Models > ProjectFolder > addFolder()', (group) => {
297
+ let project: HttpProject
298
+ group.each.setup(() => {
299
+ project = new HttpProject()
300
+ })
301
+
302
+ test("calls the project's add folder function", ({ assert }) => {
303
+ const parent = project.addFolder('parent')
304
+ const spy = sinon.spy(project, 'addFolder')
305
+ parent.addFolder('a folder')
306
+ assert.isTrue(spy.calledOnce)
307
+ assert.equal(spy.args[0][0], 'a folder', 'has the name')
308
+ assert.deepEqual(spy.args[0][1], { parent: parent.key }, 'has the options')
309
+ spy.restore()
310
+ })
311
+
312
+ test('adds the folder to the items', ({ assert }) => {
313
+ const parent = project.addFolder('parent')
314
+ parent.addFolder('sub')
315
+ assert.lengthOf(parent.items, 1)
316
+ })
317
+
318
+ test('adds a folder by name', ({ assert }) => {
319
+ const parent = project.addFolder('parent')
320
+ parent.addFolder('sub')
321
+ const def = project.findFolder('sub')!
322
+ assert.equal(def.info.name, 'sub')
323
+ })
324
+
325
+ test('adds a folder by schema', ({ assert }) => {
326
+ const parent = project.addFolder('parent')
327
+ const f = new ProjectFolder(project)
328
+ f.info.name = 'sub'
329
+ parent.addFolder(f.toJSON())
330
+ const def = project.findFolder('sub')!
331
+ assert.equal(def.info.name, 'sub')
332
+ })
333
+
334
+ test('adds a folder by an instance', ({ assert }) => {
335
+ const parent = project.addFolder('parent')
336
+ const f = new ProjectFolder(project)
337
+ f.info.name = 'sub'
338
+ parent.addFolder(f)
339
+ const def = project.findFolder('sub')!
340
+ assert.equal(def.info.name, 'sub')
341
+ })
342
+ })
343
+
344
+ test.group('Models > ProjectFolder > addRequest()', (group) => {
345
+ let project: HttpProject
346
+ group.each.setup(() => {
347
+ project = new HttpProject()
348
+ })
349
+
350
+ test("calls the project's add request function", ({ assert }) => {
351
+ const parent = project.addFolder('parent')
352
+ const spy = sinon.spy(project, 'addRequest')
353
+ const request = ProjectRequest.fromName('test', project)
354
+ parent.addRequest(request)
355
+ assert.isTrue(spy.calledOnce)
356
+ assert.deepEqual(spy.args[0][0], request, 'has the request')
357
+ assert.deepEqual(spy.args[0][1], { parent: parent.key }, 'has the options')
358
+ spy.restore()
359
+ })
360
+
361
+ test('adds the request to the items', ({ assert }) => {
362
+ const parent = project.addFolder('parent')
363
+ const request = ProjectRequest.fromName('test', project)
364
+ parent.addRequest(request)
365
+ assert.lengthOf(parent.items, 1)
366
+ })
367
+
368
+ test('adds a request from the url', ({ assert }) => {
369
+ const parent = project.addFolder('parent')
370
+ const request = parent.addRequest('https://api.com')
371
+ assert.equal(request.info.name, 'https://api.com')
372
+ assert.equal(request.expects.url, 'https://api.com')
373
+ })
374
+ })
375
+
376
+ test.group('Models > ProjectFolder > listFolderItems()', (group) => {
377
+ let project: HttpProject
378
+ group.each.setup(() => {
379
+ project = new HttpProject()
380
+ })
381
+
382
+ test('returns empty array when no folders', ({ assert }) => {
383
+ const folder = project.addFolder('parent')
384
+
385
+ const request = ProjectRequest.fromName('test', project)
386
+ folder.addRequest(request)
387
+
388
+ const result = folder.listFolderItems()
389
+ assert.deepEqual(result, [])
390
+ })
391
+
392
+ test('returns folder folders', ({ assert }) => {
393
+ const folder = project.addFolder('parent')
394
+ const f1 = folder.addFolder('f1')
395
+ const f2 = folder.addFolder('f2')
396
+
397
+ const request = ProjectRequest.fromName('test', project)
398
+ folder.addRequest(request)
399
+
400
+ const result = folder.listFolderItems()
401
+ assert.lengthOf(result, 2, 'has 2 items')
402
+ assert.equal(result[0].key, f1.key, 'has the first folder')
403
+ assert.equal(result[1].key, f2.key, 'has the second folder')
404
+ })
405
+ })
406
+
407
+ test.group('Models > ProjectFolder > listRequestItems()', (group) => {
408
+ let project: HttpProject
409
+ group.each.setup(() => {
410
+ project = new HttpProject()
411
+ })
412
+
413
+ test('returns empty array when no requests', ({ assert }) => {
414
+ const folder = project.addFolder('parent')
415
+ folder.addFolder('f1')
416
+
417
+ const result = folder.listRequestItems()
418
+ assert.deepEqual(result, [])
419
+ })
420
+
421
+ test('returns folder requests', ({ assert }) => {
422
+ const folder = project.addFolder('parent')
423
+ const request = ProjectRequest.fromName('test', project)
424
+ folder.addRequest(request)
425
+
426
+ const result = folder.listRequestItems()
427
+ assert.lengthOf(result, 1, 'has the request')
428
+ assert.equal(result[0].key, request.key, 'has the key')
429
+ })
430
+ })
431
+
432
+ test.group('Models > ProjectFolder > listFolders()', (group) => {
433
+ let project: HttpProject
434
+ group.each.setup(() => {
435
+ project = new HttpProject()
436
+ })
437
+
438
+ test("calls the project's listFolders function", ({ assert }) => {
439
+ const folder = project.addFolder('parent')
440
+ const spy = sinon.spy(project, 'listFolders')
441
+ folder.listFolders()
442
+ assert.isTrue(spy.calledOnce)
443
+ assert.deepEqual(spy.args[0][0], { folder: folder.key }, 'has the only argument')
444
+ // Original was spy.args[0][0]!.folder
445
+ spy.restore()
446
+ })
447
+
448
+ test('returns the list', ({ assert }) => {
449
+ const folder = project.addFolder('parent')
450
+ const child = folder.addFolder('child')
451
+ const result = folder.listFolders()
452
+ assert.deepEqual(result, [child])
453
+ })
454
+ })
455
+
456
+ test.group('Models > ProjectFolder > listRequests()', (group) => {
457
+ let project: HttpProject
458
+ group.each.setup(() => {
459
+ project = new HttpProject()
460
+ })
461
+
462
+ test("calls the project's listRequests function", ({ assert }) => {
463
+ const folder = project.addFolder('parent')
464
+ const spy = sinon.spy(project, 'listRequests')
465
+ folder.listRequests()
466
+ assert.isTrue(spy.calledOnce)
467
+ assert.equal(spy.args[0][0], folder.key, 'has the only argument')
468
+ spy.restore()
469
+ })
470
+
471
+ test('returns the list', ({ assert }) => {
472
+ const folder = project.addFolder('parent')
473
+
474
+ const request = ProjectRequest.fromName('test', project)
475
+ folder.addRequest(request)
476
+
477
+ const result = folder.listRequests()
478
+ assert.deepEqual(result, [request])
479
+ })
480
+ })
481
+
482
+ test.group('Models > ProjectFolder > remove()', (group) => {
483
+ let project: HttpProject
484
+ let folder: ProjectFolder
485
+
486
+ group.each.setup(() => {
487
+ project = new HttpProject()
488
+ folder = project.addFolder('test')
489
+ })
490
+
491
+ test('removes the folder from the project definitions', ({ assert }) => {
492
+ folder.remove()
493
+ assert.deepEqual(project.definitions.folders, [])
494
+ })
495
+
496
+ test('removes the folder from the project items', ({ assert }) => {
497
+ folder.remove()
498
+ assert.deepEqual(project.items, [])
499
+ })
500
+
501
+ test('removes the folder from the parent folder items', ({ assert }) => {
502
+ const sub = folder.addFolder('sub')
503
+ sub.remove()
504
+ assert.deepEqual(folder.items, [])
505
+ })
506
+
507
+ test('removes the sub-folder from the project definitions', ({ assert }) => {
508
+ const sub = folder.addFolder('sub')
509
+ assert.lengthOf(project.definitions.folders, 2, 'has 2 definitions')
510
+ sub.remove()
511
+ assert.lengthOf(project.definitions.folders, 1, 'has 1 definition')
512
+ })
513
+ })
514
+
515
+ test.group('Models > ProjectFolder > getParent()', (group) => {
516
+ let project: HttpProject
517
+ group.each.setup(() => {
518
+ project = new HttpProject()
519
+ })
520
+
521
+ test('returns the project object', ({ assert }) => {
522
+ const folder = project.addFolder('test')
523
+ const result = folder.getParent()
524
+ assert.isTrue(result === project)
525
+ })
526
+
527
+ test('returns the folder object', ({ assert }) => {
528
+ const parent = project.addFolder('test')
529
+ const folder = parent.addFolder('test 2')
530
+ const result = folder.getParent()
531
+ assert.isTrue(result === parent)
532
+ })
533
+ })
534
+
535
+ test.group('Models > ProjectFolder > getProject()', (group) => {
536
+ let project: HttpProject
537
+ group.each.setup(() => {
538
+ project = new HttpProject()
539
+ })
540
+
541
+ test('returns the project when added to the project', ({ assert }) => {
542
+ const folder = project.addFolder('test')
543
+ const result = folder.getProject()
544
+ assert.isTrue(result === project)
545
+ })
546
+
547
+ test('returns the project when added to a folder', ({ assert }) => {
548
+ const parent = project.addFolder('test')
549
+ const folder = parent.addFolder('test 2')
550
+ const result = folder.getProject()
551
+ assert.isTrue(result === project)
552
+ })
553
+ })
554
+
555
+ test.group('Models > ProjectFolder > clone()', (group) => {
556
+ let project: HttpProject
557
+ let folder: ProjectFolder
558
+
559
+ group.each.setup(() => {
560
+ project = new HttpProject()
561
+ folder = project.addFolder('test')
562
+ })
563
+
564
+ test('updates the key by default', ({ assert }) => {
565
+ const { key: oldKey } = folder
566
+ const copy = folder.clone()
567
+ assert.typeOf(copy.key, 'string', 'has the key')
568
+ assert.notEqual(copy.key, oldKey, 'has a new key')
569
+ })
570
+
571
+ test('adds the copy to the project definitions (project root)', ({ assert }) => {
572
+ const copy = folder.clone()
573
+ assert.lengthOf(project.definitions.folders, 2, 'has 2 definitions')
574
+ assert.isTrue(
575
+ project.definitions.folders.some((i) => i.key === copy.key),
576
+ 'has the folder definition'
577
+ )
578
+ })
579
+
580
+ test('adds the copy to the project definitions (folder root)', ({ assert }) => {
581
+ const sub = folder.addFolder('sub')
582
+ const copy = sub.clone()
583
+ assert.lengthOf(project.definitions.folders, 3, 'has 3 definitions')
584
+ assert.isTrue(
585
+ project.definitions.folders.some((i) => i.key === copy.key),
586
+ 'has the folder definition'
587
+ )
588
+ })
589
+
590
+ test('adds the copy to the project items (project root)', ({ assert }) => {
591
+ const copy = folder.clone()
592
+ assert.lengthOf(project.items, 2, 'has 2 items')
593
+ assert.isTrue(
594
+ project.items.some((i) => i.key === copy.key),
595
+ 'has the folder item'
596
+ )
597
+ })
598
+
599
+ test('adds the copy to the sub-folder items', ({ assert }) => {
600
+ const sub = folder.addFolder('sub')
601
+ const copy = sub.clone()
602
+ assert.lengthOf(project.items, 1, 'project has 1 item')
603
+ assert.lengthOf(folder.items, 2, 'parent has 2 items')
604
+ assert.isTrue(
605
+ folder.items.some((i) => i.key === copy.key),
606
+ 'the folder is added to the parent'
607
+ )
608
+ })
609
+
610
+ test('copies requests with the folder by default', ({ assert }) => {
611
+ const r = folder.addRequest('https://copy.com')
612
+ const copy = folder.clone()
613
+
614
+ assert.lengthOf(copy.items, 1, 'the copy has one request')
615
+ assert.typeOf(copy.items[0].key, 'string', 'the request has the key')
616
+ assert.notEqual(copy.items[0].key, r.key, 'the copied request has a different key')
617
+ })
618
+
619
+ test('adds the copied folder and request to the project definitions', ({ assert }) => {
620
+ folder.addRequest('https://copy.com')
621
+ folder.clone()
622
+
623
+ assert.lengthOf(project.definitions.requests, 2, 'the project has 2 request definitions')
624
+ assert.lengthOf(project.definitions.folders, 2, 'the project has 2 folder definitions')
625
+ // Corrected from project.definitions.requests
626
+
627
+ const [f1, f2] = project.definitions.folders
628
+ const [r1, r2] = project.definitions.requests
629
+
630
+ assert.notEqual(f1.key, f2.key, 'folder keys are different')
631
+ assert.notEqual(r1.key, r2.key, 'request keys are different')
632
+ })
633
+
634
+ test('quietly ignores missing requests', ({ assert }) => {
635
+ const r = folder.addRequest('https://copy.com')
636
+ const i = project.definitions.requests.findIndex((item) => item.key === r.key)
637
+ project.definitions.requests.splice(i, 1)
638
+ folder.clone()
639
+ assert.lengthOf(project.definitions.folders, 2, 'the project has 2 definitions')
640
+ const [f1, f2] = project.definitions.folders
641
+ assert.notEqual(f1.key, f2.key, 'folder keys are different')
642
+ })
643
+
644
+ test('copies sub-folders with the folder by default', ({ assert }) => {
645
+ const sub = folder.addFolder('sub')
646
+ const copy = folder.clone()
647
+
648
+ assert.lengthOf(copy.items, 1, 'the copy has one item') // Corrected from 'one request'
649
+ assert.typeOf(copy.items[0].key, 'string', 'the folder has the key')
650
+ assert.notEqual(copy.items[0].key, sub.key, 'the copied folder has a different key')
651
+ })
652
+
653
+ test('adds a sub-folder of the copied folder to the project definitions', ({ assert }) => {
654
+ folder.addFolder('sub orig')
655
+ folder.clone()
656
+
657
+ assert.lengthOf(project.definitions.folders, 4, 'the project has 4 folder definitions')
658
+
659
+ // It's better to find them by known properties if order is not guaranteed
660
+ const originalMainFolder = project.definitions.folders.find((f) => f.info.name === 'test' && f.key === folder.key)
661
+ const originalSubFolder = project.definitions.folders.find((f) => f.info.name === 'sub orig')
662
+ const clonedMainFolder = project.definitions.folders.find((f) => f.info.name === 'test' && f.key !== folder.key)
663
+ const clonedSubFolder = project.definitions.folders.find(
664
+ (f) => f.info.name === 'sub orig' && f.key !== originalSubFolder!.key
665
+ )
666
+
667
+ assert.ok(originalMainFolder, 'Original main folder found')
668
+ assert.ok(originalSubFolder, 'Original sub folder found')
669
+ assert.ok(clonedMainFolder, 'Cloned main folder found')
670
+ assert.ok(clonedSubFolder, 'Cloned sub folder found')
671
+
672
+ assert.notEqual(originalMainFolder!.key, clonedMainFolder!.key, 'folder keys are different')
673
+ assert.equal(originalMainFolder!.info.name, clonedMainFolder!.info.name, 'folder 1 names match')
674
+ // Corrected from 'request keys'
675
+ assert.notEqual(originalSubFolder!.key, clonedSubFolder!.key, 'sub-folder keys are different')
676
+ assert.equal(originalSubFolder!.info.name, clonedSubFolder!.info.name, 'folder 2 names match')
677
+ })
678
+
679
+ test('quietly ignores missing folders', ({ assert }) => {
680
+ const sub = folder.addFolder('sub')
681
+ const i = project.definitions.folders.findIndex((item) => item.key === sub.key)
682
+ project.definitions.folders.splice(i, 1)
683
+ folder.clone()
684
+ assert.lengthOf(project.definitions.folders, 2, 'the project has 2 definitions')
685
+ const [f1, f2] = project.definitions.folders
686
+ assert.notEqual(f1.key, f2.key, 'folder keys are different')
687
+ })
688
+
689
+ test('copies a folder with a sub-folder with requests', ({ assert }) => {
690
+ const sub = folder.addFolder('sub')
691
+ const origRequest = sub.addRequest('http://api.com')
692
+
693
+ const result = folder.clone()
694
+
695
+ const projectFolders = project.listFolders() // This lists all folders in the project
696
+ // After clone, project should have original 'test' folder and its clone.
697
+ // 'sub' is inside 'test', and its clone is inside the clone of 'test'.
698
+ // So, project.listFolders() without arguments should list 'test' and its clone.
699
+ assert.lengthOf(
700
+ projectFolders.filter((pf) => pf.getParent() === project),
701
+ 2,
702
+ 'the project has 2 top-level folders'
703
+ )
704
+
705
+ const originalTestFolder = projectFolders.find((pf) => pf.key === folder.key)
706
+ const clonedTestFolder = projectFolders.find((pf) => pf.key === result.key)
707
+
708
+ assert.deepEqual(originalTestFolder, folder, 'folder #1 is set')
709
+ assert.deepEqual(clonedTestFolder, result, 'folder #2 is set')
710
+
711
+ const originalSubFolder = originalTestFolder!.listFolders()[0]
712
+ assert.lengthOf(originalSubFolder.listRequests(), 1, 'original sub-folder has a single request')
713
+ assert.deepEqual(originalSubFolder.listRequests()[0], origRequest, 'original sub-folder has the original request')
714
+
715
+ const topRequests = result.listRequests()
716
+ assert.lengthOf(topRequests, 0, 'root copy folder has no requests')
717
+
718
+ const foldersInCloned = result.listFolders()
719
+ assert.lengthOf(foldersInCloned, 1, 'root copy folder has a folder')
720
+
721
+ const [subCopy] = foldersInCloned
722
+ const subRequests = subCopy.listRequests()
723
+ assert.lengthOf(subRequests, 1, 'sub folder has a request')
724
+ })
725
+
726
+ test('copies a folder to a specific folder inside the same project', ({ assert }) => {
727
+ const sub = folder.addFolder('sub1')
728
+ sub.addRequest('http://api.com')
729
+ const targetFolder = project.addFolder('sub2') // This is a top-level folder
730
+ const clonedFolderInTarget = folder.clone({ targetFolder: targetFolder.key })
731
+
732
+ const subFoldersInTarget = targetFolder.listFolders()
733
+ assert.lengthOf(subFoldersInTarget, 1, 'has the copied folder')
734
+ const [copyTopLevelFolder] = subFoldersInTarget
735
+ assert.equal(copyTopLevelFolder.key, clonedFolderInTarget.key)
736
+ assert.equal(copyTopLevelFolder.info.name, folder.info.name)
737
+
738
+ const [subLevelCopy] = copyTopLevelFolder.listFolders()
739
+ assert.ok(subLevelCopy, 'has the copied sub-folder')
740
+ assert.equal(subLevelCopy.info.name, sub.info.name)
741
+
742
+ const subRequests = subLevelCopy.listRequests()
743
+ assert.lengthOf(subRequests, 1, 'has the copied request')
744
+ })
745
+
746
+ test('copies a folder to another project to the root level', ({ assert }) => {
747
+ const sub = folder.addFolder('sub')
748
+ const origRequest = sub.addRequest('http://api.com')
749
+
750
+ const origSnapshot = project.toJSON()
751
+
752
+ const targetProject = new HttpProject()
753
+ const clonedInTargetProject = folder.clone({ targetProject })
754
+
755
+ assert.deepEqual(project.toJSON(), origSnapshot, 'the original project is not changed')
756
+
757
+ const copiedTopFolder = targetProject.findFolder(folder.info.name!)!
758
+ assert.ok(copiedTopFolder, 'target project has the top-level folder')
759
+ assert.equal(copiedTopFolder.key, clonedInTargetProject.key)
760
+ assert.notEqual(copiedTopFolder.key, folder.key, 'target folder has a new key')
761
+
762
+ const subFolderInTarget = copiedTopFolder.listFolders()[0]
763
+ assert.ok(subFolderInTarget, 'target project has the sub-folder')
764
+ assert.notEqual(subFolderInTarget.key, sub.key, 'the sub-folder has a new key')
765
+
766
+ const copiedRequest = subFolderInTarget.listRequests()[0]
767
+ assert.ok(copiedRequest, 'target project has the request')
768
+ assert.notEqual(copiedRequest.key, origRequest.key, 'the request has a new key')
769
+ })
770
+
771
+ test('copies a folder to another project under a folder', ({ assert }) => {
772
+ const sub = folder.addFolder('sub')
773
+ sub.addRequest('http://api.com')
774
+
775
+ const origSnapshot = project.toJSON()
776
+
777
+ const targetProject = new HttpProject()
778
+ const targetFolderInTargetProject = targetProject.addFolder('parent')
779
+ folder.clone({ targetProject, targetFolder: targetFolderInTargetProject.key })
780
+
781
+ assert.deepEqual(project.toJSON(), origSnapshot, 'the original project is not changed')
782
+
783
+ // the target project has 'parent' folder, then 'test' (cloned) inside 'parent', then 'sub' (cloned) inside 'test'.
784
+ // So 3 folder definitions. And 1 request definition.
785
+ assert.lengthOf(targetProject.definitions.folders, 3, 'has the copied folder definitions')
786
+ assert.lengthOf(targetProject.definitions.requests, 1, 'has the copied requests definitions')
787
+
788
+ const rootFoldersInTarget = targetFolderInTargetProject.listFolders()
789
+ assert.lengthOf(rootFoldersInTarget, 1, 'the target folder has a root folder from the originating project')
790
+
791
+ const [rootFolderCopy] = rootFoldersInTarget
792
+ const subFoldersInCopy = rootFolderCopy.listFolders()
793
+ assert.lengthOf(subFoldersInCopy, 1, 'the copied folder has a sub-folder')
794
+
795
+ const [subFolderCopy] = subFoldersInCopy
796
+
797
+ const requestsInSubCopy = subFolderCopy.listRequests()
798
+ assert.lengthOf(requestsInSubCopy, 1, 'the sub-folder has a request')
799
+ })
800
+
801
+ test('throws when unable to find a parent in the same project', ({ assert }) => {
802
+ const sub = folder.addFolder('sub')
803
+ sub.addRequest('http://api.com')
804
+ assert.throws(() => {
805
+ folder.clone({ targetFolder: 'test-non-existent' })
806
+ })
807
+ })
808
+
809
+ test('throws when unable to find a parent in the foreign project', ({ assert }) => {
810
+ const sub = folder.addFolder('sub')
811
+ sub.addRequest('http://api.com')
812
+
813
+ const targetProject = new HttpProject()
814
+ assert.throws(() => {
815
+ folder.clone({ targetProject, targetFolder: 'test-non-existent' })
816
+ })
817
+ })
818
+ })
819
+
820
+ test.group('Models > ProjectFolder > addEnvironment()', (group) => {
821
+ let project: HttpProject
822
+ let f1: ProjectFolder
823
+ group.each.setup(() => {
824
+ project = HttpProject.fromName('test')
825
+ f1 = project.addFolder('f1')
826
+ })
827
+
828
+ test('adds environment by name', ({ assert }) => {
829
+ const created = f1.addEnvironment('test')
830
+ assert.lengthOf(f1.items, 1, 'has an item')
831
+ assert.equal(f1.items[0].key, created.key, 'has the item key')
832
+ assert.equal(f1.items[0].kind, EnvironmentKind, 'has the item kind')
833
+ })
834
+
835
+ test('adds environment from an instance', ({ assert }) => {
836
+ const created = Environment.fromName('test')
837
+ f1.addEnvironment(created)
838
+ assert.lengthOf(f1.items, 1, 'has an item')
839
+ assert.equal(f1.items[0].key, created.key, 'has the item key')
840
+ })
841
+
842
+ test('adds environment from a schema', ({ assert }) => {
843
+ const created = Environment.fromName('test')
844
+ f1.addEnvironment(created.toJSON())
845
+ assert.lengthOf(f1.items, 1, 'has an item')
846
+ assert.equal(f1.items[0].key, created.key, 'has the item key')
847
+ })
848
+ })
849
+
850
+ test.group('Models > ProjectFolder > getEnvironments()', () => {
851
+ test('returns project class initialization environments', ({ assert }) => {
852
+ const project = new HttpProject(undefined, [Environment.fromName('test').toJSON()])
853
+ const f1 = project.addFolder('f1') // Corrected: addFolder needs project instance
854
+ f1.addEnvironment(Environment.fromName('other'))
855
+ const envs = f1.getEnvironments()
856
+ assert.typeOf(envs, 'array')
857
+ assert.lengthOf(envs, 1)
858
+ assert.equal(envs[0].info.name, 'test')
859
+ })
860
+
861
+ test('returns environments when no initialization environments', ({ assert }) => {
862
+ const project = new HttpProject()
863
+ const f1 = project.addFolder('f1')
864
+ const e1 = f1.addEnvironment(Environment.fromName('other'))
865
+ project.addEnvironment('e2') // This is a root environment, getEnvironments on folder should not see it.
866
+
867
+ const result = f1.getEnvironments()
868
+ assert.deepEqual(result, [e1])
869
+ })
870
+ })
871
+
872
+ test.group('Models > ProjectFolder > listEnvironments()', (group) => {
873
+ let project: HttpProject
874
+ let f1: ProjectFolder
875
+ let e2: Environment
876
+ group.each.setup(() => {
877
+ project = new HttpProject()
878
+ project.addEnvironment('e1') // Root environment
879
+ f1 = project.addFolder('f1')
880
+ e2 = f1.addEnvironment('e2') // Environment in folder f1
881
+ })
882
+
883
+ test('returns environments defined in the folder', ({ assert }) => {
884
+ // This method is on HttpProject, not ProjectFolder.
885
+ // It lists environments associated with a specific parent (folder key or project).
886
+ const result = project.listEnvironments({ parent: f1.key })
887
+ assert.deepEqual(result, [e2])
888
+ })
889
+
890
+ test('ignores sub-folders', ({ assert }) => {
891
+ const f2 = f1.addFolder('f2')
892
+ f2.addEnvironment('e3')
893
+ const result = project.listEnvironments({ parent: f1.key })
894
+ assert.deepEqual(result, [e2]) // Should only list e2, as e3 is in f2, not directly in f1.
895
+ })
896
+ })
897
+
898
+ test.group('Models > ProjectFolder > removeEnvironment()', (group) => {
899
+ let project: HttpProject
900
+ let f1: ProjectFolder
901
+ let e2: Environment
902
+ group.each.setup(() => {
903
+ project = new HttpProject()
904
+ project.addEnvironment('e1')
905
+ f1 = project.addFolder('f1')
906
+ e2 = f1.addEnvironment('e2')
907
+ })
908
+
909
+ test('removes the environment from folder items', ({ assert }) => {
910
+ f1.removeEnvironment(e2.key)
911
+ assert.deepEqual(f1.items, [])
912
+ })
913
+
914
+ test('does nothing when the environment is not in the folder', ({ assert }) => {
915
+ const f2 = f1.addFolder('f2') // e2 is in f1, f2 is a child of f1
916
+ const e3 = f2.addEnvironment('e3') // e3 is in f2
917
+ const result = f1.removeEnvironment(e3.key) // Trying to remove e3 from f1
918
+ assert.isUndefined(result)
919
+ assert.lengthOf(f1.items, 2) // f1 should still have e2 and f2
920
+ })
921
+
922
+ test('returns the removed environment', ({ assert }) => {
923
+ const result = f1.removeEnvironment(e2.key)
924
+ assert.deepEqual(result, e2)
925
+ })
926
+ })