codecharta-visualization 1.87.1 → 1.88.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 (67) hide show
  1. package/app/app.module.ts +18 -8
  2. package/app/codeCharta/codeCharta.component.ts +2 -0
  3. package/app/codeCharta/codeCharta.model.ts +2 -0
  4. package/app/codeCharta/codeCharta.service.spec.ts +41 -50
  5. package/app/codeCharta/codeCharta.service.ts +33 -32
  6. package/app/codeCharta/e2e/url.e2e.ts +1 -1
  7. package/app/codeCharta/state/store/appStatus/appStatus.reducer.ts +3 -1
  8. package/app/codeCharta/state/store/appStatus/appStatus.selector.ts +3 -0
  9. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.actions.ts +23 -0
  10. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.reducer.ts +15 -0
  11. package/app/codeCharta/state/store/appStatus/rightClickedNodeData/rightClickedNodeData.selector.ts +4 -0
  12. package/app/codeCharta/state/store/state.actions.ts +3 -1
  13. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +6 -8
  14. package/app/codeCharta/ui/customConfigs/customConfigs.component.html +9 -9
  15. package/app/codeCharta/ui/dialog/dialog.addCustomConfigSettings.component.html +2 -2
  16. package/app/codeCharta/ui/dialog/dialog.changelog.component.scss +15 -0
  17. package/app/codeCharta/ui/dialog/dialog.changelog.component.spec.ts +15 -15
  18. package/app/codeCharta/ui/dialog/dialog.changelog.component.ts +2 -1
  19. package/app/codeCharta/ui/dialog/dialog.service.spec.ts +68 -0
  20. package/app/codeCharta/ui/dialog/dialog.service.ts +38 -17
  21. package/app/codeCharta/ui/edgeChooser/edgeChooser.e2e.ts +3 -2
  22. package/app/codeCharta/ui/fileChooser/fileChooser.e2e.ts +5 -6
  23. package/app/codeCharta/ui/filePanel/filePanel.component.html +24 -106
  24. package/app/codeCharta/ui/filePanel/filePanel.component.scss +12 -57
  25. package/app/codeCharta/ui/filePanel/filePanel.component.spec.ts +40 -72
  26. package/app/codeCharta/ui/filePanel/filePanel.component.ts +29 -81
  27. package/app/codeCharta/ui/filePanel/filePanel.module.ts +13 -1
  28. package/app/codeCharta/ui/filePanel/filePanel.po.ts +6 -24
  29. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.html +23 -0
  30. package/app/codeCharta/ui/filePanel/filePanelDeltaSelector/filePanelDeltaSelector.component.ts +18 -0
  31. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.html +18 -0
  32. package/app/codeCharta/ui/filePanel/filePanelFileSelector/filePanelFileSelector.component.ts +16 -0
  33. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.html +18 -0
  34. package/app/codeCharta/ui/filePanel/filePanelStateButtons/filePanelStateButtons.component.ts +11 -0
  35. package/app/codeCharta/ui/mapTreeView/mapTreeView.level.e2e.ts +7 -5
  36. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.html +1 -1
  37. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.spec.ts +6 -16
  38. package/app/codeCharta/ui/mapTreeView/mapTreeViewLevel/mapTreeViewLevel.component.ts +15 -11
  39. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.html +22 -0
  40. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.scss +31 -0
  41. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.spec.ts +35 -0
  42. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/markFolderRow.component.ts +30 -0
  43. package/app/codeCharta/ui/nodeContextMenu/{markFolderColorPicker/markFolderColorPicker.module.ts → markFolderRow/markFolderRow.module.ts} +4 -5
  44. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.spec.ts +17 -0
  45. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/markFolderItems.selector.ts +29 -0
  46. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.spec.ts +15 -0
  47. package/app/codeCharta/ui/nodeContextMenu/markFolderRow/selectors/rightClickedNode.selector.ts +9 -0
  48. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +2 -15
  49. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +0 -15
  50. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +10 -119
  51. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +40 -134
  52. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +2 -2
  53. package/app/codeCharta/ui/ribbonBar/ribbonBar.component.html +1 -1
  54. package/app/codeCharta/ui/toolBar/toolBar.component.html +1 -1
  55. package/app/codeCharta/ui/toolBar/toolBar.component.scss +1 -1
  56. package/app/codeCharta/ui/ui.ts +2 -2
  57. package/app/codeCharta/util/customConfigHelper.spec.ts +155 -60
  58. package/app/codeCharta/util/customConfigHelper.ts +33 -3
  59. package/app/codeCharta/util/dataMocks.ts +4 -2
  60. package/app/codeCharta/util/fileValidator.spec.ts +69 -182
  61. package/app/codeCharta/util/fileValidator.ts +61 -37
  62. package/dist/webpack/bundle.js +852 -485
  63. package/dist/webpack/bundle.js.map +1 -1
  64. package/package.json +1 -1
  65. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +0 -9
  66. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.scss +0 -13
  67. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +0 -10
