@devrev/ts-adaas 1.13.1-beta.2 → 1.13.1

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 (88) hide show
  1. package/package.json +3 -2
  2. package/dist/tests/backwards-compatibility/backwards-compatibility.test.d.ts +0 -3
  3. package/dist/tests/backwards-compatibility/backwards-compatibility.test.d.ts.map +0 -1
  4. package/dist/tests/backwards-compatibility/backwards-compatibility.test.js +0 -441
  5. package/dist/tests/backwards-compatibility/helpers.d.ts +0 -21
  6. package/dist/tests/backwards-compatibility/helpers.d.ts.map +0 -1
  7. package/dist/tests/backwards-compatibility/helpers.js +0 -151
  8. package/dist/tests/backwards-compatibility/jest.setup.d.ts +0 -2
  9. package/dist/tests/backwards-compatibility/jest.setup.d.ts.map +0 -1
  10. package/dist/tests/backwards-compatibility/jest.setup.js +0 -5
  11. package/dist/tests/dummy-connector/data-extraction.d.ts +0 -2
  12. package/dist/tests/dummy-connector/data-extraction.d.ts.map +0 -1
  13. package/dist/tests/dummy-connector/data-extraction.js +0 -43
  14. package/dist/tests/dummy-connector/data-extraction.test.d.ts +0 -2
  15. package/dist/tests/dummy-connector/data-extraction.test.d.ts.map +0 -1
  16. package/dist/tests/dummy-connector/data-extraction.test.js +0 -24
  17. package/dist/tests/dummy-connector/external-sync-units-extraction.d.ts +0 -2
  18. package/dist/tests/dummy-connector/external-sync-units-extraction.d.ts.map +0 -1
  19. package/dist/tests/dummy-connector/external-sync-units-extraction.js +0 -26
  20. package/dist/tests/dummy-connector/external-sync-units-extraction.test.d.ts +0 -2
  21. package/dist/tests/dummy-connector/external-sync-units-extraction.test.d.ts.map +0 -1
  22. package/dist/tests/dummy-connector/external-sync-units-extraction.test.js +0 -21
  23. package/dist/tests/dummy-connector/extraction.d.ts +0 -4
  24. package/dist/tests/dummy-connector/extraction.d.ts.map +0 -1
  25. package/dist/tests/dummy-connector/extraction.js +0 -19
  26. package/dist/tests/dummy-connector/metadata-extraction.d.ts +0 -2
  27. package/dist/tests/dummy-connector/metadata-extraction.d.ts.map +0 -1
  28. package/dist/tests/dummy-connector/metadata-extraction.js +0 -23
  29. package/dist/tests/dummy-connector/metadata-extraction.test.d.ts +0 -2
  30. package/dist/tests/dummy-connector/metadata-extraction.test.d.ts.map +0 -1
  31. package/dist/tests/dummy-connector/metadata-extraction.test.js +0 -54
  32. package/dist/tests/jest.setup.d.ts +0 -3
  33. package/dist/tests/jest.setup.d.ts.map +0 -1
  34. package/dist/tests/jest.setup.js +0 -14
  35. package/dist/tests/mock-server/mock-server.d.ts +0 -79
  36. package/dist/tests/mock-server/mock-server.d.ts.map +0 -1
  37. package/dist/tests/mock-server/mock-server.interfaces.d.ts +0 -53
  38. package/dist/tests/mock-server/mock-server.interfaces.d.ts.map +0 -1
  39. package/dist/tests/mock-server/mock-server.interfaces.js +0 -4
  40. package/dist/tests/mock-server/mock-server.js +0 -237
  41. package/dist/tests/spawn-worker/delete-event-type.test.d.ts +0 -2
  42. package/dist/tests/spawn-worker/delete-event-type.test.d.ts.map +0 -1
  43. package/dist/tests/spawn-worker/delete-event-type.test.js +0 -31
  44. package/dist/tests/spawn-worker/extraction.d.ts +0 -4
  45. package/dist/tests/spawn-worker/extraction.d.ts.map +0 -1
  46. package/dist/tests/spawn-worker/extraction.js +0 -19
  47. package/dist/tests/spawn-worker/some-cleanup-worker.d.ts +0 -2
  48. package/dist/tests/spawn-worker/some-cleanup-worker.d.ts.map +0 -1
  49. package/dist/tests/spawn-worker/some-cleanup-worker.js +0 -16
  50. package/dist/tests/spawn-worker/unknown-event-type.d.ts +0 -2
  51. package/dist/tests/spawn-worker/unknown-event-type.d.ts.map +0 -1
  52. package/dist/tests/spawn-worker/unknown-event-type.js +0 -19
  53. package/dist/tests/spawn-worker/unknown-event-type.test.d.ts +0 -2
  54. package/dist/tests/spawn-worker/unknown-event-type.test.d.ts.map +0 -1
  55. package/dist/tests/spawn-worker/unknown-event-type.test.js +0 -21
  56. package/dist/tests/test-helpers.d.ts +0 -10
  57. package/dist/tests/test-helpers.d.ts.map +0 -1
  58. package/dist/tests/test-helpers.interfaces.d.ts +0 -14
  59. package/dist/tests/test-helpers.interfaces.d.ts.map +0 -1
  60. package/dist/tests/test-helpers.interfaces.js +0 -2
  61. package/dist/tests/test-helpers.js +0 -101
  62. package/dist/tests/timeout-handling/extraction.d.ts +0 -4
  63. package/dist/tests/timeout-handling/extraction.d.ts.map +0 -1
  64. package/dist/tests/timeout-handling/extraction.js +0 -21
  65. package/dist/tests/timeout-handling/no-timeout.d.ts +0 -2
  66. package/dist/tests/timeout-handling/no-timeout.d.ts.map +0 -1
  67. package/dist/tests/timeout-handling/no-timeout.js +0 -14
  68. package/dist/tests/timeout-handling/no-timeout.test.d.ts +0 -2
  69. package/dist/tests/timeout-handling/no-timeout.test.d.ts.map +0 -1
  70. package/dist/tests/timeout-handling/no-timeout.test.js +0 -24
  71. package/dist/tests/timeout-handling/timeout-blocked.d.ts +0 -2
  72. package/dist/tests/timeout-handling/timeout-blocked.d.ts.map +0 -1
  73. package/dist/tests/timeout-handling/timeout-blocked.js +0 -23
  74. package/dist/tests/timeout-handling/timeout-blocked.test.d.ts +0 -2
  75. package/dist/tests/timeout-handling/timeout-blocked.test.d.ts.map +0 -1
  76. package/dist/tests/timeout-handling/timeout-blocked.test.js +0 -25
  77. package/dist/tests/timeout-handling/timeout-graceful.d.ts +0 -2
  78. package/dist/tests/timeout-handling/timeout-graceful.d.ts.map +0 -1
  79. package/dist/tests/timeout-handling/timeout-graceful.js +0 -17
  80. package/dist/tests/timeout-handling/timeout-graceful.test.d.ts +0 -2
  81. package/dist/tests/timeout-handling/timeout-graceful.test.d.ts.map +0 -1
  82. package/dist/tests/timeout-handling/timeout-graceful.test.js +0 -25
  83. package/dist/tests/timeout-handling/timeout-unblocked.d.ts +0 -2
  84. package/dist/tests/timeout-handling/timeout-unblocked.d.ts.map +0 -1
  85. package/dist/tests/timeout-handling/timeout-unblocked.js +0 -26
  86. package/dist/tests/timeout-handling/timeout-unblocked.test.d.ts +0 -2
  87. package/dist/tests/timeout-handling/timeout-unblocked.test.d.ts.map +0 -1
  88. package/dist/tests/timeout-handling/timeout-unblocked.test.js +0 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrev/ts-adaas",
