froth-webdriverio-framework 7.0.119-dev1.0 → 7.0.119-dev1.10

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 (44) hide show
  1. package/README.md +245 -0
  2. package/allure-report-utils/allure-helper.js +226 -0
  3. package/allure-report-utils/froth-report.js +142 -0
  4. package/allure-report-utils/generate-allure-report.js +167 -0
  5. package/allure-report-utils/open-allure-report.js +97 -0
  6. package/allure-screenshots/Recorded_Scripts_Recorded_test_steps_success.png +0 -0
  7. package/allure-screenshots/Recorded_Scripts_Recorded_test_steps_success_2026-06-19T08-07-53-694Z.png +0 -0
  8. package/allure-screenshots/Recorded_Scripts_Recorded_test_steps_success_2026-06-19T08-10-50-605Z.png +0 -0
  9. package/allure-screenshots/action_001_setWindowSize_2026-06-19T08-10-35-850Z.png +0 -0
  10. package/allure-screenshots/action_001_url.png +0 -0
  11. package/allure-screenshots/action_002_click.png +0 -0
  12. package/allure-screenshots/action_002_url_2026-06-19T08-10-37-002Z.png +0 -0
  13. package/allure-screenshots/action_003_clearValue.png +0 -0
  14. package/allure-screenshots/action_003_setValue.png +0 -0
  15. package/allure-screenshots/action_003_waitForExist_2026-06-19T08-10-42-230Z.png +0 -0
  16. package/allure-screenshots/action_004_click.png +0 -0
  17. package/allure-screenshots/action_004_waitForExist_2026-06-19T08-10-42-353Z.png +0 -0
  18. package/allure-screenshots/action_005_clearValue.png +0 -0
  19. package/allure-screenshots/action_005_click_2026-06-19T08-10-43-186Z.png +0 -0
  20. package/allure-screenshots/action_005_setValue.png +0 -0
  21. package/allure-screenshots/action_006_click_2026-06-19T08-10-43-301Z.png +0 -0
  22. package/allure-screenshots/action_007_clearValue_2026-06-19T08-10-43-974Z.png +0 -0
  23. package/allure-screenshots/action_008_clearValue_2026-06-19T08-10-44-058Z.png +0 -0
  24. package/allure-screenshots/action_009_addValue_2026-06-19T08-10-44-559Z.png +0 -0
  25. package/allure-screenshots/action_010_addValue_2026-06-19T08-10-44-656Z.png +0 -0
  26. package/allure-screenshots/action_011_setValue_2026-06-19T08-10-44-779Z.png +0 -0
  27. package/allure-screenshots/action_012_setValue_2026-06-19T08-10-44-905Z.png +0 -0
  28. package/allure-screenshots/action_013_click_2026-06-19T08-10-45-787Z.png +0 -0
  29. package/allure-screenshots/action_014_click_2026-06-19T08-10-45-892Z.png +0 -0
  30. package/allure-screenshots/action_015_clearValue_2026-06-19T08-10-46-549Z.png +0 -0
  31. package/allure-screenshots/action_016_clearValue_2026-06-19T08-10-46-635Z.png +0 -0
  32. package/allure-screenshots/action_017_addValue_2026-06-19T08-10-46-868Z.png +0 -0
  33. package/allure-screenshots/action_018_addValue_2026-06-19T08-10-46-997Z.png +0 -0
  34. package/allure-screenshots/action_019_setValue_2026-06-19T08-10-47-080Z.png +0 -0
  35. package/allure-screenshots/action_020_setValue_2026-06-19T08-10-47-163Z.png +0 -0
  36. package/allure-screenshots/action_021_click_2026-06-19T08-10-47-377Z.png +0 -0
  37. package/allure-screenshots/action_022_click_2026-06-19T08-10-47-472Z.png +0 -0
  38. package/froth_configs/base.config.js +47 -3
  39. package/froth_configs/commonhook.js +53 -0
  40. package/froth_configs/local/mobile.config.js +57 -9
  41. package/froth_configs/local/web.config.js +140 -35
  42. package/froth_configs/screenshot-service.js +157 -0
  43. package/froth_configs/wdio.common.conf.js +112 -1
  44. package/package.json +62 -50