@@ -7,8 +7,7 @@ import {
7
7
  } from "./dataMocks"
8
8
  import { CodeMapNode, NameDataPair, NodeType } from "../codeCharta.model"
9
9
  import packageJson from "../../../package.json"
10
- import { CCValidationResult, ERROR_MESSAGES, validate } from "./fileValidator"
11
- import assert from "assert"
10
+ import { checkErrors, checkWarnings, ERROR_MESSAGES } from "./fileValidator"
12
11
  import { fileWithFixedFolders, fileWithFixedOverlappingSubFolders } from "../resources/fixed-folders/fixed-folders-example"
13
12
  import { APIVersions, ExportCCFile } from "../codeCharta.api.model"
14
13
  import { clone } from "./clone"
@@ -25,14 +24,9 @@ describe("FileValidator", () => {
25
24
  })
26
25
 
27
26
  it("should throw on null", () => {
28
- const expectedError: CCValidationResult = {
29
- error: [ERROR_MESSAGES.fileIsInvalid],
30
- warning: []
31
- }
27
+ const expectedErrors = [ERROR_MESSAGES.fileIsInvalid]
32
28
 
33
- assert.throws(() => {
34
- validate(null)
35
- }, expectedError)
29
+ expect(checkErrors(null)).toEqual(expectedErrors)
36
30
  })
37
31
 
