@malloydata/malloy 0.0.43-dev230621180201 → 0.0.43-dev230621212545

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.
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  /*
4
7
  * Copyright 2023 Google LLC
@@ -24,30 +27,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
24
27
  */
25
28
  require("./parse-expects");
26
29
  const test_translator_1 = require("./test-translator");
30
+ const escapeRegExp_1 = __importDefault(require("lodash/escapeRegExp"));
27
31
  describe('import:', () => {
28
32
  test('simple source', () => {
29
33
  const docParse = new test_translator_1.TestTranslator('import "child"');
30
34
  const xr = docParse.unresolved();
31
- expect(docParse).toBeErrorless();
35
+ expect(docParse).toParse();
32
36
  expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
33
37
  docParse.update({
34
38
  urls: { 'internal://test/langtests/child': 'source: aa is a' },
35
39
  });
36
- expect(docParse).modelCompiled();
40
+ expect(docParse).toTranslate();
37
41
  const aa = docParse.getSourceDef('aa');
38
42
  expect(aa).toBeDefined();
39
43
  });
40
44
  test('simple query', () => {
41
45
  const docParse = new test_translator_1.TestTranslator('import "child"');
42
46
  const xr = docParse.unresolved();
43
- expect(docParse).toBeErrorless();
47
+ expect(docParse).toParse();
44
48
  expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
45
49
  docParse.update({
46
50
  urls: {
47
51
  'internal://test/langtests/child': 'query: aq is a->{ project: * }',
48
52
  },
49
53
  });
50
- expect(docParse).modelCompiled();
54
+ expect(docParse).toTranslate();
51
55
  const aq = docParse.getQuery('aq');
52
56
  expect(aq).toBeDefined();
53
57
  });
@@ -59,7 +63,7 @@ source: newSrc is a {
59
63
  }
60
64
  `);
61
65
  const xr = docParse.unresolved();
62
- expect(docParse).toBeErrorless();
66
+ expect(docParse).toParse();
63
67
  expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
64
68
  docParse.update({
65
69
  urls: {
@@ -70,7 +74,7 @@ source: botProjQSrc is from(->botProjQ)
70
74
  `,
71
75
  },
72
76
  });
73
- expect(docParse).modelCompiled();
77
+ expect(docParse).toTranslate();
74
78
  const newSrc = docParse.getSourceDef('newSrc');
75
79
  const f = newSrc === null || newSrc === void 0 ? void 0 : newSrc.fields.find(f => f.name === 'b');
76
80
  expect(f === null || f === void 0 ? void 0 : f.type).toBe('struct');
@@ -85,7 +89,7 @@ source: botProjQSrc is from(->botProjQ)
85
89
  test('missing import', () => {
86
90
  const docParse = new test_translator_1.TestTranslator('import "child"');
87
91
  const xr = docParse.unresolved();
88
- expect(docParse).toBeErrorless();
92
+ expect(docParse).toParse();
89
93
  expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
90
94
  const reportedError = 'ENOWAY: No way to find your child';
91
95
  docParse.update({
@@ -94,8 +98,7 @@ source: botProjQSrc is from(->botProjQ)
94
98
  },
95
99
  });
96
100
  docParse.translate();
97
- expect(docParse).not.toBeErrorless();
98
- expect(docParse.prettyErrors()).toContain(reportedError);
101
+ expect(docParse).translationToFailWith(new RegExp((0, escapeRegExp_1.default)(reportedError)));
99
102
  });
100
103
  test('chained imports', () => {
101
104
  const docParse = new test_translator_1.TestTranslator('import "child"');
@@ -103,12 +106,12 @@ source: botProjQSrc is from(->botProjQ)
103
106
  urls: { 'internal://test/langtests/child': 'import "grandChild"' },
104
107
  });
105
108
  const xr = docParse.unresolved();
106
- expect(docParse).toBeErrorless();
109
+ expect(docParse).toParse();
107
110
  expect(xr).toEqual({ urls: ['internal://test/langtests/grandChild'] });
108
111
  });