package/README.md ADDED
@@ -0,0 +1,245 @@
1
+ # README.md
2
+
3
+ ## Project Overview
4
+
5
+ **Version:** 9.0.5-ytlc
6
+
7
+ **Repository:** https://github.com/RoboticoDigitalProjects/froth-webdriverio.git
8
+
9
+ This is a WebdriverIO test automation framework (FROTH - "froth-webdriverio-framework") that supports web, Android, and iOS testing on both BrowserStack and local environments. The framework integrates with a Froth TestOps backend API for execution tracking, reporting, and test data management.
10
+
11
+ ## Commands
12
+
13
+ ### Running Tests
14
+
15
+ Tests are run using the WebdriverIO CLI. The framework uses `wdio.common.conf.js` directly without requiring platform-specific config files.
16
+
17
+ ```bash
18
+ # Lint code
19
+ npm run lint
20
+ ```
21
+
22
+ ### Viewing Test Results
23
+
24
+ #### Local Execution Reports (Automatic)
25
+
26
+ When running tests with `PLATFORM=local`, the framework **automatically generates Mochawesome HTML reports** after test execution completes:
27
+
28
+ - Reports are saved in: `./reports/mochawesome/`
29
+ - Each execution gets a **unique report directory** using `BROWSERSTACK_BUILD_NAME` and timestamp
30
+ - Format: `./reports/mochawesome/{BUILD_NAME}-{YYYY-MM-DD}/mochawesome.html`
31
+ - Reports **auto-open in browser** after generation
32
+
33
+ **Example:**
34
+ ```bash
35
+ # Run tests with unique build name
36
+ BROWSERSTACK_BUILD_NAME="Web_Login_Test_20250619" \
37
+ PLATFORM=local \
38
+ YML_NAME="./ymls/browserstack/web/TOASTER_CHECK.yml" \
39
+ SUITE="./web_suites/Login_RD.js" \
40
+ npx wdio ./froth_configs/wdio.common.conf.js
41
+
42
+ # āœ… Report generates automatically after execution completes!
43
+ # šŸ“ Location: ./reports/mochawesome/Web_Login_Test_20250619-2025-06-19/mochawesome.html
44
+ ```
45
+
46
+ **Manual report generation (if needed):**
47
+ ```bash
48
+ # Generate latest report manually
49
+ npm run generate:report
50
+
51
+ # Generate all available reports
52
+ npm run generate:report:all
53
+ ```
54
+
55
+ #### BrowserStack Execution Reports
56
+
57
+ For BrowserStack execution, test results are tracked via the Froth TestOps API. The framework automatically:
58
+ - Updates execution status for each test script
59
+ - Calculates total execution time
60
+ - Posts results back to TestOps via `updateScriptExecutionStatus` and `updateExecuitonDetails`
61
+ - Tracks BrowserStack session information
62
+
63
+ View detailed results and execution logs in your Froth TestOps dashboard using the `EXECUTION_ID`.
64
+
65
+ ### Running Tests
66
+
67
+ Tests are run by specifying environment variables and the config file:
68
+
69
+ **Local execution (using BrowserStack from local machine):**
70
+
71
+ ```bash
72
+ EXECUTION_ID=12995 \
73
+ ORGANISATION_DOMAIN_URL='https://api.frothtestops.com' \
74
+ BROWSERSTACK_BUILD_NAME="Web_Build- api-module-testing_2345_20260619" \
75
+ PLATFORM=local \
76
+ YML_NAME="./ymls/browserstack/web/TOASTER_CHECK.yml" \
77
+ SUITE="./web_suites/Login_RD.js" \
78
+ API_TOKEN="" \
79
+ CICD_RUN_ID=1 \
80
+ npx wdio ./froth_configs/wdio.common.conf.js
81
+ ```
82
+
83
+ **BrowserStack execution:**
84
+
85
+ ```bash
86
+ SUITE=./android_suites/samplesuite_x.js \
87
+ YML_NAME=./ymls/browserstack/android/android_pixel8.yml \
88
+ PLATFORM=browserstack \
89
+ EXECUTION_ID=123 \
90
+ API_TOKEN=your_token \
91
+ ORGANISATION_DOMAIN_URL=https://api.frothtestops.com \
92
+ npx wdio ./froth_configs/wdio.common.conf.js
93
+ ```
94
+
95
+ ## Architecture
96
+
97
+ ### Configuration Hierarchy
98
+
99
+ The framework uses a multi-layered configuration system:
100
+
101
+ 1. __Base Configuration__ (`froth_configs/base.config.js`): Contains framework settings, specs path, timeouts, and Mocha options. Initializes a global `BUFFER` using `node-localstorage` for cross-module state sharing.
102
+ 2. __Common Configuration__ (`froth_configs/wdio.common.conf.js`): Acts as the entry point. It:
103
+
104
+ - Loads capabilities from a YAML file specified by `YML_NAME`
105
+ - Decodes BrowserStack credentials from base64
106
+ - Determines platform (web vs mobile) based on `platformName` in capabilities
107
+ - Merges base config with platform-specific config
108
+
109
+ 3. __Platform-Specific Configs__ (`froth_configs/browserstack/` and `froth_configs/local/`):
110
+
111
+ - `web.config.js`: BrowserStack web testing configuration
112
+ - `mobile.config.js`: BrowserStack mobile (Android/iOS) testing configuration
113
+ - Supports `BS_UPLOAD_MEDIA` for injecting media files into tests
114
+
115
+ ### Test Lifecycle and Hooks
116
+
117
+ All test lifecycle hooks are defined in `froth_configs/commonhook.js`:
118
+
119
+ - **onPrepare**: Initializes environment variables, execution details, suite details, and test data via `setallDatailinBuffer.js`. Registers global error handlers.
120
+ - **beforeSession**: Validates test syntax, configures BrowserStack capabilities, sets app path for mobile testing
121
+ - **beforeSuite**: Fetches BrowserStack session details, updates CICD run ID
122
+ - **beforeTest/afterTest**: Updates individual script execution status via API
123
+ - **afterSession**: Calculates total execution time, updates final execution status
124
+ - **onComplete**: Clears the BUFFER storage
125
+
126
+ ### Directory Structure
127
+
128
+ ```ini
129
+ froth_common_actions/ # Reusable test utilities and actions
130
+ ā”œā”€ā”€ Utils.js # Central export point for all utilities
131
+ ā”œā”€ā”€ scroll.js # Scrolling helpers (scrollToEnd, scrollDownToView, etc.)
132
+ ā”œā”€ā”€ swipe.js # Gesture helpers (swipeUp, swipeDown, swipeWithCoordinates)
133
+ ā”œā”€ā”€ click.js # Click helpers (clickIfVisible, doubleClick)
134
+ ā”œā”€ā”€ assert.js # Assertion helpers (assertText, assertAttributeValue)
135
+ ā”œā”€ā”€ random.js # Random data generators (RANDOMTEXT, RNDNUMBER, etc.)
136
+ ā”œā”€ā”€ storeToBuffer.js # Buffer storage helpers for runtime data
137
+ ā”œā”€ā”€ dbValidator.js # Database field validation
138
+ └── ... # Other common actions
139
+
140
+ froth_api_calls/ # API integration layer
141
+ ā”œā”€ā”€ loginapi.js # Authentication token retrieval
142
+ ā”œā”€ā”€ getexecutionDetails.js # Fetch/update execution details via TestOps API
143
+ ā”œā”€ā”€ getsuiteDetails.js # Fetch test suite and script mappings
144
+ ā”œā”€ā”€ readTestdata.js # Fetch test data by ID
145
+ └── browsersatckSessionInfo.js # BrowserStack session management
146
+
147
+ froth_configs/ # Configuration files
148
+ ā”œā”€ā”€ base.config.js
149
+ ā”œā”€ā”€ wdio.common.conf.js
150
+ ā”œā”€ā”€ commonhook.js
151
+ ā”œā”€ā”€ setallDatailinBuffer.js
152
+ ā”œā”€ā”€ browserstack/ # BrowserStack-specific configs
153
+ └── local/ # Local execution configs
154
+
155
+ android/ # Android test scripts
156
+ android_suites/ # Android suite definitions (array of test files)
157
+ web/ # Web test scripts
158
+ web_suites/ # Web suite definitions
159
+ ymls/browserstack/ # Capability YAML files for different devices/browsers
160
+ ```
161
+
162
+ ### Test Data Flow
163
+
164
+ 1. Environment variables are loaded in `setallDatailinBuffer.js` during `onPrepare`
165
+ 2. Global state is stored in `BUFFER` (node-localstorage at `./buffer_storage`)
166
+ 3. Execution details are fetched from the Froth TestOps API
167
+ 4. Test scripts access data via `BUFFER.getItem()` / `BUFFER.setItem()`
168
+ 5. Results are posted back to the API via `updateScriptExecutionStatus` and `updateExecuitonDetails`
169
+
170
+ ### Test Suite Pattern
171
+
172
+ Suites are defined as simple modules exporting a `tests` array:
173
+
174
+ ```javascript
175
+ // Example: android_suites/samplesuite_x.js
176
+ module.exports = {
177
+ tests: [
178
+ '/absolute/path/to/android/test_script.js'
179
+ ]
180
+ };
181
+ ```
182
+
183
+ ### Common Actions Usage
184
+
185
+ Tests import utilities from the Utils export:
186
+
187
+ ```javascript
188
+ const Util = require('../froth_common_actions/Utils');
189
+
190
+ // Scrolling
191
+ await Util.scrollToEnd(2, 3);
192
+ await Util.scrollDownToView("Some Text");
193
+
194
+ // Swiping
195
+ await Util.swipeWithCoordinates(x1, y1, x2, y2);
196
+
197
+ // Random data
198
+ const randomText = Util.randomtext(10);
199
+ const randomNumber = Util.randomnumber(100, 999);
200
+
201
+ // Buffer storage
202
+ Util.storetext('key', 'value');
203
+ const value = BUFFER.getItem('key');
204
+ ```
205
+
206
+ ## Required Environment Variables
207
+
208
+ | Variable | Description | Example |
209
+ |----------|-------------|---------|
210
+ | `YML_NAME` | Path to capability YAML file | `./ymls/browserstack/android/android_pixel8.yml` |
211
+ | `SUITE` | Path to suite file | `./android_suites/samplesuite_x.js` |
212
+ | `PLATFORM` | `local` for local execution, `browserstack` or `browserstacklocal` for BrowserStack | `local` or `browserstack` |
213
+ | `EXECUTION_ID` | Test execution ID from TestOps | `12995` |
214
+ | `API_TOKEN` | Authentication token for TestOps API | `eyJhbG...` |
215
+ | `ORGANISATION_DOMAIN_URL` | Froth TestOps API base URL | `https://api.frothtestops.com` |
216
+ | `CICD_RUN_ID` | CI/CD pipeline run ID (optional) | `1` |
217
+ | `BROWSERSTACK_BUILD_NAME` | Build name for BrowserStack session tracking | `Web_Build- api-module-testing_2345_20260619` |
218
+ | `BS_UPLOAD_MEDIA` | Comma-separated media URLs for BrowserStack (optional) | `url1,url2` |
219
+
220
+ ## Capability YAML Format
221
+
222
+ YAML files define device/browser capabilities. Example for Android:
223
+
224
+ ```yaml
225
+ userName: "bs_username"
226
+ accessKey: "base64_encoded_key"
227
+ platformName: "Android"
228
+ deviceName: "Samsung Galaxy S22 Ultra"
229
+ platformVersion: "12.0"
230
+ debug: true
231
+ networkLogs: true
232
+ interactiveDebugging: false
233
+ ```
234
+
235
+ ## Important Notes
236
+
237
+ - The framework uses `node-localstorage` to create a global `BUFFER` accessible across all modules
238
+ - All API responses from TestOps are AES-decrypted via `aesEncryptionDecryption.js`
239
+ - Test scripts map to TestOps via filename (script name must match `scriptName` in suite details)
240
+ - Mobile tests use Appium selectors like `id:com.example:id/elementId` and `-android uiautomator:...`
241
+ - Web tests use standard WebdriverIO selectors (`$`, `$$`)
242
+ - Framework supports both BrowserStack App Automate (mobile) and Automate (web) sessions
243
+ - **PLATFORM variable:**
244
+ - Use `PLATFORM=local` when executing tests from your local machine (even when targeting BrowserStack devices)
245
+ - Use `PLATFORM=browserstack` or `PLATFORM=browserstacklocal` when running from BrowserStack infrastructure
@@ -0,0 +1,226 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Allure Helper Utility for WebDriverIO
6
+ * Provides methods to add steps, screenshots, and attachments to Allure reports
7
+ */
8
+
9
+ class AllureHelper {
10
+ /**
11
+ * Add a step to the Allure report
12
+ * @param {string} name - Step name
13
+ * @param {Function} stepFn - Step function to execute
14
+ */
15
+ static async step(name, stepFn) {
16
+ const allure = require('@wdio/allure-reporter').default;
17
+
18
+ console.log(`šŸ“ Step: ${name}`);
19
+
20
+ // Create a step in Allure
21
+ allure.startStep(name);
22
+
23
+ try {
24
+ // Execute the step function
25
+ await stepFn();
26
+ allure.endStep('passed');
27
+ } catch (error) {
28
+ allure.endStep('failed');
29
+ throw error;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Add a description step
35
+ * @param {string} text - Description text
36
+ */
37
+ static description(text) {
38
+ const allure = require('@wdio/allure-reporter').default;
39
+ console.log(`šŸ“„ ${text}`);
40
+ }
41
+
42
+ /**
43
+ * Capture and attach screenshot to Allure report
44
+ * @param {string} screenshotName - Name for the screenshot
45
+ */
46
+ static async captureScreenshot(screenshotName = 'screenshot') {
47
+ try {
48
+ // Ensure screenshot directory exists
49
+ const screenshotDir = './allure-screenshots';
50
+ if (!fs.existsSync(screenshotDir)) {
51
+ fs.mkdirSync(screenshotDir, { recursive: true });
52
+ }
53
+
54
+ // Take screenshot and save to file
55
+ const screenshotPath = path.join(screenshotDir, `${screenshotName}.png`);
56
+ await browser.saveScreenshot(screenshotPath);
57
+
58
+ // Read the screenshot
59
+ if (fs.existsSync(screenshotPath)) {
60
+ const imageBuffer = fs.readFileSync(screenshotPath);
61
+
62
+ // Attach to Allure using the proper method
63
+ const allure = require('@wdio/allure-reporter').default;
64
+ allure.addAttachment(screenshotName, imageBuffer, 'image/png');
65
+
66
+ console.log(`šŸ“ø Screenshot captured: ${screenshotName}`);
67
+ } else {
68
+ console.warn(`āš ļø Screenshot file not found: ${screenshotPath}`);
69
+ }
70
+ } catch (error) {
71
+ console.error(`āŒ Error capturing screenshot: ${error.message}`);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Add text attachment to Allure report
77
+ * @param {string} name - Attachment name
78
+ * @param {string} text - Text content
79
+ * @param {string} mimeType - MIME type (default: text/plain)
80
+ */
81
+ static addAttachment(name, text, mimeType = 'text/plain') {
82
+ const allure = require('@wdio/allure-reporter').default;
83
+ allure.addAttachment(name, text, mimeType);
84
+ console.log(`šŸ“Ž Attachment added: ${name}`);
85
+ }
86
+
87
+ /**
88
+ * Add severity level to test
89
+ * @param {string} level - Severity level (blocker, critical, normal, minor, trivial)
90
+ */
91
+ static severity(level = 'normal') {
92
+ const allure = require('@wdio/allure-reporter').default;
93
+ allure.addArgument('severity', level);
94
+ console.log(`šŸ”– Severity: ${level}`);
95
+ }
96
+
97
+ /**
98
+ * Add epic label
99
+ * @param {string} epic - Epic name
100
+ */
101
+ static epic(epic) {
102
+ const allure = require('@wdio/allure-reporter').default;
103
+ allure.addArgument('epic', epic);
104
+ console.log(`šŸ“š Epic: ${epic}`);
105
+ }
106
+
107
+ /**
108
+ * Add feature label
109
+ * @param {string} feature - Feature name
110
+ */
111
+ static feature(feature) {
112
+ const allure = require('@wdio/allure-reporter').default;
113
+ allure.addArgument('feature', feature);
114
+ console.log(`⭐ Feature: ${feature}`);
115
+ }
116
+
117
+ /**
118
+ * Add story label
119
+ * @param {string} story - Story name
120
+ */
121
+ static story(story) {
122
+ const allure = require('@wdio/allure-reporter').default;
123
+ allure.addArgument('story', story);
124
+ console.log(`šŸ“– Story: ${story}`);
125
+ }
126
+
127
+ /**
128
+ * Add test ID/TC tag
129
+ * @param {string} testId - Test ID
130
+ */
131
+ static testId(testId) {
132
+ const allure = require('@wdio/allure-reporter').default;
133
+ allure.addArgument('testId', testId);
134
+ console.log(`šŸ·ļø Test ID: ${testId}`);
135
+ }
136
+
137
+ /**
138
+ * Capture screenshot on test failure
139
+ */
140
+ static async captureOnFailure() {
141
+ const allure = require('@wdio/allure-reporter').default;
142
+
143
+ try {
144
+ const testName = expect.getState().currentTestName || 'test';
145
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
146
+ const screenshotName = `${testName}-failure-${timestamp}`;
147
+
148
+ await this.captureScreenshot(screenshotName);
149
+ } catch (error) {
150
+ console.error(`āŒ Error capturing failure screenshot: ${error.message}`);
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Add environment information to report
156
+ * @param {object} envInfo - Environment information object
157
+ */
158
+ static addEnvironment(envInfo) {
159
+ const allure = require('@wdio/allure-reporter').default;
160
+
161
+ Object.entries(envInfo).forEach(([key, value]) => {
162
+ allure.addArgument(`env:${key}`, value);
163
+ console.log(`šŸŒ Environment: ${key} = ${value}`);
164
+ });
165
+ }
166
+
167
+ /**
168
+ * Log text as a step
169
+ * @param {string} message - Log message
170
+ */
171
+ static log(message) {
172
+ const allure = require('@wdio/allure-reporter').default;
173
+ allure.addStep(message);
174
+ console.log(`šŸ“ ${message}`);
175
+ }
176
+
177
+ /**
178
+ * Take a screenshot and attach it as an attachment (simpler method)
179
+ * @param {string} name - Attachment name
180
+ */
181
+ static async attachScreenshot(name = 'screenshot') {
182
+ try {
183
+ // Take screenshot to buffer
184
+ const screenshot = await browser.takeScreenshot();
185
+
186
+ // Attach directly to Allure
187
+ const allure = require('@wdio/allure-reporter').default;
188
+ const buffer = Buffer.from(screenshot, 'base64');
189
+ allure.addAttachment(name, buffer, 'image/png');
190
+
191
+ console.log(`šŸ“ø Screenshot attached: ${name}`);
192
+ } catch (error) {
193
+ console.error(`āŒ Error attaching screenshot: ${error.message}`);
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Add screenshot attachment with detailed logging
199
+ * @param {string} stepName - Name of the current step
200
+ * @param {string} description - Description of what the screenshot shows
201
+ */
202
+ static async screenshot(stepName, description = 'Screenshot') {
203
+ try {
204
+ const allure = require('@wdio/allure-reporter').default;
205
+
206
+ // Start step if not already in one
207
+ allure.startStep(description);
208
+
209
+ // Take screenshot
210
+ const screenshot = await browser.takeScreenshot();
211
+ const buffer = Buffer.from(screenshot, 'base64');
212
+
213
+ // Attach screenshot to the step
214
+ allure.addAttachment(description, buffer, 'image/png');
215
+
216
+ // End the step
217
+ allure.endStep('passed');
218
+
219
+ console.log(`šŸ“ø Screenshot attached for step: ${stepName}`);
220
+ } catch (error) {
221
+ console.error(`āŒ Error with screenshot: ${error.message}`);
222
+ }
223
+ }
224
+ }
225
+
226
+ module.exports = AllureHelper;
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Froth Allure Report CLI
5
+ * Usage:
6
+ * npx froth-report open - Open the latest Allure report in browser
7
+ * npx froth-report generate - Generate Allure HTML report from results
8
+ * npx froth-report - Shows help
9
+ *
10
+ * Works from any project folder that has the framework installed.
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { execSync } = require('child_process');
16
+
17
+ // Commands
18
+ const command = process.argv[2];
19
+
20
+ function showHelp() {
21
+ console.log(`
22
+ šŸŽÆ Froth Allure Report CLI
23
+ ============================
24
+
25
+ Usage:
26
+ npx froth-report open Open the latest Allure report in browser (http://localhost:8080)
27
+ npx froth-report generate Generate Allure HTML report from test results
28
+ npx froth-report help Show this help message
29
+
30
+ Examples:
31
+ npx froth-report open
32
+ npx froth-report generate
33
+
34
+ The report must be in: ./reports/allure/ (relative to current folder)
35
+ `);
36
+ }
37
+
38
+ function findLatestReport() {
39
+ const REPORTS_DIR = './reports/allure';
40
+ if (!fs.existsSync(REPORTS_DIR)) {
41
+ return null;
42
+ }
43
+
44
+ const directories = fs.readdirSync(REPORTS_DIR)
45
+ .map(file => path.join(REPORTS_DIR, file))
46
+ .filter(file => fs.statSync(file).isDirectory())
47
+ .filter(file => {
48
+ // Check if any subdirectory ending with _report exists
49
+ try {
50
+ const subdirs = fs.readdirSync(file)
51
+ .map(sub => path.join(file, sub))
52
+ .filter(sub => {
53
+ const stat = fs.statSync(sub);
54
+ return stat.isDirectory() && path.basename(sub).endsWith('_report');
55
+ });
56
+ return subdirs.length > 0;
57
+ } catch (e) {
58
+ return false;
59
+ }
60
+ })
61
+ .sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);
62
+
63
+ return directories.length > 0 ? directories[0] : null;
64
+ }
65
+
66
+ function openReport() {
67
+ const reportDir = findLatestReport();
68
+
69
+ if (!reportDir) {
70
+ console.log('āŒ No Allure HTML reports found.');
71
+ console.log('šŸ’” Run tests first. Reports are generated in: ./reports/allure/');
72
+ console.log('šŸ’” Or generate manually: npx froth-report generate');
73
+ process.exit(1);
74
+ }
75
+
76
+ // Find the report folder ending with _report
77
+ const reportSubdirs = fs.readdirSync(reportDir)
78
+ .map(sub => path.join(reportDir, sub))
79
+ .filter(sub => {
80
+ const stat = fs.statSync(sub);
81
+ return stat.isDirectory() && path.basename(sub).endsWith('_report');
82
+ });
83
+
84
+ if (reportSubdirs.length === 0) {
85
+ console.log('āŒ No HTML report found in:', reportDir);
86
+ console.log('šŸ’” Generate it first: npx froth-report generate');
87
+ process.exit(1);
88
+ }
89
+
90
+ const htmlReportPath = reportSubdirs[0];
91
+ const indexPath = path.join(htmlReportPath, 'index.html');
92
+
93
+ console.log('šŸŽÆ Opening Allure Report');
94
+ console.log('========================\n');
95
+ console.log(`šŸ“ Report location: ${htmlReportPath}`);
96
+ console.log(`šŸ·ļø Build: ${path.basename(reportDir)}\n`);
97
+ console.log('🌐 Opening report in browser on http://localhost:8080');
98
+ console.log('šŸ’” Press Ctrl+C to stop the server\n');
99
+
100
+ try {
101
+ execSync(`npx allure open ${htmlReportPath} --port 8080`, { stdio: 'inherit' });
102
+ } catch (error) {
103
+ console.error(`āŒ Error opening report: ${error.message}`);
104
+ console.log(`\nšŸ’” To view manually, open: file://${path.resolve(indexPath)}`);
105
+ }
106
+ }
107
+
108
+ function generateReport() {
109
+ // Run the generate-allure-report.js script
110
+ const scriptPath = path.resolve(__dirname, 'generate-allure-report.js');
111
+
112
+ if (!fs.existsSync(scriptPath)) {
113
+ console.log('āŒ Report generator script not found:', scriptPath);
114
+ process.exit(1);
115
+ }
116
+
117
+ try {
118
+ execSync(`node "${scriptPath}"`, { stdio: 'inherit' });
119
+ } catch (error) {
120
+ console.error(`āŒ Error generating report: ${error.message}`);
121
+ process.exit(1);
122
+ }
123
+ }
124
+
125
+ // Main
126
+ switch (command) {
127
+ case 'open':
128
+ openReport();
129
+ break;
130
+ case 'generate':
131
+ generateReport();
132
+ break;
133
+ case 'help':
134
+ case '--help':
135
+ case '-h':
136
+ showHelp();
137
+ break;
138
+ default:
139
+ console.log('\nšŸŽÆ Froth Allure Report CLI\n');
140
+ showHelp();
141
+ break;
142
+ }