plum-e2e 1.0.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.
Files changed (56) hide show
  1. package/.husky/pre-commit +2 -0
  2. package/.prettierignore +21 -0
  3. package/.prettierrc +15 -0
  4. package/LICENSE +677 -0
  5. package/README.md +5 -0
  6. package/backend/Dockerfile +30 -0
  7. package/backend/README.md +0 -0
  8. package/backend/_scaffold/features/LoginPage.feature +6 -0
  9. package/backend/_scaffold/pages/LoginPage.js +22 -0
  10. package/backend/_scaffold/step_definitions/LoginSteps.js +9 -0
  11. package/backend/_scaffold/utils/constants.js +3 -0
  12. package/backend/_scaffold/utils/hooks.js +65 -0
  13. package/backend/_scaffold/utils/utils.js +10 -0
  14. package/backend/app.js +37 -0
  15. package/backend/config/scripts/create-settings.js +60 -0
  16. package/backend/config/scripts/generate-report.js +135 -0
  17. package/backend/config/scripts/run-tests.js +37 -0
  18. package/backend/cucumber.json +6 -0
  19. package/backend/package-lock.json +3403 -0
  20. package/backend/package.json +29 -0
  21. package/backend/playwright.config.js +97 -0
  22. package/backend/routes/cron.routes.js +127 -0
  23. package/backend/routes/reports.routes.js +42 -0
  24. package/backend/routes/schedules.routes.js +32 -0
  25. package/backend/routes/tests.routes.js +33 -0
  26. package/backend/server.js +39 -0
  27. package/backend/services/cronService.js +127 -0
  28. package/backend/services/envService.js +43 -0
  29. package/backend/services/reportService.js +50 -0
  30. package/backend/services/scheduleService.js +34 -0
  31. package/backend/services/testService.js +70 -0
  32. package/backend/websockets/socketHandler.js +46 -0
  33. package/bin/plum.js +188 -0
  34. package/docker-compose.yml +41 -0
  35. package/frontend/Dockerfile +26 -0
  36. package/frontend/README.md +0 -0
  37. package/frontend/jsconfig.json +13 -0
  38. package/frontend/package-lock.json +2894 -0
  39. package/frontend/package.json +26 -0
  40. package/frontend/postcss.config.js +23 -0
  41. package/frontend/src/app.css +35 -0
  42. package/frontend/src/app.html +28 -0
  43. package/frontend/src/lib/index.js +18 -0
  44. package/frontend/src/routes/+layout.svelte +34 -0
  45. package/frontend/src/routes/+page.svelte +188 -0
  46. package/frontend/src/routes/components/Navigation.svelte +53 -0
  47. package/frontend/src/routes/reports/+page.svelte +160 -0
  48. package/frontend/src/routes/scheduled-tests/+page.svelte +363 -0
  49. package/frontend/static/favicon.png +0 -0
  50. package/frontend/svelte.config.js +30 -0
  51. package/frontend/tailwind.config.js +44 -0
  52. package/frontend/vite.config.js +23 -0
  53. package/license-config.json +37 -0
  54. package/package.json +28 -0
  55. package/resources/comments-format.text +23 -0
  56. package/resources/gpl-3.0-license.txt +14 -0
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "plum-backend",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "create-env": "node services/envService.js",
7
+ "test": "node config/scripts/run-tests.js"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "devDependencies": {
13
+ "@playwright/test": "^1.50.1",
14
+ "@types/node": "^22.13.1",
15
+ "cross-env": "^7.0.3",
16
+ "cucumber-html-reporter": "^7.2.0"
17
+ },
18
+ "dependencies": {
19
+ "@cucumber/cucumber": "^11.2.0",
20
+ "chai": "^4.3.6",
21
+ "chai-soft-assert": "^0.0.5",
22
+ "cors": "^2.8.5",
23
+ "dotenv": "^16.4.7",
24
+ "express": "^4.21.2",
25
+ "node-cron": "^3.0.3",
26
+ "playwright": "^1.50.1",
27
+ "socket.io": "^4.8.1"
28
+ }
29
+ }
@@ -0,0 +1,97 @@
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
+ // @ts-check
19
+ import { defineConfig, devices } from '@playwright/test';
20
+
21
+ /**
22
+ * Read environment variables from file.
23
+ * https://github.com/motdotla/dotenv
24
+ */
25
+ // import dotenv from 'dotenv';
26
+ // import path from 'path';
27
+ // dotenv.config({ path: path.resolve(__dirname, '.env') });
28
+
29
+ /**
30
+ * @see https://playwright.dev/docs/test-configuration
31
+ */
32
+ export default defineConfig({
33
+ testDir: './tests',
34
+ /* Run tests in files in parallel */
35
+ fullyParallel: true,
36
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
37
+ forbidOnly: !!process.env.CI,
38
+ /* Retry on CI only */
39
+ retries: process.env.CI ? 2 : 0,
40
+ /* Opt out of parallel tests on CI. */
41
+ workers: process.env.CI ? 1 : undefined,
42
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
43
+ reporter: 'html',
44
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
45
+ use: {
46
+ /* Base URL to use in actions like `await page.goto('/')`. */
47
+ // baseURL: 'http://127.0.0.1:3000',
48
+
49
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
50
+ trace: 'on-first-retry'
51
+ },
52
+
53
+ /* Configure projects for major browsers */
54
+ projects: [
55
+ {
56
+ name: 'chromium',
57
+ use: { ...devices['Desktop Chrome'] }
58
+ },
59
+
60
+ {
61
+ name: 'firefox',
62
+ use: { ...devices['Desktop Firefox'] }
63
+ },
64
+
65
+ {
66
+ name: 'webkit',
67
+ use: { ...devices['Desktop Safari'] }
68
+ }
69
+
70
+ /* Test against mobile viewports. */
71
+ // {
72
+ // name: 'Mobile Chrome',
73
+ // use: { ...devices['Pixel 5'] },
74
+ // },
75
+ // {
76
+ // name: 'Mobile Safari',
77
+ // use: { ...devices['iPhone 12'] },
78
+ // },
79
+
80
+ /* Test against branded browsers. */
81
+ // {
82
+ // name: 'Microsoft Edge',
83
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
84
+ // },
85
+ // {
86
+ // name: 'Google Chrome',
87
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
88
+ // },
89
+ ]
90
+
91
+ /* Run your local dev server before starting the tests */
92
+ // webServer: {
93
+ // command: 'npm run start',
94
+ // url: 'http://127.0.0.1:3000',
95
+ // reuseExistingServer: !process.env.CI,
96
+ // },
97
+ });
@@ -0,0 +1,127 @@
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
+ const express = require('express');
19
+ const router = express.Router();
20
+ const cronService = require('../services/cronService');
21
+
22
+ /* -----------------------------------------------------
23
+ * Get Cron Jobs
24
+ * Description:
25
+ * - Get all cron jobs from config/cron-jobs.json
26
+ * ------------------------------------------------------ */
27
+ router.get('/', (req, res) => {
28
+ try {
29
+ const cronJobs = cronService.getAllCronJobs();
30
+ res.json({ cronJobs });
31
+ } catch (error) {
32
+ console.error('Error fetching cron jobs:', error);
33
+ res.status(500).json({ error: 'Failed to fetch cron jobs' });
34
+ }
35
+ });
36
+
37
+ /* -----------------------------------------------------
38
+ * Create Cron Job
39
+ * Description:
40
+ * Add a new cron job to config/cron-jobs.json
41
+ * Params:
42
+ * - cronExpression:
43
+ * e.g. "* * * * *"
44
+ * https://www.baeldung.com/cron-expressions
45
+ * - taskName:
46
+ * the unique identifier
47
+ * - tags:
48
+ * cucumber tag you want to run when cron job
49
+ * is triggered.
50
+ * ------------------------------------------------------ */
51
+ router.post('/', (req, res) => {
52
+ try {
53
+ const { cronExpression, taskName, tags } = req.body;
54
+ if (!cronExpression || !taskName || !tags) {
55
+ return res.status(400).json({ error: 'Missing required fields' });
56
+ }
57
+
58
+ cronService.addCronJob(req.body);
59
+ res.json({
60
+ message: `Cron job ${taskName} added with tags: ${tags}`,
61
+ taskName,
62
+ cronExpression
63
+ });
64
+ } catch (error) {
65
+ console.error('Error adding cron job:', error);
66
+ res.status(500).json({ error: 'Failed to add cron job' });
67
+ }
68
+ });
69
+
70
+ /* -----------------------------------------------------
71
+ * Edit Cron Job
72
+ * Description:
73
+ * Edit an existing cron job from
74
+ * config/cron-jobs.json
75
+ * Params:
76
+ * - taskName:
77
+ * the unique identifier
78
+ * - cronExpression:
79
+ * e.g. "* * * * *"
80
+ * https://www.baeldung.com/cron-expressions
81
+ * - tags:
82
+ * cucumber tag you want to run when cron job
83
+ * is triggered.
84
+ * ------------------------------------------------------ */
85
+ router.put('/:taskName', (req, res) => {
86
+ try {
87
+ const { taskName } = req.params;
88
+ const { cronExpression, tags } = req.body;
89
+
90
+ if (!cronExpression || !tags) {
91
+ return res.status(400).json({ error: 'Missing required fields' });
92
+ }
93
+
94
+ const updatedCronJob = cronService.updateCronJob(taskName, req.body); // Assuming this is a function to update the cron job
95
+ res.json({
96
+ message: `Cron job ${taskName} updated`,
97
+ taskName,
98
+ cronExpression,
99
+ tags: updatedCronJob.tags
100
+ });
101
+ } catch (error) {
102
+ console.error('Error updating cron job:', error);
103
+ res.status(500).json({ error: 'Failed to update cron job' });
104
+ }
105
+ });
106
+
107
+ /* -----------------------------------------------------
108
+ * Delete Cron Job
109
+ * Description:
110
+ * Delete cron job from config/cron-jobs.json
111
+ * by taskName
112
+ * Params:
113
+ * - taskName:
114
+ * the unique identifier
115
+ * ------------------------------------------------------ */
116
+ router.delete('/:taskName', (req, res) => {
117
+ try {
118
+ const { taskName } = req.params;
119
+ cronService.removeCronJob(taskName);
120
+ res.json({ message: `Cron job ${taskName} deleted` });
121
+ } catch (error) {
122
+ console.error('Error deleting cron job:', error);
123
+ res.status(500).json({ error: 'Failed to delete cron job' });
124
+ }
125
+ });
126
+
127
+ module.exports = router;
@@ -0,0 +1,42 @@
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
+ const express = require('express');
19
+ const router = express.Router();
20
+ const reportService = require('../services/reportService');
21
+
22
+ /* -----------------------------------------------------
23
+ * Get Reports
24
+ * Description:
25
+ * Get all reports from reports/
26
+ * ------------------------------------------------------ */
27
+ router.get('/', (req, res) => {
28
+ const reports = reportService.getAllReports();
29
+ res.json({ reports });
30
+ });
31
+
32
+ /* -----------------------------------------------------
33
+ * Get Latest Report
34
+ * Description:
35
+ * Get latest report
36
+ * ------------------------------------------------------ */
37
+ router.get('/latest', (req, res) => {
38
+ const latestReport = reportService.getLatestReport();
39
+ res.json({ latestReport });
40
+ });
41
+
42
+ module.exports = router;
@@ -0,0 +1,32 @@
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
+ const express = require('express');
19
+ const router = express.Router();
20
+ const scheduleService = require('../services/scheduleService');
21
+
22
+ /* -----------------------------------------------------
23
+ * Get Schedules
24
+ * Description:
25
+ * Get all schedules from schedules/
26
+ * ------------------------------------------------------ */
27
+ router.get('/', (req, res) => {
28
+ const schedules = scheduleService.getAllSchedules();
29
+ res.json({ schedules });
30
+ });
31
+
32
+ module.exports = router;
@@ -0,0 +1,33 @@
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
+ const express = require('express');
19
+ const router = express.Router();
20
+ const testService = require('../services/testService');
21
+
22
+ /* -----------------------------------------------------
23
+ * Get all tests
24
+ * Description:
25
+ * Gets all suites and its own test cases in
26
+ * features/
27
+ * ------------------------------------------------------ */
28
+ router.get('/', (req, res) => {
29
+ const suites = testService.getTestSuites();
30
+ res.json({ suites });
31
+ });
32
+
33
+ module.exports = router;
@@ -0,0 +1,39 @@
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
+ const http = require('http');
19
+ const { Server } = require('socket.io');
20
+ const app = require('./app');
21
+ const socketHandler = require('./websockets/socketHandler.js');
22
+ const server = http.createServer(app);
23
+ const io = new Server(server, { cors: { origin: '*' } });
24
+ const path = require('path');
25
+ const fs = require('fs');
26
+
27
+ // Always point to the mounted tests directory
28
+ const testsDir = path.resolve(process.cwd(), 'tests');
29
+
30
+ if (!fs.existsSync(testsDir)) {
31
+ console.error('❌ No tests folder found at /app/tests');
32
+ process.exit(1);
33
+ }
34
+
35
+ console.log('📂 Loading tests from:', testsDir);
36
+
37
+ socketHandler(io);
38
+
39
+ server.listen(3001, () => console.log('Backend running on port 3001'));
@@ -0,0 +1,127 @@
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
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const cron = require('node-cron');
21
+ const { spawn } = require('child_process');
22
+
23
+ const CRON_JOBS_FILE = path.join(__dirname, '../config/cron-jobs.json');
24
+ let cronJobs = {};
25
+
26
+ const loadCronJobs = () => {
27
+ if (fs.existsSync(CRON_JOBS_FILE)) {
28
+ cronJobs = JSON.parse(fs.readFileSync(CRON_JOBS_FILE, 'utf8'));
29
+
30
+ // Schedule all loaded cron jobs and store only necessary data in memory
31
+ Object.keys(cronJobs).forEach((taskName) => {
32
+ const { cronExpression, tags } = cronJobs[taskName];
33
+ const scheduledCronJob = cron.schedule(cronExpression, () => {
34
+ console.log(`Running new task: ${taskName}`);
35
+
36
+ const task = spawn('npm', ['run', 'test'], {
37
+ env: { ...process.env, TAG: tags, TRIGGER: taskName }
38
+ });
39
+
40
+ task.stdout.on('data', (data) => console.log(data.toString()));
41
+ task.stderr.on('data', (data) => console.error(data.toString()));
42
+ task.on('close', (code) => console.log(`Task ${taskName} finished with code ${code}`));
43
+ });
44
+
45
+ // Store the reference to the cron job only in memory
46
+ cronJobs[taskName].cronJob = scheduledCronJob;
47
+ });
48
+ }
49
+ };
50
+
51
+ const saveCronJobs = () => {
52
+ // Save only cron job data (not the reference to the cron job object) to the file
53
+ const cronJobsData = Object.keys(cronJobs).reduce((acc, taskName) => {
54
+ const { cronExpression, tags } = cronJobs[taskName];
55
+ acc[taskName] = { cronExpression, tags }; // Exclude the cronJob reference
56
+ return acc;
57
+ }, {});
58
+
59
+ fs.writeFileSync(CRON_JOBS_FILE, JSON.stringify(cronJobsData, null, 2), 'utf8');
60
+ };
61
+
62
+ const getAllCronJobs = () =>
63
+ Object.keys(cronJobs).map((taskName) => ({
64
+ taskName,
65
+ cronExpression: cronJobs[taskName].cronExpression,
66
+ tags: cronJobs[taskName].tags
67
+ }));
68
+
69
+ const addCronJob = ({ cronExpression, taskName, tags }) => {
70
+ if (!cronExpression || !taskName || !tags) {
71
+ return { status: 400, message: 'Missing required parameters' };
72
+ }
73
+
74
+ cronJobs[taskName] = { cronExpression, tags };
75
+ saveCronJobs();
76
+ loadCronJobs(); // Re-load and schedule the new cron job
77
+ return { status: 201, message: `Cron job ${taskName} added` };
78
+ };
79
+
80
+ const removeCronJob = (taskName) => {
81
+ if (!cronJobs[taskName]) {
82
+ return { status: 404, message: `Cron job ${taskName} not found` };
83
+ }
84
+
85
+ // Stop the cron job before removing
86
+ cronJobs[taskName].cronJob.stop();
87
+
88
+ delete cronJobs[taskName];
89
+ saveCronJobs();
90
+ loadCronJobs(); // Re-load and re-schedule cron jobs without the removed one
91
+ return { status: 200, message: `Cron job ${taskName} deleted` };
92
+ };
93
+
94
+ const updateCronJob = (taskName, { cronExpression, tags }) => {
95
+ if (!cronJobs[taskName]) {
96
+ return { status: 404, message: `Cron job ${taskName} not found` };
97
+ }
98
+
99
+ // Stop the old cron job
100
+ cronJobs[taskName].cronJob.stop();
101
+
102
+ // Update the cron job with new values
103
+ cronJobs[taskName] = { cronExpression, tags };
104
+
105
+ // Reschedule the updated cron job and store the reference
106
+ const scheduledCronJob = cron.schedule(cronExpression, () => {
107
+ console.log(`Running updated task: ${taskName}`);
108
+
109
+ const task = spawn('npm', ['run', 'test'], {
110
+ env: { ...process.env, TAG: tags, TRIGGER: taskName }
111
+ });
112
+
113
+ task.stdout.on('data', (data) => console.log(data.toString()));
114
+ task.stderr.on('data', (data) => console.error(data.toString()));
115
+ task.on('close', (code) => console.log(`Task ${taskName} finished with code ${code}`));
116
+ });
117
+
118
+ // Store the new cron job reference in memory
119
+ cronJobs[taskName].cronJob = scheduledCronJob;
120
+
121
+ saveCronJobs(); // Save the updated cron jobs to file (excluding cron job references)
122
+ return { status: 200, message: `Cron job ${taskName} updated` };
123
+ };
124
+
125
+ loadCronJobs(); // Initial load and scheduling of cron jobs
126
+
127
+ module.exports = { getAllCronJobs, addCronJob, removeCronJob, updateCronJob };
@@ -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
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ /* -----------------------------------------------------
22
+ * .env Generator
23
+ * Description:
24
+ * If .env file doesn't exist, this will create
25
+ * a .env file in root with sauce demo's base URL
26
+ * ------------------------------------------------------ */
27
+ const envPath = path.join(__dirname, '../.env');
28
+
29
+ if (!fs.existsSync(envPath)) {
30
+ const envContent = 'BASE_URL=https://www.saucedemo.com/v1/\nIS_HEADLESS=false';
31
+ fs.writeFileSync(envPath, envContent);
32
+ console.log('.env file created in the root directory');
33
+ } else {
34
+ let envContent = fs.readFileSync(envPath, 'utf8');
35
+
36
+ if (!envContent.includes('IS_HEADLESS=')) {
37
+ envContent += '\nIS_HEADLESS=false';
38
+ fs.writeFileSync(envPath, envContent);
39
+ console.log('IS_HEADLESS=false added to .env');
40
+ } else {
41
+ console.log('.env file already contains IS_HEADLESS setting');
42
+ }
43
+ }
@@ -0,0 +1,50 @@
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
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ const REPORTS_DIR = path.join(__dirname, '../reports');
22
+
23
+ const getAllReports = () => {
24
+ const files = fs.readdirSync(REPORTS_DIR);
25
+
26
+ // Get all files ending with '.html'
27
+ const htmlFiles = files.filter((file) => file.endsWith('.html'));
28
+
29
+ // Sort files by modification time (latest first)
30
+ const sortedFiles = htmlFiles.sort((a, b) => {
31
+ const aStats = fs.statSync(path.join(REPORTS_DIR, a));
32
+ const bStats = fs.statSync(path.join(REPORTS_DIR, b));
33
+ return bStats.mtime - aStats.mtime; // Sort in descending order of modification time
34
+ });
35
+
36
+ return sortedFiles;
37
+ };
38
+
39
+ const getLatestReport = () => {
40
+ const reportFiles = getAllReports()
41
+ .map((file) => ({
42
+ file,
43
+ time: fs.statSync(path.join(REPORTS_DIR, file)).mtime.getTime()
44
+ }))
45
+ .sort((a, b) => b.time - a.time);
46
+
47
+ return reportFiles.length ? reportFiles[0].file : null;
48
+ };
49
+
50
+ module.exports = { getAllReports, getLatestReport };
@@ -0,0 +1,34 @@
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
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ const SETTINGS_PATH = path.join(__dirname, '../config/settings.json');
22
+
23
+ const getAllSchedules = () => {
24
+ try {
25
+ const fileContent = fs.readFileSync(SETTINGS_PATH, 'utf8');
26
+ const settings = JSON.parse(fileContent);
27
+ return settings.cronJobSchedules || [];
28
+ } catch (error) {
29
+ console.error('Error reading or parsing the settings file:', error);
30
+ return [];
31
+ }
32
+ };
33
+
34
+ module.exports = { getAllSchedules };