xdbc 1.0.211 → 1.0.212

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/.gitattributes +8 -0
  2. package/.github/workflows/ci.yml +51 -0
  3. package/.vscode/tasks.json +23 -23
  4. package/CODE_OF_CONDUCT.md +1 -1
  5. package/README.md +1 -0
  6. package/__tests__/DBC/AE.test.ts +1 -1
  7. package/__tests__/DBC/DEFINED.test.ts +49 -49
  8. package/__tests__/DBC/Decorators.test.ts +334 -332
  9. package/__tests__/DBC/HasAttribute.test.ts +56 -52
  10. package/__tests__/DBC/IF.test.ts +57 -57
  11. package/__tests__/DBC/OR.test.ts +1 -1
  12. package/__tests__/DBC/UNDEFINED.test.ts +41 -41
  13. package/__tests__/DBC/ZOD.test.ts +50 -50
  14. package/biome.json +40 -33
  15. package/dist/bundle.js +2297 -0
  16. package/docs/assets/highlight.css +22 -22
  17. package/docs/assets/icons.js +17 -17
  18. package/docs/assets/main.js +60 -60
  19. package/docs/assets/style.css +1640 -1640
  20. package/docs/classes/DBC.DBC.html +98 -98
  21. package/docs/classes/DBC_AE.AE.html +160 -160
  22. package/docs/classes/DBC_EQ.EQ.html +131 -131
  23. package/docs/classes/DBC_GREATER.GREATER.html +139 -139
  24. package/docs/classes/DBC_INSTANCE.INSTANCE.html +130 -130
  25. package/docs/classes/DBC_JSON.OP.JSON_OP.html +138 -138
  26. package/docs/classes/DBC_JSON.Parse.JSON_Parse.html +129 -129
  27. package/docs/classes/DBC_OR.OR.html +137 -137
  28. package/docs/classes/DBC_REGEX.REGEX.html +136 -136
  29. package/docs/classes/DBC_TYPE.TYPE.html +130 -130
  30. package/docs/classes/Demo.Demo.html +14 -14
  31. package/docs/hierarchy.html +1 -1
  32. package/docs/index.html +1 -1
  33. package/docs/modules/DBC.html +1 -1
  34. package/docs/modules/DBC_AE.html +1 -1
  35. package/docs/modules/DBC_EQ.html +1 -1
  36. package/docs/modules/DBC_GREATER.html +1 -1
  37. package/docs/modules/DBC_INSTANCE.html +1 -1
  38. package/docs/modules/DBC_JSON.OP.html +1 -1
  39. package/docs/modules/DBC_JSON.Parse.html +1 -1
  40. package/docs/modules/DBC_OR.html +1 -1
  41. package/docs/modules/DBC_REGEX.html +1 -1
  42. package/docs/modules/DBC_TYPE.html +1 -1
  43. package/docs/modules/Demo.html +1 -1
  44. package/jest.config.js +29 -18
  45. package/package.json +12 -1
  46. package/src/DBC/AE.ts +14 -9
  47. package/src/DBC/COMPARISON/GREATER.ts +2 -2
  48. package/src/DBC/COMPARISON.ts +159 -136
  49. package/src/DBC/DEFINED.ts +10 -10
  50. package/src/DBC/EQ/DIFFERENT.ts +3 -3
  51. package/src/DBC/EQ.ts +25 -9
  52. package/src/DBC/HasAttribute.ts +17 -3
  53. package/src/DBC/IF.ts +63 -19
  54. package/src/DBC/INSTANCE.ts +29 -14
  55. package/src/DBC/JSON.OP.ts +18 -3
  56. package/src/DBC/JSON.Parse.ts +21 -4
  57. package/src/DBC/OR.ts +12 -7
  58. package/src/DBC/REGEX.ts +30 -21
  59. package/src/DBC/TYPE.ts +15 -11
  60. package/src/DBC/UNDEFINED.ts +7 -10
  61. package/src/DBC/ZOD.ts +14 -9
  62. package/src/DBC.ts +165 -69
  63. package/src/Demo.ts +21 -18
  64. package/test.drawio +0 -0
  65. package/tsconfig.json +2 -5
  66. package/tsconfig.test.json +6 -11
  67. package/webpack.config.js +1 -1
