@snowtop/ent 0.1.0-alpha9 → 0.1.0-alpha91
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/action/action.d.ts +36 -31
- package/action/action.js +2 -6
- package/action/executor.d.ts +3 -3
- package/action/executor.js +2 -2
- package/action/experimental_action.d.ts +29 -22
- package/action/experimental_action.js +29 -6
- package/action/orchestrator.d.ts +38 -16
- package/action/orchestrator.js +223 -61
- package/action/privacy.d.ts +2 -2
- package/core/base.d.ts +45 -24
- package/core/base.js +7 -1
- package/core/clause.d.ts +83 -7
- package/core/clause.js +334 -63
- package/core/config.d.ts +8 -0
- package/core/config.js +5 -1
- package/core/context.d.ts +5 -3
- package/core/context.js +20 -2
- package/core/convert.d.ts +1 -1
- package/core/db.d.ts +2 -2
- package/core/db.js +6 -2
- package/core/ent.d.ts +79 -24
- package/core/ent.js +527 -176
- package/core/loaders/assoc_count_loader.d.ts +3 -2
- package/core/loaders/assoc_count_loader.js +14 -2
- package/core/loaders/assoc_edge_loader.d.ts +2 -2
- package/core/loaders/assoc_edge_loader.js +5 -1
- package/core/loaders/index.d.ts +1 -1
- package/core/loaders/index.js +1 -3
- package/core/loaders/index_loader.d.ts +2 -2
- package/core/loaders/loader.js +5 -5
- package/core/loaders/object_loader.d.ts +6 -5
- package/core/loaders/object_loader.js +67 -59
- package/core/loaders/query_loader.d.ts +6 -12
- package/core/loaders/query_loader.js +52 -11
- package/core/loaders/raw_count_loader.d.ts +2 -2
- package/core/loaders/raw_count_loader.js +5 -1
- package/core/logger.d.ts +1 -1
- package/core/logger.js +1 -0
- package/core/privacy.d.ts +26 -25
- package/core/privacy.js +21 -25
- package/core/query/assoc_query.d.ts +7 -6
- package/core/query/assoc_query.js +9 -1
- package/core/query/custom_clause_query.d.ts +26 -0
- package/core/query/custom_clause_query.js +78 -0
- package/core/query/custom_query.d.ts +20 -5
- package/core/query/custom_query.js +87 -12
- package/core/query/index.d.ts +1 -0
- package/core/query/index.js +3 -1
- package/core/query/query.d.ts +8 -4
- package/core/query/query.js +101 -53
- package/core/query/shared_assoc_test.d.ts +2 -1
- package/core/query/shared_assoc_test.js +34 -43
- package/core/query/shared_test.d.ts +8 -1
- package/core/query/shared_test.js +470 -236
- package/core/viewer.d.ts +3 -3
- package/core/viewer.js +1 -1
- package/graphql/graphql.js +16 -6
- package/graphql/query/edge_connection.d.ts +9 -9
- package/graphql/query/page_info.d.ts +1 -1
- package/graphql/query/shared_edge_connection.js +1 -15
- package/imports/index.js +5 -1
- package/index.d.ts +11 -5
- package/index.js +20 -7
- package/package.json +1 -1
- package/parse_schema/parse.d.ts +12 -3
- package/parse_schema/parse.js +70 -11
- package/schema/base_schema.js +3 -0
- package/schema/field.d.ts +44 -8
- package/schema/field.js +136 -10
- package/schema/index.d.ts +2 -2
- package/schema/index.js +5 -1
- package/schema/json_field.d.ts +13 -1
- package/schema/json_field.js +28 -1
- package/schema/schema.d.ts +66 -11
- package/schema/schema.js +18 -4
- package/schema/struct_field.d.ts +11 -1
- package/schema/struct_field.js +44 -5
- package/scripts/custom_compiler.js +10 -6
- package/scripts/custom_graphql.js +13 -4
- package/scripts/{transform_schema.d.ts → migrate_v0.1.d.ts} +0 -0
- package/scripts/migrate_v0.1.js +36 -0
- package/scripts/read_schema.js +20 -5
- package/testutils/builder.d.ts +31 -21
- package/testutils/builder.js +83 -29
- package/testutils/db/fixture.d.ts +10 -0
- package/testutils/db/fixture.js +26 -0
- package/testutils/db/{test_db.d.ts → temp_db.d.ts} +20 -7
- package/testutils/db/{test_db.js → temp_db.js} +102 -36
- package/testutils/db/value.d.ts +6 -0
- package/testutils/db/value.js +251 -0
- package/testutils/db_mock.js +3 -1
- package/testutils/db_time_zone.d.ts +4 -0
- package/testutils/db_time_zone.js +41 -0
- package/testutils/ent-graphql-tests/index.js +8 -1
- package/testutils/fake_data/const.d.ts +2 -1
- package/testutils/fake_data/const.js +3 -0
- package/testutils/fake_data/fake_contact.d.ts +7 -4
- package/testutils/fake_data/fake_contact.js +14 -6
- package/testutils/fake_data/fake_event.d.ts +5 -3
- package/testutils/fake_data/fake_event.js +8 -5
- package/testutils/fake_data/fake_tag.d.ts +35 -0
- package/testutils/fake_data/fake_tag.js +88 -0
- package/testutils/fake_data/fake_user.d.ts +6 -4
- package/testutils/fake_data/fake_user.js +16 -13
- package/testutils/fake_data/index.js +5 -1
- package/testutils/fake_data/internal.d.ts +2 -0
- package/testutils/fake_data/internal.js +7 -1
- package/testutils/fake_data/tag_query.d.ts +13 -0
- package/testutils/fake_data/tag_query.js +43 -0
- package/testutils/fake_data/test_helpers.d.ts +11 -4
- package/testutils/fake_data/test_helpers.js +28 -12
- package/testutils/fake_data/user_query.d.ts +13 -6
- package/testutils/fake_data/user_query.js +54 -22
- package/testutils/fake_log.d.ts +3 -3
- package/testutils/parse_sql.d.ts +6 -0
- package/testutils/parse_sql.js +16 -2
- package/testutils/test_edge_global_schema.d.ts +15 -0
- package/testutils/test_edge_global_schema.js +62 -0
- package/testutils/write.d.ts +2 -2
- package/testutils/write.js +33 -7
- package/tsc/ast.d.ts +44 -0
- package/tsc/ast.js +271 -0
- package/tsc/compilerOptions.d.ts +6 -0
- package/tsc/compilerOptions.js +45 -2
- package/tsc/move_generated.d.ts +1 -0
- package/tsc/move_generated.js +164 -0
- package/tsc/transform.d.ts +21 -0
- package/tsc/transform.js +171 -0
- package/tsc/transform_action.d.ts +22 -0
- package/tsc/transform_action.js +183 -0
- package/tsc/transform_ent.d.ts +17 -0
- package/tsc/transform_ent.js +59 -0
- package/tsc/transform_schema.d.ts +27 -0
- package/tsc/transform_schema.js +383 -0
- package/scripts/transform_schema.js +0 -445
|
@@ -1,190 +1,306 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.commonTests = void 0;
|
|
4
|
-
const db_mock_1 = require("../../testutils/db_mock");
|
|
5
4
|
const ent_1 = require("../ent");
|
|
6
5
|
const viewer_1 = require("../viewer");
|
|
7
6
|
const index_1 = require("../../testutils/fake_data/index");
|
|
8
7
|
const test_helpers_1 = require("../../testutils/fake_data/test_helpers");
|
|
9
|
-
const
|
|
8
|
+
const temp_db_1 = require("../../testutils/db/temp_db");
|
|
10
9
|
const test_context_1 = require("../../testutils/context/test_context");
|
|
11
10
|
const logger_1 = require("../logger");
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
const test_edge_global_schema_1 = require("../../testutils/test_edge_global_schema");
|
|
12
|
+
const builder_1 = require("../../testutils/builder");
|
|
13
|
+
const action_1 = require("../../action");
|
|
14
|
+
const clause_1 = require("../clause");
|
|
15
|
+
function getWhereClause(query) {
|
|
16
|
+
const idx = query.query.indexOf("WHERE");
|
|
17
|
+
if (idx !== -1) {
|
|
18
|
+
return query.query.substr(idx + 6);
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
async testIDs() {
|
|
33
|
-
const ids = await this.getQuery().queryIDs();
|
|
34
|
-
this.verifyIDs(ids);
|
|
35
|
-
}
|
|
36
|
-
verifyIDs(ids) {
|
|
37
|
-
expect(ids).toEqual(this.filteredContacts.map((contact) => contact.id));
|
|
38
|
-
}
|
|
39
|
-
// rawCount isn't affected by filters...
|
|
40
|
-
async testRawCount() {
|
|
41
|
-
const count = await this.getQuery().queryRawCount();
|
|
42
|
-
this.verifyRawCount(count);
|
|
43
|
-
}
|
|
44
|
-
verifyRawCount(count) {
|
|
45
|
-
expect(count).toBe(test_helpers_1.inputs.length);
|
|
46
|
-
}
|
|
47
|
-
async testCount() {
|
|
48
|
-
const count = await this.getQuery().queryCount();
|
|
49
|
-
this.verifyCount(count);
|
|
50
|
-
}
|
|
51
|
-
verifyCount(count) {
|
|
52
|
-
expect(count).toBe(this.filteredContacts.length);
|
|
53
|
-
}
|
|
54
|
-
async testEdges() {
|
|
55
|
-
const edges = await this.getQuery().queryEdges();
|
|
56
|
-
this.verifyEdges(edges);
|
|
57
|
-
}
|
|
58
|
-
verifyEdges(edges) {
|
|
59
|
-
const q = this.getQuery();
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const commonTests = (opts) => {
|
|
23
|
+
(0, logger_1.setLogLevels)(["query", "error"]);
|
|
24
|
+
const ml = opts.ml;
|
|
25
|
+
ml.mock();
|
|
26
|
+
function isCustomQuery(q) {
|
|
27
|
+
if (q.customQuery !== undefined) {
|
|
28
|
+
return q.customQuery;
|
|
29
|
+
}
|
|
60
30
|
// TODO sad not generic enough
|
|
61
|
-
|
|
62
|
-
|
|
31
|
+
return (q instanceof index_1.UserToContactsFkeyQuery ||
|
|
32
|
+
q instanceof index_1.UserToContactsFkeyQueryDeprecated ||
|
|
33
|
+
q instanceof index_1.UserToContactsFkeyQueryAsc);
|
|
34
|
+
}
|
|
35
|
+
class TestQueryFilter {
|
|
36
|
+
constructor(filter, newQuery, ents, defaultViewer) {
|
|
37
|
+
this.filter = filter;
|
|
38
|
+
this.newQuery = newQuery;
|
|
39
|
+
this.ents = ents;
|
|
40
|
+
this.defaultViewer = defaultViewer;
|
|
41
|
+
this.allContacts = [];
|
|
42
|
+
this.filteredContacts = [];
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
const q = this.newQuery(this.defaultViewer);
|
|
45
|
+
this.customQuery = isCustomQuery(q);
|
|
63
46
|
}
|
|
64
|
-
|
|
65
|
-
|
|
47
|
+
async createData() {
|
|
48
|
+
[this.user, this.allContacts] = await (0, test_helpers_1.createAllContacts)();
|
|
49
|
+
// this.allContacts = this.allContacts.reverse();
|
|
50
|
+
this.filteredContacts = this.ents(this.allContacts);
|
|
51
|
+
ml.clear();
|
|
66
52
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const query = this.getQuery(new viewer_1.IDViewer(this.user.id));
|
|
77
|
-
const [edges, count, ids, rawCount, ents] = await Promise.all([
|
|
78
|
-
query.queryEdges(),
|
|
79
|
-
query.queryCount(),
|
|
80
|
-
query.queryIDs(),
|
|
81
|
-
query.queryRawCount(),
|
|
82
|
-
query.queryEnts(),
|
|
83
|
-
]);
|
|
84
|
-
this.verifyCount(count);
|
|
85
|
-
this.verifyEdges(edges);
|
|
86
|
-
this.verifyIDs(ids);
|
|
87
|
-
this.verifyRawCount(rawCount);
|
|
88
|
-
this.verifyEnts(ents);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const preparedVar = /(\$(\d))/g;
|
|
92
|
-
const commonTests = (opts) => {
|
|
93
|
-
function verifyQuery({ length = 1, numQueries = 1, limit = ent_1.DefaultLimit, disablePaginationBump = false, }) {
|
|
94
|
-
if (opts.livePostgresDB || opts.sqlite) {
|
|
95
|
-
return;
|
|
53
|
+
getQuery(viewer) {
|
|
54
|
+
return this.filter(this.newQuery(viewer || this.defaultViewer, this.user), this.user, this.allContacts);
|
|
55
|
+
}
|
|
56
|
+
async testIDs() {
|
|
57
|
+
const ids = await this.getQuery().queryIDs();
|
|
58
|
+
this.verifyIDs(ids);
|
|
59
|
+
}
|
|
60
|
+
verifyIDs(ids) {
|
|
61
|
+
expect(ids).toEqual(this.filteredContacts.map((contact) => contact.id));
|
|
96
62
|
}
|
|
97
|
-
|
|
98
|
-
|
|
63
|
+
// rawCount isn't affected by filters...
|
|
64
|
+
async testRawCount(expectedCount) {
|
|
65
|
+
const count = await this.getQuery().queryRawCount();
|
|
66
|
+
this.verifyRawCount(count, expectedCount);
|
|
67
|
+
}
|
|
68
|
+
verifyRawCount(count, expectedCount) {
|
|
69
|
+
expect(count).toBe(expectedCount ?? test_helpers_1.inputs.length);
|
|
70
|
+
}
|
|
71
|
+
async testCount(expectedCount) {
|
|
72
|
+
const count = await this.getQuery().queryCount();
|
|
73
|
+
this.verifyCount(count, expectedCount);
|
|
74
|
+
}
|
|
75
|
+
verifyCount(count, expectedCount) {
|
|
76
|
+
expect(count).toBe(expectedCount ?? this.filteredContacts.length);
|
|
77
|
+
}
|
|
78
|
+
async testEdges() {
|
|
79
|
+
const edges = await this.getQuery().queryEdges();
|
|
80
|
+
this.verifyEdges(edges);
|
|
81
|
+
}
|
|
82
|
+
verifyEdges(edges) {
|
|
83
|
+
const q = this.getQuery();
|
|
84
|
+
// TODO sad not generic enough
|
|
85
|
+
if (this.customQuery) {
|
|
86
|
+
(0, test_helpers_1.verifyUserToContactRawData)(this.user, edges, this.filteredContacts);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
(0, test_helpers_1.verifyUserToContactEdges)(this.user, edges, this.filteredContacts);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async testEnts(v) {
|
|
93
|
+
const ents = await this.getQuery(v || new viewer_1.IDViewer(this.user.id)).queryEnts();
|
|
94
|
+
this.verifyEnts(ents);
|
|
95
|
+
return ents;
|
|
96
|
+
}
|
|
97
|
+
async testEntsCache() {
|
|
98
|
+
if (!this.customQuery) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
(0, logger_1.setLogLevels)(["query", "cache"]);
|
|
102
|
+
const v = new test_context_1.TestContext(new viewer_1.IDViewer(this.user.id)).getViewer();
|
|
103
|
+
const ents = await this.testEnts(v);
|
|
104
|
+
expect(ml.logs.length).toBe(1);
|
|
105
|
+
expect(ml.logs[0].query).toMatch(/SELECT (.+) FROM /);
|
|
106
|
+
await Promise.all(ents.map((ent) => index_1.FakeContact.loadX(v, ent.id)));
|
|
107
|
+
expect(ml.logs.length).toBe(this.filteredContacts.length + 1);
|
|
108
|
+
for (const log of ml.logs.slice(1)) {
|
|
109
|
+
expect(log["ent-cache-hit"]).toBeDefined();
|
|
110
|
+
}
|
|
111
|
+
// "restore" back to previous
|
|
112
|
+
(0, logger_1.setLogLevels)("query");
|
|
113
|
+
}
|
|
114
|
+
async testDataCache() {
|
|
115
|
+
if (!this.customQuery) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
(0, logger_1.setLogLevels)(["query", "cache"]);
|
|
119
|
+
const v = new test_context_1.TestContext(new viewer_1.IDViewer(this.user.id)).getViewer();
|
|
120
|
+
const ents = await this.testEnts(v);
|
|
121
|
+
expect(ml.logs.length).toBe(1);
|
|
122
|
+
expect(ml.logs[0].query).toMatch(/SELECT (.+) FROM /);
|
|
123
|
+
await Promise.all(ents.map((ent) => index_1.FakeContact.loadRawData(ent.id, v.context)));
|
|
124
|
+
expect(ml.logs.length).toBe(this.filteredContacts.length + 1);
|
|
125
|
+
for (const log of ml.logs.slice(1)) {
|
|
126
|
+
expect(log["dataloader-cache-hit"]).toBeDefined();
|
|
127
|
+
}
|
|
128
|
+
// "restore" back to previous
|
|
129
|
+
(0, logger_1.setLogLevels)("query");
|
|
130
|
+
}
|
|
131
|
+
verifyEnts(ents) {
|
|
132
|
+
(0, test_helpers_1.verifyUserToContacts)(this.user, ents, this.filteredContacts);
|
|
133
|
+
}
|
|
134
|
+
async testAll(expectedCount) {
|
|
135
|
+
const query = this.getQuery(new viewer_1.IDViewer(this.user.id));
|
|
136
|
+
const [edges, count, ids, rawCount, ents] = await Promise.all([
|
|
137
|
+
query.queryEdges(),
|
|
138
|
+
query.queryCount(),
|
|
139
|
+
query.queryIDs(),
|
|
140
|
+
query.queryRawCount(),
|
|
141
|
+
query.queryEnts(),
|
|
142
|
+
]);
|
|
143
|
+
this.verifyCount(count, expectedCount);
|
|
144
|
+
this.verifyEdges(edges);
|
|
145
|
+
this.verifyIDs(ids);
|
|
146
|
+
this.verifyRawCount(rawCount, expectedCount);
|
|
147
|
+
this.verifyEnts(ents);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function verifyQuery(filter, { length = 1, numQueries = 1, limit = ent_1.DefaultLimit, disablePaginationBump = false, orderby = opts.orderby, }) {
|
|
151
|
+
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
152
|
+
expect(ml.logs.length).toBe(length);
|
|
99
153
|
for (let i = 0; i < numQueries; i++) {
|
|
100
|
-
const
|
|
154
|
+
const whereClause = getWhereClause(ml.logs[i]);
|
|
101
155
|
let expLimit = disablePaginationBump ? limit : limit + 1;
|
|
102
|
-
expect(
|
|
156
|
+
expect(whereClause, `${i}`).toBe(
|
|
103
157
|
// default limit
|
|
104
|
-
`${opts.
|
|
158
|
+
`${opts.clause.clause(1)} ORDER BY ${opts.sortCol} ${orderby}, ${uniqCol} ${orderby} LIMIT ${expLimit}`);
|
|
105
159
|
}
|
|
106
160
|
}
|
|
107
161
|
function verifyCountQuery({ length = 1, numQueries = 1 }) {
|
|
108
|
-
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const queries = db_mock_1.QueryRecorder.getCurrentQueries();
|
|
112
|
-
expect(queries.length).toBe(length);
|
|
162
|
+
expect(ml.logs.length).toBe(length);
|
|
113
163
|
for (let i = 0; i < numQueries; i++) {
|
|
114
|
-
const
|
|
115
|
-
expect(
|
|
116
|
-
expect(query.qs?.columns).toHaveLength(1);
|
|
117
|
-
expect(query.qs?.columns).toStrictEqual(["count(1) as count"]);
|
|
164
|
+
const whereClause = getWhereClause(ml.logs[i]);
|
|
165
|
+
expect(whereClause).toBe(opts.clause.clause(1));
|
|
118
166
|
}
|
|
119
167
|
}
|
|
120
|
-
function verifyFirstAfterCursorQuery(length = 1) {
|
|
121
|
-
|
|
122
|
-
|
|
168
|
+
function verifyFirstAfterCursorQuery(filter, length = 1, limit = 3) {
|
|
169
|
+
// cache showing up in a few because of cross runs...
|
|
170
|
+
expect(ml.logs.length).toBeGreaterThanOrEqual(length);
|
|
171
|
+
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
172
|
+
let parts = opts.clause.clause(1).split(" AND ");
|
|
173
|
+
const cmp = (0, clause_1.PaginationMultipleColsSubQuery)(opts.sortCol, opts.orderby === "DESC" ? "<" : ">", opts.tableName, uniqCol, "").clause(opts.clause.values().length + 1);
|
|
174
|
+
if (parts[parts.length - 1] === "deleted_at IS NULL") {
|
|
175
|
+
parts = parts
|
|
176
|
+
.slice(0, parts.length - 1)
|
|
177
|
+
.concat([cmp, "deleted_at IS NULL"]);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
parts.push(cmp);
|
|
123
181
|
}
|
|
124
|
-
|
|
125
|
-
expect(queries.length).toBe(length);
|
|
126
|
-
const query = queries[0];
|
|
127
|
-
const result = [...opts.where.matchAll(preparedVar)];
|
|
128
|
-
expect(query.qs?.whereClause).toBe(`${opts.where} AND ${opts.sortCol} < $${result.length + 1} ORDER BY ${opts.sortCol} DESC LIMIT 4`);
|
|
182
|
+
expect(getWhereClause(ml.logs[0])).toBe(`${parts.join(" AND ")} ORDER BY ${opts.sortCol} ${opts.orderby}, ${uniqCol} ${opts.orderby} LIMIT ${limit + 1}`);
|
|
129
183
|
}
|
|
130
|
-
function verifyLastBeforeCursorQuery(length = 1) {
|
|
131
|
-
|
|
132
|
-
|
|
184
|
+
function verifyLastBeforeCursorQuery(filter, length = 1, limit = 3) {
|
|
185
|
+
// cache showing up in a few because of cross runs...
|
|
186
|
+
expect(ml.logs.length).toBeGreaterThanOrEqual(length);
|
|
187
|
+
const uniqCol = isCustomQuery(filter) ? "id" : "id2";
|
|
188
|
+
let op = "";
|
|
189
|
+
let orderby = "";
|
|
190
|
+
if (opts.orderby === "DESC") {
|
|
191
|
+
op = ">";
|
|
192
|
+
orderby = "ASC";
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
op = "<";
|
|
196
|
+
orderby = "DESC";
|
|
197
|
+
}
|
|
198
|
+
let parts = opts.clause.clause(1).split(" AND ");
|
|
199
|
+
const cmp = (0, clause_1.PaginationMultipleColsSubQuery)(opts.sortCol, op, opts.tableName, uniqCol, "").clause(opts.clause.values().length + 1);
|
|
200
|
+
if (parts[parts.length - 1] === "deleted_at IS NULL") {
|
|
201
|
+
parts = parts
|
|
202
|
+
.slice(0, parts.length - 1)
|
|
203
|
+
.concat([cmp, "deleted_at IS NULL"]);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
parts.push(cmp);
|
|
133
207
|
}
|
|
134
|
-
|
|
135
|
-
expect(queries.length).toBe(length);
|
|
136
|
-
const query = queries[0];
|
|
137
|
-
const result = [...opts.where.matchAll(preparedVar)];
|
|
138
|
-
expect(query.qs?.whereClause).toBe(
|
|
208
|
+
expect(getWhereClause(ml.logs[0])).toBe(
|
|
139
209
|
// extra fetched for pagination
|
|
140
|
-
`${
|
|
210
|
+
`${parts.join(" AND ")} ORDER BY ${opts.sortCol} ${orderby}, ${uniqCol} ${orderby} LIMIT ${limit + 1}`);
|
|
141
211
|
}
|
|
142
212
|
function getViewer() {
|
|
143
|
-
// live db, let's do context because we're testing complicated paths
|
|
144
|
-
// may be worth breaking this out later
|
|
145
|
-
// opts.liveDB no context too...
|
|
146
|
-
// maybe this one we just always hit the db
|
|
147
|
-
// we don't get value out of testing parse_sql no context....
|
|
148
|
-
if (opts.livePostgresDB || opts.sqlite) {
|
|
149
|
-
return new test_context_1.TestContext().getViewer();
|
|
150
|
-
}
|
|
151
|
-
// no context when not live db
|
|
152
213
|
return new viewer_1.LoggedOutViewer();
|
|
153
214
|
}
|
|
154
215
|
function getCursorFrom(contacts, idx) {
|
|
155
|
-
// we depend on the fact that the same time is used for the edge and created_at
|
|
156
|
-
// based on getContactBuilder
|
|
157
|
-
// so regardless of if we're doing assoc or custom queries, we can get the time
|
|
158
|
-
// from the created_at field
|
|
159
216
|
return (0, ent_1.getCursor)({
|
|
160
217
|
row: contacts[idx],
|
|
161
|
-
col: "
|
|
162
|
-
conv: (t) => {
|
|
163
|
-
//sqlite
|
|
164
|
-
if (typeof t === "string") {
|
|
165
|
-
return Date.parse(t);
|
|
166
|
-
}
|
|
167
|
-
return t.getTime();
|
|
168
|
-
},
|
|
169
|
-
// we want the right column to be encoded in the cursor as opposed e.g. time for
|
|
170
|
-
// assoc queries, created_at for index/custom queries
|
|
171
|
-
cursorKey: opts.sortCol,
|
|
218
|
+
col: "id",
|
|
172
219
|
});
|
|
173
220
|
}
|
|
221
|
+
function getVerifyAfterEachCursor(edges, pageLength, user) {
|
|
222
|
+
let query;
|
|
223
|
+
async function verify(i, hasEdge, hasNextPage, cursor) {
|
|
224
|
+
ml.clear();
|
|
225
|
+
query = opts.newQuery(getViewer(), user);
|
|
226
|
+
const newEdges = await query.first(pageLength, cursor).queryEdges();
|
|
227
|
+
const pagination = query.paginationInfo().get(user.id);
|
|
228
|
+
if (hasEdge) {
|
|
229
|
+
expect(newEdges[0], `${i}`).toStrictEqual(edges[i]);
|
|
230
|
+
expect(newEdges.length, `${i}`).toBe(edges.length - i >= pageLength ? pageLength : edges.length - i);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
expect(newEdges.length, `${i}`).toBe(0);
|
|
234
|
+
}
|
|
235
|
+
if (hasNextPage) {
|
|
236
|
+
expect(pagination?.hasNextPage, `${i}`).toBe(true);
|
|
237
|
+
expect(pagination?.hasPreviousPage, `${i}`).toBe(false);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
expect(pagination?.hasNextPage, `${i}`).toBe(undefined);
|
|
241
|
+
expect(pagination?.hasNextPage, `${i}`).toBe(undefined);
|
|
242
|
+
}
|
|
243
|
+
if (cursor) {
|
|
244
|
+
verifyFirstAfterCursorQuery(query, 1, pageLength);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
verifyQuery(query, { orderby: opts.orderby, limit: pageLength });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function getCursor(edge) {
|
|
251
|
+
return query.getCursor(edge);
|
|
252
|
+
}
|
|
253
|
+
return { verify, getCursor };
|
|
254
|
+
}
|
|
255
|
+
function getVerifyBeforeEachCursor(edges, pageLength, user) {
|
|
256
|
+
let query;
|
|
257
|
+
async function verify(i, hasEdge, hasPreviousPage, cursor) {
|
|
258
|
+
ml.clear();
|
|
259
|
+
query = opts.newQuery(getViewer(), user);
|
|
260
|
+
const newEdges = await query.last(pageLength, cursor).queryEdges();
|
|
261
|
+
const pagination = query.paginationInfo().get(user.id);
|
|
262
|
+
if (hasEdge) {
|
|
263
|
+
expect(newEdges.length, `${i}`).toBe(i >= pageLength ? pageLength : i + 1);
|
|
264
|
+
expect(newEdges[0], `${i}`).toStrictEqual(edges[i]);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
expect(newEdges.length, `${i}`).toBe(0);
|
|
268
|
+
}
|
|
269
|
+
if (hasPreviousPage) {
|
|
270
|
+
expect(pagination?.hasPreviousPage, `${i}`).toBe(true);
|
|
271
|
+
expect(pagination?.hasNextPage, `${i}`).toBe(false);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
expect(pagination?.hasPreviousPage, `${i}`).toBe(undefined);
|
|
275
|
+
expect(pagination?.hasNextPage, `${i}`).toBe(undefined);
|
|
276
|
+
}
|
|
277
|
+
if (cursor) {
|
|
278
|
+
verifyLastBeforeCursorQuery(query, 1, pageLength);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
verifyQuery(query, {
|
|
282
|
+
orderby: opts.orderby === "DESC" ? "ASC" : "DESC",
|
|
283
|
+
limit: pageLength,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function getCursor(edge) {
|
|
288
|
+
return query.getCursor(edge);
|
|
289
|
+
}
|
|
290
|
+
return { verify, getCursor };
|
|
291
|
+
}
|
|
292
|
+
if (opts.globalSchema) {
|
|
293
|
+
(0, ent_1.setGlobalSchema)(test_edge_global_schema_1.testEdgeGlobalSchema);
|
|
294
|
+
}
|
|
174
295
|
let tdb;
|
|
175
296
|
if (opts.sqlite) {
|
|
176
|
-
|
|
177
|
-
|
|
297
|
+
(0, temp_db_1.setupSqlite)(`sqlite:///shared_test+${opts.uniqKey}.db`, () => (0, test_helpers_1.tempDBTables)(opts.globalSchema), {
|
|
298
|
+
disableDeleteAfterEachTest: true,
|
|
299
|
+
});
|
|
178
300
|
}
|
|
179
301
|
beforeAll(async () => {
|
|
180
|
-
// want error on by default in tests?
|
|
181
|
-
(0, logger_1.setLogLevels)(["error", "warn", "info"]);
|
|
182
|
-
if (opts.livePostgresDB) {
|
|
183
|
-
tdb = await (0, test_helpers_1.setupTempDB)();
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
beforeEach(async () => {
|
|
187
302
|
if (opts.livePostgresDB) {
|
|
303
|
+
tdb = await (0, test_helpers_1.setupTempDB)(opts.globalSchema);
|
|
188
304
|
return;
|
|
189
305
|
}
|
|
190
306
|
await (0, test_helpers_1.createEdges)();
|
|
@@ -196,19 +312,22 @@ const commonTests = (opts) => {
|
|
|
196
312
|
});
|
|
197
313
|
describe("simple queries", () => {
|
|
198
314
|
const filter = new TestQueryFilter((q) => {
|
|
199
|
-
// no
|
|
315
|
+
// no filters
|
|
200
316
|
return q;
|
|
201
317
|
}, opts.newQuery, (contacts) => {
|
|
202
318
|
// nothing to do here
|
|
203
319
|
// reverse because edges are most recent first
|
|
204
|
-
|
|
320
|
+
if (opts.orderby === "DESC") {
|
|
321
|
+
return contacts.reverse();
|
|
322
|
+
}
|
|
323
|
+
return contacts;
|
|
205
324
|
}, getViewer());
|
|
206
325
|
beforeEach(async () => {
|
|
207
|
-
await filter.
|
|
326
|
+
await filter.createData();
|
|
208
327
|
});
|
|
209
328
|
test("ids", async () => {
|
|
210
329
|
await filter.testIDs();
|
|
211
|
-
verifyQuery({});
|
|
330
|
+
verifyQuery(filter, {});
|
|
212
331
|
});
|
|
213
332
|
test("rawCount", async () => {
|
|
214
333
|
await filter.testRawCount();
|
|
@@ -216,19 +335,80 @@ const commonTests = (opts) => {
|
|
|
216
335
|
});
|
|
217
336
|
test("count", async () => {
|
|
218
337
|
await filter.testCount();
|
|
219
|
-
verifyQuery({});
|
|
338
|
+
verifyQuery(filter, {});
|
|
220
339
|
});
|
|
221
340
|
test("edges", async () => {
|
|
222
341
|
await filter.testEdges();
|
|
223
|
-
verifyQuery({});
|
|
342
|
+
verifyQuery(filter, {});
|
|
224
343
|
});
|
|
225
344
|
test("ents", async () => {
|
|
226
345
|
await filter.testEnts();
|
|
227
|
-
verifyQuery({ length: opts.entsLength });
|
|
346
|
+
verifyQuery(filter, { length: opts.entsLength });
|
|
228
347
|
});
|
|
229
348
|
test("all", async () => {
|
|
230
349
|
await filter.testAll();
|
|
231
350
|
});
|
|
351
|
+
test("ents cache", async () => {
|
|
352
|
+
await filter.testEntsCache();
|
|
353
|
+
});
|
|
354
|
+
test("data cache", async () => {
|
|
355
|
+
await filter.testDataCache();
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
describe("after delete", () => {
|
|
359
|
+
const filter = new TestQueryFilter((q) => {
|
|
360
|
+
// no filters
|
|
361
|
+
return q;
|
|
362
|
+
}, opts.newQuery, (contacts) => {
|
|
363
|
+
// nothing expected since deleted
|
|
364
|
+
return [];
|
|
365
|
+
}, getViewer());
|
|
366
|
+
beforeEach(async () => {
|
|
367
|
+
await filter.createData();
|
|
368
|
+
const action = new builder_1.SimpleAction(filter.user.viewer, index_1.FakeUserSchema, new Map(), action_1.WriteOperation.Edit, filter.user);
|
|
369
|
+
await Promise.all(filter.allContacts.map(async (contact) => {
|
|
370
|
+
action.builder.orchestrator.removeOutboundEdge(contact.id, index_1.EdgeType.UserToContacts);
|
|
371
|
+
const action2 = new builder_1.SimpleAction(filter.user.viewer, index_1.FakeContactSchema, new Map(), action_1.WriteOperation.Delete, contact);
|
|
372
|
+
await action2.save();
|
|
373
|
+
}));
|
|
374
|
+
await action.save();
|
|
375
|
+
ml.clear();
|
|
376
|
+
});
|
|
377
|
+
test("ids", async () => {
|
|
378
|
+
await filter.testIDs();
|
|
379
|
+
verifyQuery(filter, {});
|
|
380
|
+
});
|
|
381
|
+
test("rawCount", async () => {
|
|
382
|
+
await filter.testRawCount(0);
|
|
383
|
+
verifyCountQuery({});
|
|
384
|
+
});
|
|
385
|
+
test("count", async () => {
|
|
386
|
+
await filter.testCount(0);
|
|
387
|
+
verifyQuery(filter, {});
|
|
388
|
+
});
|
|
389
|
+
test("edges", async () => {
|
|
390
|
+
await filter.testEdges();
|
|
391
|
+
verifyQuery(filter, {});
|
|
392
|
+
});
|
|
393
|
+
test("ents", async () => {
|
|
394
|
+
await filter.testEnts();
|
|
395
|
+
// no ents so no subsequent query. just the edge query
|
|
396
|
+
verifyQuery(filter, { length: 1 });
|
|
397
|
+
});
|
|
398
|
+
test("all", async () => {
|
|
399
|
+
await filter.testAll(0);
|
|
400
|
+
});
|
|
401
|
+
test("raw_data", async () => {
|
|
402
|
+
if (opts.rawDataVerify) {
|
|
403
|
+
await opts.rawDataVerify(filter.user);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
test("ents cache", async () => {
|
|
407
|
+
await filter.testEntsCache();
|
|
408
|
+
});
|
|
409
|
+
test("data cache", async () => {
|
|
410
|
+
await filter.testDataCache();
|
|
411
|
+
});
|
|
232
412
|
});
|
|
233
413
|
describe("first. no cursor", () => {
|
|
234
414
|
const N = 2;
|
|
@@ -236,14 +416,17 @@ const commonTests = (opts) => {
|
|
|
236
416
|
// no filters
|
|
237
417
|
return q.first(N);
|
|
238
418
|
}, opts.newQuery, (contacts) => {
|
|
239
|
-
|
|
419
|
+
if (opts.orderby === "DESC") {
|
|
420
|
+
return contacts.reverse().slice(0, N);
|
|
421
|
+
}
|
|
422
|
+
return contacts.slice(0, N);
|
|
240
423
|
}, getViewer());
|
|
241
424
|
beforeEach(async () => {
|
|
242
|
-
await filter.
|
|
425
|
+
await filter.createData();
|
|
243
426
|
});
|
|
244
427
|
test("ids", async () => {
|
|
245
428
|
await filter.testIDs();
|
|
246
|
-
verifyQuery({ limit: 2 });
|
|
429
|
+
verifyQuery(filter, { limit: 2 });
|
|
247
430
|
});
|
|
248
431
|
test("rawCount", async () => {
|
|
249
432
|
await filter.testRawCount();
|
|
@@ -251,19 +434,25 @@ const commonTests = (opts) => {
|
|
|
251
434
|
});
|
|
252
435
|
test("count", async () => {
|
|
253
436
|
await filter.testCount();
|
|
254
|
-
verifyQuery({ limit: 2 });
|
|
437
|
+
verifyQuery(filter, { limit: 2 });
|
|
255
438
|
});
|
|
256
439
|
test("edges", async () => {
|
|
257
440
|
await filter.testEdges();
|
|
258
|
-
verifyQuery({ limit: 2 });
|
|
441
|
+
verifyQuery(filter, { limit: 2 });
|
|
259
442
|
});
|
|
260
443
|
test("ents", async () => {
|
|
261
444
|
await filter.testEnts();
|
|
262
|
-
verifyQuery({ limit: 2, length: opts.entsLength });
|
|
445
|
+
verifyQuery(filter, { limit: 2, length: opts.entsLength });
|
|
263
446
|
});
|
|
264
447
|
test("all", async () => {
|
|
265
448
|
await filter.testAll();
|
|
266
449
|
});
|
|
450
|
+
test("ents cache", async () => {
|
|
451
|
+
await filter.testEntsCache();
|
|
452
|
+
});
|
|
453
|
+
test("data cache", async () => {
|
|
454
|
+
await filter.testDataCache();
|
|
455
|
+
});
|
|
267
456
|
});
|
|
268
457
|
describe("last", () => {
|
|
269
458
|
const N = 2;
|
|
@@ -271,15 +460,23 @@ const commonTests = (opts) => {
|
|
|
271
460
|
// no filters
|
|
272
461
|
return q.last(N);
|
|
273
462
|
}, opts.newQuery, (contacts) => {
|
|
274
|
-
|
|
275
|
-
|
|
463
|
+
if (opts.orderby === "DESC") {
|
|
464
|
+
return contacts.slice(0, N);
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
return contacts.reverse().slice(0, N);
|
|
468
|
+
}
|
|
276
469
|
}, getViewer());
|
|
470
|
+
const orderby = opts.orderby === "ASC" ? "DESC" : "ASC";
|
|
277
471
|
beforeEach(async () => {
|
|
278
|
-
await filter.
|
|
472
|
+
await filter.createData();
|
|
279
473
|
});
|
|
280
474
|
test("ids", async () => {
|
|
281
475
|
await filter.testIDs();
|
|
282
|
-
verifyQuery({
|
|
476
|
+
verifyQuery(filter, {
|
|
477
|
+
orderby,
|
|
478
|
+
limit: N,
|
|
479
|
+
});
|
|
283
480
|
});
|
|
284
481
|
test("rawCount", async () => {
|
|
285
482
|
await filter.testRawCount();
|
|
@@ -287,19 +484,29 @@ const commonTests = (opts) => {
|
|
|
287
484
|
});
|
|
288
485
|
test("count", async () => {
|
|
289
486
|
await filter.testCount();
|
|
290
|
-
verifyQuery({
|
|
487
|
+
verifyQuery(filter, { orderby, limit: N });
|
|
291
488
|
});
|
|
292
489
|
test("edges", async () => {
|
|
293
490
|
await filter.testEdges();
|
|
294
|
-
verifyQuery({
|
|
491
|
+
verifyQuery(filter, { orderby, limit: N });
|
|
295
492
|
});
|
|
296
493
|
test("ents", async () => {
|
|
297
494
|
await filter.testEnts();
|
|
298
|
-
verifyQuery(
|
|
495
|
+
verifyQuery(filter, {
|
|
496
|
+
orderby,
|
|
497
|
+
limit: N,
|
|
498
|
+
length: opts.entsLength,
|
|
499
|
+
});
|
|
299
500
|
});
|
|
300
501
|
test("all", async () => {
|
|
301
502
|
await filter.testAll();
|
|
302
503
|
});
|
|
504
|
+
test("ents cache", async () => {
|
|
505
|
+
await filter.testEntsCache();
|
|
506
|
+
});
|
|
507
|
+
test("data cache", async () => {
|
|
508
|
+
await filter.testDataCache();
|
|
509
|
+
});
|
|
303
510
|
});
|
|
304
511
|
describe("first after cursor", () => {
|
|
305
512
|
const idx = 2;
|
|
@@ -307,15 +514,23 @@ const commonTests = (opts) => {
|
|
|
307
514
|
const filter = new TestQueryFilter((q, user, contacts) => {
|
|
308
515
|
return q.first(N, getCursorFrom(contacts, idx));
|
|
309
516
|
}, opts.newQuery, (contacts) => {
|
|
310
|
-
|
|
311
|
-
|
|
517
|
+
if (opts.orderby === "DESC") {
|
|
518
|
+
// < check so we shouldn't get that index
|
|
519
|
+
return contacts.reverse().slice(idx + 1, idx + N);
|
|
520
|
+
}
|
|
521
|
+
else {
|
|
522
|
+
return contacts.slice(idx + 1, idx + N);
|
|
523
|
+
}
|
|
312
524
|
}, getViewer());
|
|
313
|
-
|
|
314
|
-
await filter.
|
|
525
|
+
beforeAll(async () => {
|
|
526
|
+
await filter.createData();
|
|
527
|
+
});
|
|
528
|
+
beforeEach(() => {
|
|
529
|
+
ml.clear();
|
|
315
530
|
});
|
|
316
531
|
test("ids", async () => {
|
|
317
532
|
await filter.testIDs();
|
|
318
|
-
verifyFirstAfterCursorQuery();
|
|
533
|
+
verifyFirstAfterCursorQuery(filter);
|
|
319
534
|
});
|
|
320
535
|
test("rawCount", async () => {
|
|
321
536
|
await filter.testRawCount();
|
|
@@ -323,51 +538,36 @@ const commonTests = (opts) => {
|
|
|
323
538
|
});
|
|
324
539
|
test("count", async () => {
|
|
325
540
|
await filter.testCount();
|
|
326
|
-
verifyFirstAfterCursorQuery();
|
|
541
|
+
verifyFirstAfterCursorQuery(filter);
|
|
327
542
|
});
|
|
328
543
|
test("edges", async () => {
|
|
329
544
|
await filter.testEdges();
|
|
330
|
-
verifyFirstAfterCursorQuery();
|
|
545
|
+
verifyFirstAfterCursorQuery(filter);
|
|
331
546
|
});
|
|
332
547
|
test("ents", async () => {
|
|
333
548
|
await filter.testEnts();
|
|
334
|
-
verifyFirstAfterCursorQuery(opts.entsLength);
|
|
549
|
+
verifyFirstAfterCursorQuery(filter, opts.entsLength);
|
|
335
550
|
});
|
|
336
551
|
test("all", async () => {
|
|
337
552
|
await filter.testAll();
|
|
338
553
|
});
|
|
554
|
+
test("ents cache", async () => {
|
|
555
|
+
await filter.testEntsCache();
|
|
556
|
+
});
|
|
557
|
+
test("data cache", async () => {
|
|
558
|
+
await filter.testDataCache();
|
|
559
|
+
});
|
|
339
560
|
});
|
|
340
561
|
test("first. after each cursor", async () => {
|
|
341
|
-
let [user
|
|
342
|
-
contacts = contacts.reverse();
|
|
562
|
+
let [user] = await (0, test_helpers_1.createAllContacts)();
|
|
343
563
|
const edges = await opts.newQuery(getViewer(), user).queryEdges();
|
|
344
|
-
|
|
345
|
-
async function verify(i, hasEdge, hasNextPage, cursor) {
|
|
346
|
-
query = opts.newQuery(getViewer(), user);
|
|
347
|
-
const newEdges = await query.first(1, cursor).queryEdges();
|
|
348
|
-
const pagination = query.paginationInfo().get(user.id);
|
|
349
|
-
if (hasEdge) {
|
|
350
|
-
expect(newEdges.length, `${i}`).toBe(1);
|
|
351
|
-
expect(newEdges[0], `${i}`).toStrictEqual(edges[i]);
|
|
352
|
-
}
|
|
353
|
-
else {
|
|
354
|
-
expect(newEdges.length, `${i}`).toBe(0);
|
|
355
|
-
}
|
|
356
|
-
if (hasNextPage) {
|
|
357
|
-
expect(pagination?.hasNextPage).toBe(true);
|
|
358
|
-
expect(pagination?.hasPreviousPage).toBe(false);
|
|
359
|
-
}
|
|
360
|
-
else {
|
|
361
|
-
expect(pagination?.hasNextPage).toBe(undefined);
|
|
362
|
-
expect(pagination?.hasNextPage).toBe(undefined);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
564
|
+
const { verify, getCursor } = getVerifyAfterEachCursor(edges, 1, user);
|
|
365
565
|
await verify(0, true, true, undefined);
|
|
366
|
-
await verify(1, true, true,
|
|
367
|
-
await verify(2, true, true,
|
|
368
|
-
await verify(3, true, true,
|
|
369
|
-
await verify(4, true, false,
|
|
370
|
-
await verify(5, false, false,
|
|
566
|
+
await verify(1, true, true, getCursor(edges[0]));
|
|
567
|
+
await verify(2, true, true, getCursor(edges[1]));
|
|
568
|
+
await verify(3, true, true, getCursor(edges[2]));
|
|
569
|
+
await verify(4, true, false, getCursor(edges[3]));
|
|
570
|
+
await verify(5, false, false, getCursor(edges[4]));
|
|
371
571
|
});
|
|
372
572
|
describe("last. before cursor", () => {
|
|
373
573
|
const idx = 2;
|
|
@@ -376,14 +576,22 @@ const commonTests = (opts) => {
|
|
|
376
576
|
return q.last(N, getCursorFrom(contacts, idx));
|
|
377
577
|
}, opts.newQuery, (contacts) => {
|
|
378
578
|
// > check so we don't want that index
|
|
379
|
-
|
|
579
|
+
if (opts.orderby === "DESC") {
|
|
580
|
+
return contacts.reverse().slice(0, idx).reverse(); // because of order returned
|
|
581
|
+
}
|
|
582
|
+
return contacts.slice(0, idx).reverse(); // because of order returned
|
|
380
583
|
}, getViewer());
|
|
584
|
+
beforeAll(async () => {
|
|
585
|
+
if (opts.livePostgresDB || opts.sqlite) {
|
|
586
|
+
await filter.createData();
|
|
587
|
+
}
|
|
588
|
+
});
|
|
381
589
|
beforeEach(async () => {
|
|
382
|
-
|
|
590
|
+
ml.clear();
|
|
383
591
|
});
|
|
384
592
|
test("ids", async () => {
|
|
385
593
|
await filter.testIDs();
|
|
386
|
-
verifyLastBeforeCursorQuery();
|
|
594
|
+
verifyLastBeforeCursorQuery(filter);
|
|
387
595
|
});
|
|
388
596
|
test("rawCount", async () => {
|
|
389
597
|
await filter.testRawCount();
|
|
@@ -391,51 +599,77 @@ const commonTests = (opts) => {
|
|
|
391
599
|
});
|
|
392
600
|
test("count", async () => {
|
|
393
601
|
await filter.testCount();
|
|
394
|
-
verifyLastBeforeCursorQuery();
|
|
602
|
+
verifyLastBeforeCursorQuery(filter);
|
|
395
603
|
});
|
|
396
604
|
test("edges", async () => {
|
|
397
605
|
await filter.testEdges();
|
|
398
|
-
verifyLastBeforeCursorQuery();
|
|
606
|
+
verifyLastBeforeCursorQuery(filter);
|
|
399
607
|
});
|
|
400
608
|
test("ents", async () => {
|
|
401
609
|
await filter.testEnts();
|
|
402
|
-
verifyLastBeforeCursorQuery(opts.entsLength);
|
|
610
|
+
verifyLastBeforeCursorQuery(filter, opts.entsLength);
|
|
403
611
|
});
|
|
404
612
|
test("all", async () => {
|
|
405
613
|
await filter.testAll();
|
|
406
614
|
});
|
|
615
|
+
test("ents cache", async () => {
|
|
616
|
+
await filter.testEntsCache();
|
|
617
|
+
});
|
|
618
|
+
test("data cache", async () => {
|
|
619
|
+
await filter.testDataCache();
|
|
620
|
+
});
|
|
407
621
|
});
|
|
408
622
|
test("last. before each cursor", async () => {
|
|
409
|
-
let [user
|
|
410
|
-
contacts = contacts.reverse();
|
|
623
|
+
let [user] = await (0, test_helpers_1.createAllContacts)();
|
|
411
624
|
const edges = await opts.newQuery(getViewer(), user).queryEdges();
|
|
412
|
-
|
|
413
|
-
async function verify(i, hasEdge, hasPreviousPage, cursor) {
|
|
414
|
-
query = opts.newQuery(getViewer(), user);
|
|
415
|
-
const newEdges = await query.last(1, cursor).queryEdges();
|
|
416
|
-
const pagination = query.paginationInfo().get(user.id);
|
|
417
|
-
if (hasEdge) {
|
|
418
|
-
expect(newEdges.length, `${i}`).toBe(1);
|
|
419
|
-
expect(newEdges[0], `${i}`).toStrictEqual(edges[i]);
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
expect(newEdges.length, `${i}`).toBe(0);
|
|
423
|
-
}
|
|
424
|
-
if (hasPreviousPage) {
|
|
425
|
-
expect(pagination?.hasPreviousPage).toBe(true);
|
|
426
|
-
expect(pagination?.hasNextPage).toBe(false);
|
|
427
|
-
}
|
|
428
|
-
else {
|
|
429
|
-
expect(pagination?.hasPreviousPage).toBe(undefined);
|
|
430
|
-
expect(pagination?.hasNextPage).toBe(undefined);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
625
|
+
const { verify, getCursor } = getVerifyBeforeEachCursor(edges, 1, user);
|
|
433
626
|
await verify(4, true, true, undefined);
|
|
434
|
-
await verify(3, true, true,
|
|
435
|
-
await verify(2, true, true,
|
|
436
|
-
await verify(1, true, true,
|
|
437
|
-
await verify(0, true, false,
|
|
438
|
-
await verify(-1, false, false,
|
|
627
|
+
await verify(3, true, true, getCursor(edges[4]));
|
|
628
|
+
await verify(2, true, true, getCursor(edges[3]));
|
|
629
|
+
await verify(1, true, true, getCursor(edges[2]));
|
|
630
|
+
await verify(0, true, false, getCursor(edges[1]));
|
|
631
|
+
await verify(-1, false, false, getCursor(edges[0]));
|
|
632
|
+
});
|
|
633
|
+
describe("with conflicts", () => {
|
|
634
|
+
let user;
|
|
635
|
+
let allEdges = [];
|
|
636
|
+
beforeEach(async () => {
|
|
637
|
+
const [u, contacts] = await (0, test_helpers_1.createAllContacts)();
|
|
638
|
+
user = u;
|
|
639
|
+
const [_, contacts2] = await (0, test_helpers_1.createAllContacts)({
|
|
640
|
+
user,
|
|
641
|
+
start: contacts[contacts.length - 1].createdAt.getTime() - 100,
|
|
642
|
+
});
|
|
643
|
+
await (0, test_helpers_1.createAllContacts)({
|
|
644
|
+
user,
|
|
645
|
+
start: contacts2[contacts.length - 1].createdAt.getTime() - 100,
|
|
646
|
+
});
|
|
647
|
+
const edges = await opts.newQuery(getViewer(), user).queryEdges();
|
|
648
|
+
// confirm there are duplicates...
|
|
649
|
+
expect(edges[4].created_at).toStrictEqual(edges[5].created_at);
|
|
650
|
+
expect(edges[9].created_at).toStrictEqual(edges[10].created_at);
|
|
651
|
+
allEdges = edges;
|
|
652
|
+
});
|
|
653
|
+
test("first after each cursor", async () => {
|
|
654
|
+
const { verify, getCursor } = getVerifyAfterEachCursor(allEdges, 5, user);
|
|
655
|
+
// regular pagination
|
|
656
|
+
await verify(0, true, true, undefined);
|
|
657
|
+
await verify(5, true, true, getCursor(allEdges[4]));
|
|
658
|
+
await verify(10, true, false, getCursor(allEdges[9]));
|
|
659
|
+
await verify(15, false, false, getCursor(allEdges[14]));
|
|
660
|
+
// one without duplicates work if we were paginating at a different place...
|
|
661
|
+
await verify(6, true, true, getCursor(allEdges[5]));
|
|
662
|
+
await verify(11, true, false, getCursor(allEdges[10]));
|
|
663
|
+
});
|
|
664
|
+
test("last before each cursor", async () => {
|
|
665
|
+
const { verify, getCursor } = getVerifyBeforeEachCursor(allEdges, 5, user);
|
|
666
|
+
await verify(14, true, true, undefined);
|
|
667
|
+
await verify(13, true, true, getCursor(allEdges[14]));
|
|
668
|
+
await verify(8, true, true, getCursor(allEdges[9]));
|
|
669
|
+
await verify(9, true, true, getCursor(allEdges[10]));
|
|
670
|
+
await verify(3, true, false, getCursor(allEdges[4]));
|
|
671
|
+
await verify(4, true, false, getCursor(allEdges[5]));
|
|
672
|
+
});
|
|
439
673
|
});
|
|
440
674
|
};
|
|
441
675
|
exports.commonTests = commonTests;
|