@snowtop/ent 0.1.0-alpha15 → 0.1.0-alpha151

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