@@ -1,365 +1,367 @@
1
1
  import "reflect-metadata";
2
2
  import { DBC } from "../../src/DBC";
3
- import { REGEX } from "../../src/DBC/REGEX";
4
- import { TYPE } from "../../src/DBC/TYPE";
5
- import { EQ } from "../../src/DBC/EQ";
3
+ import { AE } from "../../src/DBC/AE";
6
4
  import { GREATER } from "../../src/DBC/COMPARISON/GREATER";
7
5
  import { GREATER_OR_EQUAL } from "../../src/DBC/COMPARISON/GREATER_OR_EQUAL";
8
6
  import { LESS } from "../../src/DBC/COMPARISON/LESS";
9
7
  import { LESS_OR_EQUAL } from "../../src/DBC/COMPARISON/LESS_OR_EQUAL";
8
+ import { EQ } from "../../src/DBC/EQ";
10
9
  import { DIFFERENT } from "../../src/DBC/EQ/DIFFERENT";
11
10
  import { INSTANCE } from "../../src/DBC/INSTANCE";
12
- import { AE } from "../../src/DBC/AE";
13
11
  import { OR } from "../../src/DBC/OR";
12
+ import { REGEX } from "../../src/DBC/REGEX";
13
+ import { TYPE } from "../../src/DBC/TYPE";
14
14
 
15
15
  // Ensure a DBC instance is registered (DBC.ts module-level code does this via DBC.register)
16
16
  const dbc: DBC = (window as any).WaXCode?.DBC;
17
17
 
