@expo/entity-testing-utils 0.54.0 → 0.57.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/src/PrivacyPolicyRuleTestUtils.d.ts +2 -2
- package/build/src/StubDatabaseAdapter.d.ts +2 -4
- package/build/src/StubDatabaseAdapter.js +3 -68
- package/build/src/StubDatabaseAdapter.js.map +1 -1
- package/package.json +5 -5
- package/src/PrivacyPolicyRuleTestUtils.ts +2 -2
- package/src/StubDatabaseAdapter.ts +12 -98
- package/src/__tests__/PrivacyPolicyRuleTestUtils-test.ts +3 -3
- package/src/__tests__/StubDatabaseAdapter-test.ts +32 -239
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EntityQueryContext, ReadonlyEntity, ViewerContext, PrivacyPolicyRule, EntityPrivacyPolicyRuleEvaluationContext } from '@expo/entity';
|
|
2
2
|
export interface Case<TFields extends Record<string, any>, TIDField extends keyof NonNullable<Pick<TFields, TSelectedFields>>, TViewerContext extends ViewerContext, TEntity extends ReadonlyEntity<TFields, TIDField, TViewerContext, TSelectedFields>, TSelectedFields extends keyof TFields = keyof TFields> {
|
|
3
3
|
viewerContext: TViewerContext;
|
|
4
4
|
queryContext: EntityQueryContext;
|
|
5
|
-
evaluationContext:
|
|
5
|
+
evaluationContext: EntityPrivacyPolicyRuleEvaluationContext<TFields, TIDField, TViewerContext, TEntity, TSelectedFields>;
|
|
6
6
|
entity: TEntity;
|
|
7
7
|
}
|
|
8
8
|
export type CaseMap<TFields extends Record<string, any>, TIDField extends keyof NonNullable<Pick<TFields, TSelectedFields>>, TViewerContext extends ViewerContext, TEntity extends ReadonlyEntity<TFields, TIDField, TViewerContext, TSelectedFields>, TSelectedFields extends keyof TFields = keyof TFields> = Map<string, () => Promise<Case<TFields, TIDField, TViewerContext, TEntity, TSelectedFields>>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityConfiguration, EntityDatabaseAdapter, FieldTransformerMap
|
|
1
|
+
import { EntityConfiguration, EntityDatabaseAdapter, FieldTransformerMap } from '@expo/entity';
|
|
2
2
|
export declare class StubDatabaseAdapter<TFields extends Record<string, any>, TIDField extends keyof TFields> extends EntityDatabaseAdapter<TFields, TIDField> {
|
|
3
3
|
private readonly entityConfiguration2;
|
|
4
4
|
private readonly dataStore;
|
|
@@ -14,9 +14,7 @@ export declare class StubDatabaseAdapter<TFields extends Record<string, any>, TI
|
|
|
14
14
|
protected getFieldTransformerMap(): FieldTransformerMap;
|
|
15
15
|
private static uniqBy;
|
|
16
16
|
protected fetchManyWhereInternalAsync(_queryInterface: any, tableName: string, tableColumns: readonly string[], tableTuples: (readonly any[])[]): Promise<object[]>;
|
|
17
|
-
|
|
18
|
-
protected fetchManyByFieldEqualityConjunctionInternalAsync(_queryInterface: any, tableName: string, tableFieldSingleValueEqualityOperands: TableFieldSingleValueEqualityCondition[], tableFieldMultiValueEqualityOperands: TableFieldMultiValueEqualityCondition[], querySelectionModifiers: TableQuerySelectionModifiers): Promise<object[]>;
|
|
19
|
-
protected fetchManyByRawWhereClauseInternalAsync(_queryInterface: any, _tableName: string, _rawWhereClause: string, _bindings: object | any[], _querySelectionModifiers: TableQuerySelectionModifiers): Promise<object[]>;
|
|
17
|
+
protected fetchOneWhereInternalAsync(queryInterface: any, tableName: string, tableColumns: readonly string[], tableTuple: readonly any[]): Promise<object | null>;
|
|
20
18
|
private generateRandomID;
|
|
21
19
|
protected insertInternalAsync(_queryInterface: any, tableName: string, object: object): Promise<object[]>;
|
|
22
20
|
protected updateInternalAsync(_queryInterface: any, tableName: string, tableIdField: string, id: any, object: object): Promise<object[]>;
|
|
@@ -46,74 +46,9 @@ class StubDatabaseAdapter extends entity_1.EntityDatabaseAdapter {
|
|
|
46
46
|
}, []);
|
|
47
47
|
return [...results];
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
const currentOrderBy = orderBys[0];
|
|
54
|
-
const aField = objectA[currentOrderBy.columnName];
|
|
55
|
-
const bField = objectB[currentOrderBy.columnName];
|
|
56
|
-
switch (currentOrderBy.order) {
|
|
57
|
-
case entity_1.OrderByOrdering.DESCENDING: {
|
|
58
|
-
// simulate NULLS FIRST for DESC
|
|
59
|
-
if (aField === null && bField === null) {
|
|
60
|
-
return 0;
|
|
61
|
-
}
|
|
62
|
-
else if (aField === null) {
|
|
63
|
-
return -1;
|
|
64
|
-
}
|
|
65
|
-
else if (bField === null) {
|
|
66
|
-
return 1;
|
|
67
|
-
}
|
|
68
|
-
return aField > bField
|
|
69
|
-
? -1
|
|
70
|
-
: aField < bField
|
|
71
|
-
? 1
|
|
72
|
-
: this.compareByOrderBys(orderBys.slice(1), objectA, objectB);
|
|
73
|
-
}
|
|
74
|
-
case entity_1.OrderByOrdering.ASCENDING: {
|
|
75
|
-
// simulate NULLS LAST for ASC
|
|
76
|
-
if (aField === null && bField === null) {
|
|
77
|
-
return 0;
|
|
78
|
-
}
|
|
79
|
-
else if (bField === null) {
|
|
80
|
-
return -1;
|
|
81
|
-
}
|
|
82
|
-
else if (aField === null) {
|
|
83
|
-
return 1;
|
|
84
|
-
}
|
|
85
|
-
return bField > aField
|
|
86
|
-
? -1
|
|
87
|
-
: bField < aField
|
|
88
|
-
? 1
|
|
89
|
-
: this.compareByOrderBys(orderBys.slice(1), objectA, objectB);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
async fetchManyByFieldEqualityConjunctionInternalAsync(_queryInterface, tableName, tableFieldSingleValueEqualityOperands, tableFieldMultiValueEqualityOperands, querySelectionModifiers) {
|
|
94
|
-
let filteredObjects = this.getObjectCollectionForTable(tableName);
|
|
95
|
-
for (const { tableField, tableValue } of tableFieldSingleValueEqualityOperands) {
|
|
96
|
-
filteredObjects = filteredObjects.filter((obj) => obj[tableField] === tableValue);
|
|
97
|
-
}
|
|
98
|
-
for (const { tableField, tableValues } of tableFieldMultiValueEqualityOperands) {
|
|
99
|
-
filteredObjects = filteredObjects.filter((obj) => tableValues.includes(obj[tableField]));
|
|
100
|
-
}
|
|
101
|
-
const orderBy = querySelectionModifiers.orderBy;
|
|
102
|
-
if (orderBy !== undefined) {
|
|
103
|
-
filteredObjects = filteredObjects.sort((a, b) => StubDatabaseAdapter.compareByOrderBys(orderBy, a, b));
|
|
104
|
-
}
|
|
105
|
-
const offset = querySelectionModifiers.offset;
|
|
106
|
-
if (offset !== undefined) {
|
|
107
|
-
filteredObjects = filteredObjects.slice(offset);
|
|
108
|
-
}
|
|
109
|
-
const limit = querySelectionModifiers.limit;
|
|
110
|
-
if (limit !== undefined) {
|
|
111
|
-
filteredObjects = filteredObjects.slice(0, 0 + limit);
|
|
112
|
-
}
|
|
113
|
-
return filteredObjects;
|
|
114
|
-
}
|
|
115
|
-
fetchManyByRawWhereClauseInternalAsync(_queryInterface, _tableName, _rawWhereClause, _bindings, _querySelectionModifiers) {
|
|
116
|
-
throw new Error('Raw WHERE clauses not supported for StubDatabaseAdapter');
|
|
49
|
+
async fetchOneWhereInternalAsync(queryInterface, tableName, tableColumns, tableTuple) {
|
|
50
|
+
const results = await this.fetchManyWhereInternalAsync(queryInterface, tableName, tableColumns, [tableTuple]);
|
|
51
|
+
return results[0] ?? null;
|
|
117
52
|
}
|
|
118
53
|
generateRandomID() {
|
|
119
54
|
const idSchemaField = this.entityConfiguration2.schema.get(this.entityConfiguration2.idField);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StubDatabaseAdapter.js","sourceRoot":"","sources":["../../src/StubDatabaseAdapter.ts"],"names":[],"mappings":";;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"StubDatabaseAdapter.js","sourceRoot":"","sources":["../../src/StubDatabaseAdapter.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/entity-testing-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0",
|
|
4
4
|
"description": "A package containing utilities for testing applications that use Entity",
|
|
5
5
|
"files": [
|
|
6
6
|
"build",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"author": "Expo",
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@expo/entity": "^0.
|
|
30
|
+
"@expo/entity": "^0.57.0",
|
|
31
31
|
"lodash": "^4.17.21",
|
|
32
32
|
"ts-mockito": "^2.6.1"
|
|
33
33
|
},
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@jest/globals": "30.2.0",
|
|
39
|
-
"@types/lodash": "4.17.
|
|
40
|
-
"@types/node": "24.10.
|
|
39
|
+
"@types/lodash": "4.17.24",
|
|
40
|
+
"@types/node": "24.10.13",
|
|
41
41
|
"typescript": "5.9.3"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "e876cfb27bb9b0004d81b40c9067481e3e0c2beb"
|
|
44
44
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
EntityPrivacyPolicyEvaluationContext,
|
|
3
2
|
EntityQueryContext,
|
|
4
3
|
ReadonlyEntity,
|
|
5
4
|
ViewerContext,
|
|
6
5
|
PrivacyPolicyRule,
|
|
7
6
|
RuleEvaluationResult,
|
|
7
|
+
EntityPrivacyPolicyRuleEvaluationContext,
|
|
8
8
|
} from '@expo/entity';
|
|
9
9
|
import { describe, expect, test } from '@jest/globals';
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ export interface Case<
|
|
|
17
17
|
> {
|
|
18
18
|
viewerContext: TViewerContext;
|
|
19
19
|
queryContext: EntityQueryContext;
|
|
20
|
-
evaluationContext:
|
|
20
|
+
evaluationContext: EntityPrivacyPolicyRuleEvaluationContext<
|
|
21
21
|
TFields,
|
|
22
22
|
TIDField,
|
|
23
23
|
TViewerContext,
|
|
@@ -3,11 +3,7 @@ import {
|
|
|
3
3
|
EntityDatabaseAdapter,
|
|
4
4
|
FieldTransformerMap,
|
|
5
5
|
IntField,
|
|
6
|
-
OrderByOrdering,
|
|
7
6
|
StringField,
|
|
8
|
-
TableFieldMultiValueEqualityCondition,
|
|
9
|
-
TableFieldSingleValueEqualityCondition,
|
|
10
|
-
TableQuerySelectionModifiers,
|
|
11
7
|
computeIfAbsent,
|
|
12
8
|
getDatabaseFieldForEntityField,
|
|
13
9
|
mapMap,
|
|
@@ -83,101 +79,19 @@ export class StubDatabaseAdapter<
|
|
|
83
79
|
return [...results];
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
columnName: string;
|
|
89
|
-
order: OrderByOrdering;
|
|
90
|
-
}[],
|
|
91
|
-
objectA: { [key: string]: any },
|
|
92
|
-
objectB: { [key: string]: any },
|
|
93
|
-
): 0 | 1 | -1 {
|
|
94
|
-
if (orderBys.length === 0) {
|
|
95
|
-
return 0;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const currentOrderBy = orderBys[0]!;
|
|
99
|
-
const aField = objectA[currentOrderBy.columnName];
|
|
100
|
-
const bField = objectB[currentOrderBy.columnName];
|
|
101
|
-
switch (currentOrderBy.order) {
|
|
102
|
-
case OrderByOrdering.DESCENDING: {
|
|
103
|
-
// simulate NULLS FIRST for DESC
|
|
104
|
-
if (aField === null && bField === null) {
|
|
105
|
-
return 0;
|
|
106
|
-
} else if (aField === null) {
|
|
107
|
-
return -1;
|
|
108
|
-
} else if (bField === null) {
|
|
109
|
-
return 1;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return aField > bField
|
|
113
|
-
? -1
|
|
114
|
-
: aField < bField
|
|
115
|
-
? 1
|
|
116
|
-
: this.compareByOrderBys(orderBys.slice(1), objectA, objectB);
|
|
117
|
-
}
|
|
118
|
-
case OrderByOrdering.ASCENDING: {
|
|
119
|
-
// simulate NULLS LAST for ASC
|
|
120
|
-
if (aField === null && bField === null) {
|
|
121
|
-
return 0;
|
|
122
|
-
} else if (bField === null) {
|
|
123
|
-
return -1;
|
|
124
|
-
} else if (aField === null) {
|
|
125
|
-
return 1;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return bField > aField
|
|
129
|
-
? -1
|
|
130
|
-
: bField < aField
|
|
131
|
-
? 1
|
|
132
|
-
: this.compareByOrderBys(orderBys.slice(1), objectA, objectB);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
protected async fetchManyByFieldEqualityConjunctionInternalAsync(
|
|
138
|
-
_queryInterface: any,
|
|
82
|
+
protected async fetchOneWhereInternalAsync(
|
|
83
|
+
queryInterface: any,
|
|
139
84
|
tableName: string,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
filteredObjects = filteredObjects.filter((obj) => tableValues.includes(obj[tableField]));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const orderBy = querySelectionModifiers.orderBy;
|
|
154
|
-
if (orderBy !== undefined) {
|
|
155
|
-
filteredObjects = filteredObjects.sort((a, b) =>
|
|
156
|
-
StubDatabaseAdapter.compareByOrderBys(orderBy, a, b),
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const offset = querySelectionModifiers.offset;
|
|
161
|
-
if (offset !== undefined) {
|
|
162
|
-
filteredObjects = filteredObjects.slice(offset);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const limit = querySelectionModifiers.limit;
|
|
166
|
-
if (limit !== undefined) {
|
|
167
|
-
filteredObjects = filteredObjects.slice(0, 0 + limit);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return filteredObjects;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
protected fetchManyByRawWhereClauseInternalAsync(
|
|
174
|
-
_queryInterface: any,
|
|
175
|
-
_tableName: string,
|
|
176
|
-
_rawWhereClause: string,
|
|
177
|
-
_bindings: object | any[],
|
|
178
|
-
_querySelectionModifiers: TableQuerySelectionModifiers,
|
|
179
|
-
): Promise<object[]> {
|
|
180
|
-
throw new Error('Raw WHERE clauses not supported for StubDatabaseAdapter');
|
|
85
|
+
tableColumns: readonly string[],
|
|
86
|
+
tableTuple: readonly any[],
|
|
87
|
+
): Promise<object | null> {
|
|
88
|
+
const results = await this.fetchManyWhereInternalAsync(
|
|
89
|
+
queryInterface,
|
|
90
|
+
tableName,
|
|
91
|
+
tableColumns,
|
|
92
|
+
[tableTuple],
|
|
93
|
+
);
|
|
94
|
+
return results[0] ?? null;
|
|
181
95
|
}
|
|
182
96
|
|
|
183
97
|
private generateRandomID(): any {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
EntityPrivacyPolicyEvaluationContext,
|
|
3
2
|
EntityQueryContext,
|
|
4
3
|
ViewerContext,
|
|
5
4
|
AlwaysAllowPrivacyPolicyRule,
|
|
6
5
|
AlwaysDenyPrivacyPolicyRule,
|
|
6
|
+
EntityPrivacyPolicyRuleEvaluationContext,
|
|
7
7
|
} from '@expo/entity';
|
|
8
8
|
import { describe } from '@jest/globals';
|
|
9
9
|
import { anything, instance, mock } from 'ts-mockito';
|
|
@@ -20,7 +20,7 @@ describe(describePrivacyPolicyRuleWithAsyncTestCase, () => {
|
|
|
20
20
|
viewerContext: instance(mock(ViewerContext)),
|
|
21
21
|
queryContext: instance(mock(EntityQueryContext)),
|
|
22
22
|
evaluationContext:
|
|
23
|
-
instance(mock<
|
|
23
|
+
instance(mock<EntityPrivacyPolicyRuleEvaluationContext<any, any, any, any, any>>()),
|
|
24
24
|
entity: anything(),
|
|
25
25
|
}),
|
|
26
26
|
],
|
|
@@ -35,7 +35,7 @@ describe(describePrivacyPolicyRuleWithAsyncTestCase, () => {
|
|
|
35
35
|
viewerContext: instance(mock(ViewerContext)),
|
|
36
36
|
queryContext: instance(mock(EntityQueryContext)),
|
|
37
37
|
evaluationContext:
|
|
38
|
-
instance(mock<
|
|
38
|
+
instance(mock<EntityPrivacyPolicyRuleEvaluationContext<any, any, any, any, any>>()),
|
|
39
39
|
entity: anything(),
|
|
40
40
|
}),
|
|
41
41
|
],
|
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
CompositeFieldHolder,
|
|
3
3
|
CompositeFieldValueHolder,
|
|
4
4
|
EntityQueryContext,
|
|
5
|
-
OrderByOrdering,
|
|
6
5
|
SingleFieldHolder,
|
|
7
6
|
SingleFieldValueHolder,
|
|
8
7
|
} from '@expo/entity';
|
|
@@ -125,8 +124,8 @@ describe(StubDatabaseAdapter, () => {
|
|
|
125
124
|
});
|
|
126
125
|
});
|
|
127
126
|
|
|
128
|
-
describe('
|
|
129
|
-
it('
|
|
127
|
+
describe('fetchOneWhereAsync', () => {
|
|
128
|
+
it('fetches one where single', async () => {
|
|
130
129
|
const queryContext = instance(mock(EntityQueryContext));
|
|
131
130
|
const databaseAdapter = new StubDatabaseAdapter<TestFields, 'customIdField'>(
|
|
132
131
|
testEntityConfiguration,
|
|
@@ -139,16 +138,8 @@ describe(StubDatabaseAdapter, () => {
|
|
|
139
138
|
{
|
|
140
139
|
customIdField: 'hello',
|
|
141
140
|
testIndexedField: 'h1',
|
|
142
|
-
intField:
|
|
143
|
-
stringField: '
|
|
144
|
-
dateField: new Date(),
|
|
145
|
-
nullableField: null,
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
customIdField: 'world',
|
|
149
|
-
testIndexedField: 'h2',
|
|
150
|
-
intField: 3,
|
|
151
|
-
stringField: 'b',
|
|
141
|
+
intField: 5,
|
|
142
|
+
stringField: 'huh',
|
|
152
143
|
dateField: new Date(),
|
|
153
144
|
nullableField: null,
|
|
154
145
|
},
|
|
@@ -156,7 +147,7 @@ describe(StubDatabaseAdapter, () => {
|
|
|
156
147
|
customIdField: 'world',
|
|
157
148
|
testIndexedField: 'h2',
|
|
158
149
|
intField: 3,
|
|
159
|
-
stringField: '
|
|
150
|
+
stringField: 'huh',
|
|
160
151
|
dateField: new Date(),
|
|
161
152
|
nullableField: null,
|
|
162
153
|
},
|
|
@@ -166,101 +157,32 @@ describe(StubDatabaseAdapter, () => {
|
|
|
166
157
|
),
|
|
167
158
|
);
|
|
168
159
|
|
|
169
|
-
const
|
|
160
|
+
const result = await databaseAdapter.fetchOneWhereAsync(
|
|
170
161
|
queryContext,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
fieldName: 'customIdField',
|
|
174
|
-
fieldValues: ['hello', 'world'],
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
fieldName: 'intField',
|
|
178
|
-
fieldValue: 3,
|
|
179
|
-
},
|
|
180
|
-
],
|
|
181
|
-
{
|
|
182
|
-
limit: 2,
|
|
183
|
-
offset: 1,
|
|
184
|
-
orderBy: [
|
|
185
|
-
{
|
|
186
|
-
fieldName: 'stringField',
|
|
187
|
-
order: OrderByOrdering.DESCENDING,
|
|
188
|
-
},
|
|
189
|
-
],
|
|
190
|
-
},
|
|
162
|
+
new SingleFieldHolder('stringField'),
|
|
163
|
+
new SingleFieldValueHolder('huh'),
|
|
191
164
|
);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
165
|
+
expect(result).toMatchObject({
|
|
166
|
+
stringField: 'huh',
|
|
167
|
+
});
|
|
195
168
|
});
|
|
196
169
|
|
|
197
|
-
it('
|
|
170
|
+
it('returns null when no record found', async () => {
|
|
198
171
|
const queryContext = instance(mock(EntityQueryContext));
|
|
199
172
|
const databaseAdapter = new StubDatabaseAdapter<TestFields, 'customIdField'>(
|
|
200
173
|
testEntityConfiguration,
|
|
201
|
-
|
|
202
|
-
testEntityConfiguration,
|
|
203
|
-
new Map([
|
|
204
|
-
[
|
|
205
|
-
testEntityConfiguration.tableName,
|
|
206
|
-
[
|
|
207
|
-
{
|
|
208
|
-
customIdField: 'hello',
|
|
209
|
-
testIndexedField: 'h1',
|
|
210
|
-
intField: 3,
|
|
211
|
-
stringField: 'a',
|
|
212
|
-
dateField: new Date(),
|
|
213
|
-
nullableField: null,
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
customIdField: 'world',
|
|
217
|
-
testIndexedField: 'h2',
|
|
218
|
-
intField: 3,
|
|
219
|
-
stringField: 'b',
|
|
220
|
-
dateField: new Date(),
|
|
221
|
-
nullableField: null,
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
customIdField: 'world',
|
|
225
|
-
testIndexedField: 'h2',
|
|
226
|
-
intField: 3,
|
|
227
|
-
stringField: 'c',
|
|
228
|
-
dateField: new Date(),
|
|
229
|
-
nullableField: null,
|
|
230
|
-
},
|
|
231
|
-
],
|
|
232
|
-
],
|
|
233
|
-
]),
|
|
234
|
-
),
|
|
174
|
+
new Map(),
|
|
235
175
|
);
|
|
236
176
|
|
|
237
|
-
const
|
|
177
|
+
const result = await databaseAdapter.fetchOneWhereAsync(
|
|
238
178
|
queryContext,
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
fieldName: 'intField',
|
|
242
|
-
fieldValue: 3,
|
|
243
|
-
},
|
|
244
|
-
],
|
|
245
|
-
{
|
|
246
|
-
orderBy: [
|
|
247
|
-
{
|
|
248
|
-
fieldName: 'intField',
|
|
249
|
-
order: OrderByOrdering.DESCENDING,
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
fieldName: 'stringField',
|
|
253
|
-
order: OrderByOrdering.DESCENDING,
|
|
254
|
-
},
|
|
255
|
-
],
|
|
256
|
-
},
|
|
179
|
+
new SingleFieldHolder('stringField'),
|
|
180
|
+
new SingleFieldValueHolder('huh'),
|
|
257
181
|
);
|
|
258
|
-
|
|
259
|
-
expect(results).toHaveLength(3);
|
|
260
|
-
expect(results.map((e) => e.stringField)).toEqual(['c', 'b', 'a']);
|
|
182
|
+
expect(result).toBeNull();
|
|
261
183
|
});
|
|
262
184
|
|
|
263
|
-
it('
|
|
185
|
+
it('fetches one where composite', async () => {
|
|
264
186
|
const queryContext = instance(mock(EntityQueryContext));
|
|
265
187
|
const databaseAdapter = new StubDatabaseAdapter<TestFields, 'customIdField'>(
|
|
266
188
|
testEntityConfiguration,
|
|
@@ -271,34 +193,18 @@ describe(StubDatabaseAdapter, () => {
|
|
|
271
193
|
testEntityConfiguration.tableName,
|
|
272
194
|
[
|
|
273
195
|
{
|
|
274
|
-
customIdField: '
|
|
196
|
+
customIdField: 'hello',
|
|
275
197
|
testIndexedField: 'h1',
|
|
276
|
-
intField:
|
|
277
|
-
stringField: '
|
|
278
|
-
dateField: new Date(),
|
|
279
|
-
nullableField: 'a',
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
customIdField: '2',
|
|
283
|
-
testIndexedField: 'h2',
|
|
284
|
-
intField: 2,
|
|
285
|
-
stringField: 'a',
|
|
286
|
-
dateField: new Date(),
|
|
287
|
-
nullableField: 'b',
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
customIdField: '3',
|
|
291
|
-
testIndexedField: 'h3',
|
|
292
|
-
intField: 3,
|
|
293
|
-
stringField: 'a',
|
|
198
|
+
intField: 5,
|
|
199
|
+
stringField: 'huh',
|
|
294
200
|
dateField: new Date(),
|
|
295
201
|
nullableField: null,
|
|
296
202
|
},
|
|
297
203
|
{
|
|
298
|
-
customIdField: '
|
|
299
|
-
testIndexedField: '
|
|
300
|
-
intField:
|
|
301
|
-
stringField: '
|
|
204
|
+
customIdField: 'world',
|
|
205
|
+
testIndexedField: 'h2',
|
|
206
|
+
intField: 5,
|
|
207
|
+
stringField: 'huh',
|
|
302
208
|
dateField: new Date(),
|
|
303
209
|
nullableField: null,
|
|
304
210
|
},
|
|
@@ -308,44 +214,15 @@ describe(StubDatabaseAdapter, () => {
|
|
|
308
214
|
),
|
|
309
215
|
);
|
|
310
216
|
|
|
311
|
-
const
|
|
217
|
+
const result = await databaseAdapter.fetchOneWhereAsync(
|
|
312
218
|
queryContext,
|
|
313
|
-
|
|
314
|
-
{},
|
|
315
|
-
);
|
|
316
|
-
expect(results).toHaveLength(2);
|
|
317
|
-
expect(results[0]!.nullableField).toBeNull();
|
|
318
|
-
|
|
319
|
-
const results2 = await databaseAdapter.fetchManyByFieldEqualityConjunctionAsync(
|
|
320
|
-
queryContext,
|
|
321
|
-
[
|
|
322
|
-
{ fieldName: 'nullableField', fieldValues: ['a', null] },
|
|
323
|
-
{ fieldName: 'stringField', fieldValue: 'a' },
|
|
324
|
-
],
|
|
325
|
-
{
|
|
326
|
-
orderBy: [
|
|
327
|
-
{
|
|
328
|
-
fieldName: 'nullableField',
|
|
329
|
-
order: OrderByOrdering.DESCENDING,
|
|
330
|
-
},
|
|
331
|
-
],
|
|
332
|
-
},
|
|
333
|
-
);
|
|
334
|
-
expect(results2).toHaveLength(2);
|
|
335
|
-
expect(results2.map((e) => e.nullableField)).toEqual([null, 'a']);
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
describe('fetchManyByRawWhereClauseAsync', () => {
|
|
340
|
-
it('throws because it is unsupported', async () => {
|
|
341
|
-
const queryContext = instance(mock(EntityQueryContext));
|
|
342
|
-
const databaseAdapter = new StubDatabaseAdapter<TestFields, 'customIdField'>(
|
|
343
|
-
testEntityConfiguration,
|
|
344
|
-
new Map(),
|
|
219
|
+
new CompositeFieldHolder<TestFields, 'customIdField'>(['stringField', 'intField']),
|
|
220
|
+
new CompositeFieldValueHolder({ stringField: 'huh', intField: 5 }),
|
|
345
221
|
);
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
222
|
+
expect(result).toMatchObject({
|
|
223
|
+
stringField: 'huh',
|
|
224
|
+
intField: 5,
|
|
225
|
+
});
|
|
349
226
|
});
|
|
350
227
|
});
|
|
351
228
|
|
|
@@ -502,90 +379,6 @@ describe(StubDatabaseAdapter, () => {
|
|
|
502
379
|
'Unsupported ID type for StubDatabaseAdapter: DateField',
|
|
503
380
|
);
|
|
504
381
|
});
|
|
505
|
-
|
|
506
|
-
describe('compareByOrderBys', () => {
|
|
507
|
-
describe('comparison', () => {
|
|
508
|
-
it.each([
|
|
509
|
-
// nulls compare with 0
|
|
510
|
-
[OrderByOrdering.DESCENDING, null, 0, -1],
|
|
511
|
-
[OrderByOrdering.ASCENDING, null, 0, 1],
|
|
512
|
-
[OrderByOrdering.DESCENDING, 0, null, 1],
|
|
513
|
-
[OrderByOrdering.ASCENDING, 0, null, -1],
|
|
514
|
-
|
|
515
|
-
// nulls compare with nulls
|
|
516
|
-
[OrderByOrdering.DESCENDING, null, null, 0],
|
|
517
|
-
[OrderByOrdering.ASCENDING, null, null, 0],
|
|
518
|
-
|
|
519
|
-
// nulls compare with -1
|
|
520
|
-
[OrderByOrdering.DESCENDING, null, -1, -1],
|
|
521
|
-
[OrderByOrdering.ASCENDING, null, -1, 1],
|
|
522
|
-
[OrderByOrdering.DESCENDING, -1, null, 1],
|
|
523
|
-
[OrderByOrdering.ASCENDING, -1, null, -1],
|
|
524
|
-
|
|
525
|
-
// basic compares
|
|
526
|
-
[OrderByOrdering.ASCENDING, 'a', 'b', -1],
|
|
527
|
-
[OrderByOrdering.ASCENDING, 'b', 'a', 1],
|
|
528
|
-
[OrderByOrdering.DESCENDING, 'a', 'b', 1],
|
|
529
|
-
[OrderByOrdering.DESCENDING, 'b', 'a', -1],
|
|
530
|
-
])('case (%p; %p; %p)', (order, v1, v2, expectedResult) => {
|
|
531
|
-
expect(
|
|
532
|
-
StubDatabaseAdapter['compareByOrderBys'](
|
|
533
|
-
[
|
|
534
|
-
{
|
|
535
|
-
columnName: 'hello',
|
|
536
|
-
order,
|
|
537
|
-
},
|
|
538
|
-
],
|
|
539
|
-
{
|
|
540
|
-
hello: v1,
|
|
541
|
-
},
|
|
542
|
-
{
|
|
543
|
-
hello: v2,
|
|
544
|
-
},
|
|
545
|
-
),
|
|
546
|
-
).toEqual(expectedResult);
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
it('works for empty', () => {
|
|
550
|
-
expect(
|
|
551
|
-
StubDatabaseAdapter['compareByOrderBys'](
|
|
552
|
-
[],
|
|
553
|
-
{
|
|
554
|
-
hello: 'test',
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
hello: 'blah',
|
|
558
|
-
},
|
|
559
|
-
),
|
|
560
|
-
).toEqual(0);
|
|
561
|
-
});
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
describe('recursing', () => {
|
|
565
|
-
expect(
|
|
566
|
-
StubDatabaseAdapter['compareByOrderBys'](
|
|
567
|
-
[
|
|
568
|
-
{
|
|
569
|
-
columnName: 'hello',
|
|
570
|
-
order: OrderByOrdering.ASCENDING,
|
|
571
|
-
},
|
|
572
|
-
{
|
|
573
|
-
columnName: 'world',
|
|
574
|
-
order: OrderByOrdering.ASCENDING,
|
|
575
|
-
},
|
|
576
|
-
],
|
|
577
|
-
{
|
|
578
|
-
hello: 'a',
|
|
579
|
-
world: 1,
|
|
580
|
-
},
|
|
581
|
-
{
|
|
582
|
-
hello: 'a',
|
|
583
|
-
world: 2,
|
|
584
|
-
},
|
|
585
|
-
),
|
|
586
|
-
).toEqual(-1);
|
|
587
|
-
});
|
|
588
|
-
});
|
|
589
382
|
});
|
|
590
383
|
|
|
591
384
|
/**
|