plum-e2e 2.4.13 → 2.5.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/CLAUDE.md +1 -1
- package/backend/_scaffold/utils/browser.ts +47 -2
- package/backend/_scaffold/utils/hooks.ts +25 -2
- package/backend/config/scripts/run-tests.js +35 -13
- package/backend/logs/runner-cmr8o2x3n0000mg01410tpuck.log +20 -0
- package/backend/logs/runner-cmr90hvcx0000n2016edtmrtv.log +43 -0
- package/backend/logs/runner-cmr90i7h20001n201g2wg6v3n.log +43 -0
- package/backend/logs/runner-cmr90iilm0002n201mmisva95.log +43 -0
- package/backend/logs/runner-cmr90j70r0003n201xz8525dz.log +20 -0
- package/backend/logs/runner-cmr90yup70000qp017ianc2gp.log +43 -0
- package/backend/logs/runner-cmr90zbtm0001qp01u9tfdkh1.log +20 -0
- package/backend/logs/runner-cmr91a3mw0000tb01414rd1df.log +20 -0
- package/backend/logs/runner-cmr91dhla0001tb01jp7thjnl.log +20 -0
- package/backend/prisma/migrations/20260706000000_add_report_logs/migration.sql +2 -0
- package/backend/prisma/migrations/20260707032554_add_perf_indexes/migration.sql +44 -0
- package/backend/prisma/schema.prisma +20 -0
- package/backend/routes/node.routes.js +42 -4
- package/backend/routes/reports.routes.js +4 -2
- package/backend/services/reportService.js +58 -20
- package/backend/services/runnerService.js +11 -1
- package/backend/websockets/socketHandler.js +162 -16
- package/bin/plum.js +96 -68
- package/frontend/package.json +1 -1
- package/frontend/src/lib/api/reports.js +16 -5
- package/frontend/src/lib/components/layout/RunnerPanel.svelte +53 -55
- package/frontend/src/lib/components/ui/AutomatedBadge.svelte +56 -0
- package/frontend/src/lib/components/ui/BackLink.svelte +77 -0
- package/frontend/src/lib/components/ui/Badge.svelte +1 -1
- package/frontend/src/lib/components/ui/Button.svelte +1 -1
- package/frontend/src/lib/components/ui/CaseIdChip.svelte +59 -0
- package/frontend/src/lib/components/ui/ConfirmModal.svelte +1 -1
- package/frontend/src/lib/components/ui/Pagination.svelte +1 -1
- package/frontend/src/lib/components/ui/PriorityBadge.svelte +83 -0
- package/frontend/src/lib/components/ui/ResultChip.svelte +92 -0
- package/frontend/src/lib/components/ui/StatusDot.svelte +64 -0
- package/frontend/src/lib/components/ui/StepKeyword.svelte +79 -0
- package/frontend/src/lib/components/ui/StepStatusIcon.svelte +66 -0
- package/frontend/src/lib/components/ui/TagChip.svelte +51 -0
- package/frontend/src/lib/constants.js +14 -0
- package/frontend/src/lib/stores/runner.js +5 -3
- package/frontend/src/lib/styles/tokens.css +26 -0
- package/frontend/src/lib/utils/format.js +74 -0
- package/frontend/src/routes/+page.svelte +3 -3
- package/frontend/src/routes/login/+page.svelte +55 -40
- package/frontend/src/routes/reports/+page.svelte +35 -27
- package/frontend/src/routes/reports/[id]/+page.svelte +703 -215
- package/frontend/src/routes/reports/live/+page.svelte +281 -283
- package/frontend/src/routes/scheduled-tests/+page.svelte +3 -3
- package/frontend/src/routes/settings/+page.svelte +6 -6
- package/frontend/src/routes/setup/+page.svelte +2 -1
- package/frontend/src/routes/test-repository/+page.svelte +5 -5
- package/frontend/src/routes/test-repository/runs/[id]/+page.svelte +33 -152
- package/frontend/src/routes/test-repository/suites/[id]/+page.svelte +4 -4
- package/frontend/vite.config.js +7 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -145,7 +145,7 @@ The GPL license header at the top of every file is a legal requirement — do no
|
|
|
145
145
|
- All schema changes require a Prisma migration file in `backend/prisma/migrations/`.
|
|
146
146
|
- Run `npx prisma migrate deploy` (or rebuild Docker) to apply.
|
|
147
147
|
- Report content is stored as JSONB in the `Report.content` column — never reconstruct report metadata from filenames.
|
|
148
|
-
- The `
|
|
148
|
+
- The `getReports()` service function is paginated (`page`/`limit`) and deliberately excludes `content` for list performance — only `getReportDetail(id)` fetches it.
|
|
149
149
|
|
|
150
150
|
---
|
|
151
151
|
|
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of Plum.
|
|
3
|
+
*
|
|
4
|
+
* Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
* it under the terms of the GNU General Public License as published by
|
|
6
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
* (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* Plum is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License
|
|
15
|
+
* along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
|
|
1
18
|
import { chromium, firefox, webkit, Browser, BrowserContext, Page } from 'playwright';
|
|
19
|
+
import * as fs from 'fs';
|
|
20
|
+
import * as path from 'path';
|
|
2
21
|
|
|
3
22
|
let _browser: Browser;
|
|
4
23
|
let _context: BrowserContext;
|
|
5
24
|
let _page: Page;
|
|
25
|
+
let _ssCounter = 0;
|
|
6
26
|
|
|
7
27
|
export const page = (): Page => _page;
|
|
8
28
|
|
|
@@ -16,14 +36,39 @@ export async function setup(): Promise<void> {
|
|
|
16
36
|
_page = await _context.newPage();
|
|
17
37
|
}
|
|
18
38
|
|
|
39
|
+
export async function screenshotStep(
|
|
40
|
+
attach: (data: Buffer, mime: string) => Promise<void>
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
if (!_page) return;
|
|
43
|
+
try {
|
|
44
|
+
const screenshot = await _page.screenshot({ type: 'png' });
|
|
45
|
+
await attach(screenshot, 'image/png');
|
|
46
|
+
} catch {
|
|
47
|
+
// page may be navigating or already closed
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function streamLiveScreenshot(stepName: string): Promise<void> {
|
|
52
|
+
const ssDir = process.env.PLUM_SS_DIR;
|
|
53
|
+
if (!ssDir || !_page) return;
|
|
54
|
+
try {
|
|
55
|
+
const seq = `${String(Date.now()).padStart(16, '0')}-${String(++_ssCounter).padStart(4, '0')}`;
|
|
56
|
+
const screenshot = await _page.screenshot({ type: 'jpeg', quality: 70 });
|
|
57
|
+
fs.writeFileSync(
|
|
58
|
+
path.join(ssDir, `${seq}.ss.json`),
|
|
59
|
+
JSON.stringify({ stepName, data: screenshot.toString('base64') })
|
|
60
|
+
);
|
|
61
|
+
} catch {
|
|
62
|
+
// ignore — live streaming is best-effort
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
19
66
|
export async function teardown(
|
|
20
67
|
attach: (data: Buffer, mime: string) => Promise<void>,
|
|
21
68
|
failed: boolean
|
|
22
69
|
): Promise<void> {
|
|
23
70
|
if (failed && _page) {
|
|
24
71
|
const screenshotDir = 'reports/screenshots';
|
|
25
|
-
const fs = await import('fs');
|
|
26
|
-
const path = await import('path');
|
|
27
72
|
if (!fs.existsSync(screenshotDir)) {
|
|
28
73
|
fs.mkdirSync(screenshotDir, { recursive: true });
|
|
29
74
|
}
|
|
@@ -1,5 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of Plum.
|
|
3
|
+
*
|
|
4
|
+
* Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
* it under the terms of the GNU General Public License as published by
|
|
6
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
* (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* Plum is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License
|
|
15
|
+
* along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { Before, After, AfterStep, ITestCaseHookParameter } from '@cucumber/cucumber';
|
|
19
|
+
import { setup, teardown, screenshotStep, streamLiveScreenshot } from './browser';
|
|
3
20
|
import dotenv from 'dotenv';
|
|
4
21
|
|
|
5
22
|
dotenv.config();
|
|
@@ -10,6 +27,12 @@ Before(async ({ pickle }: ITestCaseHookParameter) => {
|
|
|
10
27
|
await setup();
|
|
11
28
|
});
|
|
12
29
|
|
|
30
|
+
AfterStep(async function ({ pickleStep, result }: { pickleStep: any; result: any }) {
|
|
31
|
+
if (result?.status === 'SKIPPED') return;
|
|
32
|
+
await screenshotStep(this.attach.bind(this));
|
|
33
|
+
await streamLiveScreenshot(pickleStep?.text ?? '');
|
|
34
|
+
});
|
|
35
|
+
|
|
13
36
|
After(async function (scenario: ITestCaseHookParameter) {
|
|
14
37
|
await teardown(this.attach.bind(this), scenario.result?.status === 'FAILED');
|
|
15
38
|
});
|
|
@@ -52,21 +52,39 @@ try {
|
|
|
52
52
|
`BROWSER=${browser}`,
|
|
53
53
|
'TS_NODE_TRANSPILE_ONLY=true',
|
|
54
54
|
'cucumber-js',
|
|
55
|
-
|
|
55
|
+
// Pass the directory, not a glob — avoids shell globstar expansion differences
|
|
56
|
+
// across platforms and lets cucumber-js discover .feature files recursively.
|
|
57
|
+
`${testsRoot}/features`
|
|
56
58
|
];
|
|
57
59
|
|
|
58
|
-
// A dispatched run executes test files in a temp dir on a runner node.
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
// skipped entirely (an explicit --config disables auto-discovery of the cwd file).
|
|
60
|
+
// A dispatched run executes test files in a temp dir on a runner node. Running
|
|
61
|
+
// cucumber from that temp dir (cwd = testsRootAbs) makes it auto-discover the
|
|
62
|
+
// cucumber.json written there, so the node's own backend cucumber.json is never
|
|
63
|
+
// loaded — preventing step-definition conflicts without relying on --config path
|
|
64
|
+
// resolution (which is fragile when the temp path is outside the project).
|
|
65
|
+
let execCwd;
|
|
65
66
|
if (process.env.TESTS_ROOT) {
|
|
66
|
-
const testsRootAbs = path.resolve(testsRoot);
|
|
67
|
-
|
|
67
|
+
const testsRootAbs = path.isAbsolute(testsRoot) ? testsRoot : path.resolve(testsRoot);
|
|
68
|
+
execCwd = testsRootAbs;
|
|
69
|
+
|
|
70
|
+
// hooks.ts calls dotenv.config() with no path, which defaults to process.cwd().
|
|
71
|
+
// When running from a temp dir there is no .env there, so vars like BASE_URL
|
|
72
|
+
// would be undefined. Pre-load BACKEND_DIR's .env so they are already in
|
|
73
|
+
// process.env before dotenv.config() runs (dotenv never overwrites existing vars).
|
|
74
|
+
const backendEnvPath = path.resolve(__dirname, '..', '..', '.env');
|
|
75
|
+
if (fs.existsSync(backendEnvPath)) {
|
|
76
|
+
for (const line of fs.readFileSync(backendEnvPath, 'utf8').split(/\r?\n/)) {
|
|
77
|
+
const m = line.match(/^([A-Za-z_]\w*)\s*=\s*(.*?)(\s*#.*)?$/);
|
|
78
|
+
if (m) {
|
|
79
|
+
const key = m[1];
|
|
80
|
+
const val = m[2].trim().replace(/^(['"])(.*)\1$/, '$2');
|
|
81
|
+
if (!(key in process.env)) process.env[key] = val;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
68
86
|
fs.writeFileSync(
|
|
69
|
-
|
|
87
|
+
path.join(testsRootAbs, 'cucumber.json'),
|
|
70
88
|
JSON.stringify({
|
|
71
89
|
default: {
|
|
72
90
|
requireModule: ['ts-node/register'],
|
|
@@ -77,7 +95,6 @@ try {
|
|
|
77
95
|
}
|
|
78
96
|
})
|
|
79
97
|
);
|
|
80
|
-
baseCommand.push('--config', path.relative(process.cwd(), configPath).replace(/\\/g, '/'));
|
|
81
98
|
} else {
|
|
82
99
|
baseCommand.push(
|
|
83
100
|
'--require-module',
|
|
@@ -102,11 +119,16 @@ try {
|
|
|
102
119
|
const cucumberCommand = baseCommand.join(' ');
|
|
103
120
|
execSync(cucumberCommand, {
|
|
104
121
|
stdio: 'inherit',
|
|
122
|
+
...(execCwd && { cwd: execCwd }),
|
|
105
123
|
env: {
|
|
106
124
|
...process.env,
|
|
107
125
|
NODE_PATH: process.env.NODE_PATH
|
|
108
126
|
? `${nodeModulesPath}${path.delimiter}${process.env.NODE_PATH}`
|
|
109
|
-
: nodeModulesPath
|
|
127
|
+
: nodeModulesPath,
|
|
128
|
+
// When running from a temp dir there is no tsconfig.json above it, so
|
|
129
|
+
// ts-node falls back to defaults that may conflict with the Node version.
|
|
130
|
+
// Point it at the backend tsconfig explicitly.
|
|
131
|
+
...(execCwd && { TS_NODE_PROJECT: path.resolve(__dirname, '..', '..', 'tsconfig.json') })
|
|
110
132
|
}
|
|
111
133
|
});
|
|
112
134
|
} catch (error) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
Backend running on port 3002 (node/runner mode)
|
|
19
|
+
(node:89713) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated.
|
|
20
|
+
(Use `node --trace-deprecation ...` to show where the warning was created)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
node:events:487
|
|
19
|
+
throw er; // Unhandled 'error' event
|
|
20
|
+
^
|
|
21
|
+
|
|
22
|
+
Error: listen EADDRINUSE: address already in use :::3002
|
|
23
|
+
at Server.setupListenHandle [as _listen2] (node:net:2008:16)
|
|
24
|
+
at listenInCluster (node:net:2065:12)
|
|
25
|
+
at Server.listen (node:net:2170:7)
|
|
26
|
+
at start (/Users/silverlunah/Projects/plum/backend/server.js:65:9)
|
|
27
|
+
at Object.<anonymous> (/Users/silverlunah/Projects/plum/backend/server.js:139:1)
|
|
28
|
+
at Module._compile (node:internal/modules/cjs/loader:1829:14)
|
|
29
|
+
at Module._extensions..js (node:internal/modules/cjs/loader:1969:10)
|
|
30
|
+
at Module.load (node:internal/modules/cjs/loader:1552:32)
|
|
31
|
+
at Module._load (node:internal/modules/cjs/loader:1354:12)
|
|
32
|
+
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
|
|
33
|
+
Emitted 'error' event on Server instance at:
|
|
34
|
+
at emitErrorNT (node:net:2044:8)
|
|
35
|
+
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
|
|
36
|
+
code: 'EADDRINUSE',
|
|
37
|
+
errno: -48,
|
|
38
|
+
syscall: 'listen',
|
|
39
|
+
address: '::',
|
|
40
|
+
port: 3002
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Node.js v25.9.0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
node:events:487
|
|
19
|
+
throw er; // Unhandled 'error' event
|
|
20
|
+
^
|
|
21
|
+
|
|
22
|
+
Error: listen EADDRINUSE: address already in use :::3003
|
|
23
|
+
at Server.setupListenHandle [as _listen2] (node:net:2008:16)
|
|
24
|
+
at listenInCluster (node:net:2065:12)
|
|
25
|
+
at Server.listen (node:net:2170:7)
|
|
26
|
+
at start (/Users/silverlunah/Projects/plum/backend/server.js:65:9)
|
|
27
|
+
at Object.<anonymous> (/Users/silverlunah/Projects/plum/backend/server.js:139:1)
|
|
28
|
+
at Module._compile (node:internal/modules/cjs/loader:1829:14)
|
|
29
|
+
at Module._extensions..js (node:internal/modules/cjs/loader:1969:10)
|
|
30
|
+
at Module.load (node:internal/modules/cjs/loader:1552:32)
|
|
31
|
+
at Module._load (node:internal/modules/cjs/loader:1354:12)
|
|
32
|
+
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
|
|
33
|
+
Emitted 'error' event on Server instance at:
|
|
34
|
+
at emitErrorNT (node:net:2044:8)
|
|
35
|
+
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
|
|
36
|
+
code: 'EADDRINUSE',
|
|
37
|
+
errno: -48,
|
|
38
|
+
syscall: 'listen',
|
|
39
|
+
address: '::',
|
|
40
|
+
port: 3003
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Node.js v25.9.0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
node:events:487
|
|
19
|
+
throw er; // Unhandled 'error' event
|
|
20
|
+
^
|
|
21
|
+
|
|
22
|
+
Error: listen EADDRINUSE: address already in use :::3009
|
|
23
|
+
at Server.setupListenHandle [as _listen2] (node:net:2008:16)
|
|
24
|
+
at listenInCluster (node:net:2065:12)
|
|
25
|
+
at Server.listen (node:net:2170:7)
|
|
26
|
+
at start (/Users/silverlunah/Projects/plum/backend/server.js:65:9)
|
|
27
|
+
at Object.<anonymous> (/Users/silverlunah/Projects/plum/backend/server.js:139:1)
|
|
28
|
+
at Module._compile (node:internal/modules/cjs/loader:1829:14)
|
|
29
|
+
at Module._extensions..js (node:internal/modules/cjs/loader:1969:10)
|
|
30
|
+
at Module.load (node:internal/modules/cjs/loader:1552:32)
|
|
31
|
+
at Module._load (node:internal/modules/cjs/loader:1354:12)
|
|
32
|
+
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
|
|
33
|
+
Emitted 'error' event on Server instance at:
|
|
34
|
+
at emitErrorNT (node:net:2044:8)
|
|
35
|
+
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
|
|
36
|
+
code: 'EADDRINUSE',
|
|
37
|
+
errno: -48,
|
|
38
|
+
syscall: 'listen',
|
|
39
|
+
address: '::',
|
|
40
|
+
port: 3009
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Node.js v25.9.0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
Backend running on port 5177 (node/runner mode)
|
|
19
|
+
(node:98310) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated.
|
|
20
|
+
(Use `node --trace-deprecation ...` to show where the warning was created)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
node:events:487
|
|
19
|
+
throw er; // Unhandled 'error' event
|
|
20
|
+
^
|
|
21
|
+
|
|
22
|
+
Error: listen EADDRINUSE: address already in use :::3002
|
|
23
|
+
at Server.setupListenHandle [as _listen2] (node:net:2008:16)
|
|
24
|
+
at listenInCluster (node:net:2065:12)
|
|
25
|
+
at Server.listen (node:net:2170:7)
|
|
26
|
+
at start (/Users/silverlunah/Projects/plum/backend/server.js:65:9)
|
|
27
|
+
at Object.<anonymous> (/Users/silverlunah/Projects/plum/backend/server.js:139:1)
|
|
28
|
+
at Module._compile (node:internal/modules/cjs/loader:1829:14)
|
|
29
|
+
at Module._extensions..js (node:internal/modules/cjs/loader:1969:10)
|
|
30
|
+
at Module.load (node:internal/modules/cjs/loader:1552:32)
|
|
31
|
+
at Module._load (node:internal/modules/cjs/loader:1354:12)
|
|
32
|
+
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
|
|
33
|
+
Emitted 'error' event on Server instance at:
|
|
34
|
+
at emitErrorNT (node:net:2044:8)
|
|
35
|
+
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
|
|
36
|
+
code: 'EADDRINUSE',
|
|
37
|
+
errno: -48,
|
|
38
|
+
syscall: 'listen',
|
|
39
|
+
address: '::',
|
|
40
|
+
port: 3002
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Node.js v25.9.0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
Backend running on port 5178 (node/runner mode)
|
|
19
|
+
(node:825) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated.
|
|
20
|
+
(Use `node --trace-deprecation ...` to show where the warning was created)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
Backend running on port 5178 (node/runner mode)
|
|
19
|
+
(node:2599) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated.
|
|
20
|
+
(Use `node --trace-deprecation ...` to show where the warning was created)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of Plum.
|
|
3
|
+
|
|
4
|
+
Plum is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Plum is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with Plum. If not, see https://www.gnu.org/licenses/.
|
|
16
|
+
*/
|
|
17
|
+
📂 Loading tests from: /Users/silverlunah/Projects/plum/backend/tests
|
|
18
|
+
Backend running on port 5180 (node/runner mode)
|
|
19
|
+
(node:3077) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated.
|
|
20
|
+
(Use `node --trace-deprecation ...` to show where the warning was created)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
-- AlterTable
|
|
2
|
+
ALTER TABLE "Report" ALTER COLUMN "content" DROP DEFAULT;
|
|
3
|
+
|
|
4
|
+
-- AlterTable
|
|
5
|
+
ALTER TABLE "TestRun" ALTER COLUMN "status" SET DEFAULT 'backlog';
|
|
6
|
+
|
|
7
|
+
-- CreateIndex
|
|
8
|
+
CREATE INDEX "Report_createdAt_idx" ON "Report"("createdAt");
|
|
9
|
+
|
|
10
|
+
-- CreateIndex
|
|
11
|
+
CREATE INDEX "Report_status_idx" ON "Report"("status");
|
|
12
|
+
|
|
13
|
+
-- CreateIndex
|
|
14
|
+
CREATE INDEX "Report_testRunId_idx" ON "Report"("testRunId");
|
|
15
|
+
|
|
16
|
+
-- CreateIndex
|
|
17
|
+
CREATE INDEX "Report_runnerId_idx" ON "Report"("runnerId");
|
|
18
|
+
|
|
19
|
+
-- CreateIndex
|
|
20
|
+
CREATE INDEX "Report_cronJobId_idx" ON "Report"("cronJobId");
|
|
21
|
+
|
|
22
|
+
-- CreateIndex
|
|
23
|
+
CREATE INDEX "TestCase_suiteId_idx" ON "TestCase"("suiteId");
|
|
24
|
+
|
|
25
|
+
-- CreateIndex
|
|
26
|
+
CREATE INDEX "TestCaseHistory_caseId_idx" ON "TestCaseHistory"("caseId");
|
|
27
|
+
|
|
28
|
+
-- CreateIndex
|
|
29
|
+
CREATE INDEX "TestCaseHistory_runId_idx" ON "TestCaseHistory"("runId");
|
|
30
|
+
|
|
31
|
+
-- CreateIndex
|
|
32
|
+
CREATE INDEX "TestCaseHistory_reportId_idx" ON "TestCaseHistory"("reportId");
|
|
33
|
+
|
|
34
|
+
-- CreateIndex
|
|
35
|
+
CREATE INDEX "TestRun_createdAt_idx" ON "TestRun"("createdAt");
|
|
36
|
+
|
|
37
|
+
-- CreateIndex
|
|
38
|
+
CREATE INDEX "TestRunEntry_runId_idx" ON "TestRunEntry"("runId");
|
|
39
|
+
|
|
40
|
+
-- CreateIndex
|
|
41
|
+
CREATE INDEX "TestRunEntry_caseId_idx" ON "TestRunEntry"("caseId");
|
|
42
|
+
|
|
43
|
+
-- CreateIndex
|
|
44
|
+
CREATE INDEX "TestSuite_createdAt_idx" ON "TestSuite"("createdAt");
|
|
@@ -67,8 +67,15 @@ model Report {
|
|
|
67
67
|
testRunId String?
|
|
68
68
|
testRun TestRun? @relation(fields: [testRunId], references: [id], onDelete: SetNull)
|
|
69
69
|
content Json
|
|
70
|
+
logs String?
|
|
70
71
|
createdAt DateTime @default(now())
|
|
71
72
|
testHistory TestCaseHistory[]
|
|
73
|
+
|
|
74
|
+
@@index([createdAt])
|
|
75
|
+
@@index([status])
|
|
76
|
+
@@index([testRunId])
|
|
77
|
+
@@index([runnerId])
|
|
78
|
+
@@index([cronJobId])
|
|
72
79
|
}
|
|
73
80
|
|
|
74
81
|
model Project {
|
|
@@ -123,6 +130,8 @@ model TestSuite {
|
|
|
123
130
|
createdAt DateTime @default(now())
|
|
124
131
|
updatedAt DateTime @updatedAt
|
|
125
132
|
cases TestCase[]
|
|
133
|
+
|
|
134
|
+
@@index([createdAt])
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
model TestCase {
|
|
@@ -141,6 +150,8 @@ model TestCase {
|
|
|
141
150
|
steps TestStep[]
|
|
142
151
|
runEntries TestRunEntry[]
|
|
143
152
|
history TestCaseHistory[]
|
|
153
|
+
|
|
154
|
+
@@index([suiteId])
|
|
144
155
|
}
|
|
145
156
|
|
|
146
157
|
model TestStep {
|
|
@@ -165,6 +176,8 @@ model TestRun {
|
|
|
165
176
|
entries TestRunEntry[]
|
|
166
177
|
history TestCaseHistory[]
|
|
167
178
|
reports Report[]
|
|
179
|
+
|
|
180
|
+
@@index([createdAt])
|
|
168
181
|
}
|
|
169
182
|
|
|
170
183
|
model TestRunEntry {
|
|
@@ -181,6 +194,9 @@ model TestRunEntry {
|
|
|
181
194
|
executedAt DateTime?
|
|
182
195
|
assignedToId String?
|
|
183
196
|
assignedTo User? @relation("entryAssignee", fields: [assignedToId], references: [id])
|
|
197
|
+
|
|
198
|
+
@@index([runId])
|
|
199
|
+
@@index([caseId])
|
|
184
200
|
}
|
|
185
201
|
|
|
186
202
|
model TestCaseHistory {
|
|
@@ -197,4 +213,8 @@ model TestCaseHistory {
|
|
|
197
213
|
executedById String?
|
|
198
214
|
executedBy User? @relation(fields: [executedById], references: [id])
|
|
199
215
|
executedAt DateTime @default(now())
|
|
216
|
+
|
|
217
|
+
@@index([caseId])
|
|
218
|
+
@@index([runId])
|
|
219
|
+
@@index([reportId])
|
|
200
220
|
}
|