@cuppet/core 1.0.0 → 1.0.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/README.md CHANGED
@@ -1,183 +1,355 @@
1
- # @cuppet/core
2
-
3
- Core testing framework components for Cuppet - a BDD framework based on Cucumber and Puppeteer.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @cuppet/core
9
- ```
10
-
11
- ## Usage
12
-
13
- ### Basic Setup
14
-
15
- ```javascript
16
- const {
17
- BrowserManager,
18
- elementInteraction,
19
- dataStorage
20
- } = require('@cuppet/core');
21
- ```
22
-
23
- ### In your hooks.js
24
-
25
- ```javascript
26
- const { Before, After } = require('@cucumber/cucumber');
27
- const { BrowserManager, AppiumManager } = require('@cuppet/core');
28
- const config = require('config');
29
-
30
- Before(async function (testCase) {
31
- const browserArgs = config.get('browserOptions.args');
32
- const browserViewport = config.get('browserOptions.viewport.default');
33
-
34
- const browserManager = new BrowserManager(browserViewport, browserArgs);
35
- await browserManager.initialize();
36
- this.browserManager = browserManager;
37
- this.browser = browserManager.browser;
38
- this.page = browserManager.page;
39
-
40
- });
41
- ```
42
-
43
- ### In your step definitions
44
-
45
- ```javascript
46
- const { Given, When, Then } = require('@cucumber/cucumber');
47
- const { elementInteraction, mainFunctions } = require('@cuppet/core');
48
-
49
- Given('I am on the homepage', async function() {
50
- await mainFunctions.visitPath(this.page, 'homepage');
51
- });
52
-
53
- When('I click the {string} button', async function(cssSelector) {
54
- await elementInteraction.click(this.page, cssSelector);
55
- });
56
- ```
57
-
58
- ## Available Components
59
-
60
- ### Core Functions
61
- - `elementInteraction` - Element interaction utilities
62
- - `dataStorage` - Data storage and management
63
- - `mainFunctions` - Main testing functions
64
- - `helperFunctions` - Helper utilities
65
- - `apiFunctions` - API testing functions
66
- - `appiumTesting` - Appium mobile testing
67
- - `accessibilityTesting` - Accessibility testing with Pa11y
68
- - `lighthouse` - Performance testing with Lighthouse
69
- - `visualRegression` - Visual regression testing with BackstopJS
70
-
71
- ### Managers
72
- - `BrowserManager` - Puppeteer browser management
73
- - `AppiumManager` - Appium mobile testing management
74
-
75
- ### Step Definitions
76
- - `stepDefinitions` - Pre-built Cucumber step definitions for common testing scenarios
77
-
78
- ## Using Step Definitions in Other Projects
79
-
80
- The cuppet-core package includes pre-built step definitions that you can use in your main project. Here are several ways to integrate them:
81
-
82
- ### Option 1: Import and use directly in your step definition files
83
-
84
- ```javascript
85
- // In your project's step definition file (e.g., mySteps.js)
86
- const { Given, When, Then } = require('@cucumber/cucumber');
87
- const { stepDefinitions } = require('@cuppet/core');
88
-
89
- // Use the pre-built step definitions
90
- const { generalSteps, helperSteps, apiSteps } = stepDefinitions;
91
-
92
- // You can now use the step definitions directly
93
- Given('I am on the homepage', generalSteps.givenIAmOnTheHomepage);
94
- When('I click the login button', helperSteps.whenIClickTheLoginButton);
95
- Then('I should see the dashboard', generalSteps.thenIShouldSeeTheDashboard);
96
- ```
97
-
98
- ### Option 2: Import step definitions separately
99
-
100
- ```javascript
101
- // Import step definitions directly
102
- const stepDefinitions = require('@cuppet/core/stepDefinitions');
103
-
104
- // Or import specific step definition modules
105
- const generalSteps = require('@cuppet/core/features/app/stepDefinitions/generalSteps');
106
- const apiSteps = require('@cuppet/core/features/app/stepDefinitions/apiSteps');
107
- ```
108
-
109
- ### Option 3: Extend and customize step definitions
110
-
111
- ```javascript
112
- // In your project's step definition file
113
- const { Given, When, Then } = require('@cucumber/cucumber');
114
- const { stepDefinitions } = require('@cuppet/core');
115
-
116
- // Extend the base step definitions with your custom logic
117
- Given('I am logged in as {string}', async function(userType) {
118
- // Your custom login logic
119
- await this.page.goto('https://your-app.com/login');
120
- await this.page.fill('[data-testid="username"]', userType);
121
- await this.page.fill('[data-testid="password"]', 'password');
122
- await this.page.click('[data-testid="login-button"]');
123
-
124
- // Then use the base step definition
125
- await stepDefinitions.generalSteps.thenIShouldSeeTheDashboard.call(this);
126
- });
127
- ```
128
-
129
- ### Available Step Definition Categories
130
-
131
- - `accessibilitySteps` - Accessibility testing steps
132
- - `apiSteps` - API testing and validation steps
133
- - `appiumSteps` - Mobile testing with Appium
134
- - `generalSteps` - Common navigation and interaction steps
135
- - `helperSteps` - Utility and helper steps
136
- - `iframeSteps` - Iframe handling steps
137
- - `ifVisibleSteps` - Conditional visibility steps
138
- - `lighthouseSteps` - Performance testing steps
139
- - `pageElements` - Page element management
140
- - `pageElementsConfig` - Page element configuration
141
- - `pageElementsJson` - JSON-based page elements
142
- - `visualRegressionSteps` - Visual regression testing steps
143
-
144
- ### Cucumber Configuration
145
-
146
- Make sure your Cucumber configuration includes the step definition paths:
147
-
148
- ```javascript
149
- // cucumber.js
150
- module.exports = {
151
- default: {
152
- requireModule: ['@cuppet/core'],
153
- require: [
154
- 'node_modules/@cuppet/core/features/app/stepDefinitions/*.js',
155
- 'features/step-definitions/**/*.js' // Your project's step definitions
156
- ]
157
- }
158
- };
159
- ```
160
-
161
- ## Project-Specific Components
162
-
163
- The following components should be created in your project as they are specific to your application:
164
-
165
- - `commonComponents/` - Common form fields and page paths for your application
166
- - `multilingualStrings/` - Multilingual string support for your application
167
-
168
- ## Peer Dependencies
169
-
170
- This package requires the following peer dependencies:
171
- - `@cucumber/cucumber` ^11.0.0
172
- - `puppeteer` ^24.0.1
173
- - `config` ^3.3.9
174
-
175
- Make sure to install these in your project:
176
-
177
- ```bash
178
- npm install @cucumber/cucumber puppeteer config
179
- ```
180
-
181
- ## License
182
-
183
- ISC
1
+ # @cuppet/core
2
+
3
+ Core testing framework components for Cuppet - a BDD framework based on Cucumber and Puppeteer.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @cuppet/core
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Setup
14
+
15
+ ```javascript
16
+ const { BrowserManager, elementInteraction, dataStorage } = require('@cuppet/core');
17
+ ```
18
+
19
+ ### In your hooks.js
20
+
21
+ ```javascript
22
+ const { Before, After } = require('@cucumber/cucumber');
23
+ const { BrowserManager, AppiumManager } = require('@cuppet/core');
24
+ const config = require('config');
25
+
26
+ Before(async function (testCase) {
27
+ const browserArgs = config.get('browserOptions.args');
28
+ const browserViewport = config.get('browserOptions.viewport.default');
29
+
30
+ const browserManager = new BrowserManager(browserViewport, browserArgs);
31
+ await browserManager.initialize();
32
+ this.browserManager = browserManager;
33
+ this.browser = browserManager.browser;
34
+ this.page = browserManager.page;
35
+ });
36
+ ```
37
+
38
+ ### In your step definitions
39
+
40
+ ```javascript
41
+ const { Given, When, Then } = require('@cucumber/cucumber');
42
+ const { elementInteraction, mainFunctions } = require('@cuppet/core');
43
+
44
+ Given('I am on the homepage', async function () {
45
+ await mainFunctions.visitPath(this.page, 'homepage');
46
+ });
47
+
48
+ When('I click the {string} button', async function (cssSelector) {
49
+ await elementInteraction.click(this.page, cssSelector);
50
+ });
51
+ ```
52
+
53
+ ## Available Components
54
+
55
+ ### Core Functions
56
+
57
+ - `elementInteraction` - Element interaction utilities
58
+ - `dataStorage` - Data storage and management
59
+ - `mainFunctions` - Main testing functions
60
+ - `helperFunctions` - Helper utilities
61
+ - `apiFunctions` - API testing functions
62
+ - `appiumTesting` - Appium mobile testing
63
+ - `accessibilityTesting` - Accessibility testing with Pa11y
64
+ - `lighthouse` - Performance testing with Lighthouse
65
+ - `visualRegression` - Visual regression testing with BackstopJS
66
+
67
+ ### Managers
68
+
69
+ - `BrowserManager` - Puppeteer browser management
70
+ - `AppiumManager` - Appium mobile testing management
71
+
72
+ ### Step Definitions
73
+
74
+ - `stepDefinitions` - Pre-built Cucumber step definitions for common testing scenarios
75
+
76
+ ## Using Step Definitions in Other Projects
77
+
78
+ The cuppet-core package includes pre-built step definitions that you can use in your main project. Here are several ways to integrate them:
79
+
80
+ ### Option 1: Import and use directly in your step definition files
81
+
82
+ ```javascript
83
+ // In your project's step definition file (e.g., mySteps.js)
84
+ const { Given, When, Then } = require('@cucumber/cucumber');
85
+ const { stepDefinitions } = require('@cuppet/core');
86
+
87
+ // Use the pre-built step definitions
88
+ const { generalSteps, helperSteps, apiSteps } = stepDefinitions;
89
+
90
+ // You can now use the step definitions directly
91
+ Given('I am on the homepage', generalSteps.givenIAmOnTheHomepage);
92
+ When('I click the login button', helperSteps.whenIClickTheLoginButton);
93
+ Then('I should see the dashboard', generalSteps.thenIShouldSeeTheDashboard);
94
+ ```
95
+
96
+ ### Option 2: Import step definitions separately
97
+
98
+ ```javascript
99
+ // Import step definitions directly
100
+ const stepDefinitions = require('@cuppet/core/stepDefinitions');
101
+
102
+ // Or import specific step definition modules
103
+ const generalSteps = require('@cuppet/core/features/app/stepDefinitions/generalSteps');
104
+ const apiSteps = require('@cuppet/core/features/app/stepDefinitions/apiSteps');
105
+ ```
106
+
107
+ ### Option 3: Extend and customize step definitions
108
+
109
+ ```javascript
110
+ // In your project's step definition file
111
+ const { Given, When, Then } = require('@cucumber/cucumber');
112
+ const { stepDefinitions } = require('@cuppet/core');
113
+
114
+ // Extend the base step definitions with your custom logic
115
+ Given('I am logged in as {string}', async function (userType) {
116
+ // Your custom login logic
117
+ await this.page.goto('https://your-app.com/login');
118
+ await this.page.fill('[data-testid="username"]', userType);
119
+ await this.page.fill('[data-testid="password"]', 'password');
120
+ await this.page.click('[data-testid="login-button"]');
121
+
122
+ // Then use the base step definition
123
+ await stepDefinitions.generalSteps.thenIShouldSeeTheDashboard.call(this);
124
+ });
125
+ ```
126
+
127
+ ### Available Step Definition Categories
128
+
129
+ - `accessibilitySteps` - Accessibility testing steps
130
+ - `apiSteps` - API testing and validation steps
131
+ - `appiumSteps` - Mobile testing with Appium
132
+ - `generalSteps` - Common navigation and interaction steps
133
+ - `helperSteps` - Utility and helper steps
134
+ - `iframeSteps` - Iframe handling steps
135
+ - `ifVisibleSteps` - Conditional visibility steps
136
+ - `lighthouseSteps` - Performance testing steps
137
+ - `pageElements` - Page element management
138
+ - `pageElementsConfig` - Page element configuration
139
+ - `pageElementsJson` - JSON-based page elements
140
+ - `visualRegressionSteps` - Visual regression testing steps
141
+
142
+ ### Cucumber Configuration
143
+
144
+ Make sure your Cucumber configuration includes the step definition paths:
145
+
146
+ ```javascript
147
+ // cucumber.js
148
+ module.exports = {
149
+ default: {
150
+ requireModule: ['@cuppet/core'],
151
+ require: [
152
+ 'node_modules/@cuppet/core/features/app/stepDefinitions/*.js',
153
+ 'features/step-definitions/**/*.js', // Your project's step definitions
154
+ ],
155
+ },
156
+ };
157
+ ```
158
+
159
+ ## Practical Examples
160
+
161
+ Here are real-world examples of how to use, override, and extend step definitions from cuppet-core:
162
+
163
+ ### 1. Direct Usage - Use existing steps as-is
164
+
165
+ ```javascript
166
+ // In your step definition file
167
+ const { Given, When, Then } = require('@cucumber/cucumber');
168
+ const { stepDefinitions } = require('@cuppet/core');
169
+
170
+ const { generalSteps, helperSteps } = stepDefinitions;
171
+
172
+ // Use them directly
173
+ Given('I go to homepage', async function () {
174
+ await generalSteps['I go to {string}'].call(this, 'homepage');
175
+ });
176
+
177
+ When('I wait for page to load', async function () {
178
+ await helperSteps['I wait for {string} seconds'].call(this, '3');
179
+ });
180
+ ```
181
+
182
+ ### 2. Override - Replace with your custom logic
183
+
184
+ ```javascript
185
+ // Override the default login step for your specific application
186
+ Given('I log in', async function () {
187
+ // Your custom login logic
188
+ await this.page.goto('https://myapp.com/login');
189
+ await this.page.fill('#email', 'test@example.com');
190
+ await this.page.fill('#password', 'password123');
191
+ await this.page.click('#login-button');
192
+ await this.page.waitForNavigation();
193
+ });
194
+
195
+ // Override navigation with your base URL
196
+ Given('I go to {string}', async function (path) {
197
+ const baseUrl = 'https://myapp.com';
198
+ await this.page.goto(`${baseUrl}/${path}`);
199
+ });
200
+ ```
201
+
202
+ ### 3. Extend - Add custom logic before/after existing steps
203
+
204
+ ```javascript
205
+ // Add logging to existing steps
206
+ Given('I go to {string} with logging', async function (path) {
207
+ console.log(`Navigating to: ${path}`);
208
+
209
+ // Use the original step
210
+ await generalSteps['I go to {string}'].call(this, path);
211
+
212
+ console.log(`Successfully navigated to: ${path}`);
213
+ });
214
+
215
+ // Add validation after navigation
216
+ Given('I go to {string} and verify page loaded', async function (path) {
217
+ // Use the original step
218
+ await generalSteps['I go to {string}'].call(this, path);
219
+
220
+ // Add custom validation
221
+ await this.page.waitForSelector('[data-testid="page-content"]');
222
+ });
223
+ ```
224
+
225
+ ### 4. Composite Steps - Combine multiple existing steps
226
+
227
+ ```javascript
228
+ // Create a setup step that combines multiple existing steps
229
+ Given('I set up test environment', async function () {
230
+ // Clear data
231
+ await helperSteps['I clear the json file'].call(this);
232
+
233
+ // Set viewport
234
+ await generalSteps['I set viewport size to {string}'].call(this, '1920x1080');
235
+
236
+ // Navigate to setup page
237
+ await generalSteps['I go to {string}'].call(this, 'setup');
238
+
239
+ // Wait for setup to complete
240
+ await helperSteps['I wait for {string} seconds'].call(this, '2');
241
+ });
242
+
243
+ // Create role-specific login steps
244
+ Given('I am logged in as {string}', async function (userType) {
245
+ const credentials = {
246
+ admin: { username: 'admin', password: 'admin123' },
247
+ user: { username: 'user', password: 'user123' },
248
+ };
249
+
250
+ const user = credentials[userType];
251
+ await generalSteps['I log in as {string} {string}'].call(this, user.username, user.password);
252
+ });
253
+ ```
254
+
255
+ ### 5. Error Handling - Wrap existing steps with retry logic
256
+
257
+ ```javascript
258
+ // Create a retry wrapper for navigation
259
+ Given('I go to {string} with retry', async function (path) {
260
+ const maxRetries = 3;
261
+
262
+ for (let i = 0; i < maxRetries; i++) {
263
+ try {
264
+ await generalSteps['I go to {string}'].call(this, path);
265
+ return; // Success, exit the loop
266
+ } catch (error) {
267
+ console.log(`Navigation attempt ${i + 1} failed: ${error.message}`);
268
+
269
+ if (i === maxRetries - 1) {
270
+ throw error; // Re-throw on last attempt
271
+ }
272
+
273
+ // Wait before retry
274
+ await helperSteps['I wait for {string} seconds'].call(this, '2');
275
+ }
276
+ }
277
+ });
278
+ ```
279
+
280
+ ### 6. Utility Functions - Create reusable helpers
281
+
282
+ ```javascript
283
+ // Create utility functions that use existing steps
284
+ const stepUtils = {
285
+ async loginWithRetry(page, username, password, maxRetries = 3) {
286
+ for (let i = 0; i < maxRetries; i++) {
287
+ try {
288
+ await stepDefinitions.generalSteps['I log in as {string} {string}'].call({ page }, username, password);
289
+ return true;
290
+ } catch (error) {
291
+ console.log(`Login attempt ${i + 1} failed`);
292
+ if (i === maxRetries - 1) throw error;
293
+ await stepDefinitions.helperSteps['I wait for {string} seconds'].call({ page }, '2');
294
+ }
295
+ }
296
+ },
297
+ };
298
+
299
+ // Use the utility functions
300
+ Given('I log in with retry mechanism', async function () {
301
+ await stepUtils.loginWithRetry(this.page, 'testuser', 'testpass');
302
+ });
303
+ ```
304
+
305
+ ### 7. Feature-Specific Steps - Create steps for your application
306
+
307
+ ```javascript
308
+ // E-commerce specific steps
309
+ Given('I add {string} to cart', async function (productName) {
310
+ // Navigate to product page
311
+ await generalSteps['I go to {string}'].call(this, `products/${productName}`);
312
+
313
+ // Add to cart logic
314
+ await this.page.click('[data-testid="add-to-cart"]');
315
+ await helperSteps['I wait for {string} seconds'].call(this, '1');
316
+ });
317
+
318
+ // User management specific steps
319
+ Given('I create a new user account', async function () {
320
+ await generalSteps['I go to {string}'].call(this, 'register');
321
+
322
+ // Fill registration form
323
+ await this.page.fill('[data-testid="username"]', 'newuser');
324
+ await this.page.fill('[data-testid="email"]', 'newuser@example.com');
325
+ await this.page.fill('[data-testid="password"]', 'password123');
326
+ await this.page.click('[data-testid="register-button"]');
327
+
328
+ await helperSteps['I wait for {string} seconds'].call(this, '2');
329
+ });
330
+ ```
331
+
332
+ ## Project-Specific Components
333
+
334
+ The following components should be created in your project as they are specific to your application:
335
+
336
+ - `commonComponents/` - Common form fields and page paths for your application
337
+ - `multilingualStrings/` - Multilingual string support for your application
338
+
339
+ ## Peer Dependencies
340
+
341
+ This package requires the following peer dependencies:
342
+
343
+ - `@cucumber/cucumber` ^11.0.0
344
+ - `puppeteer` ^24.0.1
345
+ - `config` ^3.3.9
346
+
347
+ Make sure to install these in your project:
348
+
349
+ ```bash
350
+ npm install @cucumber/cucumber puppeteer config
351
+ ```
352
+
353
+ ## License
354
+
355
+ ISC
@@ -1,58 +1,58 @@
1
- /**
2
- * Wdio session
3
- *
4
- * @type {import('webdriverio')}
5
- */
6
- const { remote } = require('webdriverio');
7
-
8
- /**
9
- * Appium instance manager for handling Appium sessions and capabilities.
10
- *
11
- * @class AppiumManager
12
- * @typedef {AppiumManager}
13
- */
14
- class AppiumManager {
15
- /**
16
- * Creates an instance of AppiumManager.
17
- *
18
- * @constructor
19
- * @param {*} capabilities
20
- */
21
- constructor(capabilities) {
22
- this.capabilities = capabilities;
23
- this.appiumDriver = null;
24
- this.appiumService = null;
25
- }
26
-
27
- /**
28
- * Description placeholder
29
- *
30
- * @async
31
- * @returns {Promise<void>}
32
- * @throws {Error} If the Appium service fails to start.
33
- */
34
- async initialize() {
35
- const wdOpts = {
36
- hostname: process.env.APPIUM_HOST || 'localhost',
37
- port: parseInt(process.env.APPIUM_PORT, 10) || 4723,
38
- logLevel: 'silent', // Can be: 'trace', 'debug', 'info', 'warn', 'error', or 'silent'
39
- capabilities: this.capabilities,
40
- };
41
- this.appiumDriver = await remote(wdOpts);
42
- }
43
-
44
- /**
45
- * Description placeholder
46
- *
47
- * @async
48
- * @returns {Promise<void>}
49
- */
50
- async stop() {
51
- if (this.appiumDriver) {
52
- await this.appiumDriver.deleteSession();
53
- this.appiumDriver = null;
54
- }
55
- }
56
- }
57
-
58
- module.exports = AppiumManager;
1
+ /**
2
+ * Wdio session
3
+ *
4
+ * @type {import('webdriverio')}
5
+ */
6
+ const { remote } = require('webdriverio');
7
+
8
+ /**
9
+ * Appium instance manager for handling Appium sessions and capabilities.
10
+ *
11
+ * @class AppiumManager
12
+ * @typedef {AppiumManager}
13
+ */
14
+ class AppiumManager {
15
+ /**
16
+ * Creates an instance of AppiumManager.
17
+ *
18
+ * @constructor
19
+ * @param {*} capabilities
20
+ */
21
+ constructor(capabilities) {
22
+ this.capabilities = capabilities;
23
+ this.appiumDriver = null;
24
+ this.appiumService = null;
25
+ }
26
+
27
+ /**
28
+ * Description placeholder
29
+ *
30
+ * @async
31
+ * @returns {Promise<void>}
32
+ * @throws {Error} If the Appium service fails to start.
33
+ */
34
+ async initialize() {
35
+ const wdOpts = {
36
+ hostname: process.env.APPIUM_HOST || 'localhost',
37
+ port: parseInt(process.env.APPIUM_PORT, 10) || 4723,
38
+ logLevel: 'silent', // Can be: 'trace', 'debug', 'info', 'warn', 'error', or 'silent'
39
+ capabilities: this.capabilities,
40
+ };
41
+ this.appiumDriver = await remote(wdOpts);
42
+ }
43
+
44
+ /**
45
+ * Description placeholder
46
+ *
47
+ * @async
48
+ * @returns {Promise<void>}
49
+ */
50
+ async stop() {
51
+ if (this.appiumDriver) {
52
+ await this.appiumDriver.deleteSession();
53
+ this.appiumDriver = null;
54
+ }
55
+ }
56
+ }
57
+
58
+ module.exports = AppiumManager;