@expo/entity-testing-utils 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +3 -0
  2. package/build/PrivacyPolicyRuleTestUtils.d.ts +24 -0
  3. package/build/PrivacyPolicyRuleTestUtils.js +52 -0
  4. package/build/PrivacyPolicyRuleTestUtils.js.map +1 -0
  5. package/build/StubCacheAdapter.d.ts +25 -0
  6. package/build/StubCacheAdapter.js +103 -0
  7. package/build/StubCacheAdapter.js.map +1 -0
  8. package/build/StubDatabaseAdapter.d.ts +23 -0
  9. package/build/StubDatabaseAdapter.js +158 -0
  10. package/build/StubDatabaseAdapter.js.map +1 -0
  11. package/build/StubDatabaseAdapterProvider.d.ts +5 -0
  12. package/build/StubDatabaseAdapterProvider.js +14 -0
  13. package/build/StubDatabaseAdapterProvider.js.map +1 -0
  14. package/build/StubQueryContextProvider.d.ts +6 -0
  15. package/build/StubQueryContextProvider.js +16 -0
  16. package/build/StubQueryContextProvider.js.map +1 -0
  17. package/build/TSMockitoExtensions.d.ts +9 -0
  18. package/build/TSMockitoExtensions.js +63 -0
  19. package/build/TSMockitoExtensions.js.map +1 -0
  20. package/build/createUnitTestEntityCompanionProvider.d.ts +6 -0
  21. package/build/createUnitTestEntityCompanionProvider.js +35 -0
  22. package/build/createUnitTestEntityCompanionProvider.js.map +1 -0
  23. package/build/describeFieldTestCase.d.ts +2 -0
  24. package/build/describeFieldTestCase.js +18 -0
  25. package/build/describeFieldTestCase.js.map +1 -0
  26. package/build/index.d.ts +12 -0
  27. package/build/index.js +38 -0
  28. package/build/index.js.map +1 -0
  29. package/build/tsconfig.build.tsbuildinfo +1 -0
  30. package/package.json +48 -0
  31. package/src/PrivacyPolicyRuleTestUtils.ts +138 -0
  32. package/src/StubCacheAdapter.ts +167 -0
  33. package/src/StubDatabaseAdapter.ts +249 -0
  34. package/src/StubDatabaseAdapterProvider.ts +17 -0
  35. package/src/StubQueryContextProvider.ts +19 -0
  36. package/src/TSMockitoExtensions.ts +69 -0
  37. package/src/__testfixtures__/DateIDTestEntity.ts +62 -0
  38. package/src/__testfixtures__/SimpleTestEntity.ts +95 -0
  39. package/src/__testfixtures__/TestEntity.ts +130 -0
  40. package/src/__testfixtures__/TestEntityNumberKey.ts +62 -0
  41. package/src/__tests__/FileConsistentcyWithEntity-test.ts +32 -0
  42. package/src/__tests__/PrivacyPolicyRuleTestUtils-test.ts +44 -0
  43. package/src/__tests__/StubCacheAdapter-test.ts +134 -0
  44. package/src/__tests__/StubDatabaseAdapter-test.ts +607 -0
  45. package/src/__tests__/TSMockitoExtensions-test.ts +65 -0
  46. package/src/createUnitTestEntityCompanionProvider.ts +40 -0
  47. package/src/describeFieldTestCase.ts +21 -0
  48. package/src/index.ts +14 -0
