@expo/entity 0.16.0 → 0.20.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.
- package/build/EnforcingEntityLoader.js +2 -2
- package/build/EnforcingEntityLoader.js.map +1 -1
- package/build/Entity.js +8 -2
- package/build/Entity.js.map +1 -1
- package/build/EntityAssociationLoader.js +3 -3
- package/build/EntityAssociationLoader.js.map +1 -1
- package/build/EntityCompanion.d.ts +5 -0
- package/build/EntityCompanion.js +8 -1
- package/build/EntityCompanion.js.map +1 -1
- package/build/EntityCompanionProvider.d.ts +1 -1
- package/build/EntityCompanionProvider.js +5 -5
- package/build/EntityCompanionProvider.js.map +1 -1
- package/build/EntityConfiguration.d.ts +1 -1
- package/build/EntityConfiguration.js +3 -3
- package/build/EntityConfiguration.js.map +1 -1
- package/build/EntityDatabaseAdapter.d.ts +4 -4
- package/build/EntityDatabaseAdapter.js +13 -13
- package/build/EntityDatabaseAdapter.js.map +1 -1
- package/build/EntityFieldDefinition.d.ts +77 -0
- package/build/EntityFieldDefinition.js +53 -0
- package/build/EntityFieldDefinition.js.map +1 -0
- package/build/EntityFields.d.ts +5 -78
- package/build/EntityFields.js +19 -61
- package/build/EntityFields.js.map +1 -1
- package/build/EntityLoader.d.ts +3 -1
- package/build/EntityLoader.js +19 -15
- package/build/EntityLoader.js.map +1 -1
- package/build/EntityLoaderFactory.d.ts +3 -1
- package/build/EntityLoaderFactory.js +3 -2
- package/build/EntityLoaderFactory.js.map +1 -1
- package/build/EntityMutationInfo.d.ts +26 -0
- package/build/EntityMutationInfo.js +10 -0
- package/build/EntityMutationInfo.js.map +1 -0
- package/build/EntityMutationTriggerConfiguration.d.ts +4 -4
- package/build/EntityMutationValidator.d.ts +3 -3
- package/build/EntityMutationValidator.js.map +1 -1
- package/build/EntityMutator.d.ts +5 -16
- package/build/EntityMutator.js +62 -58
- package/build/EntityMutator.js.map +1 -1
- package/build/EntityPrivacyPolicy.d.ts +5 -4
- package/build/EntityPrivacyPolicy.js +60 -12
- package/build/EntityPrivacyPolicy.js.map +1 -1
- package/build/EntityQueryContext.d.ts +13 -0
- package/build/EntityQueryContext.js +18 -0
- package/build/EntityQueryContext.js.map +1 -1
- package/build/EntitySecondaryCacheLoader.js +2 -2
- package/build/EntitySecondaryCacheLoader.js.map +1 -1
- package/build/ReadonlyEntity.js +3 -4
- package/build/ReadonlyEntity.js.map +1 -1
- package/build/ViewerScopedEntityCompanion.d.ts +5 -0
- package/build/ViewerScopedEntityCompanion.js +6 -0
- package/build/ViewerScopedEntityCompanion.js.map +1 -1
- package/build/__tests__/EnforcingEntityLoader-test.js +82 -82
- package/build/__tests__/EnforcingEntityLoader-test.js.map +1 -1
- package/build/__tests__/Entity-test.js +6 -6
- package/build/__tests__/Entity-test.js.map +1 -1
- package/build/__tests__/EntityAssociationLoader-test.js +40 -40
- package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
- package/build/__tests__/EntityCommonUseCases-test.js +11 -11
- package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
- package/build/__tests__/EntityCompanion-test.js +3 -3
- package/build/__tests__/EntityCompanion-test.js.map +1 -1
- package/build/__tests__/EntityCompanionProvider-test.js +1 -1
- package/build/__tests__/EntityCompanionProvider-test.js.map +1 -1
- package/build/__tests__/EntityDatabaseAdapter-test.js +12 -12
- package/build/__tests__/EntityDatabaseAdapter-test.js.map +1 -1
- package/build/__tests__/EntityEdges-test.js +103 -6
- package/build/__tests__/EntityEdges-test.js.map +1 -1
- package/build/__tests__/EntityFields-test.js +18 -26
- package/build/__tests__/EntityFields-test.js.map +1 -1
- package/build/__tests__/EntityLoader-constructor-test.d.ts +22 -0
- package/build/__tests__/EntityLoader-constructor-test.js +111 -0
- package/build/__tests__/EntityLoader-constructor-test.js.map +1 -0
- package/build/__tests__/EntityLoader-test.js +81 -73
- package/build/__tests__/EntityLoader-test.js.map +1 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.d.ts +1 -0
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +81 -0
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -0
- package/build/__tests__/EntityMutator-test.js +138 -136
- package/build/__tests__/EntityMutator-test.js.map +1 -1
- package/build/__tests__/EntityPrivacyPolicy-test.js +143 -67
- package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
- package/build/__tests__/EntitySecondaryCacheLoader-test.js +15 -15
- package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
- package/build/__tests__/EntitySelfReferentialEdges-test.js +13 -12
- package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
- package/build/__tests__/ReadonlyEntity-test.js +12 -12
- package/build/__tests__/ReadonlyEntity-test.js.map +1 -1
- package/build/__tests__/ViewerContext-test.js +2 -2
- package/build/__tests__/ViewerContext-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityCompanion-test.js +2 -2
- package/build/__tests__/ViewerScopedEntityCompanion-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js +2 -2
- package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +5 -5
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +5 -5
- package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +5 -5
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +2 -2
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +1 -1
- package/build/__tests__/entityUtils-test.js +21 -21
- package/build/__tests__/entityUtils-test.js.map +1 -1
- package/build/index.d.ts +3 -0
- package/build/index.js +5 -1
- package/build/index.js.map +1 -1
- package/build/internal/EntityDataManager.js +8 -7
- package/build/internal/EntityDataManager.js.map +1 -1
- package/build/internal/EntityFieldTransformationUtils.js +2 -2
- package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
- package/build/internal/ReadThroughEntityCache.js +4 -4
- package/build/internal/ReadThroughEntityCache.js.map +1 -1
- package/build/internal/__tests__/EntityDataManager-test.js +21 -21
- package/build/internal/__tests__/EntityDataManager-test.js.map +1 -1
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +8 -8
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +1 -1
- package/build/internal/__tests__/ReadThroughEntityCache-test.js +48 -48
- package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
- package/build/metrics/EntityMetricsUtils.js +1 -1
- package/build/metrics/EntityMetricsUtils.js.map +1 -1
- package/build/metrics/IEntityMetricsAdapter.d.ts +16 -0
- package/build/metrics/IEntityMetricsAdapter.js +6 -1
- package/build/metrics/IEntityMetricsAdapter.js.map +1 -1
- package/build/metrics/NoOpEntityMetricsAdapter.d.ts +2 -1
- package/build/metrics/NoOpEntityMetricsAdapter.js +1 -0
- package/build/metrics/NoOpEntityMetricsAdapter.js.map +1 -1
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +4 -4
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +4 -4
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +4 -4
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
- package/build/testfixtures/DateIDTestEntity.js.map +1 -1
- package/build/testfixtures/SimpleTestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity.d.ts +6 -6
- package/build/testfixtures/TestEntity.js +4 -4
- package/build/testfixtures/TestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity2.d.ts +5 -5
- package/build/testfixtures/TestEntity2.js.map +1 -1
- package/build/testfixtures/TestEntityNumberKey.js +1 -1
- package/build/testfixtures/TestEntityNumberKey.js.map +1 -1
- package/build/utils/collections/__tests__/maps-test.js +13 -13
- package/build/utils/collections/__tests__/maps-test.js.map +1 -1
- package/build/utils/collections/maps.js +1 -1
- package/build/utils/collections/maps.js.map +1 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +6 -6
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +1 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
- package/build/utils/testing/StubCacheAdapter.js +1 -1
- package/build/utils/testing/StubCacheAdapter.js.map +1 -1
- package/build/utils/testing/StubDatabaseAdapter.js +7 -7
- package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +26 -26
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +1 -1
- package/build/utils/testing/describeFieldTestCase.d.ts +2 -0
- package/build/utils/testing/describeFieldTestCase.js +18 -0
- package/build/utils/testing/describeFieldTestCase.js.map +1 -0
- package/package.json +2 -1
- package/src/Entity.ts +10 -2
- package/src/EntityAssociationLoader.ts +1 -1
- package/src/EntityCompanion.ts +10 -2
- package/src/EntityCompanionProvider.ts +5 -9
- package/src/EntityConfiguration.ts +1 -1
- package/src/EntityDatabaseAdapter.ts +10 -8
- package/src/EntityFieldDefinition.ts +124 -0
- package/src/EntityFields.ts +11 -126
- package/src/EntityLoader.ts +12 -4
- package/src/EntityLoaderFactory.ts +5 -2
- package/src/EntityMutationInfo.ts +47 -0
- package/src/EntityMutationTriggerConfiguration.ts +5 -5
- package/src/EntityMutationValidator.ts +10 -4
- package/src/EntityMutator.ts +98 -76
- package/src/EntityPrivacyPolicy.ts +77 -19
- package/src/EntityQueryContext.ts +20 -0
- package/src/ReadonlyEntity.ts +3 -2
- package/src/ViewerScopedEntityCompanion.ts +8 -0
- package/src/__tests__/Entity-test.ts +8 -8
- package/src/__tests__/EntityCommonUseCases-test.ts +4 -4
- package/src/__tests__/EntityEdges-test.ts +169 -14
- package/src/__tests__/EntityFields-test.ts +6 -23
- package/src/__tests__/EntityLoader-constructor-test.ts +177 -0
- package/src/__tests__/EntityLoader-test.ts +48 -20
- package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +105 -0
- package/src/__tests__/EntityMutator-test.ts +153 -146
- package/src/__tests__/EntityPrivacyPolicy-test.ts +215 -78
- package/src/__tests__/EntitySecondaryCacheLoader-test.ts +7 -9
- package/src/__tests__/EntitySelfReferentialEdges-test.ts +6 -5
- package/src/__tests__/ReadonlyEntity-test.ts +1 -1
- package/src/__tests__/ViewerContext-test.ts +7 -6
- package/src/__tests__/ViewerScopedEntityCompanion-test.ts +11 -10
- package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +4 -3
- package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +6 -6
- package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +4 -4
- package/src/index.ts +3 -0
- package/src/internal/EntityDataManager.ts +2 -1
- package/src/internal/__tests__/EntityDataManager-test.ts +6 -6
- package/src/internal/__tests__/ReadThroughEntityCache-test.ts +15 -13
- package/src/metrics/EntityMetricsUtils.ts +56 -50
- package/src/metrics/IEntityMetricsAdapter.ts +23 -0
- package/src/metrics/NoOpEntityMetricsAdapter.ts +2 -0
- package/src/testfixtures/DateIDTestEntity.ts +4 -4
- package/src/testfixtures/SimpleTestEntity.ts +4 -4
- package/src/testfixtures/TestEntity.ts +8 -8
- package/src/testfixtures/TestEntity2.ts +4 -4
- package/src/testfixtures/TestEntityNumberKey.ts +6 -6
- package/src/utils/testing/StubDatabaseAdapter.ts +4 -4
- package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +18 -18
- package/src/utils/testing/describeFieldTestCase.ts +21 -0
- package/CHANGELOG.md +0 -241
|
@@ -102,7 +102,7 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
102
102
|
ViewerContext,
|
|
103
103
|
SimpleTestDenyUpdateEntity
|
|
104
104
|
> {
|
|
105
|
-
protected readonly readRules = [
|
|
105
|
+
protected override readonly readRules = [
|
|
106
106
|
new AlwaysAllowPrivacyPolicyRule<
|
|
107
107
|
TestEntityFields,
|
|
108
108
|
string,
|
|
@@ -110,7 +110,7 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
110
110
|
SimpleTestDenyUpdateEntity
|
|
111
111
|
>(),
|
|
112
112
|
];
|
|
113
|
-
protected readonly createRules = [
|
|
113
|
+
protected override readonly createRules = [
|
|
114
114
|
new AlwaysAllowPrivacyPolicyRule<
|
|
115
115
|
TestEntityFields,
|
|
116
116
|
string,
|
|
@@ -118,7 +118,7 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
118
118
|
SimpleTestDenyUpdateEntity
|
|
119
119
|
>(),
|
|
120
120
|
];
|
|
121
|
-
protected readonly updateRules = [
|
|
121
|
+
protected override readonly updateRules = [
|
|
122
122
|
new AlwaysDenyPrivacyPolicyRule<
|
|
123
123
|
TestEntityFields,
|
|
124
124
|
string,
|
|
@@ -126,7 +126,7 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
126
126
|
SimpleTestDenyUpdateEntity
|
|
127
127
|
>(),
|
|
128
128
|
];
|
|
129
|
-
protected readonly deleteRules = [
|
|
129
|
+
protected override readonly deleteRules = [
|
|
130
130
|
new AlwaysAllowPrivacyPolicyRule<
|
|
131
131
|
TestEntityFields,
|
|
132
132
|
string,
|
|
@@ -142,7 +142,7 @@ class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
142
142
|
ViewerContext,
|
|
143
143
|
SimpleTestDenyDeleteEntity
|
|
144
144
|
> {
|
|
145
|
-
protected readonly readRules = [
|
|
145
|
+
protected override readonly readRules = [
|
|
146
146
|
new AlwaysAllowPrivacyPolicyRule<
|
|
147
147
|
TestEntityFields,
|
|
148
148
|
string,
|
|
@@ -150,7 +150,7 @@ class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
150
150
|
SimpleTestDenyDeleteEntity
|
|
151
151
|
>(),
|
|
152
152
|
];
|
|
153
|
-
protected readonly createRules = [
|
|
153
|
+
protected override readonly createRules = [
|
|
154
154
|
new AlwaysAllowPrivacyPolicyRule<
|
|
155
155
|
TestEntityFields,
|
|
156
156
|
string,
|
|
@@ -158,7 +158,7 @@ class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
158
158
|
SimpleTestDenyDeleteEntity
|
|
159
159
|
>(),
|
|
160
160
|
];
|
|
161
|
-
protected readonly updateRules = [
|
|
161
|
+
protected override readonly updateRules = [
|
|
162
162
|
new AlwaysAllowPrivacyPolicyRule<
|
|
163
163
|
TestEntityFields,
|
|
164
164
|
string,
|
|
@@ -166,7 +166,7 @@ class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
166
166
|
SimpleTestDenyDeleteEntity
|
|
167
167
|
>(),
|
|
168
168
|
];
|
|
169
|
-
protected readonly deleteRules = [
|
|
169
|
+
protected override readonly deleteRules = [
|
|
170
170
|
new AlwaysDenyPrivacyPolicyRule<
|
|
171
171
|
TestEntityFields,
|
|
172
172
|
string,
|
|
@@ -66,19 +66,19 @@ class BlahEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
66
66
|
ViewerContext,
|
|
67
67
|
BlahEntity
|
|
68
68
|
> {
|
|
69
|
-
protected readonly createRules = [
|
|
69
|
+
protected override readonly createRules = [
|
|
70
70
|
new DenyIfNotOwnerPrivacyPolicyRule(),
|
|
71
71
|
new AlwaysAllowPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
72
72
|
];
|
|
73
|
-
protected readonly readRules = [
|
|
73
|
+
protected override readonly readRules = [
|
|
74
74
|
new DenyIfNotOwnerPrivacyPolicyRule(),
|
|
75
75
|
new AlwaysAllowPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
76
76
|
];
|
|
77
|
-
protected readonly updateRules = [
|
|
77
|
+
protected override readonly updateRules = [
|
|
78
78
|
new DenyIfNotOwnerPrivacyPolicyRule(),
|
|
79
79
|
new AlwaysAllowPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
80
80
|
];
|
|
81
|
-
protected readonly deleteRules = [
|
|
81
|
+
protected override readonly deleteRules = [
|
|
82
82
|
new AlwaysDenyPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
83
83
|
];
|
|
84
84
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import Entity from '../Entity';
|
|
2
2
|
import { EntityCompanionDefinition } from '../EntityCompanionProvider';
|
|
3
3
|
import EntityConfiguration from '../EntityConfiguration';
|
|
4
|
-
import {
|
|
4
|
+
import { EntityEdgeDeletionBehavior } from '../EntityFieldDefinition';
|
|
5
|
+
import { UUIDField } from '../EntityFields';
|
|
6
|
+
import { EntityTriggerMutationInfo, EntityMutationType } from '../EntityMutationInfo';
|
|
7
|
+
import { EntityMutationTrigger } from '../EntityMutationTriggerConfiguration';
|
|
5
8
|
import EntityPrivacyPolicy from '../EntityPrivacyPolicy';
|
|
9
|
+
import { EntityTransactionalQueryContext } from '../EntityQueryContext';
|
|
6
10
|
import { CacheStatus } from '../internal/ReadThroughEntityCache';
|
|
7
11
|
import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule';
|
|
8
12
|
import TestViewerContext from '../testfixtures/TestViewerContext';
|
|
@@ -30,22 +34,141 @@ class TestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
30
34
|
any,
|
|
31
35
|
any
|
|
32
36
|
> {
|
|
33
|
-
protected readonly readRules = [
|
|
37
|
+
protected override readonly readRules = [
|
|
34
38
|
new AlwaysAllowPrivacyPolicyRule<any, string, TestViewerContext, any, any>(),
|
|
35
39
|
];
|
|
36
|
-
protected readonly createRules = [
|
|
40
|
+
protected override readonly createRules = [
|
|
37
41
|
new AlwaysAllowPrivacyPolicyRule<any, string, TestViewerContext, any, any>(),
|
|
38
42
|
];
|
|
39
|
-
protected readonly updateRules = [
|
|
43
|
+
protected override readonly updateRules = [
|
|
40
44
|
new AlwaysAllowPrivacyPolicyRule<any, string, TestViewerContext, any, any>(),
|
|
41
45
|
];
|
|
42
|
-
protected readonly deleteRules = [
|
|
46
|
+
protected override readonly deleteRules = [
|
|
43
47
|
new AlwaysAllowPrivacyPolicyRule<any, string, TestViewerContext, any, any>(),
|
|
44
48
|
];
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
48
52
|
const makeEntityClasses = (edgeDeletionBehavior: EntityEdgeDeletionBehavior) => {
|
|
53
|
+
const triggerExecutionCounts = {
|
|
54
|
+
parent: 0,
|
|
55
|
+
child: 0,
|
|
56
|
+
grandchild: 0,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
class ParentCheckInfoTrigger extends EntityMutationTrigger<
|
|
60
|
+
ParentFields,
|
|
61
|
+
string,
|
|
62
|
+
TestViewerContext,
|
|
63
|
+
ParentEntity
|
|
64
|
+
> {
|
|
65
|
+
async executeAsync(
|
|
66
|
+
_viewerContext: TestViewerContext,
|
|
67
|
+
_queryContext: EntityTransactionalQueryContext,
|
|
68
|
+
_entity: ParentEntity,
|
|
69
|
+
mutationInfo: EntityTriggerMutationInfo<ParentFields, string, TestViewerContext, ParentEntity>
|
|
70
|
+
): Promise<void> {
|
|
71
|
+
if (mutationInfo.type !== EntityMutationType.DELETE) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (mutationInfo.cascadingDeleteCause !== null) {
|
|
76
|
+
throw new Error('Parent entity should not have casade delete cause');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
triggerExecutionCounts.parent++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
class ChildCheckInfoTrigger extends EntityMutationTrigger<
|
|
84
|
+
ChildFields,
|
|
85
|
+
string,
|
|
86
|
+
TestViewerContext,
|
|
87
|
+
ChildEntity
|
|
88
|
+
> {
|
|
89
|
+
async executeAsync(
|
|
90
|
+
_viewerContext: TestViewerContext,
|
|
91
|
+
_queryContext: EntityTransactionalQueryContext,
|
|
92
|
+
_entity: ChildEntity,
|
|
93
|
+
mutationInfo: EntityTriggerMutationInfo<ChildFields, string, TestViewerContext, ChildEntity>
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
if (mutationInfo.type !== EntityMutationType.DELETE) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (mutationInfo.cascadingDeleteCause === null) {
|
|
100
|
+
throw new Error('Child entity should have casade delete cause');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const cascadingDeleteCauseEntity = mutationInfo.cascadingDeleteCause.entity;
|
|
104
|
+
if (!(cascadingDeleteCauseEntity instanceof ParentEntity)) {
|
|
105
|
+
throw new Error('Child entity should have casade delete cause entity of type ParentEntity');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const secondLevelCascadingDeleteCause =
|
|
109
|
+
mutationInfo.cascadingDeleteCause.cascadingDeleteCause;
|
|
110
|
+
if (secondLevelCascadingDeleteCause) {
|
|
111
|
+
throw new Error('Child entity should not have two-level casade delete cause');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
triggerExecutionCounts.child++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
class GrandChildCheckInfoTrigger extends EntityMutationTrigger<
|
|
119
|
+
GrandChildFields,
|
|
120
|
+
string,
|
|
121
|
+
TestViewerContext,
|
|
122
|
+
GrandChildEntity
|
|
123
|
+
> {
|
|
124
|
+
async executeAsync(
|
|
125
|
+
_viewerContext: TestViewerContext,
|
|
126
|
+
_queryContext: EntityTransactionalQueryContext,
|
|
127
|
+
_entity: GrandChildEntity,
|
|
128
|
+
mutationInfo: EntityTriggerMutationInfo<
|
|
129
|
+
GrandChildFields,
|
|
130
|
+
string,
|
|
131
|
+
TestViewerContext,
|
|
132
|
+
GrandChildEntity
|
|
133
|
+
>
|
|
134
|
+
): Promise<void> {
|
|
135
|
+
if (mutationInfo.type !== EntityMutationType.DELETE) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (mutationInfo.cascadingDeleteCause === null) {
|
|
140
|
+
throw new Error('GrandChild entity should have cascade delete cause');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const cascadingDeleteCauseEntity = mutationInfo.cascadingDeleteCause.entity;
|
|
144
|
+
if (!(cascadingDeleteCauseEntity instanceof ChildEntity)) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
'GrandChild entity should have cascade delete cause entity of type ChildEntity'
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const secondLevelCascadingDeleteCause =
|
|
151
|
+
mutationInfo.cascadingDeleteCause.cascadingDeleteCause;
|
|
152
|
+
if (!secondLevelCascadingDeleteCause) {
|
|
153
|
+
throw new Error('GrandChild entity should have two-level casade delete cause');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const secondLevelCascadingDeleteCauseEntity = secondLevelCascadingDeleteCause.entity;
|
|
157
|
+
if (!(secondLevelCascadingDeleteCauseEntity instanceof ParentEntity)) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
'GrandChild entity should have second level casade delete cause entity of type ParentEntity'
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const thirdLevelCascadingDeleteCause = secondLevelCascadingDeleteCause.cascadingDeleteCause;
|
|
164
|
+
if (thirdLevelCascadingDeleteCause) {
|
|
165
|
+
throw new Error('GrandChild entity should not have three-level casade delete cause');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
triggerExecutionCounts.grandchild++;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
49
172
|
class ParentEntity extends Entity<ParentFields, string, TestViewerContext> {
|
|
50
173
|
static getCompanionDefinition(): EntityCompanionDefinition<
|
|
51
174
|
ParentFields,
|
|
@@ -143,33 +266,45 @@ const makeEntityClasses = (edgeDeletionBehavior: EntityEdgeDeletionBehavior) =>
|
|
|
143
266
|
entityClass: ParentEntity,
|
|
144
267
|
entityConfiguration: parentEntityConfiguration,
|
|
145
268
|
privacyPolicyClass: TestEntityPrivacyPolicy,
|
|
269
|
+
mutationTriggers: () => ({
|
|
270
|
+
beforeDelete: [new ParentCheckInfoTrigger()],
|
|
271
|
+
afterDelete: [new ParentCheckInfoTrigger()],
|
|
272
|
+
}),
|
|
146
273
|
});
|
|
147
274
|
|
|
148
275
|
const childEntityCompanion = new EntityCompanionDefinition({
|
|
149
276
|
entityClass: ChildEntity,
|
|
150
277
|
entityConfiguration: childEntityConfiguration,
|
|
151
278
|
privacyPolicyClass: TestEntityPrivacyPolicy,
|
|
279
|
+
mutationTriggers: () => ({
|
|
280
|
+
beforeDelete: [new ChildCheckInfoTrigger()],
|
|
281
|
+
afterDelete: [new ChildCheckInfoTrigger()],
|
|
282
|
+
}),
|
|
152
283
|
});
|
|
153
284
|
|
|
154
285
|
const grandChildEntityCompanion = new EntityCompanionDefinition({
|
|
155
286
|
entityClass: GrandChildEntity,
|
|
156
287
|
entityConfiguration: grandChildEntityConfiguration,
|
|
157
288
|
privacyPolicyClass: TestEntityPrivacyPolicy,
|
|
289
|
+
mutationTriggers: () => ({
|
|
290
|
+
beforeDelete: [new GrandChildCheckInfoTrigger()],
|
|
291
|
+
afterDelete: [new GrandChildCheckInfoTrigger()],
|
|
292
|
+
}),
|
|
158
293
|
});
|
|
159
294
|
|
|
160
295
|
return {
|
|
161
296
|
ParentEntity,
|
|
162
297
|
ChildEntity,
|
|
163
298
|
GrandChildEntity,
|
|
299
|
+
triggerExecutionCounts,
|
|
164
300
|
};
|
|
165
301
|
};
|
|
166
302
|
|
|
167
303
|
describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => {
|
|
168
304
|
describe('EntityEdgeDeletionBehavior.CASCADE_DELETE', () => {
|
|
169
305
|
it('deletes', async () => {
|
|
170
|
-
const { ParentEntity, ChildEntity, GrandChildEntity } =
|
|
171
|
-
EntityEdgeDeletionBehavior.CASCADE_DELETE
|
|
172
|
-
);
|
|
306
|
+
const { ParentEntity, ChildEntity, GrandChildEntity, triggerExecutionCounts } =
|
|
307
|
+
makeEntityClasses(EntityEdgeDeletionBehavior.CASCADE_DELETE);
|
|
173
308
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
174
309
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
175
310
|
|
|
@@ -202,14 +337,20 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => {
|
|
|
202
337
|
await expect(
|
|
203
338
|
GrandChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(grandchild.getID())
|
|
204
339
|
).resolves.toBeNull();
|
|
340
|
+
|
|
341
|
+
// two calls for each trigger, one beforeDelete, one afterDelete
|
|
342
|
+
expect(triggerExecutionCounts).toMatchObject({
|
|
343
|
+
parent: 2,
|
|
344
|
+
child: 2,
|
|
345
|
+
grandchild: 2,
|
|
346
|
+
});
|
|
205
347
|
});
|
|
206
348
|
});
|
|
207
349
|
|
|
208
350
|
describe('EntityEdgeDeletionBehavior.SET_NULL', () => {
|
|
209
351
|
it('sets null', async () => {
|
|
210
|
-
const { ParentEntity, ChildEntity, GrandChildEntity } =
|
|
211
|
-
EntityEdgeDeletionBehavior.SET_NULL
|
|
212
|
-
);
|
|
352
|
+
const { ParentEntity, ChildEntity, GrandChildEntity, triggerExecutionCounts } =
|
|
353
|
+
makeEntityClasses(EntityEdgeDeletionBehavior.SET_NULL);
|
|
213
354
|
|
|
214
355
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
215
356
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
@@ -247,14 +388,21 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => {
|
|
|
247
388
|
.enforcing()
|
|
248
389
|
.loadByIDAsync(grandchild.getID());
|
|
249
390
|
expect(loadedGrandchild.getField('parent_id')).toEqual(loadedChild.getID());
|
|
391
|
+
|
|
392
|
+
// two calls for only parent trigger, one beforeDelete, one afterDelete
|
|
393
|
+
// when using set null the descendants aren't deleted
|
|
394
|
+
expect(triggerExecutionCounts).toMatchObject({
|
|
395
|
+
parent: 2,
|
|
396
|
+
child: 0,
|
|
397
|
+
grandchild: 0,
|
|
398
|
+
});
|
|
250
399
|
});
|
|
251
400
|
});
|
|
252
401
|
|
|
253
402
|
describe('EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE', () => {
|
|
254
403
|
it('invalidates the cache', async () => {
|
|
255
|
-
const { ParentEntity, ChildEntity, GrandChildEntity } =
|
|
256
|
-
EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE
|
|
257
|
-
);
|
|
404
|
+
const { ParentEntity, ChildEntity, GrandChildEntity, triggerExecutionCounts } =
|
|
405
|
+
makeEntityClasses(EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE);
|
|
258
406
|
|
|
259
407
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
260
408
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
@@ -318,6 +466,13 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => {
|
|
|
318
466
|
await expect(
|
|
319
467
|
GrandChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(grandchild.getID())
|
|
320
468
|
).resolves.not.toBeNull();
|
|
469
|
+
|
|
470
|
+
// two calls for each trigger, one beforeDelete, one afterDelete
|
|
471
|
+
expect(triggerExecutionCounts).toMatchObject({
|
|
472
|
+
parent: 2,
|
|
473
|
+
child: 2,
|
|
474
|
+
grandchild: 2,
|
|
475
|
+
});
|
|
321
476
|
});
|
|
322
477
|
});
|
|
323
478
|
});
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { v1 as uuidv1, v3 as uuidv3, v4 as uuidv4, v5 as uuidv5 } from 'uuid';
|
|
2
2
|
|
|
3
|
+
import { EntityFieldDefinition } from '../EntityFieldDefinition';
|
|
3
4
|
import {
|
|
4
|
-
EntityFieldDefinition,
|
|
5
5
|
StringField,
|
|
6
6
|
UUIDField,
|
|
7
7
|
DateField,
|
|
8
8
|
BooleanField,
|
|
9
|
-
|
|
9
|
+
IntField,
|
|
10
|
+
FloatField,
|
|
10
11
|
StringArrayField,
|
|
11
12
|
JSONObjectField,
|
|
12
13
|
EnumField,
|
|
13
14
|
JSONArrayField,
|
|
14
15
|
MaybeJSONArrayField,
|
|
15
16
|
} from '../EntityFields';
|
|
17
|
+
import describeFieldTestCase from '../utils/testing/describeFieldTestCase';
|
|
16
18
|
|
|
17
19
|
class TestFieldDefinition extends EntityFieldDefinition<string> {
|
|
18
20
|
protected validateInputValueInternal(value: string): boolean {
|
|
@@ -52,26 +54,6 @@ describe(EntityFieldDefinition, () => {
|
|
|
52
54
|
});
|
|
53
55
|
});
|
|
54
56
|
|
|
55
|
-
const describeFieldTestCase = <T>(
|
|
56
|
-
fieldDefinition: EntityFieldDefinition<T>,
|
|
57
|
-
validValues: T[],
|
|
58
|
-
invalidValues: any[]
|
|
59
|
-
): void => {
|
|
60
|
-
describe(fieldDefinition.constructor.name, () => {
|
|
61
|
-
if (validValues.length > 0) {
|
|
62
|
-
test.each(validValues)(`${fieldDefinition.constructor.name}.valid %p`, (value) => {
|
|
63
|
-
expect(fieldDefinition.validateInputValue(value)).toBe(true);
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (invalidValues.length > 0) {
|
|
68
|
-
test.each(invalidValues)(`${fieldDefinition.constructor.name}.invalid %p`, (value) => {
|
|
69
|
-
expect(fieldDefinition.validateInputValue(value)).toBe(false);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
};
|
|
74
|
-
|
|
75
57
|
describeFieldTestCase(new StringField({ columnName: 'wat' }), ['hello', ''], [1, true, {}, [[]]]);
|
|
76
58
|
describeFieldTestCase(
|
|
77
59
|
new UUIDField({ columnName: 'wat' }),
|
|
@@ -80,7 +62,8 @@ describeFieldTestCase(
|
|
|
80
62
|
);
|
|
81
63
|
describeFieldTestCase(new DateField({ columnName: 'wat' }), [new Date()], [Date.now()]);
|
|
82
64
|
describeFieldTestCase(new BooleanField({ columnName: 'wat' }), [true, false], [0, 1, '']);
|
|
83
|
-
describeFieldTestCase(new
|
|
65
|
+
describeFieldTestCase(new IntField({ columnName: 'wat' }), [1], ['1', 0.5, true]);
|
|
66
|
+
describeFieldTestCase(new FloatField({ columnName: 'wat' }), [1, 0.5, -0.5], ['1']);
|
|
84
67
|
describeFieldTestCase(
|
|
85
68
|
new StringArrayField({ columnName: 'wat' }),
|
|
86
69
|
[[['what']] as any, [[]] as any], // jest test cases need extra wrapping array
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { instance, mock } from 'ts-mockito';
|
|
2
|
+
|
|
3
|
+
import Entity from '../Entity';
|
|
4
|
+
import { EntityCompanionDefinition } from '../EntityCompanionProvider';
|
|
5
|
+
import EntityConfiguration from '../EntityConfiguration';
|
|
6
|
+
import { StringField } from '../EntityFields';
|
|
7
|
+
import EntityLoader from '../EntityLoader';
|
|
8
|
+
import EntityPrivacyPolicy from '../EntityPrivacyPolicy';
|
|
9
|
+
import ViewerContext from '../ViewerContext';
|
|
10
|
+
import EntityDataManager from '../internal/EntityDataManager';
|
|
11
|
+
import ReadThroughEntityCache from '../internal/ReadThroughEntityCache';
|
|
12
|
+
import IEntityMetricsAdapter from '../metrics/IEntityMetricsAdapter';
|
|
13
|
+
import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule';
|
|
14
|
+
import { NoCacheStubCacheAdapterProvider } from '../utils/testing/StubCacheAdapter';
|
|
15
|
+
import StubDatabaseAdapter from '../utils/testing/StubDatabaseAdapter';
|
|
16
|
+
import StubQueryContextProvider from '../utils/testing/StubQueryContextProvider';
|
|
17
|
+
|
|
18
|
+
export type TestFields = {
|
|
19
|
+
id: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type TestFieldSelection = keyof TestFields;
|
|
23
|
+
|
|
24
|
+
export const testEntityConfiguration = new EntityConfiguration<TestFields>({
|
|
25
|
+
idField: 'id',
|
|
26
|
+
tableName: 'test_entity_should_not_write_to_db',
|
|
27
|
+
schema: {
|
|
28
|
+
id: new StringField({
|
|
29
|
+
columnName: 'id',
|
|
30
|
+
}),
|
|
31
|
+
},
|
|
32
|
+
databaseAdapterFlavor: 'postgres',
|
|
33
|
+
cacheAdapterFlavor: 'redis',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export class TestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
37
|
+
TestFields,
|
|
38
|
+
string,
|
|
39
|
+
ViewerContext,
|
|
40
|
+
TestEntity,
|
|
41
|
+
TestFieldSelection
|
|
42
|
+
> {
|
|
43
|
+
protected override readonly readRules = [
|
|
44
|
+
new AlwaysAllowPrivacyPolicyRule<
|
|
45
|
+
TestFields,
|
|
46
|
+
string,
|
|
47
|
+
ViewerContext,
|
|
48
|
+
TestEntity,
|
|
49
|
+
TestFieldSelection
|
|
50
|
+
>(),
|
|
51
|
+
];
|
|
52
|
+
protected override readonly createRules = [
|
|
53
|
+
new AlwaysAllowPrivacyPolicyRule<
|
|
54
|
+
TestFields,
|
|
55
|
+
string,
|
|
56
|
+
ViewerContext,
|
|
57
|
+
TestEntity,
|
|
58
|
+
TestFieldSelection
|
|
59
|
+
>(),
|
|
60
|
+
];
|
|
61
|
+
protected override readonly updateRules = [
|
|
62
|
+
new AlwaysAllowPrivacyPolicyRule<
|
|
63
|
+
TestFields,
|
|
64
|
+
string,
|
|
65
|
+
ViewerContext,
|
|
66
|
+
TestEntity,
|
|
67
|
+
TestFieldSelection
|
|
68
|
+
>(),
|
|
69
|
+
];
|
|
70
|
+
protected override readonly deleteRules = [
|
|
71
|
+
new AlwaysAllowPrivacyPolicyRule<
|
|
72
|
+
TestFields,
|
|
73
|
+
string,
|
|
74
|
+
ViewerContext,
|
|
75
|
+
TestEntity,
|
|
76
|
+
TestFieldSelection
|
|
77
|
+
>(),
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const ID_SENTINEL_THROW_LITERAL = 'throw_literal';
|
|
82
|
+
const ID_SENTINEL_THROW_ERROR = 'throw_error';
|
|
83
|
+
|
|
84
|
+
export default class TestEntity extends Entity<
|
|
85
|
+
TestFields,
|
|
86
|
+
string,
|
|
87
|
+
ViewerContext,
|
|
88
|
+
TestFieldSelection
|
|
89
|
+
> {
|
|
90
|
+
constructor(viewerContext: ViewerContext, rawFields: Readonly<TestFields>) {
|
|
91
|
+
if (rawFields.id === ID_SENTINEL_THROW_LITERAL) {
|
|
92
|
+
// eslint-disable-next-line no-throw-literal,@typescript-eslint/no-throw-literal
|
|
93
|
+
throw 'hello';
|
|
94
|
+
} else if (rawFields.id === ID_SENTINEL_THROW_ERROR) {
|
|
95
|
+
throw new Error('world');
|
|
96
|
+
}
|
|
97
|
+
super(viewerContext, rawFields);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static getCompanionDefinition(): EntityCompanionDefinition<
|
|
101
|
+
TestFields,
|
|
102
|
+
string,
|
|
103
|
+
ViewerContext,
|
|
104
|
+
TestEntity,
|
|
105
|
+
TestEntityPrivacyPolicy,
|
|
106
|
+
TestFieldSelection
|
|
107
|
+
> {
|
|
108
|
+
return testEntityCompanion;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const testEntityCompanion = new EntityCompanionDefinition({
|
|
113
|
+
entityClass: TestEntity,
|
|
114
|
+
entityConfiguration: testEntityConfiguration,
|
|
115
|
+
privacyPolicyClass: TestEntityPrivacyPolicy,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe(EntityLoader, () => {
|
|
119
|
+
it('handles thrown errors and literals from constructor', async () => {
|
|
120
|
+
const viewerContext = instance(mock(ViewerContext));
|
|
121
|
+
const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
|
|
122
|
+
const queryContext = StubQueryContextProvider.getQueryContext();
|
|
123
|
+
|
|
124
|
+
const databaseAdapter = new StubDatabaseAdapter<TestFields>(
|
|
125
|
+
testEntityConfiguration,
|
|
126
|
+
StubDatabaseAdapter.convertFieldObjectsToDataStore(
|
|
127
|
+
testEntityConfiguration,
|
|
128
|
+
new Map([
|
|
129
|
+
[
|
|
130
|
+
testEntityConfiguration.tableName,
|
|
131
|
+
[
|
|
132
|
+
{
|
|
133
|
+
id: ID_SENTINEL_THROW_LITERAL,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: ID_SENTINEL_THROW_ERROR,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
],
|
|
140
|
+
])
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
const privacyPolicy = new TestEntityPrivacyPolicy();
|
|
144
|
+
const cacheAdapterProvider = new NoCacheStubCacheAdapterProvider();
|
|
145
|
+
const cacheAdapter = cacheAdapterProvider.getCacheAdapter(testEntityConfiguration);
|
|
146
|
+
const entityCache = new ReadThroughEntityCache(testEntityConfiguration, cacheAdapter);
|
|
147
|
+
const dataManager = new EntityDataManager(
|
|
148
|
+
databaseAdapter,
|
|
149
|
+
entityCache,
|
|
150
|
+
StubQueryContextProvider,
|
|
151
|
+
metricsAdapter,
|
|
152
|
+
TestEntity.name
|
|
153
|
+
);
|
|
154
|
+
const entityLoader = new EntityLoader(
|
|
155
|
+
viewerContext,
|
|
156
|
+
queryContext,
|
|
157
|
+
testEntityConfiguration,
|
|
158
|
+
TestEntity,
|
|
159
|
+
privacyPolicy,
|
|
160
|
+
dataManager,
|
|
161
|
+
metricsAdapter
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
let capturedThrownThing1: any;
|
|
165
|
+
try {
|
|
166
|
+
await entityLoader.loadByIDAsync(ID_SENTINEL_THROW_LITERAL);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
capturedThrownThing1 = e;
|
|
169
|
+
}
|
|
170
|
+
expect(capturedThrownThing1).not.toBeInstanceOf(Error);
|
|
171
|
+
expect(capturedThrownThing1).toEqual('hello');
|
|
172
|
+
|
|
173
|
+
const result = await entityLoader.loadByIDAsync(ID_SENTINEL_THROW_ERROR);
|
|
174
|
+
expect(result.ok).toBe(false);
|
|
175
|
+
expect(result.enforceError().message).toEqual('world');
|
|
176
|
+
});
|
|
177
|
+
});
|