18
18
  describe("Decorator: @PRE (Preconditions)", () => {
19
- class PreTestSubject {
20
- @DBC.ParamvalueProvider
21
- public regexPre(@REGEX.PRE(/^[A-Z]+$/) input: string): string {
22
- return input;
23
- }
24
-
25
- @DBC.ParamvalueProvider
26
- public typePre(@TYPE.PRE("string") input: unknown): unknown {
27
- return input;
28
- }
29
-
30
- @DBC.ParamvalueProvider
31
- public eqPre(@EQ.PRE("hello") input: string): string {
32
- return input;
33
- }
34
-
35
- @DBC.ParamvalueProvider
36
- public greaterPre(@GREATER.PRE(5) input: number): number {
37
- return input;
38
- }
39
-
40
- @DBC.ParamvalueProvider
41
- public greaterOrEqualPre(@GREATER_OR_EQUAL.PRE(5) input: number): number {
42
- return input;
43
- }
44
-
45
- @DBC.ParamvalueProvider
46
- public lessPre(@LESS.PRE(10) input: number): number {
47
- return input;
48
- }
49
-
50
- @DBC.ParamvalueProvider
51
- public lessOrEqualPre(@LESS_OR_EQUAL.PRE(10) input: number): number {
52
- return input;
53
- }
54
-
55
- @DBC.ParamvalueProvider
56
- public differentPre(@DIFFERENT.PRE("forbidden", undefined) input: string): string {
57
- return input;
58
- }
59
-
60
- @DBC.ParamvalueProvider
61
- public instancePre(@INSTANCE.PRE(Date) input: unknown): unknown {
62
- return input;
63
- }
64
-
65
- @DBC.ParamvalueProvider
66
- public aePre(@AE.PRE([new TYPE("string")]) input: unknown[]): unknown[] {
67
- return input;
68
- }
69
-
70
- @DBC.ParamvalueProvider
71
- public orPre(@OR.PRE([new EQ("a"), new EQ("b")]) input: string): string {
72
- return input;
73
- }
74
- }
75
-
76
- const subject = new PreTestSubject();
77
-
78
- // REGEX.PRE
79
- test("REGEX.PRE passes with matching value", () => {
80
- expect(() => subject.regexPre("ABC")).not.toThrow();
81
- });
82
- test("REGEX.PRE throws on non-matching value", () => {
83
- expect(() => subject.regexPre("abc123")).toThrow();
84
- });
85
-
86
- // TYPE.PRE
87
- test("TYPE.PRE passes with correct type", () => {
88
- expect(() => subject.typePre("hello")).not.toThrow();
89
- });
90
- test("TYPE.PRE throws with wrong type", () => {
91
- expect(() => subject.typePre(42)).toThrow();
92
- });
93
-
94
- // EQ.PRE
95
- test("EQ.PRE passes with equal value", () => {
96
- expect(() => subject.eqPre("hello")).not.toThrow();
97
- });
98
- test("EQ.PRE throws with non-equal value", () => {
99
- expect(() => subject.eqPre("world")).toThrow();
100
- });
101
-
102
- // GREATER.PRE
103
- test("GREATER.PRE passes with value > reference", () => {
104
- expect(() => subject.greaterPre(10)).not.toThrow();
105
- });
106
- test("GREATER.PRE throws with value <= reference", () => {
107
- expect(() => subject.greaterPre(5)).toThrow();
108
- });
109
- test("GREATER.PRE throws with value < reference", () => {
110
- expect(() => subject.greaterPre(3)).toThrow();
111
- });
112
-
113
- // GREATER_OR_EQUAL.PRE
114
- test("GREATER_OR_EQUAL.PRE passes with value >= reference", () => {
115
- expect(() => subject.greaterOrEqualPre(5)).not.toThrow();
116
- });
117
- test("GREATER_OR_EQUAL.PRE passes with value > reference", () => {
118
- expect(() => subject.greaterOrEqualPre(10)).not.toThrow();
119
- });
120
- test("GREATER_OR_EQUAL.PRE throws with value < reference", () => {
121
- expect(() => subject.greaterOrEqualPre(3)).toThrow();
122
- });
123
-
124
- // LESS.PRE
125
- test("LESS.PRE passes with value < reference", () => {
126
- expect(() => subject.lessPre(5)).not.toThrow();
127
- });
128
- test("LESS.PRE throws with value >= reference", () => {
129
- expect(() => subject.lessPre(10)).toThrow();
130
- });
131
-
132
- // LESS_OR_EQUAL.PRE
133
- test("LESS_OR_EQUAL.PRE passes with value <= reference", () => {
134
- expect(() => subject.lessOrEqualPre(10)).not.toThrow();
135
- });
136
- test("LESS_OR_EQUAL.PRE throws with value > reference", () => {
137
- expect(() => subject.lessOrEqualPre(15)).toThrow();
138
- });
139
-
140
- // DIFFERENT.PRE
141
- test("DIFFERENT.PRE passes with different value", () => {
142
- expect(() => subject.differentPre("allowed")).not.toThrow();
143
- });
144
- test("DIFFERENT.PRE throws with equal value", () => {
145
- expect(() => subject.differentPre("forbidden")).toThrow();
146
- });
147
-
148
- // INSTANCE.PRE
149
- test("INSTANCE.PRE passes with correct instance", () => {
150
- expect(() => subject.instancePre(new Date())).not.toThrow();
151
- });
152
- test("INSTANCE.PRE throws with wrong instance", () => {
153
- expect(() => subject.instancePre("not a date")).toThrow();
154
- });
155
-
156
- // AE.PRE
157
- test("AE.PRE passes with all elements matching", () => {
158
- expect(() => subject.aePre(["a", "b", "c"])).not.toThrow();
159
- });
160
- test("AE.PRE throws when an element does not match", () => {
161
- expect(() => subject.aePre(["a", 42, "c"])).toThrow();
162
- });
163
-
164
- // OR.PRE
165
- test("OR.PRE passes when one contract is satisfied", () => {
166
- expect(() => subject.orPre("a")).not.toThrow();
167
- });
168
- test("OR.PRE throws when no contract is satisfied", () => {
169
- expect(() => subject.orPre("c")).toThrow();
170
- });
19
+ class PreTestSubject {
20
+ @DBC.ParamvalueProvider
21
+ public regexPre(@REGEX.PRE(/^[A-Z]+$/) input: string): string {
22
+ return input;
23
+ }
24
+
25
+ @DBC.ParamvalueProvider
26
+ public typePre(@TYPE.PRE("string") input: unknown): unknown {
27
+ return input;
28
+ }
29
+
30
+ @DBC.ParamvalueProvider
31
+ public eqPre(@EQ.PRE("hello") input: string): string {
32
+ return input;
33
+ }
34
+
35
+ @DBC.ParamvalueProvider
36
+ public greaterPre(@GREATER.PRE(5) input: number): number {
37
+ return input;
38
+ }
39
+
40
+ @DBC.ParamvalueProvider
41
+ public greaterOrEqualPre(@GREATER_OR_EQUAL.PRE(5) input: number): number {
42
+ return input;
43
+ }
44
+
45
+ @DBC.ParamvalueProvider
46
+ public lessPre(@LESS.PRE(10) input: number): number {
47
+ return input;
48
+ }
49
+
50
+ @DBC.ParamvalueProvider
51
+ public lessOrEqualPre(@LESS_OR_EQUAL.PRE(10) input: number): number {
52
+ return input;
53
+ }
54
+
55
+ @DBC.ParamvalueProvider
56
+ public differentPre(
57
+ @DIFFERENT.PRE("forbidden", undefined) input: string,
58
+ ): string {
59
+ return input;
60
+ }
61
+
62
+ @DBC.ParamvalueProvider
63
+ public instancePre(@INSTANCE.PRE(Date) input: unknown): unknown {
64
+ return input;
65
+ }
66
+
67
+ @DBC.ParamvalueProvider
68
+ public aePre(@AE.PRE([new TYPE("string")]) input: unknown[]): unknown[] {
69
+ return input;
70
+ }
71
+
72
+ @DBC.ParamvalueProvider
73
+ public orPre(@OR.PRE([new EQ("a"), new EQ("b")]) input: string): string {
74
+ return input;
75
+ }
76
+ }
77
+
78
+ const subject = new PreTestSubject();
79
+
80
+ // REGEX.PRE
81
+ test("REGEX.PRE passes with matching value", () => {
82
+ expect(() => subject.regexPre("ABC")).not.toThrow();
83
+ });
84
+ test("REGEX.PRE throws on non-matching value", () => {
85
+ expect(() => subject.regexPre("abc123")).toThrow();
86
+ });
87
+
88
+ // TYPE.PRE
89
+ test("TYPE.PRE passes with correct type", () => {
90
+ expect(() => subject.typePre("hello")).not.toThrow();
91
+ });
92
+ test("TYPE.PRE throws with wrong type", () => {
93
+ expect(() => subject.typePre(42)).toThrow();
94
+ });
95
+
96
+ // EQ.PRE
97
+ test("EQ.PRE passes with equal value", () => {
98
+ expect(() => subject.eqPre("hello")).not.toThrow();
99
+ });
100
+ test("EQ.PRE throws with non-equal value", () => {
101
+ expect(() => subject.eqPre("world")).toThrow();
102
+ });
103
+
104
+ // GREATER.PRE
105
+ test("GREATER.PRE passes with value > reference", () => {
106
+ expect(() => subject.greaterPre(10)).not.toThrow();
107
+ });
108
+ test("GREATER.PRE throws with value <= reference", () => {
109
+ expect(() => subject.greaterPre(5)).toThrow();
110
+ });
111
+ test("GREATER.PRE throws with value < reference", () => {
112
+ expect(() => subject.greaterPre(3)).toThrow();
113
+ });
114
+
115
+ // GREATER_OR_EQUAL.PRE
116
+ test("GREATER_OR_EQUAL.PRE passes with value >= reference", () => {
117
+ expect(() => subject.greaterOrEqualPre(5)).not.toThrow();
118
+ });
119
+ test("GREATER_OR_EQUAL.PRE passes with value > reference", () => {
120
+ expect(() => subject.greaterOrEqualPre(10)).not.toThrow();
121
+ });
122
+ test("GREATER_OR_EQUAL.PRE throws with value < reference", () => {
123
+ expect(() => subject.greaterOrEqualPre(3)).toThrow();
124
+ });
125
+
126
+ // LESS.PRE
127
+ test("LESS.PRE passes with value < reference", () => {
128
+ expect(() => subject.lessPre(5)).not.toThrow();
129
+ });
130
+ test("LESS.PRE throws with value >= reference", () => {
131
+ expect(() => subject.lessPre(10)).toThrow();
132
+ });
133
+
134
+ // LESS_OR_EQUAL.PRE
135
+ test("LESS_OR_EQUAL.PRE passes with value <= reference", () => {
136
+ expect(() => subject.lessOrEqualPre(10)).not.toThrow();
137
+ });
138
+ test("LESS_OR_EQUAL.PRE throws with value > reference", () => {
139
+ expect(() => subject.lessOrEqualPre(15)).toThrow();
140
+ });
141
+
142
+ // DIFFERENT.PRE
143
+ test("DIFFERENT.PRE passes with different value", () => {
144
+ expect(() => subject.differentPre("allowed")).not.toThrow();
145
+ });
146
+ test("DIFFERENT.PRE throws with equal value", () => {
147
+ expect(() => subject.differentPre("forbidden")).toThrow();
148
+ });
149
+
150
+ // INSTANCE.PRE
151
+ test("INSTANCE.PRE passes with correct instance", () => {
152
+ expect(() => subject.instancePre(new Date())).not.toThrow();
153
+ });
154
+ test("INSTANCE.PRE throws with wrong instance", () => {
155
+ expect(() => subject.instancePre("not a date")).toThrow();
156
+ });
157
+
158
+ // AE.PRE
159
+ test("AE.PRE passes with all elements matching", () => {
160
+ expect(() => subject.aePre(["a", "b", "c"])).not.toThrow();
161
+ });
162
+ test("AE.PRE throws when an element does not match", () => {
163
+ expect(() => subject.aePre(["a", 42, "c"])).toThrow();
164
+ });
165
+
166
+ // OR.PRE
167
+ test("OR.PRE passes when one contract is satisfied", () => {
168
+ expect(() => subject.orPre("a")).not.toThrow();
169
+ });
170
+ test("OR.PRE throws when no contract is satisfied", () => {
171
+ expect(() => subject.orPre("c")).toThrow();
172
+ });
171
173
  });