3
- "version": "1.13.1-beta.2",
3
+ "version": "1.13.1",
4
4
  "description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
@@ -54,6 +54,7 @@
54
54
  "yargs": "^17.7.2"
55
55
  },
56
56
  "files": [
57
- "dist"
57
+ "dist/**/*",
58
+ "!dist/tests/**/*"
58
59
  ]
59
60
  }
@@ -1,3 +0,0 @@
1
- import { ApiConstructor, ApiFunction, ApiMethodSignature } from '@microsoft/api-extractor-model';
2
- export declare function checkFunctionCompatibility(newFunction: ApiFunction | ApiConstructor | ApiMethodSignature, currentFunction: ApiFunction | ApiConstructor | ApiMethodSignature): void;
3
- //# sourceMappingURL=backwards-compatibility.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"backwards-compatibility.test.d.ts","sourceRoot":"","sources":["../../../src/tests/backwards-compatibility/backwards-compatibility.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EAGd,WAAW,EAGX,kBAAkB,EAKnB,MAAM,gCAAgC,CAAC;AAgBxC,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,WAAW,GAAG,cAAc,GAAG,kBAAkB,EAC9D,eAAe,EAAE,WAAW,GAAG,cAAc,GAAG,kBAAkB,QAuHnE"}
@@ -1,441 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkFunctionCompatibility = checkFunctionCompatibility;
4
- const api_extractor_model_1 = require("@microsoft/api-extractor-model");
5
- const helpers_1 = require("./helpers");
6
- function checkFunctionCompatibility(newFunction, currentFunction) {
7
- var _a;
8
- const lengthOfPreviousParameters = currentFunction.parameters.length;
9
- it(`Function ${newFunction.displayName} should have at least as many parameters as the current function`, () => {
10
- expect(newFunction.parameters.length).toBeGreaterThanOrEqual(currentFunction.parameters.length);
11
- });
12
- it(`Function ${newFunction.displayName} should have parameters in the same order as the current function`, () => {
13
- const newFunctionParamNames = newFunction.parameters
14
- .slice(0, lengthOfPreviousParameters)
15
- .map((p) => p.name);
16
- const currentFunctionParamNames = currentFunction.parameters.map((p) => p.name);
17
- // Check each parameter position for destructured parameter compatibility
18
- for (let i = 0; i <
19
- Math.min(newFunctionParamNames.length, currentFunctionParamNames.length); i++) {
20
- const newParam = newFunctionParamNames[i];
21
- const currentParam = currentFunctionParamNames[i];
22
- // If both are destructured parameters (contain '{')
23
- if (newParam.includes('{') && currentParam.includes('{')) {
24
- // Extract field names from destructured parameters
25
- const extractFields = (param) => param
26
- .replace(/[{}\s]/g, '')
27
- .split(',')
28
- .filter((f) => f.length > 0);
29
- const newFields = extractFields(newParam);
30
- const currentFields = extractFields(currentParam);
31
- // Check that all current fields are present in new fields
32
- const missingFields = currentFields.filter((field) => !newFields.includes(field));
33
- expect(missingFields).toEqual([]);
34
- }
35
- else {
36
- // For non-destructured parameters, they must match exactly
37
- expect(newParam).toEqual(currentParam);
38
- }
39
- }
40
- });
41
- it(`Function ${newFunction.displayName} should have compatible parameter types with the current function`, () => {
42
- const newFunctionParamTypes = newFunction.parameters
43
- .slice(0, lengthOfPreviousParameters)
44
- .map((p) => p.parameterTypeExcerpt.text);
45
- const currentFunctionParameterTypes = currentFunction.parameters.map((p) => p.parameterTypeExcerpt.text);
46
- expect(newFunctionParamTypes).toEqual(currentFunctionParameterTypes);
47
- });
48
- // Check return type compatibility
49
- // This check fails if it's a constructor, as those don't have a return type
50
- if (currentFunction instanceof api_extractor_model_1.ApiFunction &&
51
- newFunction instanceof api_extractor_model_1.ApiFunction) {
52
- if (!((_a = currentFunction.returnTypeExcerpt) === null || _a === void 0 ? void 0 : _a.isEmpty)) {
53
- if (newFunction.returnTypeExcerpt.text !=
54
- currentFunction.returnTypeExcerpt.text) {
55
- // This will pass, if the new implementation is an object and the current one is not specified or a hard-coded type.
56
- if (!(currentFunction.returnTypeExcerpt.text.split(' ').length != 1 &&
57
- newFunction.returnTypeExcerpt.text.split(' ').length == 1)) {
58
- it(`Function ${newFunction.displayName} should have the same return type as the current function`, () => {
59
- expect(newFunction.returnTypeExcerpt.text).toEqual(currentFunction.returnTypeExcerpt.text);
60
- });
61
- }
62
- }
63
- }
64
- }
65
- it(`Function ${newFunction.displayName} should have all new parameters as optional`, () => {
66
- const newParameters = newFunction.parameters.slice(lengthOfPreviousParameters);
67
- expect(newParameters.every((p) => p.isOptional)).toBe(true);
68
- });
69
- it(`Function ${newFunction.displayName} should not have any optional parameters that became required`, () => {
70
- const minLength = Math.min(newFunction.parameters.length, currentFunction.parameters.length);
71
- for (let i = 0; i < minLength; i++) {
72
- const newParam = newFunction.parameters[i];
73
- const currentParam = currentFunction.parameters[i];
74
- // If current parameter was optional, new parameter should also be optional
75
- if (currentParam.isOptional && !newParam.isOptional) {
76
- throw new Error(`Parameter ${newParam.name} became required but was optional`);
77
- }
78
- // Skip interface compatibility check for destructured parameters
79
- if (newParam.name.includes('{') || currentParam.name.includes('{')) {
80
- continue;
81
- }
82
- }
83
- });
84
- }
85
- describe('Backwards Compatibility', () => {
86
- let failure = false;
87
- afterEach(() => {
88
- var _a;
89
- // Check if current test failed
90
- if (expect.getState().currentTestName &&
91
- ((_a = expect.getState().suppressedErrors) === null || _a === void 0 ? void 0 : _a.length) > 0) {
92
- failure = true;
93
- }
94
- });
95
- describe('Exports', () => {
96
- describe('should verify that all exports in current are still in new', () => {
97
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
98
- const newExports = newApiMembers.map((m) => m.displayName);
99
- const currentExports = currentApiMembers.map((m) => m.displayName);
100
- it.each(currentExports)('should contain export: %s', (exportName) => {
101
- expect(newExports).toContain(exportName);
102
- });
103
- });
104
- });
105
- describe('Functions', () => {
106
- describe('should have all current functions exported in new', () => {
107
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
108
- const newFunctions = (0, helpers_1.getFunctions)(newApiMembers);
109
- const currentFunctions = (0, helpers_1.getFunctions)(currentApiMembers);
110
- const newFunctionNames = newFunctions.map((f) => f.name);
111
- for (const currentFunction of currentFunctions) {
112
- it(`should contain function: ${currentFunction.name}`, () => {
113
- expect(newFunctionNames).toContain(currentFunction.name);
114
- });
115
- }
116
- });
117
- describe('should verify function compatibility for each function', () => {
118
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
119
- const newFunctions = (0, helpers_1.getFunctions)(newApiMembers);
120
- const currentFunctions = (0, helpers_1.getFunctions)(currentApiMembers);
121
- for (const newFunction of newFunctions) {
122
- const currentFunction = currentFunctions.find((f) => f.name === newFunction.name);
123
- // Skip if function doesn't exist in current API
124
- if (!currentFunction) {
125
- continue;
126
- }
127
- checkFunctionCompatibility(newFunction, currentFunction);
128
- }
129
- // TODO: Check that optional promotion works only one way (no required parameters becoming optional, but optional parameters can become required)
130
- // TODO: Check that function overloads weren't removed
131
- // TODO: Verify that function parameter destructuring patterns maintain compatibility
132
- // TODO: Check that function parameter default values don't change in breaking ways
133
- });
134
- });
135
- describe('Classes', () => {
136
- describe('should verify class property counts and compatibility', () => {
137
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
138
- const newClasses = (0, helpers_1.getClasses)(newApiMembers);
139
- const currentClasses = (0, helpers_1.getClasses)(currentApiMembers);
140
- for (const newClass of newClasses) {
141
- const currentClass = currentClasses.find((c) => c.name === newClass.name);
142
- // Skip if class doesn't exist in current API
143
- if (!currentClass) {
144
- continue;
145
- }
146
- const newClassProperties = (0, helpers_1.getProperties)(newClass.members);
147
- const currentClassProperties = (0, helpers_1.getProperties)(currentClass.members);
148
- describe(`Class ${newClass.name} should have at least all public properties from the current class`, () => {
149
- const newPropertyNames = newClassProperties.map((p) => p.name);
150
- for (const currentProperty of currentClassProperties) {
151
- it(`should contain property: ${currentProperty.name}`, () => {
152
- expect(newPropertyNames).toContain(currentProperty.name);
153
- });
154
- }
155
- });
156
- describe(`Class ${newClass.name} should not have any optional properties that became required`, () => {
157
- for (const currentProperty of currentClassProperties) {
158
- it(`should not have optional property that became required: ${currentProperty.name}`, () => {
159
- const newProperty = newClassProperties.find((p) => p.name === currentProperty.name);
160
- if (newProperty && currentProperty.isOptional) {
161
- // If the current property was optional, the new property should also be optional
162
- expect(newProperty.isOptional).toBe(true);
163
- }
164
- });
165
- }
166
- });
167
- // Check property compatibility
168
- const oldProperties = currentClassProperties;
169
- const newProperties = newClassProperties;
170
- for (const newProperty of newProperties) {
171
- const currentProperty = oldProperties.find((p) => p.name === newProperty.name);
172
- // If the property is new, there's no need to check for compatibility
173
- if (!currentProperty) {
174
- continue;
175
- }
176
- it(`Class ${newClass.name} property ${newProperty.name} should have the same type as the current property`, () => {
177
- expect(newProperty.propertyTypeExcerpt.text).toEqual(currentProperty.propertyTypeExcerpt.text);
178
- });
179
- it(`Class ${newClass.name} property ${newProperty.name} should have the same optionality as the current property`, () => {
180
- expect(newProperty.isOptional).toEqual(currentProperty.isOptional);
181
- });
182
- }
183
- // Check constructor signature compatibility (same rules as functions)
184
- const currentMethod = (0, helpers_1.getConstructor)(currentClass.members);
185
- const newMethod = (0, helpers_1.getConstructor)(newClass.members);
186
- checkFunctionCompatibility(newMethod, currentMethod);
187
- // Check method count
188
- const newClassMethods = (0, helpers_1.getFunctions)(newClass.members);
189
- const currentClassMethods = (0, helpers_1.getFunctions)(currentClass.members);
190
- describe(`Class ${newClass.name} should export all public methods from the current class`, () => {
191
- const newMethodNames = newClassMethods.map((m) => m.name);
192
- for (const currentMethod of currentClassMethods) {
193
- it(`should contain method: ${currentMethod.name}`, () => {
194
- expect(newMethodNames).toContain(currentMethod.name);
195
- });
196
- }
197
- });
198
- // Check method compatibility (same rules as functions)
199
- // Make sure to allow optional parameters to be added to the end
200
- for (const newMethod of newClassMethods) {
201
- const currentMethod = currentClassMethods.find((m) => m.name === newMethod.name);
202
- // If the method is new, there's no need to check for compatibility
203
- if (!currentMethod) {
204
- continue;
205
- }
206
- checkFunctionCompatibility(newMethod, currentMethod);
207
- }
208
- // TODO: Verify class inheritance hierarchy hasn't changed in breaking ways
209
- // TODO: Check that class mixins maintain their composition behavior
210
- // TODO: Verify that abstract class methods remain abstract or are properly implemented
211
- }
212
- });
213
- });
214
- describe('Interfaces', () => {
215
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
216
- const newInterfaces = (0, helpers_1.getInterfaces)(newApiMembers);
217
- const currentInterfaces = (0, helpers_1.getInterfaces)(currentApiMembers);
218
- describe('should verify interface property counts and compatibility', () => {
219
- for (const newInterface of newInterfaces) {
220
- const currentInterface = currentInterfaces.find((i) => i.name === newInterface.name);
221
- if (!currentInterface) {
222
- continue;
223
- }
224
- const newInterfaceProperties = (0, helpers_1.getPropertySignatures)(newInterface.members);
225
- const currentInterfaceProperties = (0, helpers_1.getPropertySignatures)(currentInterface.members);
226
- it(`Interface ${newInterface.name} should have at least as many properties as the current interface`, () => {
227
- expect(newInterfaceProperties.length).toBeGreaterThanOrEqual(currentInterfaceProperties.length);
228
- });
229
- it(`Interface ${newInterface.name} should not have any optional properties that became required`, () => {
230
- const requiredProperties = newInterfaceProperties.filter((p) => !p.isOptional);
231
- expect(requiredProperties.length).toBeLessThanOrEqual(currentInterfaceProperties.filter((p) => !p.isOptional).length);
232
- });
233
- // Check property compatibility
234
- const oldProperties = currentInterfaceProperties;
235
- const newProperties = newInterfaceProperties;
236
- for (const newProperty of newProperties) {
237
- const currentProperty = oldProperties.find((p) => p.name === newProperty.name);
238
- // If the property is new, there's no need to check for compatibility
239
- if (!currentProperty) {
240
- continue;
241
- }
242
- it(`Interface ${newInterface.name} property ${newProperty.name} should have the same type as the current property`, () => {
243
- expect(newProperty.propertyTypeExcerpt.text).toEqual(currentProperty.propertyTypeExcerpt.text);
244
- });
245
- it(`Interface ${newInterface.name} property ${newProperty.name} should have not been made required if it was optional`, () => {
246
- // If the new property is required, it must have been required before.
247
- // Otherwise we break backwards-compatibility.
248
- expect(
249
- // If it was required before, it can be either now.
250
- !currentProperty.isOptional ||
251
- // If it was optional before, it can only be optional now.
252
- newProperty.isOptional).toEqual(true);
253
- });
254
- }
255
- // Check method count
256
- const newInterfaceMethods = (0, helpers_1.getMethodSignatures)(newInterface.members);
257
- const currentInterfaceMethods = (0, helpers_1.getMethodSignatures)(currentInterface.members);
258
- it(`Interface ${newInterface.name} should have at least as many public methods as the current interface`, () => {
259
- expect(newInterfaceMethods.length).toBeGreaterThanOrEqual(currentInterfaceMethods.length);
260
- });
261
- // Check method compatibility (same rules as functions)
262
- // Make sure to allow optional parameters to be added to the end
263
- for (const newMethod of newInterfaceMethods) {
264
- const currentMethod = currentInterfaceMethods.find((m) => m.name === newMethod.name);
265
- // If the method is new, there's no need to check for compatibility
266
- if (!currentMethod) {
267
- continue;
268
- }
269
- checkFunctionCompatibility(newMethod, currentMethod);
270
- }
271
- }
272
- });
273
- // TODO: Verify interface inheritance hierarchy hasn't changed
274
- // TODO: Check that interface merging behavior is preserved
275
- // TODO: Verify that interface index signatures maintain their key/value types
276
- });
277
- describe('Enums', () => {
278
- let newEnums;
279
- let currentEnums;
280
- describe('should verify enum value counts and existence', () => {
281
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
282
- newEnums = (0, helpers_1.getEnums)(newApiMembers);
283
- currentEnums = (0, helpers_1.getEnums)(currentApiMembers);
284
- // Verify no enum values were removed
285
- for (const newEnum of newEnums) {
286
- const currentEnum = currentEnums.find((e) => e.name === newEnum.name);
287
- // If it's a new enum, there's no need to check for compatibility
288
- if (!currentEnum) {
289
- continue;
290
- }
291
- const currentEnumValues = currentEnum.members;
292
- const newEnumValues = newEnum.members;
293
- it(`Enum ${newEnum.name} should have at least as many enum values as the current enum`, () => {
294
- expect(newEnumValues.length).toBeGreaterThanOrEqual(currentEnumValues.length);
295
- });
296
- for (const currentEnumValue of currentEnumValues) {
297
- const newEnumValue = newEnumValues.find((v) => v.name === currentEnumValue.name);
298
- // If it's a new enum value, there's no need to check for compatibility
299
- if (!newEnumValue) {
300
- continue;
301
- }
302
- it(`Enum ${newEnum.name} should contain enum value: ${currentEnumValue.name}`, () => {
303
- expect(newEnumValue).toBeDefined();
304
- });
305
- }
306
- }
307
- });
308
- // Verify numeric enum values haven't changed (if numeric enum)
309
- describe('should verify numeric enum values have not changed', () => {
310
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
311
- newEnums = (0, helpers_1.getEnums)(newApiMembers);
312
- currentEnums = (0, helpers_1.getEnums)(currentApiMembers);
313
- for (const newEnum of newEnums) {
314
- const currentEnum = currentEnums.find((e) => e.name === newEnum.name);
315
- // If it's a new enum, there's no need to check for compatibility
316
- if (!currentEnum) {
317
- continue;
318
- }
319
- // Helper function to determine if an enum is numeric based on its members' initializer values
320
- const isNumericEnum = (enumMembers) => {
321
- return enumMembers.every((member) => {
322
- var _a, _b, _c;
323
- // Check if the member has an initializer and if it's a numeric value
324
- const initializerText = (_c = (_b = (_a = member.excerptTokens) === null || _a === void 0 ? void 0 : _a.find((token) => token.kind === 'Content' && /^\d+$/.test(token.text.trim()))) === null || _b === void 0 ? void 0 : _b.text) === null || _c === void 0 ? void 0 : _c.trim();
325
- return (initializerText !== undefined && /^\d+$/.test(initializerText));
326
- });
327
- };
328
- const newEnumNumeric = isNumericEnum([...newEnum.members]);
329
- const currentEnumNumeric = isNumericEnum([...currentEnum.members]);
330
- it(`Enum ${newEnum.name} should have the same numeric type as the current enum`, () => {
331
- expect(newEnumNumeric).toBe(currentEnumNumeric);
332
- });
333
- const currentEnumValues = currentEnum.members;
334
- const newEnumValues = newEnum.members;
335
- it(`Enum ${newEnum.name} should have at least as many enum values as the current enum`, () => {
336
- expect(newEnumValues.length).toBeGreaterThanOrEqual(currentEnumValues.length);
337
- });
338
- for (const currentEnumValue of currentEnumValues) {
339
- const newEnumValue = newEnumValues.find((v) => v.name === currentEnumValue.name);
340
- // If it's not defined, an existing value is missing from the new enum
341
- it(`Enum ${newEnum.name} should contain enum value: ${currentEnumValue.name}`, () => {
342
- expect(newEnumValue).toBeDefined();
343
- });
344
- it(`Enum ${newEnum.name} should have the same value for enum member: ${currentEnumValue.name}`, () => {
345
- var _a, _b;
346
- // Both can be undefined, but they should always equal each other
347
- const newValue = (_a = newEnumValue.initializerExcerpt) === null || _a === void 0 ? void 0 : _a.text;
348
- const currentValue = (_b = currentEnumValue.initializerExcerpt) === null || _b === void 0 ? void 0 : _b.text;
349
- expect(newValue).toEqual(currentValue);
350
- });
351
- }
352
- }
353
- });
354
- // TODO: Check that new enum values were only added at the end (best practice)
355
- // TODO: Verify that const enums maintain their compile-time behavior
356
- // TODO: Check that enum member values don't change in breaking ways
357
- describe('should verify enum value types have been added to the end', () => {
358
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
359
- newEnums = (0, helpers_1.getEnums)(newApiMembers);
360
- currentEnums = (0, helpers_1.getEnums)(currentApiMembers);
361
- for (const newEnum of newEnums) {
362
- const currentEnum = currentEnums.find((e) => e.name === newEnum.name);
363
- // If it's a new enum, there's no need to check for compatibility
364
- if (!currentEnum) {
365
- continue;
366
- }
367
- const currentEnumValues = currentEnum.members.map((a) => a.name);
368
- const newEnumValues = newEnum.members
369
- .slice(0, currentEnumValues.length)
370
- .map((a) => a.name);
371
- // This might appear to not be working sometimes, but remember that the order of enum values is determined by the enum member key name
372
- it(`Enum ${newEnum.name} should have added new options to the end of the array`, () => {
373
- expect(newEnumValues).toStrictEqual(currentEnumValues);
374
- });
375
- }
376
- });
377
- });
378
- describe('Types', () => {
379
- const { newApiMembers, currentApiMembers } = (0, helpers_1.loadApiData)();
380
- const newTypes = (0, helpers_1.getTypes)(newApiMembers);
381
- const currentTypes = (0, helpers_1.getTypes)(currentApiMembers);
382
- // Verify type aliases weren't removed
383
- describe("should verify type aliases weren't removed", () => {
384
- for (const newType of newTypes) {
385
- const currentType = currentTypes.find((t) => t.name === newType.name);
386
- if (!currentType) {
387
- continue;
388
- }
389
- it(`Type ${newType.name} should not have been removed`, () => {
390
- expect(currentType).toBeDefined();
391
- });
392
- }
393
- });
394
- // Verify that the type alias is the same as the current type alias
395
- describe('should verify type aliases are the same as the current type aliases', () => {
396
- for (const newType of newTypes) {
397
- const currentType = currentTypes.find((t) => t.name === newType.name);
398
- if (!currentType) {
399
- continue;
400
- }
401
- it(`Type ${newType.name} should have the same type as the current type`, () => {
402
- // Replace all whitespace with an empty string to ignore whitespace differences
403
- expect(newType.typeExcerpt.text.replace(/\s/g, '')).toEqual(currentType.typeExcerpt.text.replace(/\s/g, ''));
404
- });
405
- }
406
- });
407
- // TODO: Verify union types didn't become more restrictive (no types removed from union)
408
- // TODO: Verify intersection types didn't become more permissive (no required types removed)
409
- // TODO: Check generic type parameter compatibility
410
- });
411
- describe('Method Signatures', () => {
412
- // TODO: Verify generic constraints haven't become more restrictive
413
- // TODO: Check that default parameter values are still compatible
414
- // TODO: Verify rest parameters (...args) compatibility
415
- // TODO: Check function signature overloads
416
- });
417
- describe('Generics', () => {
418
- // TODO: Verify generic type parameters weren't removed
419
- // TODO: Check that generic constraints didn't become more restrictive
420
- // TODO: Verify generic parameter names haven't changed (affects explicit type arguments)
421
- // TODO: Check variance compatibility (covariant/contravariant)
422
- });
423
- describe('Property Types', () => {
424
- // TODO: Check readonly properties didn't become mutable (or vice versa in breaking way)
425
- // TODO: Verify array types compatibility (T[] vs Array<T>)
426
- // TODO: Check Promise/async compatibility
427
- // TODO: Verify callback function signature compatibility
428
- });
429
- describe('Accessibility', () => {
430
- // TODO: Verify public members didn't become private/protected
431
- // TODO: Check that protected members didn't become private
432
- // TODO: Ensure no breaking changes in static vs instance members
433
- });
434
- afterAll(() => {
435
- // If there are any failures, don't update the current API baseline files
436
- if (failure) {
437
- return;
438
- }
439
- (0, helpers_1.updateCurrentApiJson)();
440
- });
441
- });
@@ -1,21 +0,0 @@
1
- import { ApiClass, ApiConstructor, ApiEnum, ApiFunction, ApiInterface, ApiItem, ApiMethodSignature, ApiProperty, ApiPropertySignature, ApiTypeAlias } from '@microsoft/api-extractor-model';
2
- export declare const newApiMdPath: string;
3
- export declare const currentApiMdPath: string;
4
- export declare const newApiJsonPath: string;
5
- export declare const currentApiJsonPath: string;
6
- export declare function generateApiReport(): void;
7
- export declare const loadApiData: () => {
8
- newApiMembers: readonly ApiItem[];
9
- currentApiMembers: readonly ApiItem[];
10
- };
11
- export declare const getFunctions: (members: readonly ApiItem[]) => ApiFunction[];
12
- export declare const getConstructor: (members: readonly ApiItem[]) => ApiConstructor;
13
- export declare const getEnums: (members: readonly ApiItem[]) => ApiEnum[];
14
- export declare const getClasses: (members: readonly ApiItem[]) => ApiClass[];
15
- export declare const getProperties: (members: readonly ApiItem[]) => ApiProperty[];
16
- export declare const getTypes: (members: readonly ApiItem[]) => ApiTypeAlias[];
17
- export declare const getInterfaces: (members: readonly ApiItem[]) => ApiInterface[];
18
- export declare const getMethodSignatures: (members: readonly ApiItem[]) => ApiMethodSignature[];
19
- export declare const getPropertySignatures: (members: readonly ApiItem[]) => ApiPropertySignature[];
20
- export declare const updateCurrentApiJson: () => void;
21
- //# sourceMappingURL=helpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/tests/backwards-compatibility/helpers.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,QAAQ,EACR,cAAc,EACd,OAAO,EACP,WAAW,EACX,YAAY,EACZ,OAAO,EACP,kBAAkB,EAElB,WAAW,EACX,oBAAoB,EACpB,YAAY,EACb,MAAM,gCAAgC,CAAC;AAMxC,eAAO,MAAM,YAAY,QAA8C,CAAC;AACxE,eAAO,MAAM,gBAAgB,QAAsC,CAAC;AACpE,eAAO,MAAM,cAAc,QAAoD,CAAC;AAChF,eAAO,MAAM,kBAAkB,QAAsC,CAAC;AAKtE,wBAAgB,iBAAiB,IAAI,IAAI,CAkDxC;AAGD,eAAO,MAAM,WAAW,QAAO;IAC7B,aAAa,EAAE,SAAS,OAAO,EAAE,CAAC;IAClC,iBAAiB,EAAE,SAAS,OAAO,EAAE,CAAC;CAqBvC,CAAC;AAGF,eAAO,MAAM,YAAY,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,WAAW,EAIrE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,cAM5D,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,OAAO,EAI7D,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,QAAQ,EAIhE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,WAAW,EAItE,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,YAAY,EAIlE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,YAAY,EAIvE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,SAAS,OAAO,EAAE,KAC1B,kBAAkB,EAKpB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,SAAS,OAAO,EAAE,KAC1B,oBAAoB,EAKtB,CAAC;AAEF,eAAO,MAAM,oBAAoB,YAYhC,CAAC"}
@@ -1,151 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.updateCurrentApiJson = exports.getPropertySignatures = exports.getMethodSignatures = exports.getInterfaces = exports.getTypes = exports.getProperties = exports.getClasses = exports.getEnums = exports.getConstructor = exports.getFunctions = exports.loadApiData = exports.currentApiJsonPath = exports.newApiJsonPath = exports.currentApiMdPath = exports.newApiMdPath = void 0;
37
- exports.generateApiReport = generateApiReport;
38
- const api_extractor_1 = require("@microsoft/api-extractor");
39
- const api_extractor_model_1 = require("@microsoft/api-extractor-model");
40
- const fs = __importStar(require("fs"));
41
- const node_child_process_1 = require("node:child_process");
42
- const path = __importStar(require("path"));
43
- exports.newApiMdPath = path.join(__dirname, 'temp', 'ts-adaas.md');
44
- exports.currentApiMdPath = path.join(__dirname, 'ts-adaas.md');
45
- exports.newApiJsonPath = path.join(__dirname, 'temp', 'ts-adaas.api.json');
46
- exports.currentApiJsonPath = path.join(__dirname, 'latest.json');
47
- /* eslint-disable @typescript-eslint/no-explicit-any */
48
- // Generate API report before all tests run
49
- function generateApiReport() {
50
- // Before running the api extractor, make sure that the code compiles using `tsc` command
51
- const tscCommand = 'npm run build';
52
- try {
53
- (0, node_child_process_1.execSync)(tscCommand);
54
- }
55
- catch (error) {
56
- // Jest has a nice feature: if any of the setup scripts throw an error, the test run will fail
57
- // This Error is rethrown to get more information from the error.
58
- throw new Error(`Failed to compile code using tsc command:\n${error.stdout.toString()}`);
59
- }
60
- const apiExtractorJsonPath = path.join(__dirname, 'api-extractor.json');
61
- // Ensure the temp and report directories exist
62
- const tempDir = path.join(__dirname, 'temp');
63
- const reportDir = path.join(__dirname, 'report');
64
- if (!fs.existsSync(tempDir)) {
65
- fs.mkdirSync(tempDir, { recursive: true });
66
- console.log(`Created temp directory: ${tempDir}`);
67
- }
68
- if (!fs.existsSync(reportDir)) {
69
- fs.mkdirSync(reportDir, { recursive: true });
70
- console.log(`Created report directory: ${reportDir}`);
71
- }
72
- const extractorConfig = api_extractor_1.ExtractorConfig.loadFileAndPrepare(apiExtractorJsonPath);
73
- const extractorResult = api_extractor_1.Extractor.invoke(extractorConfig, {
74
- localBuild: true,
75
- showVerboseMessages: false,
76
- });
77
- if (extractorResult.succeeded) {
78
- console.log(`API Extractor completed successfully`);
79
- process.exitCode = 0;
80
- }
81
- else {
82
- console.error(`API Extractor completed with ${extractorResult.errorCount} errors` +
83
- ` and ${extractorResult.warningCount} warnings`);
84
- process.exitCode = 1;
85
- }
86
- }
87
- // Helper function to load API data
88
- const loadApiData = () => {
89
- if (!fs.existsSync(exports.newApiJsonPath)) {
90
- throw new Error('New API reports not found. Run the generate-api-report test first.');
91
- }
92
- if (!fs.existsSync(exports.currentApiJsonPath)) {
93
- throw new Error('Latest API baseline not found. Run backwards compatibility tests first to generate latest.json.');
94
- }
95
- const newApiModel = new api_extractor_model_1.ApiModel().loadPackage(exports.newApiJsonPath);
96
- const newApiMembers = newApiModel.entryPoints[0].members;
97
- const currentApiModel = new api_extractor_model_1.ApiModel().loadPackage(exports.currentApiJsonPath);
98
- const currentApiMembers = currentApiModel.entryPoints[0].members;
99
- return { newApiMembers, currentApiMembers };
100
- };
101
- exports.loadApiData = loadApiData;
102
- // Helper functions for getting different kinds of items from the API members
103
- const getFunctions = (members) => {
104
- return members.filter((m) => m instanceof api_extractor_model_1.ApiFunction && m.kind === 'Function');
105
- };
106
- exports.getFunctions = getFunctions;
107
- const getConstructor = (members) => {
108
- return members.filter((m) => m instanceof api_extractor_model_1.ApiConstructor && m.kind === 'Constructor')[0];
109
- };
110
- exports.getConstructor = getConstructor;
111
- const getEnums = (members) => {
112
- return members.filter((m) => m instanceof api_extractor_model_1.ApiEnum && m.kind === 'Enum');
113
- };
114
- exports.getEnums = getEnums;
115
- const getClasses = (members) => {
116
- return members.filter((m) => m instanceof api_extractor_model_1.ApiClass && m.kind === 'Class');
117
- };
118
- exports.getClasses = getClasses;
119
- const getProperties = (members) => {
120
- return members.filter((m) => m instanceof api_extractor_model_1.ApiProperty && m.kind === 'Property');
121
- };
122
- exports.getProperties = getProperties;
123
- const getTypes = (members) => {
124
- return members.filter((m) => m instanceof api_extractor_model_1.ApiTypeAlias && m.kind === 'TypeAlias');
125
- };
126
- exports.getTypes = getTypes;
127
- const getInterfaces = (members) => {
128
- return members.filter((m) => m instanceof api_extractor_model_1.ApiInterface && m.kind === 'Interface');
129
- };
130
- exports.getInterfaces = getInterfaces;
131
- const getMethodSignatures = (members) => {
132
- return members.filter((m) => m instanceof api_extractor_model_1.ApiMethodSignature && m.kind === 'MethodSignature');
133
- };
134
- exports.getMethodSignatures = getMethodSignatures;
135
- const getPropertySignatures = (members) => {
136
- return members.filter((m) => m instanceof api_extractor_model_1.ApiPropertySignature && m.kind === 'PropertySignature');
137
- };
138
- exports.getPropertySignatures = getPropertySignatures;
139
- const updateCurrentApiJson = () => {
140
- if (fs.existsSync(exports.newApiMdPath) && fs.existsSync(exports.newApiJsonPath)) {
141
- fs.copyFileSync(exports.newApiMdPath, exports.currentApiMdPath);
142
- // Copy new API JSON into latest.json after all tests pass
143
- const latestJsonPath = path.join(__dirname, 'latest.json');
144
- fs.copyFileSync(exports.newApiJsonPath, latestJsonPath);
145
- console.log(`Updated current API baseline files and created latest.json.`);
146
- }
147
- else {
148
- console.warn('No new API reports found.');
149
- }
150
- };
151
- exports.updateCurrentApiJson = updateCurrentApiJson;
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=jest.setup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jest.setup.d.ts","sourceRoot":"","sources":["../../../src/tests/backwards-compatibility/jest.setup.ts"],"names":[],"mappings":""}