@quenty/nevermore-cli 4.43.4 → 4.44.0
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 +4 -0
- package/build-scripts/{combine-test-places.luau → combine-test-places.lua} +3 -3
- package/build-scripts/{transform-inject-deploy-metadata.luau → transform-inject-deploy-metadata.lua} +3 -3
- package/dist/commands/batch-command/batch-deploy-command.js +4 -4
- package/dist/commands/batch-command/batch-deploy-command.js.map +1 -1
- package/dist/commands/batch-command/batch-test-command.d.ts.map +1 -1
- package/dist/commands/batch-command/batch-test-command.js +76 -19
- package/dist/commands/batch-command/batch-test-command.js.map +1 -1
- package/dist/commands/deploy-command/deploy-init-utils.d.ts.map +1 -1
- package/dist/commands/deploy-command/deploy-init-utils.js +7 -1
- package/dist/commands/deploy-command/deploy-init-utils.js.map +1 -1
- package/dist/commands/deploy-command/index.js +1 -1
- package/dist/commands/deploy-command/index.js.map +1 -1
- package/dist/utils/deploy/deploy-github-columns.d.ts +12 -2
- package/dist/utils/deploy/deploy-github-columns.d.ts.map +1 -1
- package/dist/utils/deploy/deploy-github-columns.js +11 -4
- package/dist/utils/deploy/deploy-github-columns.js.map +1 -1
- package/dist/utils/deploy/deploy-metadata.js +1 -1
- package/dist/utils/deploy/deploy-metadata.js.map +1 -1
- package/dist/utils/job-context/base-job-context.d.ts +2 -2
- package/dist/utils/job-context/base-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/base-job-context.js +1 -1
- package/dist/utils/job-context/base-job-context.js.map +1 -1
- package/dist/utils/job-context/batch-script-job-context.d.ts +37 -2
- package/dist/utils/job-context/batch-script-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/batch-script-job-context.js +59 -22
- package/dist/utils/job-context/batch-script-job-context.js.map +1 -1
- package/dist/utils/job-context/cloud-job-context.d.ts +2 -2
- package/dist/utils/job-context/cloud-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/cloud-job-context.js +10 -5
- package/dist/utils/job-context/cloud-job-context.js.map +1 -1
- package/dist/utils/job-context/cloud-job-context.test.d.ts +7 -0
- package/dist/utils/job-context/cloud-job-context.test.d.ts.map +1 -0
- package/dist/utils/job-context/cloud-job-context.test.js +91 -0
- package/dist/utils/job-context/cloud-job-context.test.js.map +1 -0
- package/dist/utils/job-context/job-context.d.ts +70 -2
- package/dist/utils/job-context/job-context.d.ts.map +1 -1
- package/dist/utils/job-context/local-job-context.d.ts +2 -2
- package/dist/utils/job-context/local-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/local-job-context.js +4 -2
- package/dist/utils/job-context/local-job-context.js.map +1 -1
- package/dist/utils/job-context/local-job-context.test.d.ts +7 -0
- package/dist/utils/job-context/local-job-context.test.d.ts.map +1 -0
- package/dist/utils/job-context/local-job-context.test.js +68 -0
- package/dist/utils/job-context/local-job-context.test.js.map +1 -0
- package/dist/utils/open-cloud/open-cloud-client.d.ts +50 -7
- package/dist/utils/open-cloud/open-cloud-client.d.ts.map +1 -1
- package/dist/utils/open-cloud/open-cloud-client.js +49 -13
- package/dist/utils/open-cloud/open-cloud-client.js.map +1 -1
- package/dist/utils/open-cloud/open-cloud-client.test.js +125 -1
- package/dist/utils/open-cloud/open-cloud-client.test.js.map +1 -1
- package/dist/utils/open-cloud/open-cloud-logs.characterization.test.d.ts +22 -0
- package/dist/utils/open-cloud/open-cloud-logs.characterization.test.d.ts.map +1 -0
- package/dist/utils/open-cloud/open-cloud-logs.characterization.test.js +202 -0
- package/dist/utils/open-cloud/open-cloud-logs.characterization.test.js.map +1 -0
- package/dist/utils/package-manager-utils.d.ts.map +1 -1
- package/dist/utils/package-manager-utils.js +32 -1
- package/dist/utils/package-manager-utils.js.map +1 -1
- package/dist/utils/package-manager-utils.test.js +25 -0
- package/dist/utils/package-manager-utils.test.js.map +1 -1
- package/dist/utils/testing/batch-run.e2e.test.d.ts +17 -0
- package/dist/utils/testing/batch-run.e2e.test.d.ts.map +1 -0
- package/dist/utils/testing/batch-run.e2e.test.js +343 -0
- package/dist/utils/testing/batch-run.e2e.test.js.map +1 -0
- package/dist/utils/testing/batch-test-runner-template.test.d.ts +11 -0
- package/dist/utils/testing/batch-test-runner-template.test.d.ts.map +1 -0
- package/dist/utils/testing/batch-test-runner-template.test.js +38 -0
- package/dist/utils/testing/batch-test-runner-template.test.js.map +1 -0
- package/dist/utils/testing/log-fetch-stats.d.ts +40 -0
- package/dist/utils/testing/log-fetch-stats.d.ts.map +1 -0
- package/dist/utils/testing/log-fetch-stats.js +18 -0
- package/dist/utils/testing/log-fetch-stats.js.map +1 -0
- package/dist/utils/testing/log-fetch-stats.test.d.ts +2 -0
- package/dist/utils/testing/log-fetch-stats.test.d.ts.map +1 -0
- package/dist/utils/testing/log-fetch-stats.test.js +41 -0
- package/dist/utils/testing/log-fetch-stats.test.js.map +1 -0
- package/dist/utils/testing/parsers/batch-log-parser.d.ts +126 -1
- package/dist/utils/testing/parsers/batch-log-parser.d.ts.map +1 -1
- package/dist/utils/testing/parsers/batch-log-parser.js +440 -103
- package/dist/utils/testing/parsers/batch-log-parser.js.map +1 -1
- package/dist/utils/testing/parsers/batch-log-parser.test.js +494 -1
- package/dist/utils/testing/parsers/batch-log-parser.test.js.map +1 -1
- package/dist/utils/testing/parsers/batch-log-renderer.d.ts +79 -0
- package/dist/utils/testing/parsers/batch-log-renderer.d.ts.map +1 -0
- package/dist/utils/testing/parsers/batch-log-renderer.js +241 -0
- package/dist/utils/testing/parsers/batch-log-renderer.js.map +1 -0
- package/dist/utils/testing/parsers/batch-log-renderer.test.d.ts +2 -0
- package/dist/utils/testing/parsers/batch-log-renderer.test.d.ts.map +1 -0
- package/dist/utils/testing/parsers/batch-log-renderer.test.js +202 -0
- package/dist/utils/testing/parsers/batch-log-renderer.test.js.map +1 -0
- package/dist/utils/testing/runner/combined-project-generator.js +1 -1
- package/dist/utils/testing/runner/combined-project-generator.js.map +1 -1
- package/dist/utils/testing/runner/test-runner.d.ts +24 -0
- package/dist/utils/testing/runner/test-runner.d.ts.map +1 -1
- package/dist/utils/testing/runner/test-runner.js +166 -6
- package/dist/utils/testing/runner/test-runner.js.map +1 -1
- package/dist/utils/testing/runner/test-runner.test.js +228 -2
- package/dist/utils/testing/runner/test-runner.test.js.map +1 -1
- package/dist/utils/testing/structured-test-results.d.ts +77 -0
- package/dist/utils/testing/structured-test-results.d.ts.map +1 -0
- package/dist/utils/testing/structured-test-results.js +140 -0
- package/dist/utils/testing/structured-test-results.js.map +1 -0
- package/dist/utils/testing/structured-test-results.test.d.ts +7 -0
- package/dist/utils/testing/structured-test-results.test.d.ts.map +1 -0
- package/dist/utils/testing/structured-test-results.test.js +179 -0
- package/dist/utils/testing/structured-test-results.test.js.map +1 -0
- package/package.json +6 -6
- package/src/commands/batch-command/batch-deploy-command.ts +4 -4
- package/src/commands/batch-command/batch-test-command.ts +94 -19
- package/src/commands/deploy-command/deploy-init-utils.ts +7 -1
- package/src/commands/deploy-command/index.ts +1 -1
- package/src/utils/deploy/deploy-github-columns.ts +14 -4
- package/src/utils/deploy/deploy-metadata.ts +1 -1
- package/src/utils/job-context/base-job-context.ts +3 -2
- package/src/utils/job-context/batch-script-job-context.ts +98 -17
- package/src/utils/job-context/cloud-job-context.test.ts +112 -0
- package/src/utils/job-context/cloud-job-context.ts +12 -6
- package/src/utils/job-context/job-context.ts +71 -2
- package/src/utils/job-context/local-job-context.test.ts +89 -0
- package/src/utils/job-context/local-job-context.ts +7 -3
- package/src/utils/open-cloud/open-cloud-client.test.ts +155 -1
- package/src/utils/open-cloud/open-cloud-client.ts +94 -18
- package/src/utils/open-cloud/open-cloud-logs.characterization.test.ts +277 -0
- package/src/utils/package-manager-utils.test.ts +27 -0
- package/src/utils/package-manager-utils.ts +34 -1
- package/src/utils/testing/batch-run.e2e.test.ts +425 -0
- package/src/utils/testing/batch-test-runner-template.test.ts +62 -0
- package/src/utils/testing/log-fetch-stats.test.ts +48 -0
- package/src/utils/testing/log-fetch-stats.ts +55 -0
- package/src/utils/testing/parsers/batch-log-parser.test.ts +660 -1
- package/src/utils/testing/parsers/batch-log-parser.ts +721 -116
- package/src/utils/testing/parsers/batch-log-renderer.test.ts +330 -0
- package/src/utils/testing/parsers/batch-log-renderer.ts +329 -0
- package/src/utils/testing/runner/combined-project-generator.ts +1 -1
- package/src/utils/testing/runner/test-runner.test.ts +332 -2
- package/src/utils/testing/runner/test-runner.ts +231 -9
- package/src/utils/testing/structured-test-results.test.ts +267 -0
- package/src/utils/testing/structured-test-results.ts +199 -0
- package/templates/batch-test-runner.lua +242 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/templates/batch-test-runner.luau +0 -137
- /package/build-scripts/{smoke-test-server.luau → smoke-test-server.lua} +0 -0
- /package/build-scripts/{transform-rojo-merge-place.luau → transform-rojo-merge-place.lua} +0 -0
|
@@ -2,6 +2,9 @@ import * as fs from 'fs/promises';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { randomUUID } from 'crypto';
|
|
4
4
|
import { parseTestLogs, parseTestCounts, } from '../test-log-parser.js';
|
|
5
|
+
import { describeLogVolume } from '../log-fetch-stats.js';
|
|
6
|
+
import { describeUnexplainedVerdict, findStructuredTestResults, structuredFailureReasons, toParsedTestCounts, } from '../structured-test-results.js';
|
|
7
|
+
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
5
8
|
import { buildDeployMetadataAttributes, gatherGitDeployInfo, injectDeployMetadataInPlaceAsync, packageUsesManifestAsync, } from '../../deploy/deploy-metadata.js';
|
|
6
9
|
import { readPackageVersionAsync } from '../../nevermore-cli-utils.js';
|
|
7
10
|
/**
|
|
@@ -64,26 +67,183 @@ export async function runSingleTestAsync(context, options) {
|
|
|
64
67
|
packageName,
|
|
65
68
|
timeoutMs,
|
|
66
69
|
});
|
|
67
|
-
const
|
|
70
|
+
const logs = await context.getLogsAsync(deployment);
|
|
71
|
+
const rawLogs = logs.text;
|
|
72
|
+
const logVolume = describeLogVolume(rawLogs, logs.stats);
|
|
73
|
+
// The runner used to announce a failing suite by throwing, which failed the
|
|
74
|
+
// task. It returns its verdict now, so the verdict has to be read: without
|
|
75
|
+
// this, a failing suite whose report fell outside the truncated log window
|
|
76
|
+
// would come back a pass.
|
|
77
|
+
//
|
|
78
|
+
// A context that already resolved the results (aggregated batch, where one
|
|
79
|
+
// execution's return value belongs to no single package) hands them over
|
|
80
|
+
// directly; otherwise they are decoded from what the script returned.
|
|
81
|
+
const structured = result.testResults ?? findStructuredTestResults(result.returnValues);
|
|
68
82
|
// A probe script is arbitrary Luau with no jest in it, so demanding a test
|
|
69
83
|
// report would fail every --script-text run. Everything else must prove a
|
|
70
|
-
// runner spoke before it can pass
|
|
84
|
+
// runner spoke before it can pass — and returned results are that proof,
|
|
85
|
+
// where a scraped report is only what survived truncation.
|
|
71
86
|
const parsed = parseTestLogs(rawLogs, {
|
|
72
|
-
requireTestReport: scriptText === undefined,
|
|
87
|
+
requireTestReport: scriptText === undefined && structured === undefined,
|
|
88
|
+
});
|
|
89
|
+
// A run that reports it never reached jest, for a package that has a
|
|
90
|
+
// jest.config on disk, did not test anything — the built place lost the
|
|
91
|
+
// config. Before results were returned, the required jest report caught this
|
|
92
|
+
// as "nothing proves any test ran"; a smoke-test result would otherwise
|
|
93
|
+
// retire that check and pass with zero tests.
|
|
94
|
+
const smokeTestedWithSpecs = structured !== undefined &&
|
|
95
|
+
!structured.ranJest &&
|
|
96
|
+
scriptText === undefined &&
|
|
97
|
+
(await packageHasJestConfigAsync(packagePath));
|
|
98
|
+
const reasons = mergeFailureReasons(result.errorMessage, [
|
|
99
|
+
...(smokeTestedWithSpecs
|
|
100
|
+
? [
|
|
101
|
+
'this package has a jest.config but the run reported no jest.config ' +
|
|
102
|
+
'in the built place, so none of its specs ran',
|
|
103
|
+
]
|
|
104
|
+
: []),
|
|
105
|
+
...(structured ? structuredFailureReasons(structured) : []),
|
|
106
|
+
...parsed.failureReasons,
|
|
107
|
+
// Said only when there was log text and it did not hold up: the reasons
|
|
108
|
+
// above are then statements about what arrived, and how much arrived is
|
|
109
|
+
// the first thing to check. With no text at all the verdict came from the
|
|
110
|
+
// absence of it, which the reason for that absence already explains —
|
|
111
|
+
// saying "0 chars received" beside it only contradicts the fetch that
|
|
112
|
+
// reported the whole window.
|
|
113
|
+
...(structured === undefined &&
|
|
114
|
+
parsed.failureReasons.length > 0 &&
|
|
115
|
+
rawLogs.length > 0
|
|
116
|
+
? [`verdict read from log text alone (${logVolume})`]
|
|
117
|
+
: []),
|
|
118
|
+
]);
|
|
119
|
+
// Returned counts outrank scraped ones: same numbers when the log
|
|
120
|
+
// survived, real numbers when it did not.
|
|
121
|
+
const scrapedCounts = parseTestCounts(parsed.logs);
|
|
122
|
+
const testCounts = structured
|
|
123
|
+
? toParsedTestCounts(structured)
|
|
124
|
+
: scrapedCounts;
|
|
125
|
+
reportCountsProvenance({
|
|
126
|
+
packageName,
|
|
127
|
+
structured,
|
|
128
|
+
scrapedCounts,
|
|
129
|
+
logVolume,
|
|
130
|
+
// A probe is not a test run, so it has no results to be missing. Neither
|
|
131
|
+
// is one package of an aggregated batch, whose context reports the whole
|
|
132
|
+
// batch's provenance once, as a group — repeating it per package printed
|
|
133
|
+
// the same fetch stats 78 times over.
|
|
134
|
+
silent: scriptText !== undefined ||
|
|
135
|
+
result.testResults !== undefined ||
|
|
136
|
+
(options.suppressCountsProvenance ?? false),
|
|
137
|
+
hadReturnChannel: result.returnValues !== undefined,
|
|
73
138
|
});
|
|
74
|
-
const reasons = mergeFailureReasons(result.errorMessage, parsed.failureReasons);
|
|
75
139
|
return {
|
|
76
|
-
success: result.success &&
|
|
140
|
+
success: result.success &&
|
|
141
|
+
parsed.success &&
|
|
142
|
+
(structured?.success ?? true) &&
|
|
143
|
+
!smokeTestedWithSpecs,
|
|
77
144
|
logs: parsed.logs,
|
|
78
|
-
testCounts
|
|
145
|
+
testCounts,
|
|
146
|
+
countsSource: structured
|
|
147
|
+
? 'returned'
|
|
148
|
+
: scrapedCounts
|
|
149
|
+
? 'scraped'
|
|
150
|
+
: undefined,
|
|
79
151
|
durationMs: result.durationMs,
|
|
80
152
|
error: reasons.length > 0 ? reasons.join('; ') : undefined,
|
|
153
|
+
logsLost: result.logsLost,
|
|
81
154
|
};
|
|
82
155
|
}
|
|
83
156
|
finally {
|
|
84
157
|
await context.releaseAsync(deployment);
|
|
85
158
|
}
|
|
86
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Say where a run's counts came from, and complain when they had to be scraped.
|
|
162
|
+
*
|
|
163
|
+
* The structured channel exists because Open Cloud truncates a long run's logs.
|
|
164
|
+
* A channel that is plumbed but not flowing produces output identical to one
|
|
165
|
+
* that works, so the fallback is a warning rather than silence — the first
|
|
166
|
+
* version of this shipped inert and looked green.
|
|
167
|
+
*/
|
|
168
|
+
function reportCountsProvenance(options) {
|
|
169
|
+
const { packageName, structured, scrapedCounts, silent, hadReturnChannel, logVolume, } = options;
|
|
170
|
+
if (silent) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (structured) {
|
|
174
|
+
OutputHelper.info(`${packageName}: counts returned by the run — ` +
|
|
175
|
+
`${structured.passed} passed, ${structured.failed} failed, ` +
|
|
176
|
+
`${structured.total} total.`);
|
|
177
|
+
const unexplained = describeUnexplainedVerdict(structured);
|
|
178
|
+
if (unexplained) {
|
|
179
|
+
OutputHelper.warn(`${packageName}: ${unexplained}`);
|
|
180
|
+
}
|
|
181
|
+
// A suite that runs and counts nothing is not the same as one that passed.
|
|
182
|
+
if (structured.ranJest && structured.total === 0) {
|
|
183
|
+
OutputHelper.warn(`${packageName}: jest ran but found no tests to run. If this package has ` +
|
|
184
|
+
`specs, they are not reaching the test place.`);
|
|
185
|
+
}
|
|
186
|
+
// Two channels reporting the same run must agree. When they do not, one is
|
|
187
|
+
// lying and neither total stands on its own.
|
|
188
|
+
if (scrapedCounts && scrapedCounts.total !== structured.total) {
|
|
189
|
+
OutputHelper.warn(`${packageName}: returned counts disagree with the log — the run returned ` +
|
|
190
|
+
`${structured.passed}/${structured.failed}/${structured.total} ` +
|
|
191
|
+
`(passed/failed/total), its jest report says ` +
|
|
192
|
+
`${scrapedCounts.passed}/${scrapedCounts.failed}/${scrapedCounts.total}. ` +
|
|
193
|
+
`Reporting the returned counts; one of the two channels is wrong.`);
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
OutputHelper.warn(`${packageName}: the run returned no test results, so its counts were ` +
|
|
198
|
+
(scrapedCounts ? 'scraped from log text' : 'unavailable') +
|
|
199
|
+
` — the channel Open Cloud truncates on long runs (${logVolume}). ` +
|
|
200
|
+
(hadReturnChannel
|
|
201
|
+
? 'The run delivered a return channel but nothing recognizable in it: the ' +
|
|
202
|
+
'test script should end with "return results" (see docs/testing/testing.md).'
|
|
203
|
+
: 'No return channel was delivered at all, so the transport lost it.'));
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Whether this package ships a jest.config, i.e. whether it has specs to run.
|
|
207
|
+
*
|
|
208
|
+
* Deliberately a bounded walk, not a recursive glob: every package under `src/`
|
|
209
|
+
* has a symlinked, self-referential `node_modules`, so recursive search here
|
|
210
|
+
* hangs. Two levels covers the layouts in use (`src/jest.config.lua` for a
|
|
211
|
+
* package, `src/modules/jest.config.lua` for a game) without needing a list of
|
|
212
|
+
* them.
|
|
213
|
+
*/
|
|
214
|
+
export async function packageHasJestConfigAsync(packagePath) {
|
|
215
|
+
async function scanAsync(dir, depth) {
|
|
216
|
+
let entries;
|
|
217
|
+
try {
|
|
218
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
for (const entry of entries) {
|
|
224
|
+
if (entry.isFile() && entry.name.startsWith('jest.config')) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (depth === 0) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
for (const entry of entries) {
|
|
232
|
+
if (!entry.isDirectory()) {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
// `test` holds the test place, never the specs the place runs.
|
|
236
|
+
if (entry.name === 'node_modules' || entry.name === 'test') {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (await scanAsync(path.join(dir, entry.name), depth - 1)) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
return scanAsync(packagePath, 2);
|
|
246
|
+
}
|
|
87
247
|
/**
|
|
88
248
|
* Read a test script from the deploy target's configured script path.
|
|
89
249
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC,OAAO,EAEL,aAAa,EACb,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,6BAA6B,EAC7B,mBAAmB,EACnB,gCAAgC,EAChC,wBAAwB,GACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,196 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { afterAll, afterEach, beforeAll, describe, expect, it, vi, } from 'vitest';
|
|
5
|
+
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
6
|
+
import { mergeFailureReasons, runSingleTestAsync } from './test-runner.js';
|
|
7
|
+
import { TEST_RESULTS_FORMAT } from '../structured-test-results.js';
|
|
8
|
+
const PASSING_LOGS = [
|
|
9
|
+
'Test Suites: 3 passed, 3 total',
|
|
10
|
+
'Tests: 25 passed, 25 total',
|
|
11
|
+
].join('\n');
|
|
12
|
+
function structuredResults(overrides = {}) {
|
|
13
|
+
return {
|
|
14
|
+
format: TEST_RESULTS_FORMAT,
|
|
15
|
+
success: true,
|
|
16
|
+
ranJest: true,
|
|
17
|
+
passed: 25,
|
|
18
|
+
failed: 0,
|
|
19
|
+
skipped: 0,
|
|
20
|
+
total: 25,
|
|
21
|
+
suitesPassed: 3,
|
|
22
|
+
suitesFailed: 0,
|
|
23
|
+
suitesTotal: 3,
|
|
24
|
+
failures: [],
|
|
25
|
+
omittedFailures: 0,
|
|
26
|
+
...overrides,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Collect what the runner said out loud, so silence can be asserted on. */
|
|
30
|
+
function captureWarnings() {
|
|
31
|
+
const warnings = [];
|
|
32
|
+
vi.spyOn(OutputHelper, 'warn').mockImplementation((message) => {
|
|
33
|
+
warnings.push(message);
|
|
34
|
+
});
|
|
35
|
+
vi.spyOn(OutputHelper, 'info').mockImplementation(() => { });
|
|
36
|
+
return () => warnings;
|
|
37
|
+
}
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
vi.restoreAllMocks();
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* A context that runs nothing: it hands back the run result and logs the test
|
|
43
|
+
* wants to reason about. Everything else is the minimum the runner touches.
|
|
44
|
+
*/
|
|
45
|
+
function createContext(run, logs) {
|
|
46
|
+
return {
|
|
47
|
+
buildPlaceAsync: async (options) => ({
|
|
48
|
+
rbxlPath: 'unused.rbxl',
|
|
49
|
+
target: options.target,
|
|
50
|
+
}),
|
|
51
|
+
deployBuiltPlaceAsync: async () => ({}),
|
|
52
|
+
runScriptAsync: async () => run,
|
|
53
|
+
getLogsAsync: async () => ({ text: logs, messages: [] }),
|
|
54
|
+
releaseAsync: async () => { },
|
|
55
|
+
releaseBuiltPlaceAsync: async () => { },
|
|
56
|
+
disposeAsync: async () => { },
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
describe('runSingleTestAsync', () => {
|
|
60
|
+
let packagePath;
|
|
61
|
+
beforeAll(async () => {
|
|
62
|
+
packagePath = await fs.mkdtemp(path.join(os.tmpdir(), 'nevermore-test-'));
|
|
63
|
+
await fs.writeFile(path.join(packagePath, 'ServerMain.server.lua'), 'return nil\n');
|
|
64
|
+
});
|
|
65
|
+
afterAll(async () => {
|
|
66
|
+
await fs.rm(packagePath, { recursive: true, force: true });
|
|
67
|
+
});
|
|
68
|
+
async function runAsync(run, logs) {
|
|
69
|
+
return runSingleTestAsync(createContext(run, logs), {
|
|
70
|
+
packagePath,
|
|
71
|
+
packageName: 'maid',
|
|
72
|
+
target: {
|
|
73
|
+
scriptTemplate: 'ServerMain.server.lua',
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
it('fails a run whose returned results say it failed', async () => {
|
|
78
|
+
// The runner used to announce this by throwing, which failed the task. Now
|
|
79
|
+
// it returns the verdict, and these logs are what a truncated window leaves
|
|
80
|
+
// behind: a jest report from a suite that passed and no sign of the one
|
|
81
|
+
// that did not.
|
|
82
|
+
const result = await runAsync({
|
|
83
|
+
success: true,
|
|
84
|
+
returnValues: [structuredResults({ success: false, failed: 2 })],
|
|
85
|
+
}, PASSING_LOGS);
|
|
86
|
+
expect(result.success).toBe(false);
|
|
87
|
+
expect(result.error).toContain('2 test(s) failed');
|
|
88
|
+
});
|
|
89
|
+
it('reports the counts the run returned, not the ones in the log', async () => {
|
|
90
|
+
const result = await runAsync({
|
|
91
|
+
success: true,
|
|
92
|
+
returnValues: [structuredResults({ passed: 400, total: 400 })],
|
|
93
|
+
}, PASSING_LOGS);
|
|
94
|
+
expect(result.success).toBe(true);
|
|
95
|
+
expect(result.testCounts).toEqual({ passed: 400, failed: 0, total: 400 });
|
|
96
|
+
});
|
|
97
|
+
it('accepts returned results as proof the runner ran', async () => {
|
|
98
|
+
// Demanding a jest report in the logs is a stand-in for that proof, and it
|
|
99
|
+
// is the first thing a truncated log window costs.
|
|
100
|
+
const result = await runAsync({ success: true, returnValues: [structuredResults()] }, '(logs truncated)');
|
|
101
|
+
expect(result.success).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
it('still fails a run with a traceback in its logs', async () => {
|
|
104
|
+
// Jest cannot count a deferred-callback crash, so passing results are no
|
|
105
|
+
// reason to stop reading the logs.
|
|
106
|
+
const result = await runAsync({ success: true, returnValues: [structuredResults()] }, `${PASSING_LOGS}\nStack Begin\nScript 'maid.spec', Line 4\nStack End`);
|
|
107
|
+
expect(result.success).toBe(false);
|
|
108
|
+
});
|
|
109
|
+
it('falls back to the logs for a script that returned nothing', async () => {
|
|
110
|
+
// A test script written before results were returned. It must keep working,
|
|
111
|
+
// and it must not start passing when its logs say otherwise.
|
|
112
|
+
const failing = await runAsync({ success: true, returnValues: [] }, 'Tests: 2 failed, 23 passed, 25 total');
|
|
113
|
+
expect(failing.success).toBe(false);
|
|
114
|
+
expect(failing.error).toContain('2 test(s) failed');
|
|
115
|
+
const passing = await runAsync({ success: true, returnValues: [] }, PASSING_LOGS);
|
|
116
|
+
expect(passing.success).toBe(true);
|
|
117
|
+
expect(passing.testCounts).toEqual({ passed: 25, failed: 0, total: 25 });
|
|
118
|
+
});
|
|
119
|
+
it('fails a script that returned nothing and logged nothing', async () => {
|
|
120
|
+
const result = await runAsync({ success: true, returnValues: undefined }, '');
|
|
121
|
+
expect(result.success).toBe(false);
|
|
122
|
+
expect(result.error).toContain('nothing proves any test ran');
|
|
123
|
+
});
|
|
124
|
+
it('records where the counts came from', async () => {
|
|
125
|
+
const returned = await runAsync({ success: true, returnValues: [structuredResults()] }, PASSING_LOGS);
|
|
126
|
+
expect(returned.countsSource).toBe('returned');
|
|
127
|
+
const scraped = await runAsync({ success: true, returnValues: [] }, PASSING_LOGS);
|
|
128
|
+
expect(scraped.countsSource).toBe('scraped');
|
|
129
|
+
});
|
|
130
|
+
it('warns out loud when the run returned no results', async () => {
|
|
131
|
+
// Silence here is what let the structured channel ship inert: a run that
|
|
132
|
+
// fell back to scraping produced output identical to one that did not.
|
|
133
|
+
const warnings = captureWarnings();
|
|
134
|
+
await runAsync({ success: true, returnValues: [] }, PASSING_LOGS);
|
|
135
|
+
expect(warnings().some((w) => w.includes('returned no test results'))).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
it('fails a package with specs whose run never reached jest', async () => {
|
|
138
|
+
// A Rojo regression that stops shipping jest.config turns a real suite into
|
|
139
|
+
// a smoke test. Before results were returned, the required jest report caught
|
|
140
|
+
// that; a smoke-test result retires the report and would otherwise pass with
|
|
141
|
+
// zero tests.
|
|
142
|
+
await fs.mkdir(path.join(packagePath, 'src'), { recursive: true });
|
|
143
|
+
await fs.writeFile(path.join(packagePath, 'src', 'jest.config.lua'), 'return {}\n');
|
|
144
|
+
const result = await runAsync({
|
|
145
|
+
success: true,
|
|
146
|
+
returnValues: [
|
|
147
|
+
structuredResults({ ranJest: false, passed: 0, total: 0 }),
|
|
148
|
+
],
|
|
149
|
+
}, '[NevermoreTestRunner] No jest.config found — smoke test passed (boot success)');
|
|
150
|
+
expect(result.success).toBe(false);
|
|
151
|
+
expect(result.error).toContain('none of its specs ran');
|
|
152
|
+
await fs.rm(path.join(packagePath, 'src'), {
|
|
153
|
+
recursive: true,
|
|
154
|
+
force: true,
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
it('passes a package with no specs that smoke tested', async () => {
|
|
158
|
+
// No jest.config on disk, so a smoke test is the whole contract.
|
|
159
|
+
const result = await runAsync({
|
|
160
|
+
success: true,
|
|
161
|
+
returnValues: [
|
|
162
|
+
structuredResults({ ranJest: false, passed: 0, total: 0 }),
|
|
163
|
+
],
|
|
164
|
+
}, '[NevermoreTestRunner] No jest.config found — smoke test passed (boot success)');
|
|
165
|
+
expect(result.success).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
it('takes results a context resolved for it, without re-reporting', async () => {
|
|
168
|
+
// Aggregated batch mode: one execution covers every package, so the batch
|
|
169
|
+
// log parser splits the per-package results out and has already reported
|
|
170
|
+
// provenance for the whole batch.
|
|
171
|
+
const warnings = captureWarnings();
|
|
172
|
+
const result = await runAsync({
|
|
173
|
+
success: true,
|
|
174
|
+
testResults: {
|
|
175
|
+
success: false,
|
|
176
|
+
ranJest: true,
|
|
177
|
+
passed: 273,
|
|
178
|
+
failed: 2,
|
|
179
|
+
skipped: 0,
|
|
180
|
+
total: 275,
|
|
181
|
+
suitesPassed: 8,
|
|
182
|
+
suitesFailed: 1,
|
|
183
|
+
suitesTotal: 9,
|
|
184
|
+
failures: [],
|
|
185
|
+
omittedFailures: 0,
|
|
186
|
+
},
|
|
187
|
+
}, '(this package’s section was truncated away)');
|
|
188
|
+
expect(result.success).toBe(false);
|
|
189
|
+
expect(result.countsSource).toBe('returned');
|
|
190
|
+
expect(result.testCounts).toEqual({ passed: 273, failed: 2, total: 275 });
|
|
191
|
+
expect(warnings()).toHaveLength(0);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
3
194
|
describe('mergeFailureReasons', () => {
|
|
4
195
|
it('does not repeat reasons the context already reported', () => {
|
|
5
196
|
// Batch mode evaluates the same logs upstream, so both sources describe the
|
|
@@ -15,4 +206,39 @@ describe('mergeFailureReasons', () => {
|
|
|
15
206
|
expect(mergeFailureReasons(undefined, [])).toEqual([]);
|
|
16
207
|
});
|
|
17
208
|
});
|
|
209
|
+
describe('runSingleTestAsync log volume reporting', () => {
|
|
210
|
+
let packagePath;
|
|
211
|
+
beforeAll(async () => {
|
|
212
|
+
packagePath = await fs.mkdtemp(path.join(os.tmpdir(), 'volume-'));
|
|
213
|
+
await fs.writeFile(path.join(packagePath, 'ServerMain.server.lua'), 'return nil\n');
|
|
214
|
+
});
|
|
215
|
+
afterAll(async () => {
|
|
216
|
+
await fs.rm(packagePath, { recursive: true, force: true });
|
|
217
|
+
});
|
|
218
|
+
function runAsync(logs) {
|
|
219
|
+
return runSingleTestAsync(createContext({ success: true }, logs), {
|
|
220
|
+
packagePath,
|
|
221
|
+
packageName: 'gameconfig',
|
|
222
|
+
target: {
|
|
223
|
+
scriptTemplate: 'ServerMain.server.lua',
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
it('reports how much log text a verdict was read from', async () => {
|
|
228
|
+
const result = await runAsync('some output with no jest report');
|
|
229
|
+
expect(result.success).toBe(false);
|
|
230
|
+
expect(result.error).toContain('verdict read from log text alone');
|
|
231
|
+
expect(result.error).toContain('31 chars, 1 line(s) received');
|
|
232
|
+
});
|
|
233
|
+
it('says nothing about log volume when there was no log text', async () => {
|
|
234
|
+
// A batch package whose section was lost has no text of its own. Reporting
|
|
235
|
+
// "0 chars received" here contradicts the fetch stats already printed for
|
|
236
|
+
// the whole batch window, and describes a judgement never made: the verdict
|
|
237
|
+
// came from the output being absent, which its own reason already says.
|
|
238
|
+
const result = await runAsync('');
|
|
239
|
+
expect(result.success).toBe(false);
|
|
240
|
+
expect(result.error).not.toContain('verdict read from log text alone');
|
|
241
|
+
expect(result.error).not.toContain('0 chars, 0 line(s)');
|
|
242
|
+
});
|
|
243
|
+
});
|
|
18
244
|
//# sourceMappingURL=test-runner.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner.test.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"test-runner.test.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type ParsedTestCounts } from './test-log-parser.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tag NevermoreTestRunnerUtils stamps on the results table a test script
|
|
4
|
+
* returns. A test place also runs probe scripts (`--script-text`) that return
|
|
5
|
+
* whatever they like, so results are recognized by this rather than by shape.
|
|
6
|
+
*/
|
|
7
|
+
export declare const TEST_RESULTS_FORMAT = "nevermore-test-results@1";
|
|
8
|
+
/** One failed test, or one suite that failed before its tests could run. */
|
|
9
|
+
export interface StructuredTestFailure {
|
|
10
|
+
name: string;
|
|
11
|
+
message?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* What a test run says about itself, returned as a value instead of printed.
|
|
15
|
+
*
|
|
16
|
+
* Open Cloud truncates a long run's logs, so counts scraped out of that text go
|
|
17
|
+
* missing on exactly the runs where they matter most. Mirrors the
|
|
18
|
+
* `TestRunResults` table in `NevermoreTestRunnerUtils`.
|
|
19
|
+
*/
|
|
20
|
+
export interface StructuredTestResults {
|
|
21
|
+
success: boolean;
|
|
22
|
+
/** False for a smoke test, whose counts are all zero because nothing counted. */
|
|
23
|
+
ranJest: boolean;
|
|
24
|
+
passed: number;
|
|
25
|
+
failed: number;
|
|
26
|
+
/** Pending plus todo. */
|
|
27
|
+
skipped: number;
|
|
28
|
+
total: number;
|
|
29
|
+
suitesPassed: number;
|
|
30
|
+
suitesFailed: number;
|
|
31
|
+
suitesTotal: number;
|
|
32
|
+
/** Capped by the runner; `omittedFailures` says how many did not fit. */
|
|
33
|
+
failures: StructuredTestFailure[];
|
|
34
|
+
omittedFailures: number;
|
|
35
|
+
/** Why the run failed when no individual test can say so. */
|
|
36
|
+
error?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decode a single returned value into results, or undefined if it is not one.
|
|
40
|
+
*
|
|
41
|
+
* Fields are read defensively rather than trusted: the value crossed a
|
|
42
|
+
* transport, and the two transports spell exotic Luau types differently, so a
|
|
43
|
+
* malformed field must not become a verdict.
|
|
44
|
+
*/
|
|
45
|
+
export declare function decodeStructuredTestResults(value: unknown): StructuredTestResults | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Find the results a run returned, if it returned any.
|
|
48
|
+
*
|
|
49
|
+
* `undefined` covers both "the transport delivered no return channel" and "the
|
|
50
|
+
* script returned nothing recognizable" — a caller falls back to the logs
|
|
51
|
+
* either way, which is what a test script written before this convention gets.
|
|
52
|
+
*/
|
|
53
|
+
export declare function findStructuredTestResults(returnValues: unknown[] | undefined): StructuredTestResults | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Describe a verdict the run's own counts do not support, for a warning.
|
|
56
|
+
*
|
|
57
|
+
* A run reporting failure while nothing in it failed is self-contradicting, and
|
|
58
|
+
* it is precisely what a runner reading the wrong field produces: the counts
|
|
59
|
+
* stay plausible, so nothing looks wrong except that every package fails at
|
|
60
|
+
* once. That shipped once — a runner consulted jest-lua's inverted
|
|
61
|
+
* `AggregatedResult.success` and failed every passing suite.
|
|
62
|
+
*
|
|
63
|
+
* Reported, never corrected. A runner that says it failed may know something its
|
|
64
|
+
* counts cannot express (an interrupted run, a snapshot check, a reporter
|
|
65
|
+
* error), so the verdict stands and the contradiction is made loud instead.
|
|
66
|
+
*/
|
|
67
|
+
export declare function describeUnexplainedVerdict(results: StructuredTestResults): string | undefined;
|
|
68
|
+
/** Counts in the shape the reporters already render. */
|
|
69
|
+
export declare function toParsedTestCounts(results: StructuredTestResults): ParsedTestCounts;
|
|
70
|
+
/**
|
|
71
|
+
* Why the runner says the run failed. Empty when it says it passed.
|
|
72
|
+
*
|
|
73
|
+
* Phrased to match the log parser's wording so that merging the two sources
|
|
74
|
+
* collapses the overlap instead of reporting every failure twice.
|
|
75
|
+
*/
|
|
76
|
+
export declare function structuredFailureReasons(results: StructuredTestResults): string[];
|
|
77
|
+
//# sourceMappingURL=structured-test-results.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-test-results.d.ts","sourceRoot":"","sources":["../../../src/utils/testing/structured-test-results.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,6BAA6B,CAAC;AAE9D,4EAA4E;AAC5E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6BD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,GACb,qBAAqB,GAAG,SAAS,CA0BnC;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,OAAO,EAAE,GAAG,SAAS,GAClC,qBAAqB,GAAG,SAAS,CAYnC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,qBAAqB,GAC7B,MAAM,GAAG,SAAS,CAapB;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,qBAAqB,GAC7B,gBAAgB,CAMlB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,qBAAqB,GAC7B,MAAM,EAAE,CAqBV"}
|