172
174
 
173
175
  describe("Decorator: @POST (Postconditions)", () => {
174
- class PostTestSubject {
175
- @REGEX.POST(/^OK:.*$/)
176
- @DBC.ParamvalueProvider
177
- public formatResponse(@TYPE.PRE("string") input: string): string {
178
- return `OK:${input}`;
179
- }
180
-
181
- @REGEX.POST(/^OK:.*$/)
182
- public failingPost(): string {
183
- return "FAIL";
184
- }
185
-
186
- @EQ.POST("hello")
187
- public eqPost(returnThis: string): string {
188
- return returnThis;
189
- }
190
- }
191
-
192
- const subject = new PostTestSubject();
193
-
194
- test("POST passes when return value matches", () => {
195
- expect(() => subject.formatResponse("test")).not.toThrow();
196
- });
197
-
198
- test("POST throws when return value does not match", () => {
199
- expect(() => subject.failingPost()).toThrow();
200
- });
201
-
202
- test("EQ.POST passes with matching return value", () => {
203
- expect(() => subject.eqPost("hello")).not.toThrow();
204
- });
205
-
206
- test("EQ.POST throws with non-matching return value", () => {
207
- expect(() => subject.eqPost("world")).toThrow();
208
- });
176
+ class PostTestSubject {
177
+ @REGEX.POST(/^OK:.*$/)
178
+ @DBC.ParamvalueProvider
179
+ public formatResponse(@TYPE.PRE("string") input: string): string {
180
+ return `OK:${input}`;
181
+ }
182
+
183
+ @REGEX.POST(/^OK:.*$/)
184
+ public failingPost(): string {
185
+ return "FAIL";
186
+ }
187
+
188
+ @EQ.POST("hello")
189
+ public eqPost(returnThis: string): string {
190
+ return returnThis;
191
+ }
192
+ }
193
+
194
+ const subject = new PostTestSubject();
195
+
196
+ test("POST passes when return value matches", () => {
197
+ expect(() => subject.formatResponse("test")).not.toThrow();
198
+ });
199
+
200
+ test("POST throws when return value does not match", () => {
201
+ expect(() => subject.failingPost()).toThrow();
202
+ });
203
+
204
+ test("EQ.POST passes with matching return value", () => {
205
+ expect(() => subject.eqPost("hello")).not.toThrow();
206
+ });
207
+
208
+ test("EQ.POST throws with non-matching return value", () => {
209
+ expect(() => subject.eqPost("world")).toThrow();
210
+ });
209
211
  });
