@coast/core-utils 0.0.25 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AssertionUtils.d.ts +0 -9
- package/dist/AssertionUtils.js +0 -16
- package/dist/AssertionUtils.js.map +1 -1
- package/dist/CompactSet.d.ts +5 -0
- package/dist/CompactSet.js +21 -0
- package/dist/CompactSet.js.map +1 -0
- package/dist/EntityRehydrator.d.ts +12 -0
- package/dist/EntityRehydrator.js +30 -0
- package/dist/EntityRehydrator.js.map +1 -0
- package/dist/EntityUtils.d.ts +11 -0
- package/dist/EntityUtils.js +24 -0
- package/dist/EntityUtils.js.map +1 -0
- package/dist/ISODateStringUtils.d.ts +5 -0
- package/dist/ISODateStringUtils.js +16 -0
- package/dist/ISODateStringUtils.js.map +1 -0
- package/dist/JsonPath.d.ts +8 -0
- package/dist/JsonPath.js +38 -0
- package/dist/JsonPath.js.map +1 -0
- package/dist/test/AssertionUtilsTest.js +0 -41
- package/dist/test/AssertionUtilsTest.js.map +1 -1
- package/dist/test/CompactSetTest.d.ts +1 -0
- package/dist/test/CompactSetTest.js +95 -0
- package/dist/test/CompactSetTest.js.map +1 -0
- package/dist/test/EntityRehydratorTest.d.ts +1 -0
- package/dist/test/EntityRehydratorTest.js +48 -0
- package/dist/test/EntityRehydratorTest.js.map +1 -0
- package/dist/test/EntityUtilsTest.d.ts +1 -0
- package/dist/test/EntityUtilsTest.js +87 -0
- package/dist/test/EntityUtilsTest.js.map +1 -0
- package/dist/test/JsonPathTest.d.ts +1 -0
- package/dist/test/JsonPathTest.js +419 -0
- package/dist/test/JsonPathTest.js.map +1 -0
- package/jest.config.js +1 -0
- package/package.json +4 -6
- package/src/AssertionUtils.ts +0 -33
- package/src/CompactSet.ts +31 -0
- package/src/EntityRehydrator.ts +35 -0
- package/src/EntityUtils.ts +37 -0
- package/src/ISODateStringUtils.ts +24 -0
- package/src/JsonPath.ts +58 -0
- package/src/test/AssertionUtilsTest.ts +0 -48
- package/src/test/CompactSetTest.ts +106 -0
- package/src/test/EntityRehydratorTest.ts +74 -0
- package/src/test/EntityUtilsTest.ts +97 -0
- package/src/test/JsonPathTest.ts +516 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EntityType } from '@coast/core-types/common/EntityType';
|
|
2
|
+
import { InvalidEntityReferenceException } from '@coast/core-types/exception/InvalidEntityReferenceException';
|
|
3
|
+
import { NotFoundException } from '@coast/core-types/exception/NotFoundException';
|
|
4
|
+
|
|
5
|
+
import { AssertionUtils } from './AssertionUtils';
|
|
6
|
+
|
|
7
|
+
export class EntityUtils {
|
|
8
|
+
public static assertValidEntityReference<T extends object>(
|
|
9
|
+
entity: T | null | undefined,
|
|
10
|
+
entityType: EntityType,
|
|
11
|
+
options: { id?: string; message?: string } = {}
|
|
12
|
+
): asserts entity is T {
|
|
13
|
+
AssertionUtils.assertIsDefined(
|
|
14
|
+
entity,
|
|
15
|
+
new InvalidEntityReferenceException({
|
|
16
|
+
entityType,
|
|
17
|
+
id: options?.id,
|
|
18
|
+
message: options?.message,
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public static assertEntityFound<T extends object>(
|
|
24
|
+
entity: T | null | undefined,
|
|
25
|
+
entityType: EntityType,
|
|
26
|
+
options: { id?: string; message?: string } = {}
|
|
27
|
+
): asserts entity is T {
|
|
28
|
+
AssertionUtils.assertIsDefined(
|
|
29
|
+
entity,
|
|
30
|
+
new NotFoundException({
|
|
31
|
+
entityType,
|
|
32
|
+
id: options?.id,
|
|
33
|
+
message: options?.message,
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ISODateString } from '@coast/core-types/common/ISODateString';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Conversions between a DTO `Date` and the `ISODateString` stored in a JSON column.
|
|
5
|
+
*
|
|
6
|
+
* A JSON column is unvalidated, so a field typed `Date` may hold any string a past write left
|
|
7
|
+
* there. Neither direction throws and neither normalizes: an unparseable value is carried through
|
|
8
|
+
* unchanged in both directions, so a read-modify-write writes the original bytes back. The cast is
|
|
9
|
+
* the cost — an unparseable stored value surfaces as a string typed `Date`, exactly as every
|
|
10
|
+
* strangler-read date does today — and it is confined to this class.
|
|
11
|
+
*/
|
|
12
|
+
export class ISODateStringUtils {
|
|
13
|
+
public static fromDate(value: Date): ISODateString {
|
|
14
|
+
const parsed = new Date(value);
|
|
15
|
+
|
|
16
|
+
return Number.isNaN(parsed.getTime()) ? (value as unknown as ISODateString) : ISODateString(parsed.toISOString());
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public static toDate(value: ISODateString): Date {
|
|
20
|
+
const parsed = new Date(value);
|
|
21
|
+
|
|
22
|
+
return Number.isNaN(parsed.getTime()) ? (value as unknown as Date) : parsed;
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/JsonPath.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export class JsonPath {
|
|
2
|
+
public constructor(public readonly value: string) {}
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Converts a dot-notation path string into a properly formatted JsonPath.
|
|
6
|
+
* Handles paths that may need bracket notation for special characters or numbers.
|
|
7
|
+
* Produces RFC 9535 compliant JSONPath syntax.
|
|
8
|
+
*/
|
|
9
|
+
public static fromString(path: string): JsonPath {
|
|
10
|
+
if (path.startsWith('$')) {
|
|
11
|
+
return new JsonPath(path);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const segments = path.split('.');
|
|
15
|
+
|
|
16
|
+
const formattedPath = segments
|
|
17
|
+
.map((segment, index) => {
|
|
18
|
+
const isFirstSegment = index === 0;
|
|
19
|
+
const requiresBrackets = this.needsBracketNotation(segment);
|
|
20
|
+
|
|
21
|
+
if (isFirstSegment) {
|
|
22
|
+
return requiresBrackets ? `$['${segment}']` : `$.${segment}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return requiresBrackets ? `['${segment}']` : `.${segment}`;
|
|
26
|
+
})
|
|
27
|
+
.join('');
|
|
28
|
+
|
|
29
|
+
return new JsonPath(formattedPath);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Determines if a path segment requires bracket notation.
|
|
34
|
+
* Returns true if the segment:
|
|
35
|
+
* 1. Starts with a number
|
|
36
|
+
* 2. Contains special characters (anything other than alphanumeric and underscore)
|
|
37
|
+
*
|
|
38
|
+
* Note: UUIDs are automatically handled by condition #2 since they contain hyphens.
|
|
39
|
+
*/
|
|
40
|
+
private static needsBracketNotation(segment: string): boolean {
|
|
41
|
+
return /^\d/.test(segment) || /\W/.test(segment);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Appends a path to the current path.
|
|
46
|
+
* If a string is provided, it will be converted to a JsonPath first.
|
|
47
|
+
*/
|
|
48
|
+
public appendPath(path: JsonPath | string): JsonPath {
|
|
49
|
+
const pathToAppend = path instanceof JsonPath ? path : JsonPath.fromString(path);
|
|
50
|
+
const appendValue = pathToAppend.value.replace('$', '');
|
|
51
|
+
|
|
52
|
+
return new JsonPath(`${this.value}${appendValue}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public toString(): string {
|
|
56
|
+
return this.value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { EntityType } from '@coast/core-types/common/EntityType';
|
|
2
|
-
import { EntityTypeLabels } from '@coast/core-types/common/EntityTypeLabels';
|
|
3
1
|
import { AssertionFailedException } from '@coast/core-types/exception/AssertionFailedException';
|
|
4
2
|
import { CoastException } from '@coast/core-types/exception/CoastException';
|
|
5
|
-
import { InvalidEntityReferenceException } from '@coast/core-types/exception/InvalidEntityReferenceException';
|
|
6
3
|
import { NotDefinedException } from '@coast/core-types/exception/NotDefinedException';
|
|
7
4
|
import { assertType } from '@coast/service-common/types/assertType';
|
|
8
5
|
import { Equals } from '@coast/service-common/types/Equals';
|
|
@@ -95,49 +92,4 @@ describe('AssertionUtils', () => {
|
|
|
95
92
|
assertType<Equals<typeof x, string>>();
|
|
96
93
|
});
|
|
97
94
|
});
|
|
98
|
-
|
|
99
|
-
describe('assertValidEntityReference', () => {
|
|
100
|
-
it('should throw if value is not defined', () => {
|
|
101
|
-
const x = undefined as object | undefined;
|
|
102
|
-
try {
|
|
103
|
-
AssertionUtils.assertValidEntityReference(x, EntityType.WORKFLOW_ENTITY);
|
|
104
|
-
} catch (error) {
|
|
105
|
-
expect(error).toBeInstanceOf(InvalidEntityReferenceException);
|
|
106
|
-
|
|
107
|
-
safeExpect((error as InvalidEntityReferenceException).message).toEqual(
|
|
108
|
-
`Invalid entity reference: ${EntityTypeLabels[EntityType.WORKFLOW_ENTITY]} not found`
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
safeExpect((error as InvalidEntityReferenceException).additionalData).toMatchObject({
|
|
112
|
-
entityType: EntityType.WORKFLOW_ENTITY,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('should use custom error message', () => {
|
|
118
|
-
const x = undefined as object | undefined;
|
|
119
|
-
try {
|
|
120
|
-
AssertionUtils.assertValidEntityReference(x, EntityType.WORKFLOW_ENTITY, {
|
|
121
|
-
message: 'x should exist...',
|
|
122
|
-
id: 'abc-123',
|
|
123
|
-
});
|
|
124
|
-
} catch (error) {
|
|
125
|
-
expect(error).toBeInstanceOf(InvalidEntityReferenceException);
|
|
126
|
-
safeExpect((error as InvalidEntityReferenceException).message).toEqual('x should exist...');
|
|
127
|
-
|
|
128
|
-
safeExpect((error as InvalidEntityReferenceException).additionalData).toMatchObject({
|
|
129
|
-
entityType: EntityType.WORKFLOW_ENTITY,
|
|
130
|
-
id: 'abc-123',
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('should not throw and should type narrow if value is defined', () => {
|
|
136
|
-
const x = { id: 'abc' } as object | undefined;
|
|
137
|
-
assertType<Equals<typeof x, object | undefined>>();
|
|
138
|
-
|
|
139
|
-
AssertionUtils.assertValidEntityReference(x, EntityType.COMPONENT);
|
|
140
|
-
assertType<Equals<typeof x, object>>();
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
95
|
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { safeExpect } from '@paradoxical-io/common-test';
|
|
2
|
+
|
|
3
|
+
import { CompactSet } from '../CompactSet';
|
|
4
|
+
|
|
5
|
+
describe('CompactSet', () => {
|
|
6
|
+
it('adds values', () => {
|
|
7
|
+
const set = new CompactSet();
|
|
8
|
+
set.add(1).add(null).add(undefined);
|
|
9
|
+
safeExpect(set.values().next().value).toEqual(1);
|
|
10
|
+
safeExpect(set.keys().next().value).toEqual(1);
|
|
11
|
+
safeExpect(set.size).toEqual(1);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('does not add null', () => {
|
|
15
|
+
const set = new CompactSet();
|
|
16
|
+
set.add(null);
|
|
17
|
+
safeExpect(set.values().next().done).toEqual(true);
|
|
18
|
+
safeExpect(set.keys().next().done).toEqual(true);
|
|
19
|
+
safeExpect(set.size).toEqual(0);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('does not add undefined', () => {
|
|
23
|
+
const set = new CompactSet();
|
|
24
|
+
set.add(undefined);
|
|
25
|
+
safeExpect(set.values().next().done).toEqual(true);
|
|
26
|
+
safeExpect(set.keys().next().done).toEqual(true);
|
|
27
|
+
safeExpect(set.size).toEqual(0);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('adds a value via the constructor iterable', () => {
|
|
31
|
+
const seedSet = new Set([1]);
|
|
32
|
+
const set = new CompactSet(seedSet);
|
|
33
|
+
safeExpect(set.values().next().value).toEqual(1);
|
|
34
|
+
safeExpect(set.keys().next().value).toEqual(1);
|
|
35
|
+
safeExpect(set.size).toEqual(1);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('adds a value via the constructor array', () => {
|
|
39
|
+
const set = new CompactSet([1]);
|
|
40
|
+
safeExpect(set.values().next().value).toEqual(1);
|
|
41
|
+
safeExpect(set.keys().next().value).toEqual(1);
|
|
42
|
+
safeExpect(set.size).toEqual(1);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('does not add a null value via the constructor iterable', () => {
|
|
46
|
+
const seedSet = new Set([1, null, 2]);
|
|
47
|
+
const set = new CompactSet(seedSet);
|
|
48
|
+
const iterator = set.values();
|
|
49
|
+
safeExpect(iterator.next().value).toEqual(1);
|
|
50
|
+
safeExpect(iterator.next().value).toEqual(2);
|
|
51
|
+
safeExpect(set.size).toEqual(2);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('does not add an undefined value via the constructor iterable', () => {
|
|
55
|
+
const seedSet = new Set([1, undefined, 2]);
|
|
56
|
+
const set = new CompactSet(seedSet);
|
|
57
|
+
const iterator = set.values();
|
|
58
|
+
safeExpect(iterator.next().value).toEqual(1);
|
|
59
|
+
safeExpect(iterator.next().value).toEqual(2);
|
|
60
|
+
safeExpect(set.size).toEqual(2);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('does not add a null value via the constructor array', () => {
|
|
64
|
+
const set = new CompactSet([1, null, 2]);
|
|
65
|
+
const iterator = set.values();
|
|
66
|
+
safeExpect(iterator.next().value).toEqual(1);
|
|
67
|
+
safeExpect(iterator.next().value).toEqual(2);
|
|
68
|
+
safeExpect(set.size).toEqual(2);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('does not add an undefined value via the constructor array', () => {
|
|
72
|
+
const set = new CompactSet([1, undefined, 2]);
|
|
73
|
+
const iterator = set.values();
|
|
74
|
+
safeExpect(iterator.next().value).toEqual(1);
|
|
75
|
+
safeExpect(iterator.next().value).toEqual(2);
|
|
76
|
+
safeExpect(set.size).toEqual(2);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('addAll adds many values', () => {
|
|
80
|
+
const set = new CompactSet();
|
|
81
|
+
set.addAll([1, 2, null, undefined, 3]);
|
|
82
|
+
const iterator = set.values();
|
|
83
|
+
safeExpect(iterator.next().value).toEqual(1);
|
|
84
|
+
safeExpect(iterator.next().value).toEqual(2);
|
|
85
|
+
safeExpect(iterator.next().value).toEqual(3);
|
|
86
|
+
safeExpect(set.size).toEqual(3);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('addAll handles undefined', () => {
|
|
90
|
+
const set = new CompactSet();
|
|
91
|
+
set.addAll(undefined);
|
|
92
|
+
safeExpect(set.size).toEqual(0);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('addAll handles null arrays', () => {
|
|
96
|
+
const set = new CompactSet();
|
|
97
|
+
set.addAll(null);
|
|
98
|
+
safeExpect(set.size).toEqual(0);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('addAll handles empty arrays', () => {
|
|
102
|
+
const set = new CompactSet();
|
|
103
|
+
set.addAll([]);
|
|
104
|
+
safeExpect(set.size).toEqual(0);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { EntityType } from '@coast/core-types/common/EntityType';
|
|
2
|
+
import { ViewTemplateId } from '@coast/core-types/view-template/ViewTemplateId';
|
|
3
|
+
import { WorkflowTemplateId } from '@coast/core-types/workflow-template/WorkflowTemplateId';
|
|
4
|
+
import { CoastLogger } from '@coast/service-common/logger/CoastLogger';
|
|
5
|
+
import { safeExpect } from '@paradoxical-io/common-test';
|
|
6
|
+
|
|
7
|
+
import { EntityRehydrator } from '../EntityRehydrator';
|
|
8
|
+
|
|
9
|
+
describe('EntityRehydrator', () => {
|
|
10
|
+
function mockLogger(): { logger: CoastLogger; warn: jest.Mock } {
|
|
11
|
+
const warn = jest.fn();
|
|
12
|
+
|
|
13
|
+
return { logger: { warn } as unknown as CoastLogger, warn };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('require', () => {
|
|
17
|
+
it('returns a stored property that is present', () => {
|
|
18
|
+
const { logger, warn } = mockLogger();
|
|
19
|
+
const rehydrator = new EntityRehydrator(EntityType.WORKFLOW_TEMPLATE, logger);
|
|
20
|
+
|
|
21
|
+
safeExpect(
|
|
22
|
+
rehydrator.require({ id: WorkflowTemplateId('wft-1'), parentTemplateId: 'wft-owner' }, 'parentTemplateId')
|
|
23
|
+
).toEqual('wft-owner');
|
|
24
|
+
|
|
25
|
+
expect(warn).not.toHaveBeenCalled();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('returns the missing property rather than throwing, and warns', () => {
|
|
29
|
+
const { logger, warn } = mockLogger();
|
|
30
|
+
const rehydrator = new EntityRehydrator(EntityType.WORKFLOW_TEMPLATE, logger);
|
|
31
|
+
|
|
32
|
+
safeExpect(
|
|
33
|
+
rehydrator.require({ id: WorkflowTemplateId('wft-1'), parentTemplateId: null }, 'parentTemplateId')
|
|
34
|
+
).toBeNull();
|
|
35
|
+
|
|
36
|
+
expect(warn).toHaveBeenCalledTimes(1);
|
|
37
|
+
|
|
38
|
+
expect(warn).toHaveBeenCalledWith(
|
|
39
|
+
expect.objectContaining({
|
|
40
|
+
msg: 'Workflow Template is missing required property parentTemplateId',
|
|
41
|
+
event: EntityRehydrator.MISSING_REQUIRED_PROPERTY,
|
|
42
|
+
entityType: EntityType.WORKFLOW_TEMPLATE,
|
|
43
|
+
id: 'wft-1',
|
|
44
|
+
propertyName: 'parentTemplateId',
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('labels the warning with the entity type it was built for', () => {
|
|
50
|
+
const { logger, warn } = mockLogger();
|
|
51
|
+
|
|
52
|
+
new EntityRehydrator(EntityType.VIEW_TEMPLATE, logger).require(
|
|
53
|
+
{ id: ViewTemplateId('vt-1'), name: undefined },
|
|
54
|
+
'name'
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(warn).toHaveBeenCalledWith(
|
|
58
|
+
expect.objectContaining({
|
|
59
|
+
msg: 'View Template is missing required property name',
|
|
60
|
+
entityType: EntityType.VIEW_TEMPLATE,
|
|
61
|
+
id: 'vt-1',
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('completes without a logger', () => {
|
|
67
|
+
const rehydrator = new EntityRehydrator(EntityType.WORKFLOW_TEMPLATE);
|
|
68
|
+
|
|
69
|
+
safeExpect(
|
|
70
|
+
rehydrator.require({ id: WorkflowTemplateId('wft-1'), parentTemplateId: undefined }, 'parentTemplateId')
|
|
71
|
+
).toBeUndefined();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { EntityType } from '@coast/core-types/common/EntityType';
|
|
2
|
+
import { EntityTypeLabels } from '@coast/core-types/common/EntityTypeLabels';
|
|
3
|
+
import { InvalidEntityReferenceException } from '@coast/core-types/exception/InvalidEntityReferenceException';
|
|
4
|
+
import { NotFoundException } from '@coast/core-types/exception/NotFoundException';
|
|
5
|
+
import { assertType } from '@coast/service-common/types/assertType';
|
|
6
|
+
import { Equals } from '@coast/service-common/types/Equals';
|
|
7
|
+
import { safeExpect } from '@paradoxical-io/common-test';
|
|
8
|
+
|
|
9
|
+
import { EntityUtils } from '../EntityUtils';
|
|
10
|
+
|
|
11
|
+
describe('EntityUtils', () => {
|
|
12
|
+
describe('assertValidEntityReference', () => {
|
|
13
|
+
it('should throw if value is not defined', () => {
|
|
14
|
+
const x = undefined as object | undefined;
|
|
15
|
+
try {
|
|
16
|
+
EntityUtils.assertValidEntityReference(x, EntityType.WORKFLOW_ENTITY);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
expect(error).toBeInstanceOf(InvalidEntityReferenceException);
|
|
19
|
+
|
|
20
|
+
safeExpect((error as InvalidEntityReferenceException).message).toEqual(
|
|
21
|
+
`Invalid entity reference: ${EntityTypeLabels[EntityType.WORKFLOW_ENTITY]} not found`
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
safeExpect((error as InvalidEntityReferenceException).additionalData).toMatchObject({
|
|
25
|
+
entityType: EntityType.WORKFLOW_ENTITY,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should use custom error message', () => {
|
|
31
|
+
const x = undefined as object | undefined;
|
|
32
|
+
try {
|
|
33
|
+
EntityUtils.assertValidEntityReference(x, EntityType.WORKFLOW_ENTITY, {
|
|
34
|
+
message: 'x should exist...',
|
|
35
|
+
id: 'abc-123',
|
|
36
|
+
});
|
|
37
|
+
} catch (error) {
|
|
38
|
+
expect(error).toBeInstanceOf(InvalidEntityReferenceException);
|
|
39
|
+
safeExpect((error as InvalidEntityReferenceException).message).toEqual('x should exist...');
|
|
40
|
+
|
|
41
|
+
safeExpect((error as InvalidEntityReferenceException).additionalData).toMatchObject({
|
|
42
|
+
entityType: EntityType.WORKFLOW_ENTITY,
|
|
43
|
+
id: 'abc-123',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should not throw and should type narrow if value is defined', () => {
|
|
49
|
+
const x = { id: 'abc' } as object | undefined;
|
|
50
|
+
assertType<Equals<typeof x, object | undefined>>();
|
|
51
|
+
|
|
52
|
+
EntityUtils.assertValidEntityReference(x, EntityType.COMPONENT);
|
|
53
|
+
assertType<Equals<typeof x, object>>();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('assertEntityFound', () => {
|
|
58
|
+
it('should throw if value is not defined', () => {
|
|
59
|
+
const x = undefined as object | undefined;
|
|
60
|
+
try {
|
|
61
|
+
EntityUtils.assertEntityFound(x, EntityType.WORKFLOW_ENTITY);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
expect(error).toBeInstanceOf(NotFoundException);
|
|
64
|
+
|
|
65
|
+
safeExpect((error as NotFoundException).additionalData).toMatchObject({
|
|
66
|
+
entityType: EntityType.WORKFLOW_ENTITY,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should use custom error message', () => {
|
|
72
|
+
const x = undefined as object | undefined;
|
|
73
|
+
try {
|
|
74
|
+
EntityUtils.assertEntityFound(x, EntityType.WORKFLOW_ENTITY, {
|
|
75
|
+
message: 'x should exist...',
|
|
76
|
+
id: 'abc-123',
|
|
77
|
+
});
|
|
78
|
+
} catch (error) {
|
|
79
|
+
expect(error).toBeInstanceOf(NotFoundException);
|
|
80
|
+
safeExpect((error as NotFoundException).message).toEqual('x should exist...');
|
|
81
|
+
|
|
82
|
+
safeExpect((error as NotFoundException).additionalData).toMatchObject({
|
|
83
|
+
entityType: EntityType.WORKFLOW_ENTITY,
|
|
84
|
+
id: 'abc-123',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should not throw and should type narrow if value is defined', () => {
|
|
90
|
+
const x = { id: 'abc' } as object | undefined;
|
|
91
|
+
assertType<Equals<typeof x, object | undefined>>();
|
|
92
|
+
|
|
93
|
+
EntityUtils.assertEntityFound(x, EntityType.COMPONENT);
|
|
94
|
+
assertType<Equals<typeof x, object>>();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|