@snowtop/ent 0.1.0-alpha16 → 0.1.0-alpha160-test1

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