210
212
 
211
213
  describe("Decorator: @INVARIANT (Field contracts)", () => {
212
- test("INVARIANT allows valid initial value", () => {
213
- expect(() => {
214
- class InvariantSubject {
215
- @REGEX.INVARIANT(/^[A-Z]+$/)
216
- public code = "ABC";
217
- }
218
- new InvariantSubject();
219
- }).not.toThrow();
220
- });
221
-
222
- test("INVARIANT throws on invalid initial value", () => {
223
- expect(() => {
224
- class InvariantSubject {
225
- @REGEX.INVARIANT(/^[A-Z]+$/)
226
- public code = "abc123";
227
- }
228
- new InvariantSubject();
229
- }).toThrow();
230
- });
231
-
232
- test("INVARIANT throws on invalid reassignment", () => {
233
- class InvariantSubject {
234
- @REGEX.INVARIANT(/^[A-Z]+$/)
235
- public code = "ABC";
236
- }
237
- const obj = new InvariantSubject();
238
- expect(() => {
239
- obj.code = "invalid!";
240
- }).toThrow();
241
- });
242
-
243
- test("INVARIANT allows valid reassignment", () => {
244
- class InvariantSubject {
245
- @REGEX.INVARIANT(/^[A-Z]+$/)
246
- public code = "ABC";
247
- }
248
- const obj = new InvariantSubject();
249
- expect(() => {
250
- obj.code = "XYZ";
251
- }).not.toThrow();
252
- });
214
+ test("INVARIANT allows valid initial value", () => {
215
+ expect(() => {
216
+ class InvariantSubject {
217
+ @REGEX.INVARIANT(/^[A-Z]+$/)
218
+ public code = "ABC";
219
+ }
220
+ new InvariantSubject();
221
+ }).not.toThrow();
222
+ });
223
+
224
+ test("INVARIANT throws on invalid initial value", () => {
225
+ expect(() => {
226
+ class InvariantSubject {
227
+ @REGEX.INVARIANT(/^[A-Z]+$/)
228
+ public code = "abc123";
229
+ }
230
+ new InvariantSubject();
231
+ }).toThrow();
232
+ });
233
+
234
+ test("INVARIANT throws on invalid reassignment", () => {
235
+ class InvariantSubject {
236
+ @REGEX.INVARIANT(/^[A-Z]+$/)
237
+ public code = "ABC";
238
+ }
239
+ const obj = new InvariantSubject();
240
+ expect(() => {
241
+ obj.code = "invalid!";
242
+ }).toThrow();
243
+ });
244
+
245
+ test("INVARIANT allows valid reassignment", () => {
246
+ class InvariantSubject {
247
+ @REGEX.INVARIANT(/^[A-Z]+$/)
248
+ public code = "ABC";
249
+ }
250
+ const obj = new InvariantSubject();
251
+ expect(() => {
252
+ obj.code = "XYZ";
253
+ }).not.toThrow();
254
+ });
253
255
  });