@@ -0,0 +1,19 @@
1
+ import { TransactionConfig, EntityQueryContextProvider } from '@expo/entity';
2
+
3
+ export default class StubQueryContextProvider extends EntityQueryContextProvider {
4
+ protected getQueryInterface(): any {
5
+ return {};
6
+ }
7
+
8
+ protected createTransactionRunner<T>(
9
+ _transactionConfig?: TransactionConfig,
10
+ ): (transactionScope: (queryInterface: any) => Promise<T>) => Promise<T> {
11
+ return (transactionScope) => Promise.resolve(transactionScope({}));
12
+ }
13
+
14
+ protected createNestedTransactionRunner<T>(
15
+ _outerQueryInterface: any,
16
+ ): (transactionScope: (queryInterface: any) => Promise<T>) => Promise<T> {
17
+ return (transactionScope) => Promise.resolve(transactionScope({}));
18
+ }
19
+ }
@@ -0,0 +1,69 @@
1
+ import {
2
+ SerializableKeyMap,
3
+ CompositeFieldHolder,
4
+ CompositeFieldValueHolder,
5
+ SingleFieldHolder,
6
+ SingleFieldValueHolder,
7
+ } from '@expo/entity';
8
+ import isEqualWith from 'lodash/isEqualWith';
9
+ import { Matcher } from 'ts-mockito/lib/matcher/type/Matcher';
10
+
11
+ export function isEqualWithEntityAware(expected: any, actual: any): boolean {
12
+ return isEqualWith(expected, actual, (expected: any, actual: any): boolean | undefined => {
13
+ if (expected instanceof Matcher) {
14
+ return expected.match(actual);
15
+ }
16
+
17
+ if (expected instanceof SingleFieldHolder && actual instanceof SingleFieldHolder) {
18
+ return expected.fieldName === actual.fieldName;
19
+ }
20
+
21
+ if (expected instanceof SingleFieldValueHolder && actual instanceof SingleFieldValueHolder) {
22
+ return expected.fieldValue === actual.fieldValue;
23
+ }
24
+
25
+ if (expected instanceof CompositeFieldHolder && actual instanceof CompositeFieldHolder) {
26
+ return expected.serialize() === actual.serialize();
27
+ }
28
+
29
+ if (
30
+ expected instanceof CompositeFieldValueHolder &&
31
+ actual instanceof CompositeFieldValueHolder
32
+ ) {
33
+ return expected.serialize() === actual.serialize();
34
+ }
35
+
36
+ if (expected instanceof SerializableKeyMap && actual instanceof SerializableKeyMap) {
37
+ for (const [key, value] of expected.entries()) {
38
+ if (!actual.has(key) || !isEqualWith(value, actual.get(key))) {
39
+ return false;
40
+ }
41
+ }
42
+ return true;
43
+ }
44
+
45
+ return undefined;
46
+ });
47
+ }
48
+
49
+ export class DeepEqualEntityAwareMatcher<T> extends Matcher {
50
+ constructor(private readonly expectedValue: T) {
51
+ super();
52
+ }
53
+
54
+ public override match(value: any): boolean {
55
+ return isEqualWithEntityAware(this.expectedValue, value);
56
+ }
57
+
58
+ public override toString(): string {
59
+ if (this.expectedValue instanceof Array) {
60
+ return `deepEqualEntityAware([${this.expectedValue}])`;
61
+ } else {
62
+ return `deepEqualEntityAware(${this.expectedValue})`;
63
+ }
64
+ }
65
+ }
66
+
67
+ export function deepEqualEntityAware<T>(expectedValue: T): T {
68
+ return new DeepEqualEntityAwareMatcher(expectedValue) as any;
69
+ }
@@ -0,0 +1,62 @@
1
+ import {
2
+ Entity,
3
+ EntityCompanionDefinition,
4
+ EntityConfiguration,
5
+ DateField,
6
+ EntityPrivacyPolicy,
7
+ ViewerContext,
8
+ AlwaysAllowPrivacyPolicyRule,
9
+ } from '@expo/entity';
10
+
11
+ export type DateIDTestFields = {
12
+ id: Date;
13
+ };
14
+
15
+ export const dateIDTestEntityConfiguration = new EntityConfiguration<DateIDTestFields, 'id'>({
16
+ idField: 'id',
17
+ tableName: 'simple_test_entity_should_not_write_to_db',
18
+ schema: {
19
+ id: new DateField({
20
+ columnName: 'custom_id',
21
+ cache: true,
22
+ }),
23
+ },
24
+ databaseAdapterFlavor: 'postgres',
25
+ cacheAdapterFlavor: 'redis',
26
+ });
27
+
28
+ export class DateIDTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
29
+ DateIDTestFields,
30
+ 'id',
31
+ ViewerContext,
32
+ DateIDTestEntity
33
+ > {
34
+ protected override readonly readRules = [
35
+ new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, 'id', ViewerContext, DateIDTestEntity>(),
36
+ ];
37
+ protected override readonly createRules = [
38
+ new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, 'id', ViewerContext, DateIDTestEntity>(),
39
+ ];
40
+ protected override readonly updateRules = [
41
+ new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, 'id', ViewerContext, DateIDTestEntity>(),
42
+ ];
43
+ protected override readonly deleteRules = [
44
+ new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, 'id', ViewerContext, DateIDTestEntity>(),
45
+ ];
46
+ }
47
+
48
+ export default class DateIDTestEntity extends Entity<DateIDTestFields, 'id', ViewerContext> {
49
+ static defineCompanionDefinition(): EntityCompanionDefinition<
50
+ DateIDTestFields,
51
+ 'id',
52
+ ViewerContext,
53
+ DateIDTestEntity,
54
+ DateIDTestEntityPrivacyPolicy
55
+ > {
56
+ return {
57
+ entityClass: DateIDTestEntity,
58
+ entityConfiguration: dateIDTestEntityConfiguration,
59
+ privacyPolicyClass: DateIDTestEntityPrivacyPolicy,
60
+ };
61
+ }
62
+ }
@@ -0,0 +1,95 @@
1
+ import {
2
+ Entity,
3
+ EntityCompanionDefinition,
4
+ EntityConfiguration,
5
+ EntityPrivacyPolicy,
6
+ ViewerContext,
7
+ AlwaysAllowPrivacyPolicyRule,
8
+ UUIDField,
9
+ } from '@expo/entity';
10
+
11
+ export type SimpleTestFields = {
12
+ id: string;
13
+ };
14
+
15
+ export type SimpleTestFieldSelection = keyof SimpleTestFields;
16
+
17
+ export const simpleTestEntityConfiguration = new EntityConfiguration<SimpleTestFields, 'id'>({
18
+ idField: 'id',
19
+ tableName: 'simple_test_entity_should_not_write_to_db',
20
+ schema: {
21
+ id: new UUIDField({
22
+ columnName: 'custom_id',
23
+ cache: true,
24
+ }),
25
+ },
26
+ databaseAdapterFlavor: 'postgres',
27
+ cacheAdapterFlavor: 'redis',
28
+ });
29
+
30
+ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
31
+ SimpleTestFields,
32
+ 'id',
33
+ ViewerContext,
34
+ SimpleTestEntity,
35
+ SimpleTestFieldSelection
36
+ > {
37
+ protected override readonly readRules = [
38
+ new AlwaysAllowPrivacyPolicyRule<
39
+ SimpleTestFields,
40
+ 'id',
41
+ ViewerContext,
42
+ SimpleTestEntity,
43
+ SimpleTestFieldSelection
44
+ >(),
45
+ ];
46
+ protected override readonly createRules = [
47
+ new AlwaysAllowPrivacyPolicyRule<
48
+ SimpleTestFields,
49
+ 'id',
50
+ ViewerContext,
51
+ SimpleTestEntity,
52
+ SimpleTestFieldSelection
53
+ >(),
54
+ ];
55
+ protected override readonly updateRules = [
56
+ new AlwaysAllowPrivacyPolicyRule<
57
+ SimpleTestFields,
58
+ 'id',
59
+ ViewerContext,
60
+ SimpleTestEntity,
61
+ SimpleTestFieldSelection
62
+ >(),
63
+ ];
64
+ protected override readonly deleteRules = [
65
+ new AlwaysAllowPrivacyPolicyRule<
66
+ SimpleTestFields,
67
+ 'id',
68
+ ViewerContext,
69
+ SimpleTestEntity,
70
+ SimpleTestFieldSelection
71
+ >(),
72
+ ];
73
+ }
74
+
75
+ export default class SimpleTestEntity extends Entity<
76
+ SimpleTestFields,
77
+ 'id',
78
+ ViewerContext,
79
+ SimpleTestFieldSelection
80
+ > {
81
+ static defineCompanionDefinition(): EntityCompanionDefinition<
82
+ SimpleTestFields,
83
+ 'id',
84
+ ViewerContext,
85
+ SimpleTestEntity,
86
+ SimpleTestEntityPrivacyPolicy,
87
+ SimpleTestFieldSelection
88
+ > {
89
+ return {
90
+ entityClass: SimpleTestEntity,
91
+ entityConfiguration: simpleTestEntityConfiguration,
92
+ privacyPolicyClass: SimpleTestEntityPrivacyPolicy,
93
+ };
94
+ }
95
+ }
@@ -0,0 +1,130 @@
1
+ import {
2
+ Entity,
3
+ EntityCompanionDefinition,
4
+ EntityConfiguration,
5
+ DateField,
6
+ EntityPrivacyPolicy,
7
+ ViewerContext,
8
+ AlwaysAllowPrivacyPolicyRule,
9
+ UUIDField,
10
+ StringField,
11
+ IntField,
12
+ } from '@expo/entity';
13
+ import { result, Result } from '@expo/results';
14
+
15
+ export type TestFields = {
16
+ customIdField: string;
17
+ testIndexedField: string;
18
+ stringField: string;
19
+ intField: number;
20
+ dateField: Date;
21
+ nullableField: string | null;
22
+ };
23
+
24
+ export const testEntityConfiguration = new EntityConfiguration<TestFields, 'customIdField'>({
25
+ idField: 'customIdField',
26
+ tableName: 'test_entity_should_not_write_to_db',
27
+ schema: {
28
+ customIdField: new UUIDField({
29
+ columnName: 'custom_id',
30
+ cache: true,
31
+ }),
32
+ testIndexedField: new StringField({
33
+ columnName: 'test_index',
34
+ cache: true,
35
+ }),
36
+ stringField: new StringField({
37
+ columnName: 'string_field',
38
+ }),
39
+ intField: new IntField({
40
+ columnName: 'number_field',
41
+ }),
42
+ dateField: new DateField({
43
+ columnName: 'date_field',
44
+ }),
45
+ nullableField: new StringField({
46
+ columnName: 'nullable_field',
47
+ }),
48
+ },
49
+ databaseAdapterFlavor: 'postgres',
50
+ cacheAdapterFlavor: 'redis',
51
+ compositeFieldDefinitions: [
52
+ { compositeField: ['stringField', 'intField'], cache: false },
53
+ { compositeField: ['stringField', 'testIndexedField'], cache: true },
54
+ { compositeField: ['nullableField', 'testIndexedField'], cache: true },
55
+ ],
56
+ });
57
+
58
+ export class TestEntityPrivacyPolicy extends EntityPrivacyPolicy<
59
+ TestFields,
60
+ 'customIdField',
61
+ ViewerContext,
62
+ TestEntity
63
+ > {
64
+ protected override readonly readRules = [
65
+ new AlwaysAllowPrivacyPolicyRule<TestFields, 'customIdField', ViewerContext, TestEntity>(),
66
+ ];
67
+ protected override readonly createRules = [
68
+ new AlwaysAllowPrivacyPolicyRule<TestFields, 'customIdField', ViewerContext, TestEntity>(),
69
+ ];
70
+ protected override readonly updateRules = [
71
+ new AlwaysAllowPrivacyPolicyRule<TestFields, 'customIdField', ViewerContext, TestEntity>(),
72
+ ];
73
+ protected override readonly deleteRules = [
74
+ new AlwaysAllowPrivacyPolicyRule<TestFields, 'customIdField', ViewerContext, TestEntity>(),
75
+ ];
76
+ }
77
+
78
+ export default class TestEntity extends Entity<TestFields, 'customIdField', ViewerContext> {
79
+ static defineCompanionDefinition(): EntityCompanionDefinition<
80
+ TestFields,
81
+ 'customIdField',
82
+ ViewerContext,
83
+ TestEntity,
84
+ TestEntityPrivacyPolicy
85
+ > {
86
+ return {
87
+ entityClass: TestEntity,
88
+ entityConfiguration: testEntityConfiguration,
89
+ privacyPolicyClass: TestEntityPrivacyPolicy,
90
+ };
91
+ }
92
+
93
+ getBlah(): string {
94
+ return 'Hello World!';
95
+ }
96
+
97
+ static async helloAsync(
98
+ viewerContext: ViewerContext,
99
+ testValue: string,
100
+ ): Promise<Result<TestEntity>> {
101
+ const fields = {
102
+ customIdField: testValue,
103
+ testIndexedField: 'hello',
104
+ stringField: 'hello',
105
+ intField: 1,
106
+ dateField: new Date(),
107
+ nullableField: null,
108
+ };
109
+ return result(
110
+ new TestEntity({
111
+ viewerContext,
112
+ id: testValue,
113
+ databaseFields: fields,
114
+ selectedFields: fields,
115
+ }),
116
+ );
117
+ }
118
+
119
+ static async returnErrorAsync(_viewerContext: ViewerContext): Promise<Result<TestEntity>> {
120
+ return result(new Error('return entity'));
121
+ }
122
+
123
+ static async throwErrorAsync(_viewerContext: ViewerContext): Promise<Result<TestEntity>> {
124
+ throw new Error('threw entity');
125
+ }
126
+
127
+ static async nonResultAsync(_viewerContext: ViewerContext, testValue: string): Promise<string> {
128
+ return testValue;
129
+ }
130
+ }
@@ -0,0 +1,62 @@
1
+ import {
2
+ Entity,
3
+ EntityCompanionDefinition,
4
+ EntityConfiguration,
5
+ IntField,
6
+ EntityPrivacyPolicy,
7
+ ViewerContext,
8
+ AlwaysAllowPrivacyPolicyRule,
9
+ } from '@expo/entity';
10
+
11
+ export type NumberKeyFields = {
12
+ id: number;
13
+ };
14
+
15
+ export const numberKeyEntityConfiguration = new EntityConfiguration<NumberKeyFields, 'id'>({
16
+ idField: 'id',
17
+ tableName: 'simple_test_entity_should_not_write_to_db',
18
+ schema: {
19
+ id: new IntField({
20
+ columnName: 'custom_id',
21
+ cache: false,
22
+ }),
23
+ },
24
+ databaseAdapterFlavor: 'postgres',
25
+ cacheAdapterFlavor: 'redis',
26
+ });
27
+
28
+ export class NumberKeyPrivacyPolicy extends EntityPrivacyPolicy<
29
+ NumberKeyFields,
30
+ 'id',
31
+ ViewerContext,
32
+ NumberKeyEntity
33
+ > {
34
+ protected override readonly readRules = [
35
+ new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, 'id', ViewerContext, NumberKeyEntity>(),
36
+ ];
37
+ protected override readonly createRules = [
38
+ new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, 'id', ViewerContext, NumberKeyEntity>(),
39
+ ];
40
+ protected override readonly updateRules = [
41
+ new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, 'id', ViewerContext, NumberKeyEntity>(),
42
+ ];
43
+ protected override readonly deleteRules = [
44
+ new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, 'id', ViewerContext, NumberKeyEntity>(),
45
+ ];
46
+ }
47
+
48
+ export default class NumberKeyEntity extends Entity<NumberKeyFields, 'id', ViewerContext> {
49
+ static defineCompanionDefinition(): EntityCompanionDefinition<
50
+ NumberKeyFields,
51
+ 'id',
52
+ ViewerContext,
53
+ NumberKeyEntity,
54
+ NumberKeyPrivacyPolicy
55
+ > {
56
+ return {
57
+ entityClass: NumberKeyEntity,
58
+ entityConfiguration: numberKeyEntityConfiguration,
59
+ privacyPolicyClass: NumberKeyPrivacyPolicy,
60
+ };
61
+ }
62
+ }
@@ -0,0 +1,32 @@
1
+ import { readFile } from 'fs/promises';
2
+ import path from 'path';
3
+
4
+ it.each([
5
+ 'createUnitTestEntityCompanionProvider',
6
+ 'describeFieldTestCase',
7
+ 'PrivacyPolicyRuleTestUtils',
8
+ 'StubCacheAdapter',
9
+ 'StubDatabaseAdapter',
10
+ 'StubDatabaseAdapterProvider',
11
+ 'StubQueryContextProvider',
12
+ 'TSMockitoExtensions',
13
+ ])('$localPath the same as in @expo/entity', async (fileName) => {
14
+ // There isn't a great way to have TSMockitoExtensions in a shared package since it circularly depends on entity itself,
15
+ // and entity would want to use it for testing. Therefore, we duplicate it and ensure it stays in sync.
16
+
17
+ const fileContentsFromEntity = await readFile(
18
+ path.resolve(__dirname, `../../../entity/src/utils/__testfixtures__/${fileName}.ts`),
19
+ 'utf-8',
20
+ );
21
+ const fileContentsFromEntityTestingUtils = await readFile(
22
+ path.resolve(__dirname, `../${fileName}.ts`),
23
+ 'utf-8',
24
+ );
25
+
26
+ const trimmedFiles = [fileContentsFromEntity, fileContentsFromEntityTestingUtils].map((file) =>
27
+ file.substring(file.indexOf('export')),
28
+ );
29
+
30
+ expect(trimmedFiles[0]?.length).toBeGreaterThan(0);
31
+ expect(trimmedFiles[0]).toEqual(trimmedFiles[1]);
32
+ });
@@ -0,0 +1,44 @@
1
+ import {
2
+ EntityPrivacyPolicyEvaluationContext,
3
+ EntityQueryContext,
4
+ ViewerContext,
5
+ AlwaysAllowPrivacyPolicyRule,
6
+ AlwaysDenyPrivacyPolicyRule,
7
+ } from '@expo/entity';
8
+ import { anything, instance, mock } from 'ts-mockito';
9
+
10
+ import { describePrivacyPolicyRuleWithAsyncTestCase } from '../PrivacyPolicyRuleTestUtils';
11
+
12
+ describe(describePrivacyPolicyRuleWithAsyncTestCase, () => {
13
+ describe('default args do not execute', () => {
14
+ describePrivacyPolicyRuleWithAsyncTestCase(new AlwaysAllowPrivacyPolicyRule(), {
15
+ allowCases: new Map([
16
+ [
17
+ 'case',
18
+ async () => ({
19
+ viewerContext: instance(mock(ViewerContext)),
20
+ queryContext: instance(mock(EntityQueryContext)),
21
+ evaluationContext:
22
+ instance(mock<EntityPrivacyPolicyEvaluationContext<any, any, any, any, any>>()),
23
+ entity: anything(),
24
+ }),
25
+ ],
26
+ ]),
27
+ });
28
+
29
+ describePrivacyPolicyRuleWithAsyncTestCase(new AlwaysDenyPrivacyPolicyRule(), {
30
+ denyCases: new Map([
31
+ [
32
+ 'case',
33
+ async () => ({
34
+ viewerContext: instance(mock(ViewerContext)),
35
+ queryContext: instance(mock(EntityQueryContext)),
36
+ evaluationContext:
37
+ instance(mock<EntityPrivacyPolicyEvaluationContext<any, any, any, any, any>>()),
38
+ entity: anything(),
39
+ }),
40
+ ],
41
+ ]),
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,134 @@
1
+ import {
2
+ CompositeFieldHolder,
3
+ CompositeFieldValueHolder,
4
+ CompositeFieldValueHolderMap,
5
+ SingleFieldHolder,
6
+ SingleFieldValueHolder,
7
+ SingleFieldValueHolderMap,
8
+ CacheStatus,
9
+ } from '@expo/entity';
10
+
11
+ import {
12
+ InMemoryFullCacheStubCacheAdapterProvider,
13
+ InMemoryFullCacheStubCacheAdapter,
14
+ NoCacheStubCacheAdapter,
15
+ } from '../StubCacheAdapter';
16
+ import { testEntityConfiguration, TestFields } from '../__testfixtures__/TestEntity';
17
+
18
+ describe(NoCacheStubCacheAdapter, () => {
19
+ describe('loadManyAsync', () => {
20
+ it('should return a map of CacheLoadResult with status CacheStatus.MISS for all single values', async () => {
21
+ const adapter = new NoCacheStubCacheAdapter<TestFields, 'customIdField'>();
22
+ const result = await adapter.loadManyAsync(new SingleFieldHolder('stringField'), [
23
+ new SingleFieldValueHolder('huh'),
24
+ ]);
25
+ expect(result).toEqual(
26
+ new SingleFieldValueHolderMap(
27
+ new Map([[new SingleFieldValueHolder('huh'), { status: CacheStatus.MISS }]]),
28
+ ),
29
+ );
30
+ });
31
+
32
+ it('should return a map of CacheLoadResult with status CacheStatus.MISS for all composite values', async () => {
33
+ const adapter = new NoCacheStubCacheAdapter<TestFields, 'customIdField'>();
34
+ const result = await adapter.loadManyAsync(
35
+ new CompositeFieldHolder<TestFields, 'customIdField'>(['stringField', 'intField']),
36
+ [new CompositeFieldValueHolder({ stringField: 'huh', intField: 42 })],
37
+ );
38
+ expect(result).toEqual(
39
+ new CompositeFieldValueHolderMap(
40
+ new Map([
41
+ [
42
+ new CompositeFieldValueHolder({ stringField: 'huh', intField: 42 }),
43
+ { status: CacheStatus.MISS },
44
+ ],
45
+ ]),
46
+ ),
47
+ );
48
+ });
49
+ });
50
+ });
51
+
52
+ describe(InMemoryFullCacheStubCacheAdapter, () => {
53
+ it('correctly functions', async () => {
54
+ const adapter = new InMemoryFullCacheStubCacheAdapterProvider().getCacheAdapter(
55
+ testEntityConfiguration,
56
+ );
57
+ const result = await adapter.loadManyAsync(new SingleFieldHolder('stringField'), [
58
+ new SingleFieldValueHolder('huh'),
59
+ ]);
60
+ expect(result).toEqual(
61
+ new SingleFieldValueHolderMap(
62
+ new Map([[new SingleFieldValueHolder('huh'), { status: CacheStatus.MISS }]]),
63
+ ),
64
+ );
65
+
66
+ await adapter.cacheManyAsync(new SingleFieldHolder('stringField'), new Map());
67
+ const result2 = await adapter.loadManyAsync(new SingleFieldHolder('stringField'), [
68
+ new SingleFieldValueHolder('huh'),
69
+ ]);
70
+ expect(result2).toEqual(
71
+ new SingleFieldValueHolderMap(
72
+ new Map([[new SingleFieldValueHolder('huh'), { status: CacheStatus.MISS }]]),
73
+ ),
74
+ );
75
+
76
+ const fields = {
77
+ stringField: 'huh',
78
+ customIdField: 'id1',
79
+ testIndexedField: 'wat',
80
+ intField: 3,
81
+ dateField: new Date(),
82
+ nullableField: null,
83
+ };
84
+
85
+ await adapter.cacheManyAsync(
86
+ new SingleFieldHolder('stringField'),
87
+ new Map([[new SingleFieldValueHolder('huh'), fields]]),
88
+ );
89
+ const result3 = await adapter.loadManyAsync(new SingleFieldHolder('stringField'), [
90
+ new SingleFieldValueHolder('huh'),
91
+ ]);
92
+ expect(result3).toEqual(
93
+ new SingleFieldValueHolderMap(
94
+ new Map([[new SingleFieldValueHolder('huh'), { status: CacheStatus.HIT, item: fields }]]),
95
+ ),
96
+ );
97
+
98
+ await adapter.invalidateManyAsync(new SingleFieldHolder('stringField'), [
99
+ new SingleFieldValueHolder('huh'),
100
+ ]);
101
+ const result4 = await adapter.loadManyAsync(new SingleFieldHolder('stringField'), [
102
+ new SingleFieldValueHolder('huh'),
103
+ ]);
104
+ expect(result4).toEqual(
105
+ new SingleFieldValueHolderMap(
106
+ new Map([[new SingleFieldValueHolder('huh'), { status: CacheStatus.MISS }]]),
107
+ ),
108
+ );
109
+
110
+ await adapter.cacheDBMissesAsync(new SingleFieldHolder('stringField'), [
111
+ new SingleFieldValueHolder('huh'),
112
+ ]);
113
+ const result5 = await adapter.loadManyAsync(new SingleFieldHolder('stringField'), [
114
+ new SingleFieldValueHolder('huh'),
115
+ ]);
116
+ expect(result5).toEqual(
117
+ new SingleFieldValueHolderMap(
118
+ new Map([[new SingleFieldValueHolder('huh'), { status: CacheStatus.NEGATIVE }]]),
119
+ ),
120
+ );
121
+
122
+ await adapter.invalidateManyAsync(new SingleFieldHolder('stringField'), [
123
+ new SingleFieldValueHolder('huh'),
124
+ ]);
125
+ const result6 = await adapter.loadManyAsync(new SingleFieldHolder('stringField'), [
126
+ new SingleFieldValueHolder('huh'),
127
+ ]);
128
+ expect(result6).toEqual(
129
+ new SingleFieldValueHolderMap(
130
+ new Map([[new SingleFieldValueHolder('huh'), { status: CacheStatus.MISS }]]),
131
+ ),
132
+ );
133
+ });
134
+ });