@quenty/nevermore-cli 4.50.0 → 4.50.1
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/CHANGELOG.md +6 -0
- package/dist/commands/tools-command/ci-post-test-results.d.ts.map +1 -1
- package/dist/commands/tools-command/ci-post-test-results.js +7 -3
- package/dist/commands/tools-command/ci-post-test-results.js.map +1 -1
- package/dist/utils/batch/changed-packages-utils.d.ts +8 -0
- package/dist/utils/batch/changed-packages-utils.d.ts.map +1 -1
- package/dist/utils/batch/changed-packages-utils.js +9 -11
- package/dist/utils/batch/changed-packages-utils.js.map +1 -1
- package/dist/utils/testing/parsers/annotation-workspace.d.ts +17 -0
- package/dist/utils/testing/parsers/annotation-workspace.d.ts.map +1 -0
- package/dist/utils/testing/parsers/annotation-workspace.js +47 -0
- package/dist/utils/testing/parsers/annotation-workspace.js.map +1 -0
- package/dist/utils/testing/parsers/index.d.ts +0 -1
- package/dist/utils/testing/parsers/index.d.ts.map +1 -1
- package/dist/utils/testing/parsers/index.js +0 -1
- package/dist/utils/testing/parsers/index.js.map +1 -1
- package/dist/utils/testing/parsers/jest-lua-parser.d.ts +14 -29
- package/dist/utils/testing/parsers/jest-lua-parser.d.ts.map +1 -1
- package/dist/utils/testing/parsers/jest-lua-parser.js +85 -100
- package/dist/utils/testing/parsers/jest-lua-parser.js.map +1 -1
- package/dist/utils/testing/parsers/jest-lua-parser.test.js +359 -56
- package/dist/utils/testing/parsers/jest-lua-parser.test.js.map +1 -1
- package/dist/utils/testing/parsers/roblox-path-resolver.d.ts +23 -17
- package/dist/utils/testing/parsers/roblox-path-resolver.d.ts.map +1 -1
- package/dist/utils/testing/parsers/roblox-path-resolver.js +89 -54
- package/dist/utils/testing/parsers/roblox-path-resolver.js.map +1 -1
- package/dist/utils/testing/parsers/roblox-path-resolver.test.js +76 -36
- package/dist/utils/testing/parsers/roblox-path-resolver.test.js.map +1 -1
- package/dist/utils/testing/runner/combined-project-generator.d.ts.map +1 -1
- package/dist/utils/testing/runner/combined-project-generator.js +5 -6
- package/dist/utils/testing/runner/combined-project-generator.js.map +1 -1
- package/dist/utils/testing/runner/test-project-slug.d.ts +11 -0
- package/dist/utils/testing/runner/test-project-slug.d.ts.map +1 -0
- package/dist/utils/testing/runner/test-project-slug.js +11 -0
- package/dist/utils/testing/runner/test-project-slug.js.map +1 -0
- package/package.json +6 -6
- package/src/commands/tools-command/ci-post-test-results.ts +7 -2
- package/src/utils/batch/changed-packages-utils.ts +21 -12
- package/src/utils/testing/parsers/annotation-workspace.ts +74 -0
- package/src/utils/testing/parsers/index.ts +0 -1
- package/src/utils/testing/parsers/jest-lua-parser.test.ts +433 -65
- package/src/utils/testing/parsers/jest-lua-parser.ts +131 -109
- package/src/utils/testing/parsers/roblox-path-resolver.test.ts +144 -61
- package/src/utils/testing/parsers/roblox-path-resolver.ts +117 -56
- package/src/utils/testing/runner/combined-project-generator.ts +9 -13
- package/src/utils/testing/runner/test-project-slug.ts +18 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jest-lua-parser.js","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/jest-lua-parser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"jest-lua-parser.js","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/jest-lua-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
1
|
+
import { beforeAll, describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
2
3
|
import { parseJestLuaOutput } from './jest-lua-parser.js';
|
|
3
4
|
import { SourcemapResolver } from '../../sourcemap/index.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
})
|
|
5
|
+
import { tryLoadAnnotationWorkspaceAsync, } from './annotation-workspace.js';
|
|
6
|
+
// Pass-through, so spec searches read the real repo unless a test stubs them.
|
|
7
|
+
vi.mock('fs', async (importOriginal) => {
|
|
8
|
+
const actual = await importOriginal();
|
|
9
|
+
return { ...actual, readFileSync: vi.fn(actual.readFileSync) };
|
|
10
|
+
});
|
|
11
|
+
const REPO_ROOT = fileURLToPath(new URL('../../../../../../', import.meta.url));
|
|
12
|
+
let workspace;
|
|
13
|
+
beforeAll(async () => {
|
|
14
|
+
workspace = await tryLoadAnnotationWorkspaceAsync(REPO_ROOT);
|
|
15
|
+
}, 30000);
|
|
10
16
|
describe('parseJestLuaOutput', () => {
|
|
11
17
|
beforeEach(() => {
|
|
12
18
|
vi.restoreAllMocks();
|
|
@@ -23,7 +29,9 @@ describe('parseJestLuaOutput', () => {
|
|
|
23
29
|
' at ServerScriptService.observablecollection.Shared.ObservableList.spec:45',
|
|
24
30
|
].join('\n');
|
|
25
31
|
const result = parseJestLuaOutput(input, {
|
|
26
|
-
packageName: 'observablecollection',
|
|
32
|
+
packageName: '@quenty/observablecollection',
|
|
33
|
+
repoRoot: REPO_ROOT,
|
|
34
|
+
workspace,
|
|
27
35
|
});
|
|
28
36
|
expect(result).toHaveLength(1);
|
|
29
37
|
expect(result[0]).toEqual({
|
|
@@ -44,20 +52,25 @@ describe('parseJestLuaOutput', () => {
|
|
|
44
52
|
' Expected: 1',
|
|
45
53
|
' Received: 2',
|
|
46
54
|
'',
|
|
47
|
-
' at ServerScriptService.
|
|
55
|
+
' at ServerScriptService.observablecollection.Shared.ObservableList.spec:10',
|
|
48
56
|
'',
|
|
49
57
|
' ● Suite > test two',
|
|
50
58
|
'',
|
|
51
59
|
' Expected: true',
|
|
52
60
|
' Received: false',
|
|
53
61
|
'',
|
|
54
|
-
' at ServerScriptService.
|
|
62
|
+
' at ServerScriptService.observablecollection.Shared.ObservableMap.spec:20',
|
|
55
63
|
].join('\n');
|
|
56
|
-
const result = parseJestLuaOutput(input, {
|
|
64
|
+
const result = parseJestLuaOutput(input, {
|
|
65
|
+
packageName: '@quenty/observablecollection',
|
|
66
|
+
repoRoot: REPO_ROOT,
|
|
67
|
+
workspace,
|
|
68
|
+
});
|
|
57
69
|
expect(result).toHaveLength(2);
|
|
58
70
|
expect(result[0].title).toBe('Suite > test one');
|
|
59
71
|
expect(result[0].line).toBe(10);
|
|
60
72
|
expect(result[1].title).toBe('Suite > test two');
|
|
73
|
+
expect(result[1].file).toBe('src/observablecollection/src/Shared/ObservableMap.spec.lua');
|
|
61
74
|
expect(result[1].line).toBe(20);
|
|
62
75
|
});
|
|
63
76
|
it('parses nested 3+ level test hierarchy', () => {
|
|
@@ -66,13 +79,17 @@ describe('parseJestLuaOutput', () => {
|
|
|
66
79
|
'',
|
|
67
80
|
' failure message',
|
|
68
81
|
'',
|
|
69
|
-
' at ServerScriptService.
|
|
82
|
+
' at ServerScriptService.maid.Shared.MaidTaskUtils.spec:99',
|
|
70
83
|
].join('\n');
|
|
71
|
-
const result = parseJestLuaOutput(input, {
|
|
84
|
+
const result = parseJestLuaOutput(input, {
|
|
85
|
+
packageName: '@quenty/maid',
|
|
86
|
+
repoRoot: REPO_ROOT,
|
|
87
|
+
workspace,
|
|
88
|
+
});
|
|
72
89
|
expect(result).toHaveLength(1);
|
|
73
90
|
expect(result[0].title).toBe('Level1 > Level2 > Level3 > Level4 > deep test');
|
|
74
91
|
});
|
|
75
|
-
it('
|
|
92
|
+
it('emits no file when there is no location', () => {
|
|
76
93
|
const input = [
|
|
77
94
|
' ● Suite > test without location',
|
|
78
95
|
'',
|
|
@@ -80,15 +97,35 @@ describe('parseJestLuaOutput', () => {
|
|
|
80
97
|
'',
|
|
81
98
|
'Test Suites: 1 failed, 1 total',
|
|
82
99
|
].join('\n');
|
|
83
|
-
const result = parseJestLuaOutput(input, {
|
|
100
|
+
const result = parseJestLuaOutput(input, {
|
|
101
|
+
packageName: '@quenty/maid',
|
|
102
|
+
repoRoot: REPO_ROOT,
|
|
103
|
+
workspace,
|
|
104
|
+
});
|
|
105
|
+
expect(result).toHaveLength(1);
|
|
106
|
+
expect(result[0].file).toBeUndefined();
|
|
107
|
+
expect(result[0].line).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
it('emits no file when the location does not exist in the repo', () => {
|
|
110
|
+
const input = [
|
|
111
|
+
' ● Suite > test one',
|
|
112
|
+
'',
|
|
113
|
+
' Expected: 1',
|
|
114
|
+
'',
|
|
115
|
+
' at ServerScriptService.unknownpkg.Shared.Bar.spec:10',
|
|
116
|
+
].join('\n');
|
|
117
|
+
const result = parseJestLuaOutput(input, {
|
|
118
|
+
packageName: '@quenty/unknownpkg',
|
|
119
|
+
repoRoot: REPO_ROOT,
|
|
120
|
+
workspace,
|
|
121
|
+
});
|
|
84
122
|
expect(result).toHaveLength(1);
|
|
85
|
-
expect(result[0].
|
|
86
|
-
expect(result[0].file).toBe('src/mypkg/src');
|
|
123
|
+
expect(result[0].file).toBeUndefined();
|
|
87
124
|
});
|
|
88
125
|
it('searches spec file for it() call when at location has no line number', async () => {
|
|
126
|
+
const actualFs = await vi.importActual('fs');
|
|
89
127
|
const { readFileSync } = await import('fs');
|
|
90
|
-
const
|
|
91
|
-
mockedReadFileSync.mockReturnValue([
|
|
128
|
+
const specContent = [
|
|
92
129
|
'local require = require(script.Parent.loader).load(script)',
|
|
93
130
|
'',
|
|
94
131
|
'describe("Suite", function()',
|
|
@@ -96,30 +133,41 @@ describe('parseJestLuaOutput', () => {
|
|
|
96
133
|
' -- test body',
|
|
97
134
|
' end)',
|
|
98
135
|
'end)',
|
|
99
|
-
].join('\n')
|
|
136
|
+
].join('\n');
|
|
137
|
+
vi.mocked(readFileSync).mockImplementation(((filePath, options) => String(filePath).endsWith('MaidTaskUtils.spec.lua')
|
|
138
|
+
? specContent
|
|
139
|
+
: actualFs.readFileSync(filePath, options)));
|
|
100
140
|
const input = [
|
|
101
|
-
' ● Suite
|
|
141
|
+
' ● Suite › my test name',
|
|
102
142
|
'',
|
|
103
143
|
' assertion failed',
|
|
104
144
|
'',
|
|
105
|
-
' at ServerScriptService.
|
|
145
|
+
' at ServerScriptService.maid.Shared.MaidTaskUtils.spec',
|
|
106
146
|
].join('\n');
|
|
107
|
-
const result = parseJestLuaOutput(input, {
|
|
147
|
+
const result = parseJestLuaOutput(input, {
|
|
148
|
+
packageName: '@quenty/maid',
|
|
149
|
+
repoRoot: REPO_ROOT,
|
|
150
|
+
workspace,
|
|
151
|
+
});
|
|
108
152
|
expect(result).toHaveLength(1);
|
|
109
|
-
expect(result[0].file).toBe('src/
|
|
153
|
+
expect(result[0].file).toBe('src/maid/src/Shared/MaidTaskUtils.spec.lua');
|
|
110
154
|
expect(result[0].line).toBe(4);
|
|
111
155
|
});
|
|
112
156
|
it('parses a runtime error with Stack Begin/Stack End', () => {
|
|
113
157
|
const input = [
|
|
114
158
|
'Error: attempt to index nil with "Connect"',
|
|
115
159
|
'Stack Begin',
|
|
116
|
-
"Script 'ServerScriptService.maid.Shared.
|
|
160
|
+
"Script 'ServerScriptService.maid.Shared.MaidTaskUtils', Line 23",
|
|
117
161
|
'Stack End',
|
|
118
162
|
].join('\n');
|
|
119
|
-
const result = parseJestLuaOutput(input, {
|
|
163
|
+
const result = parseJestLuaOutput(input, {
|
|
164
|
+
packageName: '@quenty/maid',
|
|
165
|
+
repoRoot: REPO_ROOT,
|
|
166
|
+
workspace,
|
|
167
|
+
});
|
|
120
168
|
expect(result).toHaveLength(1);
|
|
121
169
|
expect(result[0]).toEqual({
|
|
122
|
-
file: 'src/maid/src/Shared/
|
|
170
|
+
file: 'src/maid/src/Shared/MaidTaskUtils.lua',
|
|
123
171
|
line: 23,
|
|
124
172
|
severity: 'error',
|
|
125
173
|
title: 'Runtime error',
|
|
@@ -134,18 +182,24 @@ describe('parseJestLuaOutput', () => {
|
|
|
134
182
|
' Expected: 1',
|
|
135
183
|
' Received: 2',
|
|
136
184
|
'',
|
|
137
|
-
' at ServerScriptService.
|
|
185
|
+
' at ServerScriptService.maid.Shared.MaidTaskUtils.spec:10',
|
|
138
186
|
'',
|
|
139
187
|
'Error: attempt to call nil value',
|
|
140
188
|
'Stack Begin',
|
|
141
|
-
"Script 'ServerScriptService.
|
|
189
|
+
"Script 'ServerScriptService.maid.Shared.Maid', Line 5",
|
|
142
190
|
'Stack End',
|
|
143
191
|
].join('\n');
|
|
144
|
-
const result = parseJestLuaOutput(input, {
|
|
192
|
+
const result = parseJestLuaOutput(input, {
|
|
193
|
+
packageName: '@quenty/maid',
|
|
194
|
+
repoRoot: REPO_ROOT,
|
|
195
|
+
workspace,
|
|
196
|
+
});
|
|
145
197
|
expect(result).toHaveLength(2);
|
|
146
198
|
expect(result[0].title).toBe('Suite > assertion test');
|
|
147
199
|
expect(result[0].source).toBe('jest-lua');
|
|
148
200
|
expect(result[1].title).toBe('Runtime error');
|
|
201
|
+
expect(result[1].message).toBe('Error: attempt to call nil value');
|
|
202
|
+
expect(result[1].file).toBe('src/maid/src/Shared/Maid.lua');
|
|
149
203
|
expect(result[1].line).toBe(5);
|
|
150
204
|
});
|
|
151
205
|
it('returns empty array for all-passing output', () => {
|
|
@@ -158,7 +212,7 @@ describe('parseJestLuaOutput', () => {
|
|
|
158
212
|
'Test Suites: 1 passed, 1 total',
|
|
159
213
|
'Tests: 2 passed, 2 total',
|
|
160
214
|
].join('\n');
|
|
161
|
-
const result = parseJestLuaOutput(input, { packageName: 'maid' });
|
|
215
|
+
const result = parseJestLuaOutput(input, { packageName: '@quenty/maid' });
|
|
162
216
|
expect(result).toEqual([]);
|
|
163
217
|
});
|
|
164
218
|
it('strips ANSI escape codes cleanly', () => {
|
|
@@ -168,9 +222,13 @@ describe('parseJestLuaOutput', () => {
|
|
|
168
222
|
' \x1b[31mExpected: 1\x1b[39m',
|
|
169
223
|
' \x1b[32mReceived: 2\x1b[39m',
|
|
170
224
|
'',
|
|
171
|
-
' at ServerScriptService.
|
|
225
|
+
' at ServerScriptService.maid.Shared.MaidTaskUtils.spec:10',
|
|
172
226
|
].join('\n');
|
|
173
|
-
const result = parseJestLuaOutput(input, {
|
|
227
|
+
const result = parseJestLuaOutput(input, {
|
|
228
|
+
packageName: '@quenty/maid',
|
|
229
|
+
repoRoot: REPO_ROOT,
|
|
230
|
+
workspace,
|
|
231
|
+
});
|
|
174
232
|
expect(result).toHaveLength(1);
|
|
175
233
|
expect(result[0].title).toBe('Suite > test');
|
|
176
234
|
expect(result[0].line).toBe(10);
|
|
@@ -184,28 +242,239 @@ describe('parseJestLuaOutput', () => {
|
|
|
184
242
|
' partial error message',
|
|
185
243
|
// No at-line, no Stack Begin, just ends
|
|
186
244
|
].join('\n');
|
|
187
|
-
const result = parseJestLuaOutput(input, { packageName: '
|
|
188
|
-
// Should still emit a diagnostic with fallback location
|
|
245
|
+
const result = parseJestLuaOutput(input, { packageName: '@quenty/maid' });
|
|
189
246
|
expect(result).toHaveLength(1);
|
|
190
247
|
expect(result[0].title).toBe('Suite > incomplete test');
|
|
191
|
-
expect(result[0].
|
|
248
|
+
expect(result[0].file).toBeUndefined();
|
|
192
249
|
});
|
|
193
250
|
it('handles empty input', () => {
|
|
194
|
-
const result = parseJestLuaOutput('', { packageName: '
|
|
251
|
+
const result = parseJestLuaOutput('', { packageName: '@quenty/maid' });
|
|
195
252
|
expect(result).toEqual([]);
|
|
196
253
|
});
|
|
197
|
-
it('
|
|
254
|
+
it('finds an aliased it() call by its quoted test name', () => {
|
|
198
255
|
const input = [
|
|
199
|
-
'
|
|
200
|
-
'
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
'
|
|
256
|
+
' ● Brine.serialize / Brine.deserialize roundtrip › propagates a tag added after subscribe',
|
|
257
|
+
'',
|
|
258
|
+
' assertion failed',
|
|
259
|
+
'',
|
|
260
|
+
' at ServerScriptService.brine.Shared.Brine.spec',
|
|
204
261
|
].join('\n');
|
|
205
|
-
const result = parseJestLuaOutput(input, {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
262
|
+
const result = parseJestLuaOutput(input, {
|
|
263
|
+
packageName: '@quenty/brine',
|
|
264
|
+
repoRoot: REPO_ROOT,
|
|
265
|
+
workspace,
|
|
266
|
+
});
|
|
267
|
+
expect(result[0].file).toBe('src/brine/src/Shared/Brine.spec.lua');
|
|
268
|
+
expect(result[0].line).toBe(495);
|
|
269
|
+
});
|
|
270
|
+
it('falls back to the enclosing describe for a generated test name', () => {
|
|
271
|
+
const input = [
|
|
272
|
+
' ● EllipticCurveCryptography Performance › should efficiently process 500 payloads of 100 bytes',
|
|
273
|
+
'',
|
|
274
|
+
' assertion failed',
|
|
275
|
+
'',
|
|
276
|
+
' at ServerScriptService.ellipticcurvecryptography.Shared.EllipticCurveCryptographyBenchmark.spec',
|
|
277
|
+
].join('\n');
|
|
278
|
+
const result = parseJestLuaOutput(input, {
|
|
279
|
+
packageName: '@quenty/ellipticcurvecryptography',
|
|
280
|
+
repoRoot: REPO_ROOT,
|
|
281
|
+
workspace,
|
|
282
|
+
});
|
|
283
|
+
expect(result[0].file).toBe('src/ellipticcurvecryptography/src/Shared/EllipticCurveCryptographyBenchmark.spec.lua');
|
|
284
|
+
expect(result[0].line).toBe(20);
|
|
285
|
+
});
|
|
286
|
+
it('emits the file with no line when no test name matches', () => {
|
|
287
|
+
const input = [
|
|
288
|
+
' ● should efficiently process 500 payloads of 100 bytes',
|
|
289
|
+
'',
|
|
290
|
+
' assertion failed',
|
|
291
|
+
'',
|
|
292
|
+
' at ServerScriptService.ellipticcurvecryptography.Shared.EllipticCurveCryptographyBenchmark.spec',
|
|
293
|
+
].join('\n');
|
|
294
|
+
const result = parseJestLuaOutput(input, {
|
|
295
|
+
packageName: '@quenty/ellipticcurvecryptography',
|
|
296
|
+
repoRoot: REPO_ROOT,
|
|
297
|
+
workspace,
|
|
298
|
+
});
|
|
299
|
+
expect(result[0].file).toBe('src/ellipticcurvecryptography/src/Shared/EllipticCurveCryptographyBenchmark.spec.lua');
|
|
300
|
+
expect(result[0].line).toBeUndefined();
|
|
301
|
+
});
|
|
302
|
+
describe('real CI logs', () => {
|
|
303
|
+
it('unwraps chunk names and picks the innermost package frame of a runtime error', () => {
|
|
304
|
+
const input = [
|
|
305
|
+
`[string "ServerScriptService.saveslot.Server.HasSaveSlotsDataStore"]:1668: attempt to call missing method 'GetSubStore' of table`,
|
|
306
|
+
' Stack Begin',
|
|
307
|
+
` Script '[string "ServerScriptService.saveslot.Server.HasSaveSlotsDataStore"]', Line 1668 - function _stagePlaytime`,
|
|
308
|
+
` Script '[string "ServerScriptService.saveslot.Server.HasSaveSlotsDataStore"]', Line 1647 - function _flushPlaytime`,
|
|
309
|
+
` Script '[string "ServerScriptService.saveslot.Server.HasSaveSlotsDataStore"]', Line 1678 - function _endPlaySession`,
|
|
310
|
+
` Script '[string "ServerScriptService.saveslot.Server.HasSaveSlotsDataStore"]', Line 1609`,
|
|
311
|
+
` Script '[string "ServerScriptService.saveslot.node_modules.@quenty.adorneedata.node_modules.@quenty.attributeutils.node_modules.@quenty.baseobject.node_modules.@quenty.maid.Shared.Maid"]', Line 267 - function DoCleaning`,
|
|
312
|
+
` Script '[string "ServerScriptService.saveslot.node_modules.@quenty.adorneedata.node_modules.@quenty.attributeutils.node_modules.@quenty.baseobject.Shared.BaseObject"]', Line 40 - function Destroy`,
|
|
313
|
+
` Script '[string "ServerScriptService.saveslot.node_modules.@quenty.binder.Shared.Binder"]', Line 752 - function _remove`,
|
|
314
|
+
` Script '[string "ServerScriptService.saveslot.node_modules.@quenty.binder.Shared.Binder"]', Line 224`,
|
|
315
|
+
' Stack End',
|
|
316
|
+
].join('\n');
|
|
317
|
+
const result = parseJestLuaOutput(input, {
|
|
318
|
+
packageName: '@quenty/saveslot',
|
|
319
|
+
repoRoot: REPO_ROOT,
|
|
320
|
+
workspace,
|
|
321
|
+
});
|
|
322
|
+
expect(result).toHaveLength(1);
|
|
323
|
+
expect(result[0].file).toBe('src/saveslot/src/Server/HasSaveSlotsDataStore.lua');
|
|
324
|
+
expect(result[0].line).toBe(1668);
|
|
325
|
+
});
|
|
326
|
+
it('reads past frames from other service roots', () => {
|
|
327
|
+
const input = [
|
|
328
|
+
' ● GameProductCmdrService › registers commands',
|
|
329
|
+
'',
|
|
330
|
+
' Cannot provide template "CmdrExecutionTemplate"',
|
|
331
|
+
'',
|
|
332
|
+
' ServerScriptService.gameproduct.node_modules.@quenty.cmdrservice.node_modules.@quenty.templateprovider.Shared.TemplateProvider:726 function CloneTemplate',
|
|
333
|
+
' ReplicatedStorage.Packages.CmdrClient:5',
|
|
334
|
+
' ServerScriptService.gameproduct.Server.Cmdr.GameProductCmdrService:59 function _registerCommands',
|
|
335
|
+
'',
|
|
336
|
+
].join('\n');
|
|
337
|
+
const result = parseJestLuaOutput(input, {
|
|
338
|
+
packageName: '@quenty/gameproductservice',
|
|
339
|
+
repoRoot: REPO_ROOT,
|
|
340
|
+
workspace,
|
|
341
|
+
});
|
|
342
|
+
expect(result[0].file).toBe('src/gameproductservice/src/Server/Cmdr/GameProductCmdrService.lua');
|
|
343
|
+
expect(result[0].line).toBe(59);
|
|
344
|
+
});
|
|
345
|
+
it('reads Jest frames without an `at` prefix', () => {
|
|
346
|
+
const input = [
|
|
347
|
+
'\x1b[1m\x1b[31m \x1b[1m● \x1b[22m\x1b[1msave slot playtime › persists accrued playtime on the save that triggered the flush\x1b[39m\x1b[22m',
|
|
348
|
+
'',
|
|
349
|
+
" attempt to call missing method 'GetSubStore' of table",
|
|
350
|
+
'\x1b[2m\x1b[22m',
|
|
351
|
+
'\x1b[2m ServerScriptService.saveslot.Server.HasSaveSlotsDataStore:1668\x1b[22m',
|
|
352
|
+
'',
|
|
353
|
+
'\x1b[1m\x1b[31m \x1b[1m● \x1b[22m\x1b[1msave slot playtime › keeps the replicated attribute and the stored value in step\x1b[39m\x1b[22m',
|
|
354
|
+
'',
|
|
355
|
+
" attempt to call missing method 'GetSubStore' of table",
|
|
356
|
+
'\x1b[2m\x1b[22m',
|
|
357
|
+
'\x1b[2m ServerScriptService.saveslot.Server.HasSaveSlotsDataStore:1668\x1b[22m',
|
|
358
|
+
'',
|
|
359
|
+
].join('\n');
|
|
360
|
+
const result = parseJestLuaOutput(input, {
|
|
361
|
+
packageName: '@quenty/saveslot',
|
|
362
|
+
repoRoot: REPO_ROOT,
|
|
363
|
+
workspace,
|
|
364
|
+
});
|
|
365
|
+
expect(result).toHaveLength(2);
|
|
366
|
+
expect(result.map((d) => [d.file, d.line, d.title])).toEqual([
|
|
367
|
+
[
|
|
368
|
+
'src/saveslot/src/Server/HasSaveSlotsDataStore.lua',
|
|
369
|
+
1668,
|
|
370
|
+
'save slot playtime › persists accrued playtime on the save that triggered the flush',
|
|
371
|
+
],
|
|
372
|
+
[
|
|
373
|
+
'src/saveslot/src/Server/HasSaveSlotsDataStore.lua',
|
|
374
|
+
1668,
|
|
375
|
+
'save slot playtime › keeps the replicated attribute and the stored value in step',
|
|
376
|
+
],
|
|
377
|
+
]);
|
|
378
|
+
expect(result[0].message).toBe("attempt to call missing method 'GetSubStore' of table");
|
|
379
|
+
});
|
|
380
|
+
it('prefers the package under test over dependency frames', () => {
|
|
381
|
+
const input = [
|
|
382
|
+
`[string "ServerScriptService.gameproduct.node_modules.@quenty.cmdrservice.node_modules.@quenty.templateprovider.Shared.TemplateProvider"]:726: [TemplateProvider.CmdrTemplateProviderServer.CloneTemplate] - Cannot provide template "CmdrExecutionTemplate"`,
|
|
383
|
+
' Stack Begin',
|
|
384
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.cmdrservice.node_modules.@quenty.templateprovider.Shared.TemplateProvider"]', Line 726 - function CloneTemplate`,
|
|
385
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.cmdrservice.Server.CmdrService"]', Line 144 - function RegisterCommand`,
|
|
386
|
+
` Script '[string "ServerScriptService.gameproduct.Server.Cmdr.GameProductCmdrService"]', Line 59 - function _registerCommands`,
|
|
387
|
+
` Script '[string "ServerScriptService.gameproduct.Server.Cmdr.GameProductCmdrService"]', Line 55 - function Start`,
|
|
388
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.avatareditorutils.node_modules.@quenty.observablecollection.node_modules.@quenty.blend.node_modules.@quenty.playerthumbnailutils.node_modules.@quenty.playermock.node_modules.@quenty.servic..."]', Line 217`,
|
|
389
|
+
' Stack End',
|
|
390
|
+
].join('\n');
|
|
391
|
+
const result = parseJestLuaOutput(input, {
|
|
392
|
+
packageName: '@quenty/gameproductservice',
|
|
393
|
+
repoRoot: REPO_ROOT,
|
|
394
|
+
workspace,
|
|
395
|
+
});
|
|
396
|
+
expect(result).toHaveLength(1);
|
|
397
|
+
expect(result[0].file).toBe('src/gameproductservice/src/Server/Cmdr/GameProductCmdrService.lua');
|
|
398
|
+
expect(result[0].line).toBe(59);
|
|
399
|
+
});
|
|
400
|
+
it('does not let a sibling package frame land in the package under test', () => {
|
|
401
|
+
const input = [
|
|
402
|
+
`[string "ServerScriptService.saveslot.Server.HasSaveSlotsDataStore"]:1668: attempt to call missing method 'GetSubStore' of table`,
|
|
403
|
+
' Stack Begin',
|
|
404
|
+
` Script '[string "ServerScriptService.othersibling.Server.SaveSlotService"]', Line 10`,
|
|
405
|
+
` Script '[string "ServerScriptService.saveslot.Server.HasSaveSlotsDataStore"]', Line 1668 - function _stagePlaytime`,
|
|
406
|
+
' Stack End',
|
|
407
|
+
].join('\n');
|
|
408
|
+
const result = parseJestLuaOutput(input, {
|
|
409
|
+
packageName: '@quenty/saveslot',
|
|
410
|
+
repoRoot: REPO_ROOT,
|
|
411
|
+
workspace,
|
|
412
|
+
});
|
|
413
|
+
expect(result).toHaveLength(1);
|
|
414
|
+
expect(result[0].file).toBe('src/saveslot/src/Server/HasSaveSlotsDataStore.lua');
|
|
415
|
+
expect(result[0].line).toBe(1668);
|
|
416
|
+
});
|
|
417
|
+
it('maps dependency frames back to the dependency source package', () => {
|
|
418
|
+
const input = [
|
|
419
|
+
`[string "ServerScriptService.gameproduct.node_modules.@quenty.cmdrservice.node_modules.@quenty.templateprovider.Shared.TemplateProvider"]:726: [TemplateProvider.CmdrTemplateProviderServer.CloneTemplate] - Cannot provide template "CmdrExecutionTemplate"`,
|
|
420
|
+
' Stack Begin',
|
|
421
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.cmdrservice.node_modules.@quenty.templateprovider.Shared.TemplateProvider"]', Line 726 - function CloneTemplate`,
|
|
422
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.cmdrservice.Server.CmdrService"]', Line 144 - function RegisterCommand`,
|
|
423
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.gameconfig.Server.Cmdr.GameConfigCommandService"]', Line 48 - function _registerCommands`,
|
|
424
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.gameconfig.Server.Cmdr.GameConfigCommandService"]', Line 37 - function Start`,
|
|
425
|
+
` Script '[string "ServerScriptService.gameproduct.node_modules.@quenty.avatareditorutils.node_modules.@quenty.observablecollection.node_modules.@quenty.blend.node_modules.@quenty.playerthumbnailutils.node_modules.@quenty.playermock.node_modules.@quenty.servic..."]', Line 217`,
|
|
426
|
+
' Stack End',
|
|
427
|
+
].join('\n');
|
|
428
|
+
const result = parseJestLuaOutput(input, {
|
|
429
|
+
packageName: '@quenty/gameproductservice',
|
|
430
|
+
repoRoot: REPO_ROOT,
|
|
431
|
+
workspace,
|
|
432
|
+
});
|
|
433
|
+
expect(result).toHaveLength(1);
|
|
434
|
+
expect(result[0].file).toBe('src/templateprovider/src/Shared/TemplateProvider.lua');
|
|
435
|
+
expect(result[0].line).toBe(726);
|
|
436
|
+
});
|
|
437
|
+
const studioBridgeHeader = [
|
|
438
|
+
'\x1b[0m\x1b[7m\x1b[1m\x1b[31m FAIL \x1b[39m\x1b[22m\x1b[27m\x1b[0m \x1b[2mstudiobridge/Shared/\x1b[22m\x1b[1mActionRouter.spec\x1b[22m ',
|
|
439
|
+
' \x1b[1m● \x1b[22mTest suite failed to run',
|
|
440
|
+
'',
|
|
441
|
+
];
|
|
442
|
+
const studioBridgeFrames = [
|
|
443
|
+
' ServerScriptService.studiobridge.node_modules.@quenty.nevermore-test-runner.node_modules.@quentystudios.Jest._Index.jsdotlua_jest-runtime@3.10.0.jest-runtime:1263 function requireModule',
|
|
444
|
+
' ServerScriptService.studiobridge.node_modules.@quenty.nevermore-test-runner.node_modules.@quentystudios.Jest._Index.jsdotlua_jest-circus@3.10.0.jest-circus.circus.legacy-code-todo-rewrite.jestAdapter:113',
|
|
445
|
+
' ServerScriptService.studiobridge.node_modules.@quenty.nevermore-test-runner.node_modules.@quentystudios.Jest._Index.jsdotlua_promise@3.5.2.promise:172 function runExecutor',
|
|
446
|
+
'',
|
|
447
|
+
'\x1b[0m\x1b[7m\x1b[1m\x1b[31m FAIL \x1b[39m\x1b[22m\x1b[27m\x1b[0m \x1b[2mstudiobridge/Shared/\x1b[22m\x1b[1mBuiltInActions.spec\x1b[22m ',
|
|
448
|
+
];
|
|
449
|
+
it('falls back to a chunk location inside the message', () => {
|
|
450
|
+
const input = [
|
|
451
|
+
...studioBridgeHeader,
|
|
452
|
+
` ServerScriptService.studiobridge.node_modules.@quenty.nevermore-test-runner.node_modules.@quentystudios.Jest._Index.jsdotlua_jest-runtime@3.10.0.jest-runtime:1263: [string "ServerScriptService.studiobridge.node_modules.@quenty.nevermore-test-runner.node_modules.@quenty.loader"]:214: [Loader] - "Jest" is not available. Please`,
|
|
453
|
+
'',
|
|
454
|
+
...studioBridgeFrames,
|
|
455
|
+
].join('\n');
|
|
456
|
+
const result = parseJestLuaOutput(input, {
|
|
457
|
+
packageName: '@quenty/studio-bridge',
|
|
458
|
+
repoRoot: REPO_ROOT,
|
|
459
|
+
workspace,
|
|
460
|
+
});
|
|
461
|
+
expect(result).toHaveLength(1);
|
|
462
|
+
expect(result[0].title).toBe('Test suite failed to run');
|
|
463
|
+
expect(result[0].file).toBe('src/loader/src/init.lua');
|
|
464
|
+
expect(result[0].line).toBe(214);
|
|
465
|
+
});
|
|
466
|
+
it('emits no file when only vendored frames are present', () => {
|
|
467
|
+
const input = [...studioBridgeHeader, ...studioBridgeFrames].join('\n');
|
|
468
|
+
const result = parseJestLuaOutput(input, {
|
|
469
|
+
packageName: '@quenty/studio-bridge',
|
|
470
|
+
repoRoot: REPO_ROOT,
|
|
471
|
+
workspace,
|
|
472
|
+
});
|
|
473
|
+
expect(result).toHaveLength(1);
|
|
474
|
+
expect(result[0].title).toBe('Test suite failed to run');
|
|
475
|
+
expect(result[0].file).toBeUndefined();
|
|
476
|
+
expect(result[0].line).toBeUndefined();
|
|
477
|
+
});
|
|
209
478
|
});
|
|
210
479
|
describe('with sourcemap resolver', () => {
|
|
211
480
|
const repoRoot = '/repo';
|
|
@@ -240,6 +509,24 @@ describe('parseJestLuaOutput', () => {
|
|
|
240
509
|
},
|
|
241
510
|
],
|
|
242
511
|
},
|
|
512
|
+
{
|
|
513
|
+
name: 'binder',
|
|
514
|
+
className: 'Folder',
|
|
515
|
+
filePaths: [`${repoRoot}/src/binder/default.project.json`],
|
|
516
|
+
children: [
|
|
517
|
+
{
|
|
518
|
+
name: 'Shared',
|
|
519
|
+
className: 'Folder',
|
|
520
|
+
children: [
|
|
521
|
+
{
|
|
522
|
+
name: 'Binder',
|
|
523
|
+
className: 'ModuleScript',
|
|
524
|
+
filePaths: [`${repoRoot}/src/binder/src/Shared/Binder.lua`],
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
},
|
|
528
|
+
],
|
|
529
|
+
},
|
|
243
530
|
],
|
|
244
531
|
};
|
|
245
532
|
const resolver = SourcemapResolver.fromSourcemap(sourcemap, repoRoot);
|
|
@@ -253,44 +540,60 @@ describe('parseJestLuaOutput', () => {
|
|
|
253
540
|
' at ServerScriptService.mypkg.Shared.Foo.Foo.spec:10',
|
|
254
541
|
].join('\n');
|
|
255
542
|
const result = parseJestLuaOutput(input, {
|
|
256
|
-
packageName: 'mypkg',
|
|
543
|
+
packageName: '@quenty/mypkg',
|
|
257
544
|
sourcemapResolver: resolver,
|
|
258
545
|
});
|
|
259
546
|
expect(result).toHaveLength(1);
|
|
260
547
|
expect(result[0].file).toBe('src/mypkg/src/Shared/Foo.spec.lua');
|
|
261
548
|
expect(result[0].line).toBe(10);
|
|
262
549
|
});
|
|
263
|
-
it('uses sourcemap resolver for runtime error paths', () => {
|
|
550
|
+
it('uses sourcemap resolver for chunk-wrapped runtime error paths', () => {
|
|
264
551
|
const input = [
|
|
265
552
|
'Error: attempt to index nil',
|
|
266
553
|
'Stack Begin',
|
|
267
|
-
|
|
554
|
+
`Script '[string "ServerScriptService.mypkg.Shared.Foo.Foo.spec"]', Line 5`,
|
|
268
555
|
'Stack End',
|
|
269
556
|
].join('\n');
|
|
270
557
|
const result = parseJestLuaOutput(input, {
|
|
271
|
-
packageName: 'mypkg',
|
|
558
|
+
packageName: '@quenty/mypkg',
|
|
272
559
|
sourcemapResolver: resolver,
|
|
273
560
|
});
|
|
274
561
|
expect(result).toHaveLength(1);
|
|
275
562
|
expect(result[0].file).toBe('src/mypkg/src/Shared/Foo.spec.lua');
|
|
276
563
|
expect(result[0].line).toBe(5);
|
|
277
564
|
});
|
|
278
|
-
it('
|
|
565
|
+
it('looks up dependency frames by their source package', () => {
|
|
566
|
+
const input = [
|
|
567
|
+
'Error: attempt to index nil',
|
|
568
|
+
' Stack Begin',
|
|
569
|
+
` Script '[string "ServerScriptService.mypkg.node_modules.@quenty.binder.Shared.Binder"]', Line 752 - function _remove`,
|
|
570
|
+
' Stack End',
|
|
571
|
+
].join('\n');
|
|
572
|
+
const result = parseJestLuaOutput(input, {
|
|
573
|
+
packageName: '@quenty/mypkg',
|
|
574
|
+
sourcemapResolver: resolver,
|
|
575
|
+
});
|
|
576
|
+
expect(result).toHaveLength(1);
|
|
577
|
+
expect(result[0].file).toBe('src/binder/src/Shared/Binder.lua');
|
|
578
|
+
expect(result[0].line).toBe(752);
|
|
579
|
+
});
|
|
580
|
+
it('falls back to the repo layout when sourcemap has no mapping', () => {
|
|
279
581
|
const input = [
|
|
280
582
|
' ● Suite > test one',
|
|
281
583
|
'',
|
|
282
584
|
' Expected: 1',
|
|
283
585
|
' Received: 2',
|
|
284
586
|
'',
|
|
285
|
-
' at ServerScriptService.
|
|
587
|
+
' at ServerScriptService.observablecollection.Shared.ObservableList.spec:10',
|
|
286
588
|
].join('\n');
|
|
287
589
|
const result = parseJestLuaOutput(input, {
|
|
288
|
-
packageName: '
|
|
590
|
+
packageName: '@quenty/observablecollection',
|
|
289
591
|
sourcemapResolver: resolver,
|
|
592
|
+
repoRoot: REPO_ROOT,
|
|
593
|
+
workspace,
|
|
290
594
|
});
|
|
291
595
|
expect(result).toHaveLength(1);
|
|
292
|
-
|
|
293
|
-
expect(result[0].file).toBe('src/unknown/src/Shared/Bar.spec.lua');
|
|
596
|
+
expect(result[0].file).toBe('src/observablecollection/src/Shared/ObservableList.spec.lua');
|
|
294
597
|
});
|
|
295
598
|
});
|
|
296
599
|
});
|