254
256
 
255
257
  describe("Decorator: @ParamvalueProvider", () => {
256
- test("ParamvalueProvider passes multiple parameter contracts", () => {
257
- class MultiParam {
258
- @DBC.ParamvalueProvider
259
- public method(
260
- @TYPE.PRE("string") a: string,
261
- @TYPE.PRE("number") b: number,
262
- ): string {
263
- return `${a}:${b}`;
264
- }
265
- }
266
- const obj = new MultiParam();
267
- expect(() => obj.method("hello", 42)).not.toThrow();
268
- });
269
-
270
- test("ParamvalueProvider catches second parameter violation", () => {
271
- class MultiParam {
272
- @DBC.ParamvalueProvider
273
- public method(
274
- @TYPE.PRE("string") a: string,
275
- @TYPE.PRE("number") b: number,
276
- ): string {
277
- return `${a}:${b}`;
278
- }
279
- }
280
- const obj = new MultiParam();
281
- expect(() => obj.method("hello", "not a number" as any)).toThrow();
282
- });
258
+ test("ParamvalueProvider passes multiple parameter contracts", () => {
259
+ class MultiParam {
260
+ @DBC.ParamvalueProvider
261
+ public method(
262
+ @TYPE.PRE("string") a: string,
263
+ @TYPE.PRE("number") b: number,
264
+ ): string {
265
+ return `${a}:${b}`;
266
+ }
267
+ }
268
+ const obj = new MultiParam();
269
+ expect(() => obj.method("hello", 42)).not.toThrow();
270
+ });
271
+
272
+ test("ParamvalueProvider catches second parameter violation", () => {
273
+ class MultiParam {
274
+ @DBC.ParamvalueProvider
275
+ public method(
276
+ @TYPE.PRE("string") a: string,
277
+ @TYPE.PRE("number") b: number,
278
+ ): string {
279
+ return `${a}:${b}`;
280
+ }
281
+ }
282
+ const obj = new MultiParam();
283
+ expect(() => obj.method("hello", "not a number" as any)).toThrow();
284
+ });
283
285
  });