109
112
  test('relative imports', () => {
110
113
  const docParse = new test_translator_1.TestTranslator('import "../parent.malloy"');
111
- expect(docParse).modelParsed();
114
+ expect(docParse).toParse();
112
115
  const xr = docParse.unresolved();
113
116
  expect(xr).toEqual({ urls: ['internal://test/parent.malloy'] });
114
117
  docParse.update({
@@ -116,11 +119,11 @@ source: botProjQSrc is from(->botProjQ)
116
119
  'internal://test/parent.malloy': "source: aa is table('aTable')",
117
120
  },
118
121
  });
119
- expect(docParse).modelCompiled();
122
+ expect(docParse).toTranslate();
120
123
  });
121
124
  test('relative imports with errors', () => {
122
125
  const docParse = new test_translator_1.TestTranslator('import "../parent.malloy"');
123
- expect(docParse).modelParsed();
126
+ expect(docParse).toParse();
124
127
  const xr = docParse.unresolved();
125
128
  expect(xr).toEqual({ urls: ['internal://test/parent.malloy'] });
126
129
  docParse.update({
@@ -131,7 +134,7 @@ source: botProjQSrc is from(->botProjQ)
131
134
  }`,
132
135
  },
133
136
  });
134
- expect(docParse).compileToFailWith("Cannot redefine 'astr'");
137
+ expect(docParse).translationToFailWith("Cannot redefine 'astr'");
135
138
  });
136
139
  test('source references expanded when not exported', () => {
137
140
  const srcFiles = {
@@ -145,7 +148,7 @@ source: botProjQSrc is from(->botProjQ)
145
148
  import "middle"
146
149
  `);
147
150
  fullModel.update({ urls: srcFiles });
148
- expect(fullModel).modelCompiled();
151
+ expect(fullModel).toTranslate();
149
152
  const ms = fullModel.getSourceDef('midSrc');
150
153
  expect(ms).toBeDefined();
151
154
  if (ms) {
@@ -3,13 +3,39 @@ declare type ErrorSpec = string | RegExp;
3
3
  declare global {
4
4
  namespace jest {
5
5
  interface Matchers<R> {
6
- modelParsed(): R;
7
- toBeErrorless(): R;
8
- toCompile(): R;
9
- modelCompiled(): R;
10
- expressionCompiled(): R;
6
+ /**
7
+ * expect(X).toParse()
8
+ *
9
+ * Passes if the source parses to an AST without errors.
10
+ *
11
+ * X can be a MarkedSource, a string, or a model. If it is a marked
12
+ * source, the errors which are found must match the locations of
13
+ * the markings.
14
+ */
15
+ toParse(): R;
16
+ /**
17
+ * expect(X).toTranslate()
18
+ *
19
+ * Passes if the source compiles to code which could be used to
20
+ * generate SQL.
21
+ *
22
+ * X can be a MarkedSource, a string, or a model. If it is a marked
23
+ * source, the errors which are found must match the locations of
24
+ * the markings.
25
+ */
26
+ toTranslate(): R;
11
27
  toReturnType(tp: string): R;
12
- compileToFailWith(...expectedErrors: ErrorSpec[]): R;
28
+ /**
29
+ * expect(X).translateToFailWith(expectedErrors)
30
+ *
31
+ * X can be a MarkedSource, a string, or a model. If it is a marked
32
+ * source, the errors which are found must match the locations of
33
+ * the markings.
34
+ *
35
+ * @param expectedErrors varargs list of strings which must match
36
+ * exactly, or regular expressions.
37
+ */
38
+ translationToFailWith(...expectedErrors: ErrorSpec[]): R;
13
39
  isLocationIn(at: DocumentLocation, txt: string): R;
14
40
  }
15
41
  }
@@ -92,60 +92,53 @@ function highlightError(dl, txt) {
92
92
  }
93
93
  return output.join('\n');
94
94
  }
95
+ function isMarkedSource(ts) {
96
+ return typeof ts !== 'string' && !(ts instanceof test_translator_1.TestTranslator);
97
+ }
98
+ function xlator(ts) {
99
+ if (ts instanceof test_translator_1.TestTranslator) {
100
+ return ts;
101
+ }
102
+ if (typeof ts === 'string') {
103
+ return new test_translator_1.TestTranslator(ts);
104
+ }
105
+ return ts.translator || new test_translator_1.TestTranslator(ts.code);
106
+ }
107
+ function xlated(tt) {
108
+ const errorCheck = checkForErrors(tt);
109
+ if (!errorCheck.pass) {
110
+ return errorCheck;
111
+ }
112
+ tt.translate();
113
+ return checkForNeededs(tt);
114
+ }
95
115
  expect.extend({
96
- toCompile: function (s) {
97
- const x = new test_translator_1.TestTranslator(s);
98
- x.compile();
99
- const errorCheck = checkForErrors(x);
100
- if (!errorCheck.pass) {
101
- return errorCheck;
102
- }
103
- x.translate();
104
- return checkForNeededs(x);
105
- },
106
- modelParsed: function (x) {
116
+ toParse: function (tx) {
117
+ const x = xlator(tx);
107
118
  x.compile();
108
119
  return checkForErrors(x);
109
120
  },
110
- modelCompiled: function (x) {
121
+ toTranslate: function (tx) {
122
+ const x = xlator(tx);
111
123
  x.compile();
112
- const errorCheck = checkForErrors(x);
113
- if (!errorCheck.pass) {
114
- return errorCheck;
115
- }
116
- x.translate();
117
- return checkForNeededs(x);
124
+ return xlated(x);
118
125
  },
119
- expressionCompiled: function (src) {
120
- const x = new test_translator_1.BetaExpression(src);
121
- x.compile();
122
- const errorCheck = checkForErrors(x);
123
- if (!errorCheck.pass) {
124
- return errorCheck;
126
+ toReturnType: function (exprText, returnType) {
127
+ const exprModel = new test_translator_1.BetaExpression(exprText);
128
+ exprModel.compile();
129
+ const ok = xlated(exprModel);
130
+ if (!ok.pass) {
131
+ return ok;
125
132
  }
126
- return checkForNeededs(x);
133
+ const d = exprModel.generated();
134
+ const pass = d.dataType === returnType;
135
+ const msg = `Expression type ${d.dataType} ${pass ? '=' : '!='} $[returnType`;
136
+ return { pass, message: () => msg };
127
137
  },
128
- toBeErrorless: function (trans) {
129
- return checkForErrors(trans);
130
- },
131
- toReturnType: function (functionCall, returnType) {
132
- const exprModel = new test_translator_1.TestTranslator(`source: x is a { dimension: d is ${functionCall} }`);
133
- expect(exprModel).modelCompiled();
134
- const x = exprModel.getSourceDef('x');
135
- expect(x).toBeDefined();
136
- if (x) {
137
- const d = x.fields.find(f => f.name === 'd');
138
- expect(d === null || d === void 0 ? void 0 : d.type).toBe(returnType);
139
- }
140
- return {
141
- pass: true,
142
- message: () => '',
143
- };
144
- },
145
- compileToFailWith: function (s, ...msgs) {
138
+ translationToFailWith: function (s, ...msgs) {
146
139
  var _a;
147
140
  let emsg = 'Compile Error expectation not met\nExpected message';
148
- let mSrc;
141
+ const mSrc = isMarkedSource(s) ? s : undefined;
149
142
  const qmsgs = msgs.map(s => `error '${s}'`);
150
143
  if (msgs.length === 1) {
151
144
  emsg += ` ${qmsgs[0]}`;
@@ -153,22 +146,8 @@ expect.extend({
153
146
  else {
154
147
  emsg += `s [\n${qmsgs.join('\n')}\n]`;
155
148
  }
156
- let m;
157
- let src;
158
- if (s instanceof test_translator_1.TestTranslator) {
159
- m = s;
160
- src = m.testSrc;
161
- }
162
- else {
163
- if (typeof s === 'string') {
164
- src = s;
165
- }
166
- else {
167
- src = s.code;
168
- mSrc = s;
169
- }
170
- m = new test_translator_1.TestTranslator(src);
171
- }
149
+ const m = xlator(s);
150
+ const src = m.testSrc;
172
151
  emsg += `\nSource:\n${src}`;
173
152
  m.compile();
174
153
  const t = m.translate();