38
32
  it("should throw when higher Major API", () => {
@@ -41,15 +35,9 @@ describe("FileValidator", () => {
41
35
  fileSize: 30,
42
36
  content: TEST_FILE_CONTENT_INVALID_MAJOR_API
43
37
  }
38
+ const expectedErrors = [ERROR_MESSAGES.majorApiVersionIsOutdated]
44
39
 
45
- const expectedError: CCValidationResult = {
46
- error: [ERROR_MESSAGES.majorApiVersionIsOutdated],
47
- warning: []
48
- }
49
-
50
- assert.throws(() => {
51
- validate(nameDataPair)
52
- }, expectedError)
40
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
53
41
  })
54
42
 
55
43
  it("should throw on warning with higher minor API version", () => {
@@ -58,15 +46,9 @@ describe("FileValidator", () => {
58
46
  fileSize: 30,
59
47
  content: TEST_FILE_CONTENT_INVALID_MINOR_API
60
48
  }
49
+ const expectedWarnings = [`${ERROR_MESSAGES.minorApiVersionOutdated} Found: ${nameDataPair.content.apiVersion}`]
61
50
 
62
- const expectedError: CCValidationResult = {
63
- error: [],
64
- warning: [`${ERROR_MESSAGES.minorApiVersionOutdated} Found: ${nameDataPair.content.apiVersion}`]
65
- }
66
-
67
- assert.throws(() => {
68
- validate(nameDataPair)
69
- }, expectedError)
51
+ expect(checkWarnings(nameDataPair.content)).toEqual(expectedWarnings)
70
52
  })
71
53
 
72
54
  it("should throw on file missing API version", () => {
@@ -75,15 +57,9 @@ describe("FileValidator", () => {
75
57
  fileSize: 30,
76
58
  content: TEST_FILE_CONTENT_NO_API
77
59
  }
60
+ const expectedErrors = [ERROR_MESSAGES.apiVersionIsInvalid]
78
61
 
79
- const expectedError: CCValidationResult = {
80
- error: [ERROR_MESSAGES.apiVersionIsInvalid],
81
- warning: []
82
- }
83
-
84
- assert.throws(() => {
85
- validate(nameDataPair)
86
- }, expectedError)
62
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
87
63
  })
88
64
 
89
65
  it("should throw on file with wrong API version", () => {
@@ -92,15 +68,9 @@ describe("FileValidator", () => {
92
68
  fileSize: 30,
93
69
  content: TEST_FILE_CONTENT_INVALID_API
94
70
  }
71
+ const expectedErrors = [ERROR_MESSAGES.apiVersionIsInvalid]
95
72
 
96
- const expectedError: CCValidationResult = {
97
- error: [ERROR_MESSAGES.apiVersionIsInvalid],
98
- warning: []
99
- }
100
-
101
- assert.throws(() => {
102
- validate(nameDataPair)
103
- }, expectedError)
73
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
104
74
  })
105
75
 
106
76
  it("should not throw on a file with edges", () => {
@@ -117,7 +87,8 @@ describe("FileValidator", () => {
117
87
 
118
88
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
119
89
 
120
- validate(nameDataPair)
90
+ expect(checkErrors(nameDataPair.content)).toEqual([])
91
+ expect(checkWarnings(nameDataPair.content)).toEqual([])
121
92
  })
122
93
 
123
94
  it("should not throw on a file without edges", () => {
@@ -125,7 +96,8 @@ describe("FileValidator", () => {
125
96
 
126
97
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
127
98
 
128
- validate(nameDataPair)
99
+ expect(checkErrors(nameDataPair.content)).toEqual([])
100
+ expect(checkWarnings(nameDataPair.content)).toEqual([])
129
101
  })
130
102
 
131
103
  it("should not throw on a file when numbers are floating point values", () => {
@@ -133,7 +105,8 @@ describe("FileValidator", () => {
133
105
 
134
106
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
135
107
 
136
- validate(nameDataPair)
108
+ expect(checkErrors(nameDataPair.content)).toEqual([])
109
+ expect(checkWarnings(nameDataPair.content)).toEqual([])
137
110
  })
138
111
 
139
112
  it("should throw when children are not unique in name+type", () => {
@@ -142,30 +115,17 @@ describe("FileValidator", () => {
142
115
  file.nodes[0].children[1].name = "same"
143
116
  file.nodes[0].children[1].type = NodeType.FILE
144
117
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
118
+ const expectedErrors = [`${ERROR_MESSAGES.nodesNotUnique} Found duplicate of File with path: /root/same`]
145
119
 
146
- const expectedError: CCValidationResult = {
147
- error: [`${ERROR_MESSAGES.nodesNotUnique} Found duplicate of File with path: /root/same`],
148
- warning: []
149
- }
150
-
151
- assert.throws(() => {
152
- validate(nameDataPair)
153
- }, expectedError)
120
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
154
121
  })
155
122
 
156
123
  it("should throw when nodes are empty", () => {
157
124
  file.nodes = []
158
-
159
125
  const nameDataPair: NameDataPair = { fileName: "", fileSize: 30, content: file }
126
+ const expectedErrors = [ERROR_MESSAGES.nodesEmpty]
160
127
 
161
- const expectedError: CCValidationResult = {
162
- error: [ERROR_MESSAGES.nodesEmpty],
163
- warning: []
164
- }
165
-
166
- assert.throws(() => {
167
- validate(nameDataPair)
168
- }, expectedError)
128
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
169
129
  })
170
130
 
171
131
  it("should throw if nodes is not a node and therefore has no name or id", () => {
@@ -173,20 +133,13 @@ describe("FileValidator", () => {
173
133
  // @ts-expect-error
174
134
  something: "something"
175
135
  }
176
-
177
136
  const nameDataPair: NameDataPair = { fileName: "", fileSize: 30, content: file }
137
+ const expectedErrors = [
138
+ "Required error: nodes[0] should have required property 'name'",
139
+ "Required error: nodes[0] should have required property 'type'"
140
+ ]
178
141
 
179
- const expectedError: CCValidationResult = {
180
- error: [
181
- "Required error: nodes[0] should have required property 'name'",
182
- "Required error: nodes[0] should have required property 'type'"
183
- ],
184
- warning: []
185
- }
186
-
187
- assert.throws(() => {
188
- validate(nameDataPair)
189
- }, expectedError)
142
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
190
143
  })
191
144
 
192
145
  describe("fixed sub folders validation", () => {
@@ -195,19 +148,13 @@ describe("FileValidator", () => {
195
148
  const folder1: CodeMapNode = file.nodes[0].children[0].children[0]
196
149
  const folder2: CodeMapNode = file.nodes[0].children[0].children[1]
197
150
  const nameDataPair: NameDataPair = { fileName: "", fileSize: 30, content: file }
151
+ const expectedErrors = [
152
+ `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1_1 ${JSON.stringify(
153
+ folder1.fixedPosition
154
+ )} and folder_1_2 ${JSON.stringify(folder2.fixedPosition)}`
155
+ ]
198
156
 
199
- const expectedError: CCValidationResult = {
200
- error: [
201
- `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1_1 ${JSON.stringify(
202
- folder1.fixedPosition
203
- )} and folder_1_2 ${JSON.stringify(folder2.fixedPosition)}`
204
- ],
205
- warning: []
206
- }
207
-
208
- assert.throws(() => {
209
- validate(nameDataPair)
210
- }, expectedError)
157
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
211
158
  })
212
159
  })
213
160
 
@@ -223,59 +170,36 @@ describe("FileValidator", () => {
223
170
  it("should throw an error, if there are fixed folders, but not every folder on root is fixed", () => {
224
171
  folder1.fixedPosition = undefined
225
172
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
226
- const expectedError: CCValidationResult = {
227
- error: [`${ERROR_MESSAGES.notAllFoldersAreFixed} Found: folder_1`],
228
- warning: []
229
- }
173
+ const expectedErrors = [`${ERROR_MESSAGES.notAllFoldersAreFixed} Found: folder_1`]
230
174
 
231
- assert.throws(() => {
232
- validate(nameDataPair)
233
- }, expectedError)
175
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
234
176
  })
235
177
 
236
178
  it("should throw an error, if at least one fixed folder has a padding that is out of bounds", () => {
237
179
  folder1.fixedPosition.left = -5
238
180
  folder1.fixedPosition.width = 7
239
- const nameDataPair: NameDataPair = { fileName: "", fileSize: 30, content: file }
240
-
241
- const expectedError: CCValidationResult = {
242
- error: [`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: folder_1 ${JSON.stringify(folder1.fixedPosition)}`],
243
- warning: []
244
- }
181
+ const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
182
+ const expectedErrors = [`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: folder_1 ${JSON.stringify(folder1.fixedPosition)}`]
245
183
 
246
- assert.throws(() => {
247
- validate(nameDataPair)
248
- }, expectedError)
184
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
249
185
  })
250
186
 
251
187
  it("should throw an error, if at least one fixed folder has a width or height that is out of bounds", () => {
252
188
  folder1.fixedPosition.left = 10
253
189
  folder1.fixedPosition.width = -50
254
190
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
191
+ const expectedErrors = [`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: folder_1 ${JSON.stringify(folder1.fixedPosition)}`]
255
192
 
256
- const expectedError: CCValidationResult = {
257
- error: [`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: folder_1 ${JSON.stringify(folder1.fixedPosition)}`],
258
- warning: []
259
- }
260
-
261
- assert.throws(() => {
262
- validate(nameDataPair)
263
- }, expectedError)
193
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
264
194
  })
265
195
 
266
196
  it("should throw an error, if at least one fixed folder exceeds the maximum coordinate of 100", () => {
267
197
  folder1.fixedPosition.left = 99
268
198
  folder1.fixedPosition.width = 2
269
199
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
200
+ const expectedErrors = [`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: folder_1 ${JSON.stringify(folder1.fixedPosition)}`]
270
201
 
271
- const expectedError: CCValidationResult = {
272
- error: [`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: folder_1 ${JSON.stringify(folder1.fixedPosition)}`],
273
- warning: []
274
- }
275
-
276
- assert.throws(() => {
277
- validate(nameDataPair)
278
- }, expectedError)
202
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
279
203
  })
280
204
 
281
205
  it("should throw an error, if two folders horizontally overlap", () => {
@@ -292,19 +216,13 @@ describe("FileValidator", () => {
292
216
  height: 10
293
217
  }
294
218
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
219
+ const expectedErrors = [
220
+ `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1 ${JSON.stringify(
221
+ folder1.fixedPosition
222
+ )} and folder_2 ${JSON.stringify(folder2.fixedPosition)}`
223
+ ]
295
224
 
296
- const expectedError: CCValidationResult = {
297
- error: [
298
- `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1 ${JSON.stringify(
299
- folder1.fixedPosition
300
- )} and folder_2 ${JSON.stringify(folder2.fixedPosition)}`
301
- ],
302
- warning: []
303
- }
304
-
305
- assert.throws(() => {
306
- validate(nameDataPair)
307
- }, expectedError)
225
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
308
226
  })
309
227
 
310
228
  it("should throw an error, if two folders vertically overlap", () => {
@@ -321,19 +239,12 @@ describe("FileValidator", () => {
321
239
  height: 10
322
240
  }
323
241
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
324
-
325
- const expectedError: CCValidationResult = {
326
- error: [
327
- `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1 ${JSON.stringify(
328
- folder1.fixedPosition
329
- )} and folder_2 ${JSON.stringify(folder2.fixedPosition)}`
330
- ],
331
- warning: []
332
- }
333
-
334
- assert.throws(() => {
335
- validate(nameDataPair)
336
- }, expectedError)
242
+ const expectedErrors = [
243
+ `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1 ${JSON.stringify(
244
+ folder1.fixedPosition
245
+ )} and folder_2 ${JSON.stringify(folder2.fixedPosition)}`
246
+ ]
247
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
337
248
  })
338
249
 
339
250
  it("should throw an error, if a folder is placed inside another", () => {
@@ -350,19 +261,13 @@ describe("FileValidator", () => {
350
261
  height: 1
351
262
  }
352
263
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
264
+ const expectedErrors = [
265
+ `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_2 ${JSON.stringify(
266
+ folder2.fixedPosition
267
+ )} and folder_1 ${JSON.stringify(folder1.fixedPosition)}`
268
+ ]
353
269
 
354
- const expectedError: CCValidationResult = {
355
- error: [
356
- `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_2 ${JSON.stringify(
357
- folder2.fixedPosition
358
- )} and folder_1 ${JSON.stringify(folder1.fixedPosition)}`
359
- ],
360
- warning: []
361
- }
362
-
363
- assert.throws(() => {
364
- validate(nameDataPair)
365
- }, expectedError)
270
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
366
271
  })
367
272
 
368
273
  it("should throw an error, if a folder has the same boundaries as another", () => {
@@ -374,47 +279,29 @@ describe("FileValidator", () => {
374
279
  }
375
280
  folder2.fixedPosition = folder1.fixedPosition
376
281
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
282
+ const expectedErrors = [
283
+ `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1 ${JSON.stringify(
284
+ folder1.fixedPosition
285
+ )} and folder_2 ${JSON.stringify(folder2.fixedPosition)}`
286
+ ]
377
287
 
378
- const expectedError: CCValidationResult = {
379
- error: [
380
- `${ERROR_MESSAGES.fixedFoldersOverlapped} Found: folder_1 ${JSON.stringify(
381
- folder1.fixedPosition
382
- )} and folder_2 ${JSON.stringify(folder2.fixedPosition)}`
383
- ],
384
- warning: []
385
- }
386
-
387
- assert.throws(() => {
388
- validate(nameDataPair)
389
- }, expectedError)
288
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
390
289
  })
391
290
 
392
291
  it("should throw an error, if the major api version is smaller and fixed folders were defined", () => {
393
292
  file.apiVersion = APIVersions.ZERO_POINT_ONE
394
293
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
294
+ const expectedErrors = [`${ERROR_MESSAGES.fixedFoldersNotAllowed} Found: 0.1`]
395
295
 
396
- const expectedError: CCValidationResult = {
397
- error: [`${ERROR_MESSAGES.fixedFoldersNotAllowed} Found: 0.1`],
398
- warning: []
399
- }
400
-
401
- assert.throws(() => {
402
- validate(nameDataPair)
403
- }, expectedError)
296
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
404
297
  })
405
298
 
406
299
  it("should throw an error, if the minor api version is smaller and fixed folders were defined", () => {
407
300
  file.apiVersion = APIVersions.ONE_POINT_ONE
408
301
  const nameDataPair: NameDataPair = { fileName: "fileName", fileSize: 30, content: file }
302
+ const expectedErrors = [`${ERROR_MESSAGES.fixedFoldersNotAllowed} Found: 1.1`]
409
303
 
410
- const expectedError: CCValidationResult = {
411
- error: [`${ERROR_MESSAGES.fixedFoldersNotAllowed} Found: 1.1`],
412
- warning: []
413
- }
414
-
415
- assert.throws(() => {
416
- validate(nameDataPair)
417
- }, expectedError)
304
+ expect(checkErrors(nameDataPair.content)).toEqual(expectedErrors)
418
305
  })
419
306
  })
420
307
  })
@@ -1,4 +1,4 @@
1
- import { CodeMapNode, FixedPosition, NameDataPair } from "../codeCharta.model"
1
+ import { CodeMapNode, FixedPosition } from "../codeCharta.model"
2
2
  import Ajv from "ajv"
3
3
  import packageJson from "../../../package.json"
4
4
  import { ExportCCFile } from "../codeCharta.api.model"
@@ -12,9 +12,10 @@ interface ApiVersion {
12
12
  minor: number
13
13
  }
14
14
 
15
- export interface CCValidationResult {
16
- error: string[]
17
- warning: string[]
15
+ export interface CCFileValidationResult {
16
+ fileName: string
17
+ errors: string[]
18
+ warnings: string[]
18
19
  }
19
20
 
20
21
  export const ERROR_MESSAGES = {
@@ -32,42 +33,50 @@ export const ERROR_MESSAGES = {
32
33
  blacklistError: "Excluding all buildings is not possible."
33
34
  }
34
35
 
35
- export function validate(nameDataPair: NameDataPair) {
36
- const file = nameDataPair?.content
37
- const result: CCValidationResult = { error: [], warning: [] }
36
+ export function checkWarnings(file: ExportCCFile) {
37
+ const warnings: string[] = []
38
+ if (!file) {
39
+ return warnings
40
+ }
41
+ if (fileHasHigherMinorVersion(file)) {
42
+ warnings.push(`${ERROR_MESSAGES.minorApiVersionOutdated} Found: ${file.apiVersion}`)
43
+ }
44
+ return warnings
45
+ }
46
+
47
+ export function checkErrors(file: ExportCCFile) {
48
+ const errors: string[] = []
38
49
  switch (true) {
39
50
  case !file:
40
- result.error.push(ERROR_MESSAGES.fileIsInvalid)
51
+ errors.push(ERROR_MESSAGES.fileIsInvalid)
41
52
  break
42
53
  case !isValidApiVersion(file):
43
- result.error.push(ERROR_MESSAGES.apiVersionIsInvalid)
54
+ errors.push(ERROR_MESSAGES.apiVersionIsInvalid)
44
55
  break
45
56
  case fileHasHigherMajorVersion(file):
46
- result.error.push(ERROR_MESSAGES.majorApiVersionIsOutdated)
47
- break
48
- case fileHasHigherMinorVersion(file):
49
- result.warning.push(`${ERROR_MESSAGES.minorApiVersionOutdated} Found: ${file.apiVersion}`)
57
+ errors.push(ERROR_MESSAGES.majorApiVersionIsOutdated)
50
58
  break
51
59
  }
60
+ if (errors.length === 0) errors.push(...checkJsonSchema(file))
61
+ return errors
62
+ }
52
63
 
53
- if (result.error.length === 0) {
64
+ function checkJsonSchema(file: ExportCCFile) {
65
+ const errors: string[] = []
66
+ if (errors.length === 0) {
54
67
  const ajv = new Ajv({ allErrors: true })
55
68
  const validate = ajv.compile(jsonSchema)
56
69
  const valid = validate(file)
57
70
 
58
71
  if (!valid) {
59
- result.error = validate.errors.map((error: Ajv.ErrorObject) => getValidationMessage(error))
72
+ errors.push(...validate.errors.map((error: Ajv.ErrorObject) => getValidationMessage(error)))
60
73
  } else if (file.nodes.length === 0) {
61
- result.error.push(ERROR_MESSAGES.nodesEmpty)
74
+ errors.push(ERROR_MESSAGES.nodesEmpty)
62
75
  } else {
63
- validateAllNodesAreUnique(file.nodes[0], result)
64
- validateFixedFolders(file, result)
76
+ errors.push(...validateAllNodesAreUnique(file.nodes[0]), ...validateFixedFolders(file))
65
77
  }
66
78
  }
67
-
68
- if (result.error.length > 0 || result.warning.length > 0) {
69
- throw result
70
- }
79
+ return errors
71
80
  }
72
81
 
73
82
  function isValidApiVersion(file: ExportCCFile) {
@@ -101,13 +110,15 @@ function getValidationMessage(error: Ajv.ErrorObject) {
101
110
  return `${errorType} error: ${errorParameter} ${error.message}`
102
111
  }
103
112
 
104
- function validateAllNodesAreUnique(node: CodeMapNode, result: CCValidationResult) {
113
+ function validateAllNodesAreUnique(node: CodeMapNode) {
114
+ const errors: string[] = []
105
115
  const names = new Set<string>()
106
116
  names.add(`${node.name}|${node.type}`)
107
- validateChildrenAreUniqueRecursive(node, result, names, `/${node.name}`)
117
+ validateChildrenAreUniqueRecursive(node, errors, names, `/${node.name}`)
118
+ return errors
108
119
  }
109
120
 
110
- function validateChildrenAreUniqueRecursive(node: CodeMapNode, result: CCValidationResult, names: Set<string>, subPath: string) {
121
+ function validateChildrenAreUniqueRecursive(node: CodeMapNode, errors: string[], names: Set<string>, subPath: string) {
111
122
  if (isLeaf(node)) {
112
123
  return
113
124
  }
@@ -115,26 +126,29 @@ function validateChildrenAreUniqueRecursive(node: CodeMapNode, result: CCValidat
115
126
  for (const child of node.children) {
116
127
  const path = `${subPath}/${child.name}`
117
128
  if (names.has(`${path}|${child.type}`)) {
118
- result.error.push(`${ERROR_MESSAGES.nodesNotUnique} Found duplicate of ${child.type} with path: ${path}`)
129
+ errors.push(`${ERROR_MESSAGES.nodesNotUnique} Found duplicate of ${child.type} with path: ${path}`)
119
130
  } else {
120
131
  names.add(`${path}|${child.type}`)
121
- validateChildrenAreUniqueRecursive(child, result, names, path)
132
+ validateChildrenAreUniqueRecursive(child, errors, names, path)
122
133
  }
123
134
  }
124
135
  }
125
136
 
126
- function validateFixedFolders(file: ExportCCFile, result: CCValidationResult, childNodes: CodeMapNode[] = file.nodes[0].children) {
127
- const notFixed: string[] = []
128
- const outOfBounds: string[] = []
129
- const intersections: Set<string> = new Set()
130
-
137
+ function checkChildNodes(
138
+ childNodes: CodeMapNode[],
139
+ notFixed: string[],
140
+ file: ExportCCFile,
141
+ errors: string[],
142
+ outOfBounds: string[],
143
+ intersections: Set<string>
144
+ ) {
131
145
  for (const node of childNodes) {
132
146
  if (node.fixedPosition === undefined) {
133
147
  notFixed.push(`${node.name}`)
134
148
  } else {
135
149
  const apiVersion = getAsApiVersion(file.apiVersion)
136
150
  if (apiVersion.major < 1 || (apiVersion.major === 1 && apiVersion.minor < 2)) {
137
- result.error.push(`${ERROR_MESSAGES.fixedFoldersNotAllowed} Found: ${file.apiVersion}`)
151
+ errors.push(`${ERROR_MESSAGES.fixedFoldersNotAllowed} Found: ${file.apiVersion}`)
138
152
  return
139
153
  }
140
154
 
@@ -154,24 +168,34 @@ function validateFixedFolders(file: ExportCCFile, result: CCValidationResult, ch
154
168
  }
155
169
  }
156
170
  }
171
+ }
172
+
173
+ function validateFixedFolders(file: ExportCCFile, childNodes: CodeMapNode[] = file.nodes[0].children) {
174
+ const errors: string[] = []
175
+ const notFixed: string[] = []
176
+ const outOfBounds: string[] = []
177
+ const intersections: Set<string> = new Set()
178
+
179
+ checkChildNodes(childNodes, notFixed, file, errors, outOfBounds, intersections)
157
180
 
158
181
  if (notFixed.length > 0 && notFixed.length !== childNodes.length) {
159
- result.error.push(`${ERROR_MESSAGES.notAllFoldersAreFixed} Found: ${notFixed.join(", ")}`)
182
+ errors.push(`${ERROR_MESSAGES.notAllFoldersAreFixed} Found: ${notFixed.join(", ")}`)
160
183
  }
161
184
 
162
185
  if (outOfBounds.length > 0) {
163
- result.error.push(`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: ${outOfBounds.join(", ")}`)
186
+ errors.push(`${ERROR_MESSAGES.fixedFoldersOutOfBounds} Found: ${outOfBounds.join(", ")}`)
164
187
  }
165
188
 
166
189
  if (intersections.size > 0) {
167
- result.error.push(`${ERROR_MESSAGES.fixedFoldersOverlapped} Found: ${[...intersections].join(", ")}`)
190
+ errors.push(`${ERROR_MESSAGES.fixedFoldersOverlapped} Found: ${[...intersections].join(", ")}`)
168
191
  }
169
192
 
170
193
  for (const node of childNodes) {
171
194
  if (node.children) {
172
- validateFixedFolders(file, result, node.children)
195
+ errors.push(...validateFixedFolders(file, node.children))
173
196
  }
174
197
  }
198
+ return errors
175
199
  }
176
200
 
177
201
  function getFoundFolderMessage(node: CodeMapNode) {