284
286
 
285
287
  describe("DBC infringement settings", () => {
286
- class InfringementTest {
287
- @DBC.ParamvalueProvider
288
- public method(@TYPE.PRE("string") input: unknown): unknown {
289
- return input;
290
- }
291
- }
292
-
293
- test("Violations throw DBC.Infringement by default", () => {
294
- const obj = new InfringementTest();
295
- expect(() => obj.method(42)).toThrow(/XDBC Infringement/);
296
- });
297
-
298
- test("Error message includes class name, method name, and parameter info", () => {
299
- const obj = new InfringementTest();
300
- try {
301
- obj.method(42);
302
- fail("Should have thrown");
303
- } catch (e: any) {
304
- expect(e.message).toContain("InfringementTest");
305
- expect(e.message).toContain("method");
306
- expect(e.message).toContain("1st parameter");
307
- }
308
- });
288
+ class InfringementTest {
289
+ @DBC.ParamvalueProvider
290
+ public method(@TYPE.PRE("string") input: unknown): unknown {
291
+ return input;
292
+ }
293
+ }
294
+
295
+ test("Violations throw DBC.Infringement by default", () => {
296
+ const obj = new InfringementTest();
297
+ expect(() => obj.method(42)).toThrow(/XDBC Infringement/);
298
+ });
299
+
300
+ test("Error message includes class name, method name, and parameter info", () => {
301
+ const obj = new InfringementTest();
302
+ try {
303
+ obj.method(42);
304
+ fail("Should have thrown");
305
+ } catch (e: any) {
306
+ expect(e.message).toContain("InfringementTest");
307
+ expect(e.message).toContain("method");
308
+ expect(e.message).toContain("1st parameter");
309
+ }
310
+ });
309
311
  });
310
312
 
