@malloydata/malloy-tests 0.0.140-dev240409200123 → 0.0.140

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/package.json CHANGED
@@ -21,13 +21,13 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@jest/globals": "^29.4.3",
24
- "@malloydata/db-bigquery": "^0.0.140-dev240409200123",
25
- "@malloydata/db-duckdb": "^0.0.140-dev240409200123",
26
- "@malloydata/db-postgres": "^0.0.140-dev240409200123",
27
- "@malloydata/db-snowflake": "^0.0.140-dev240409200123",
28
- "@malloydata/db-trino": "^0.0.140-dev240409200123",
29
- "@malloydata/malloy": "^0.0.140-dev240409200123",
30
- "@malloydata/render": "^0.0.140-dev240409200123",
24
+ "@malloydata/db-bigquery": "^0.0.140",
25
+ "@malloydata/db-duckdb": "^0.0.140",
26
+ "@malloydata/db-postgres": "^0.0.140",
27
+ "@malloydata/db-snowflake": "^0.0.140",
28
+ "@malloydata/db-trino": "^0.0.140",
29
+ "@malloydata/malloy": "^0.0.140",
30
+ "@malloydata/render": "^0.0.140",
31
31
  "jsdom": "^22.1.0",
32
32
  "luxon": "^2.4.0",
33
33
  "madge": "^6.0.0"
@@ -36,5 +36,5 @@
36
36
  "@types/jsdom": "^21.1.1",
37
37
  "@types/luxon": "^2.4.0"
38
38
  },
39
- "version": "0.0.140-dev240409200123"
39
+ "version": "0.0.140"
40
40
  }
@@ -150,7 +150,8 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
150
150
  `).malloyResultMatches(expressionModel, {
151
151
  'o.by_state.state': 'TX',
152
152
  'o.by_state.airport_count': 1845,
153
- //'o.inline.inline_sum': 19701, // this should work.. @mtoy
153
+ 'o.airport_count': 11146,
154
+ 'o.inline/inline_sum': 11146,
154
155
  'airport_count': 19701,
155
156
  });
156
157
  });
@@ -31,6 +31,7 @@ import {
31
31
  LogMessage,
32
32
  SingleConnectionRuntime,
33
33
  } from '@malloydata/malloy';
34
+ import {inspect} from 'util';
34
35
 
35
36
  type ExpectedResultRow = Record<string, unknown>;
36
37
  type ExpectedResult = ExpectedResultRow | ExpectedResultRow[];
@@ -50,9 +51,18 @@ declare global {
50
51
  * await expect('query').malloyResultMatches(runtime, {colName: colValue});
51
52
  * await expect('query').malloyResultMatches(runtime, [{colName: colValue}]);
52
53
  *
53
- * * If "colName" has a dot in it, it is assumed to be a reference to a value in a nest
54
54
  * * If you use an array, the number of rows in the result must match the rows in the match
55
55
  * * The empty match {} accepts ANY data, but will errror if there is not a row
56
+ * * If the query is tagged with # test.debug then the test will fail and the result will be printed
57
+ * * If the query is tagged with # test.verbose then the result will be printed only if the test fails
58
+ * * A match key of nestName.colName expects nestName to be a query which returns multiple rows, it will match
59
+ * fields from the first row of the rows of nestName
60
+ * * A match key of nestName/colName expects nestName to be a record/struct type
61
+ *
62
+ * In addition, the query is checked for the following tags
63
+ *
64
+ * * test.verbose -- If the test fails, also pretty-print the result data
65
+ * * test.debug -- Force test failure, and the result data will be printed
56
66
  *
57
67
  * @param querySrc Malloy source, last query in source will be run
58
68
  * @param runtime Database connection runtime OR Model ( for the call to loadQuery )
@@ -118,6 +128,8 @@ expect.extend({
118
128
  };
119
129
  }
120
130
 
131
+ const queryTags = (await query.getPreparedQuery()).tagParse().tag;
132
+ const queryTestTag = queryTags.tag('test');
121
133
  let result: Result;
122
134
  try {
123
135
  result = await query.run();
@@ -139,34 +151,36 @@ expect.extend({
139
151
  return {pass: false, message: () => failMsg};
140
152
  }
141
153
 
142
- const debug = querySrc.indexOf('--debug') >= 0;
143
154
  const allRows = Array.isArray(shouldEqual) ? shouldEqual : [shouldEqual];
144
- let i = 0;
145
155
  const fails: string[] = [];
146
-
147
- if (debug) {
148
- fails.push(
149
- `Debug: Result Data: ${JSON.stringify(result.data.toObject())}`
150
- );
151
- }
152
-
153
156
  const gotRows = result.data.toObject().length;
157
+
154
158
  if (Array.isArray(shouldEqual)) {
155
159
  if (gotRows !== allRows.length) {
156
160
  fails.push(`Expected result.rows=${allRows.length} Got: ${gotRows}`);
157
161
  }
158
162
  }
163
+ let matchRow = 0;
159
164
  for (const expected of allRows) {
160
165
  for (const [name, value] of Object.entries(expected)) {
161
166
  const pExpect = JSON.stringify(value);
162
- const row = allRows.length > 1 ? `[${i}]` : '';
167
+ const row = allRows.length > 1 ? `[${matchRow}]` : '';
163
168
  const expected = `Expected ${row}{${name}: ${pExpect}}`;
164
169
  try {
165
- const nestOne = name.split('.');
166
- const resultPath = [i, nestOne[0]];
167
- for (const child of nestOne.slice(1)) {
168
- resultPath.push(0);
169
- resultPath.push(child);
170
+ // the internet taught me this, use lookahead/behind to preserve delimiters
171
+ // but we are splitting on / and .
172
+ const nestParse = name.split(/(?=[./])|(?<=[./])/g);
173
+
174
+ const resultPath = [matchRow, nestParse[0]];
175
+ for (
176
+ let pathCursor = 1;
177
+ pathCursor < nestParse.length;
178
+ pathCursor += 2
179
+ ) {
180
+ if (nestParse[pathCursor] === '.') {
181
+ resultPath.push(0);
182
+ }
183
+ resultPath.push(nestParse[pathCursor + 1]);
170
184
  }
171
185
  const got = result.data.path(...resultPath).value;
172
186
  const pGot = JSON.stringify(got);
@@ -181,10 +195,19 @@ expect.extend({
181
195
  fails.push(`${expected} Error: ${e.message}`);
182
196
  }
183
197
  }
184
- i += 1;
198
+ matchRow += 1;
199
+ }
200
+ const failedTest = fails.length > 0;
201
+ const debugFail = queryTestTag?.has('debug');
202
+ if (debugFail || (failedTest && queryTestTag?.has('verbose'))) {
203
+ fails.unshift(`Result Data: ${humanReadable(result.data.toObject())}\n`);
185
204
  }
186
- if (fails.length !== 0) {
205
+
206
+ if (fails.length > 0) {
187
207
  const fromSQL = ' ' + (await query.getSQL()).split('\n').join('\n ');
208
+ if (debugFail && !failedTest) {
209
+ fails.push('\nTest forced failure (# test.debug)');
210
+ }
188
211
  const failMsg = `SQL Generated:\n${fromSQL}\n${fails.join('\n')}`;
189
212
  return {pass: false, message: () => failMsg};
190
213
  }
@@ -213,3 +236,7 @@ function errorLogToString(src: string, msgs: LogMessage[]) {
213
236
  }
214
237
  return lovely;
215
238
  }
239
+
240
+ function humanReadable(thing: unknown): string {
241
+ return inspect(thing, {breakLength: 72, depth: Infinity});
242
+ }