plum-e2e 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@ Plum makes setting up your testing framework easy. In just a few seconds, you ca
11
11
 
12
12
  By combining [Playwright](https://playwright.dev) and [Cucumber](https://cucumber.io), tests are easy to write and read. The code follows a POM (Page Object Model) structure, making it scalable and easy for developers to understand, while Cucumber test cases are written in [Gherkin](https://cucumber.io/docs/gherkin/) format, making them accessible to non-developers as well.
13
13
 
14
- You can view, run, schedule tests in a simple UI and even view the history of your runs in the Report page!
14
+ You can view, run, and schedule tests in a simple UI. You can even view the history of your runs in the reports page!
15
15
 
16
16
  **_Pre-requisite:_**
17
17
 
@@ -19,7 +19,7 @@ You can view, run, schedule tests in a simple UI and even view the history of yo
19
19
 
20
20
  ## For Users
21
21
 
22
- For normal users. People that want to use Plum as a test environment for their website.
22
+ People that want to use Plum as a test environment for their website.
23
23
 
24
24
  **_I. How to Run:_**
25
25
 
@@ -31,7 +31,8 @@ For normal users. People that want to use Plum as a test environment for their w
31
31
  1. `\tests` folder: This include sample test cases for [SauceLabs](https://www.saucedemo.com/v1/)
32
32
  2. `.env` file: Your starting .env file. You can set the BASE_URL to your own site after you're done with the scaffold tests.
33
33
  5. There are two ways to start testing:
34
- 1. By running the server. Run:<br/> `plum start to start the server`
34
+ 1. By running the server. Run:<br/> `plum start` to start the server
35
+ 1. Access the UI at: http://localhost:5173/
35
36
  2. Without running the server. Recommended while you're writing your tests. Run:<br/> `plum dev <@test-id>`. If no test ID is included, it will run all tests
36
37
 
37
38
  ## Basic Structure
@@ -49,8 +50,8 @@ After you run `plum init`, these files will be created inside your project direc
49
50
 
50
51
  ## Tutorial
51
52
 
52
- 1. For a complete guide on how to write tests, visit our [Wiki](https://github.com/silverlunah/plum/wiki)
53
- 2. An easy way to learn is to check the scaffold files starting from the Feature files -> Step Definitions -> Page files and utils/hooks.js for the CustomWorld and Before hook page class initialization. Those are the main files you need to write a test case.
53
+ 1. For a complete guide on how to write tests, visit our [Coming Soon](https://github.com/silverlunah/plum/wiki)
54
+ 2. An easy way to learn is to check the scaffold files starting from the Feature files -> Step Definitions -> Page files and utils/world.ts for the CustomWorld initialization. Those are the main files you need to write a test case.
54
55
 
55
56
  ## For Developers/Contributors
56
57
 
@@ -63,4 +64,4 @@ For people that want to contribute to the project
63
64
 
64
65
  ## Other
65
66
 
66
- Plum is completely free to use! But if you want to share some love, here's my [PayPal](https://www.paypal.me/silverlunah) or [Wise](<[https://www.paypal.me/silverlunah](https://wise.com/pay/me/janneserjosee)>)
67
+ Plum is completely free to use! But if you want to share some love, here's my [PayPal](https://www.paypal.me/silverlunah) or [Wise](https://wise.com/pay/me/janneserjosee)
@@ -0,0 +1,24 @@
1
+ // loginPage.ts
2
+ import test, { Page } from '@playwright/test';
3
+ import { SAMPLE_CONSTANT } from '../utils/constants';
4
+ import { Utils } from '../utils/utils';
5
+
6
+ export class LoginPage {
7
+ private page: Page;
8
+ private utils: Utils;
9
+
10
+ constructor(page: Page) {
11
+ this.page = page;
12
+ this.utils = new Utils(this.page);
13
+ }
14
+
15
+ async goToLoginPage() {
16
+ console.log(SAMPLE_CONSTANT);
17
+ await this.utils.goToPage(process.env.BASE_URL as string);
18
+ await this.page.waitForTimeout(3000);
19
+ }
20
+
21
+ async skipTest() {
22
+ test.skip();
23
+ }
24
+ }
@@ -1,4 +1,4 @@
1
- const { Given, When, Then } = require('@cucumber/cucumber');
1
+ import { Given } from '@cucumber/cucumber';
2
2
 
3
3
  Given('I am in Demo Sauce Login page', async function () {
4
4
  await this.loginPage.goToLoginPage();
@@ -0,0 +1 @@
1
+ export const SAMPLE_CONSTANT = 'this is a constant';
@@ -0,0 +1,36 @@
1
+ import { Before, After, setWorldConstructor, ITestCaseHookParameter } from '@cucumber/cucumber';
2
+ import { chromium } from 'playwright';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { CustomWorld } from './world';
6
+ import dotenv from 'dotenv';
7
+
8
+ dotenv.config();
9
+ setWorldConstructor(CustomWorld);
10
+
11
+ Before(async function (this: CustomWorld) {
12
+ const isHeadless = process.env.IS_HEADLESS?.toLowerCase() !== 'false';
13
+
14
+ this.browser = await chromium.launch({ headless: isHeadless });
15
+ this.context = await this.browser.newContext();
16
+ this.page = await this.context.newPage();
17
+
18
+ this.initPages(this.page);
19
+ });
20
+
21
+ After(async function (this: CustomWorld, scenario: ITestCaseHookParameter) {
22
+ if (scenario.result?.status === 'FAILED' && this.page) {
23
+ const screenshotDir = path.join('reports', 'screenshots');
24
+ if (!fs.existsSync(screenshotDir)) {
25
+ fs.mkdirSync(screenshotDir, { recursive: true });
26
+ }
27
+
28
+ const screenshotPath = path.join(screenshotDir, `screenshot_${Date.now()}.png`);
29
+ await this.page.screenshot({ path: screenshotPath });
30
+
31
+ const screenshotData = fs.readFileSync(screenshotPath);
32
+ await this.attach(screenshotData, 'image/png');
33
+ }
34
+
35
+ await this.browser?.close();
36
+ });
@@ -0,0 +1,13 @@
1
+ import { Page } from '@playwright/test';
2
+
3
+ export class Utils {
4
+ private page: Page;
5
+
6
+ constructor(page: Page) {
7
+ this.page = page;
8
+ }
9
+
10
+ async goToPage(url: string) {
11
+ await this.page.goto(url);
12
+ }
13
+ }
@@ -0,0 +1,25 @@
1
+ import { IWorldOptions, setWorldConstructor, World } from '@cucumber/cucumber';
2
+ import { Browser, Page, BrowserContext } from 'playwright';
3
+ import { LoginPage } from '../pages/LoginPage';
4
+ import { Utils } from './utils';
5
+
6
+ export class CustomWorld extends World {
7
+ browser!: Browser;
8
+ context!: BrowserContext;
9
+ page!: Page;
10
+
11
+ loginPage!: LoginPage;
12
+ utils!: Utils;
13
+
14
+ constructor(options: IWorldOptions) {
15
+ super(options);
16
+ }
17
+
18
+ initPages(page: Page) {
19
+ this.utils = new Utils(page);
20
+ this.loginPage = new LoginPage(page);
21
+ // Add other pages here
22
+ }
23
+ }
24
+
25
+ setWorldConstructor(CustomWorld);
@@ -16,19 +16,32 @@
16
16
  */
17
17
 
18
18
  const { execSync } = require('child_process');
19
- const tag = process.env.TAG; // Read the TAG environment variable
19
+ const tag = process.env.TAG;
20
20
 
21
21
  try {
22
- // Run the tests with the tag filter, only if a tag is provided
23
- const cucumberCommand = tag
24
- ? `cucumber-js tests/features/**/*.feature --format json:reports/cucumber_report.json --tags "${tag}"`
25
- : `cucumber-js tests/features/**/*.feature --format json:reports/cucumber_report.json`;
22
+ const baseCommand = [
23
+ 'npx',
24
+ 'cross-env',
25
+ 'TS_NODE_TRANSPILE_ONLY=true',
26
+ 'cucumber-js',
27
+ 'tests/features/**/*.feature',
28
+ '--require-module',
29
+ 'ts-node/register',
30
+ '--require',
31
+ 'tests/step_definitions/**/*.ts',
32
+ '--format',
33
+ 'json:reports/cucumber_report.json'
34
+ ];
26
35
 
36
+ if (tag) {
37
+ baseCommand.push('--tags', `"${tag}"`);
38
+ }
39
+
40
+ const cucumberCommand = baseCommand.join(' ');
27
41
  execSync(cucumberCommand, { stdio: 'inherit' });
28
42
  } catch (error) {
29
43
  console.error('Tests failed:', error.message);
30
44
  } finally {
31
- // Always run the report generation after tests (even if they fail)
32
45
  try {
33
46
  execSync('node config/scripts/generate-report.js', { stdio: 'inherit' });
34
47
  } catch (error) {
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "default": {
3
- "require": ["tests/step_definitions/*.js", "tests/utils/hooks.js"],
4
- "featurePaths": ["tests/features/**/*.feature"]
3
+ "require": ["tests/step_definitions/*.ts", "tests/utils/hooks.ts"],
4
+ "featurePaths": ["tests/features/**/*.feature"],
5
+ "requireModule": ["ts-node/register"]
5
6
  }
6
7
  }