plum-e2e 2.4.4 โ 2.4.6
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/backend/server.js +8 -0
- package/backend/services/reportService.js +21 -0
- package/frontend/src/lib/components/layout/RunnerPanel.svelte +10 -3
- package/frontend/src/lib/stores/runner.js +2 -2
- package/frontend/src/routes/reports/+page.svelte +3 -0
- package/frontend/src/routes/test-repository/runs/[id]/+page.svelte +3 -0
- package/package.json +1 -1
package/backend/server.js
CHANGED
|
@@ -87,6 +87,11 @@ async function start() {
|
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
// Sync automated flags from feature files on every startup
|
|
91
|
+
require('./services/reportService')
|
|
92
|
+
.syncAutomatedFromFeatures()
|
|
93
|
+
.catch(() => {});
|
|
94
|
+
|
|
90
95
|
// chokidar v5+ is ESM-only โ use dynamic import to stay compatible with CJS
|
|
91
96
|
let chokidar;
|
|
92
97
|
try {
|
|
@@ -109,6 +114,9 @@ async function start() {
|
|
|
109
114
|
`๐ Tests changed (${event}: ${path.basename(filePath)}) โ notifying clients`
|
|
110
115
|
);
|
|
111
116
|
io.emit('tests-changed');
|
|
117
|
+
require('./services/reportService')
|
|
118
|
+
.syncAutomatedFromFeatures()
|
|
119
|
+
.catch(() => {});
|
|
112
120
|
}, 300);
|
|
113
121
|
});
|
|
114
122
|
console.log('๐ Watching for test file changes...');
|
|
@@ -400,12 +400,33 @@ const deleteReports = async (ids) => {
|
|
|
400
400
|
await prisma.report.deleteMany({ where: { id: { in: ids } } });
|
|
401
401
|
};
|
|
402
402
|
|
|
403
|
+
const FEATURES_DIR = path.join(__dirname, '../tests/features');
|
|
404
|
+
|
|
405
|
+
async function syncAutomatedFromFeatures() {
|
|
406
|
+
try {
|
|
407
|
+
if (!fs.existsSync(FEATURES_DIR)) return;
|
|
408
|
+
const tagSet = new Set();
|
|
409
|
+
for (const file of fs.readdirSync(FEATURES_DIR).filter((f) => f.endsWith('.feature'))) {
|
|
410
|
+
const content = fs.readFileSync(path.join(FEATURES_DIR, file), 'utf8');
|
|
411
|
+
for (const m of content.matchAll(/@(\S+)/g)) tagSet.add(m[1]);
|
|
412
|
+
}
|
|
413
|
+
if (tagSet.size === 0) return;
|
|
414
|
+
await prisma.testCase.updateMany({
|
|
415
|
+
where: { displayId: { in: [...tagSet] }, isAutomated: false },
|
|
416
|
+
data: { isAutomated: true }
|
|
417
|
+
});
|
|
418
|
+
} catch (e) {
|
|
419
|
+
console.error('[sync] syncAutomatedFromFeatures failed:', e.message);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
403
423
|
module.exports = {
|
|
404
424
|
getAllReports,
|
|
405
425
|
getLatestReportId,
|
|
406
426
|
getReportDetail,
|
|
407
427
|
saveReport,
|
|
408
428
|
saveCombinedReport,
|
|
429
|
+
syncAutomatedFromFeatures,
|
|
409
430
|
deleteReport,
|
|
410
431
|
deleteReports
|
|
411
432
|
};
|
|
@@ -198,6 +198,13 @@
|
|
|
198
198
|
|
|
199
199
|
$: state = $runnerState;
|
|
200
200
|
$: cfg = $runnerConfig;
|
|
201
|
+
|
|
202
|
+
$: truncatedRunTag = (() => {
|
|
203
|
+
if (!state.currentRun?.tag) return 'all tests';
|
|
204
|
+
const parts = state.currentRun.tag.split(/ or /i);
|
|
205
|
+
if (parts.length <= 5) return state.currentRun.tag;
|
|
206
|
+
return parts.slice(0, 5).join(' or ') + ` +${parts.length - 5} more`;
|
|
207
|
+
})();
|
|
201
208
|
$: cronJobs = Object.keys($activeCronJobs);
|
|
202
209
|
$: anyCronRunning = cronJobs.length > 0;
|
|
203
210
|
$: anyRunning = state.running || anyCronRunning;
|
|
@@ -263,7 +270,7 @@
|
|
|
263
270
|
if (selectedRun) {
|
|
264
271
|
if (selectedRunLoading || !selectedRun.tags) return;
|
|
265
272
|
if (selectedRun.tags.length === 0) return;
|
|
266
|
-
triggerRun(selectedRun.tags.join(' or '), selectedRun.id, notify);
|
|
273
|
+
triggerRun(selectedRun.tags.join(' or '), selectedRun.id, notify, selectedRun.title);
|
|
267
274
|
} else if ($runnerConfig.testID.trim() === '') {
|
|
268
275
|
runAllModalOpen = true;
|
|
269
276
|
} else {
|
|
@@ -682,10 +689,10 @@
|
|
|
682
689
|
<a href="/reports/live" class="run-card active-run">
|
|
683
690
|
<span class="run-card-dot pulse-accent"></span>
|
|
684
691
|
<div class="run-card-info">
|
|
685
|
-
<span class="run-card-label">Manual run</span>
|
|
692
|
+
<span class="run-card-label">{state.currentRun?.runTitle || 'Manual run'}</span>
|
|
686
693
|
{#if state.currentRun}
|
|
687
694
|
<span class="run-card-meta">
|
|
688
|
-
{
|
|
695
|
+
{truncatedRunTag}
|
|
689
696
|
<span class="meta-dot">ยท</span>
|
|
690
697
|
{state.currentRun.workers}w
|
|
691
698
|
<span class="meta-dot">ยท</span>
|
|
@@ -48,7 +48,7 @@ export const runsVersion = writable(0);
|
|
|
48
48
|
// Map of taskName โ true for every cron job currently executing
|
|
49
49
|
export const activeCronJobs = writable({});
|
|
50
50
|
|
|
51
|
-
export function triggerRun(id, testRunId, notify = {}) {
|
|
51
|
+
export function triggerRun(id, testRunId, notify = {}, runTitle = null) {
|
|
52
52
|
const s = get(socket);
|
|
53
53
|
if (!s) return;
|
|
54
54
|
|
|
@@ -63,7 +63,7 @@ export function triggerRun(id, testRunId, notify = {}) {
|
|
|
63
63
|
status: 'running',
|
|
64
64
|
lastRunId: runId,
|
|
65
65
|
lanes: [],
|
|
66
|
-
currentRun: { tag: runId, workers, browser, runners: selectedRunners }
|
|
66
|
+
currentRun: { tag: runId, workers, browser, runners: selectedRunners, runTitle }
|
|
67
67
|
});
|
|
68
68
|
panelExpanded.set(true);
|
|
69
69
|
|