311
313
  describe("DBC.register()", () => {
312
- test("registers an instance at the default path", () => {
313
- const custom = new DBC();
314
- DBC.register(custom);
315
- expect((window as any).WaXCode.DBC).toBe(custom);
316
- // Restore original
317
- DBC.register(dbc);
318
- });
319
-
320
- test("registers an instance at a custom path", () => {
321
- const custom = new DBC();
322
- DBC.register(custom, "TestVendor.DBC");
323
- expect((window as any).TestVendor.DBC).toBe(custom);
324
- });
325
-
326
- test("constructor does not auto-mount to globalThis", () => {
327
- const original = (window as any).WaXCode.DBC;
328
- const orphan = new DBC();
329
- // Constructor should NOT have replaced the registered instance
330
- expect((window as any).WaXCode.DBC).toBe(original);
331
- expect(orphan).not.toBe(original);
332
- });
314
+ test("registers an instance at the default path", () => {
315
+ const custom = new DBC();
316
+ DBC.register(custom);
317
+ expect((window as any).WaXCode.DBC).toBe(custom);
318
+ // Restore original
319
+ DBC.register(dbc);
320
+ });
321
+
322
+ test("registers an instance at a custom path", () => {
323
+ const custom = new DBC();
324
+ DBC.register(custom, "TestVendor.DBC");
325
+ expect((window as any).TestVendor.DBC).toBe(custom);
326
+ });
327
+
328
+ test("constructor does not auto-mount to globalThis", () => {
329
+ const original = (window as any).WaXCode.DBC;
330
+ const orphan = new DBC();
331
+ // Constructor should NOT have replaced the registered instance
332
+ expect((window as any).WaXCode.DBC).toBe(original);
333
+ expect(orphan).not.toBe(original);
334
+ });
333
335
  });
334
336
 
335
337
  describe("DBC.isolated()", () => {
336
- test("provides a temporary DBC instance and restores the original", () => {
337
- const original = (window as any).WaXCode.DBC;
338
- let isolatedInstance: DBC | undefined;
339
- DBC.isolated((tempDbc) => {
340
- isolatedInstance = tempDbc;
341
- expect(tempDbc).not.toBe(original);
342
- expect((window as any).WaXCode.DBC).toBe(tempDbc);
343
- });
344
- // After isolated() returns, the original is restored
345
- expect((window as any).WaXCode.DBC).toBe(original);
346
- expect(isolatedInstance).toBeDefined();
347
- });
348
-
349
- test("restores original even if callback throws", () => {
350
- const original = (window as any).WaXCode.DBC;
351
- expect(() => {
352
- DBC.isolated(() => {
353
- throw new Error("test error");
354
- });
355
- }).toThrow("test error");
356
- expect((window as any).WaXCode.DBC).toBe(original);
357
- });
358
-
359
- test("isolated instance has independent settings", () => {
360
- DBC.isolated((tempDbc) => {
361
- tempDbc.executionSettings.checkPreconditions = false;
362
- expect(dbc.executionSettings.checkPreconditions).toBe(true);
363
- });
364
- });
338
+ test("provides a temporary DBC instance and restores the original", () => {
339
+ const original = (window as any).WaXCode.DBC;
340
+ let isolatedInstance: DBC | undefined;
341
+ DBC.isolated((tempDbc) => {
342
+ isolatedInstance = tempDbc;
343
+ expect(tempDbc).not.toBe(original);
344
+ expect((window as any).WaXCode.DBC).toBe(tempDbc);
345
+ });
346
+ // After isolated() returns, the original is restored
347
+ expect((window as any).WaXCode.DBC).toBe(original);
348
+ expect(isolatedInstance).toBeDefined();
349
+ });
350
+
351
+ test("restores original even if callback throws", () => {
352
+ const original = (window as any).WaXCode.DBC;
353
+ expect(() => {
354
+ DBC.isolated(() => {
355
+ throw new Error("test error");
356
+ });
357
+ }).toThrow("test error");
358
+ expect((window as any).WaXCode.DBC).toBe(original);
359
+ });
360
+
361
+ test("isolated instance has independent settings", () => {
362
+ DBC.isolated((tempDbc) => {
363
+ tempDbc.executionSettings.checkPreconditions = false;
364
+ expect(dbc.executionSettings.checkPreconditions).toBe(true);
365
+ });
366
+ });
365
367
  });