Skip to content

Commit 1ecf587

Browse files
authored
[MOB-12017] playwright initial setup (#534)
* install playwright * set playwright config * initial build out of page objects * resolve lint error * rename AUT to UUA * add readme
1 parent 1483ef5 commit 1ecf587

23 files changed

+1578
-1655
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ This SDK helps you integrate your web apps with Iterable.
1818
- [FAQ](#faq)
1919
- [Link handling](#link-handling)
2020
- [TypeScript](#typescript)
21+
- [Development and Testing](#development-and-testing)
2122
- [Contributing](#contributing)
2223
- [License](#license)
2324

@@ -2706,6 +2707,39 @@ Request and response payloads should all be available.
27062707

27072708
If something is missing, please let us know.
27082709

2710+
# Development and Testing
2711+
2712+
## React Example Application
2713+
2714+
This repository includes a React example application that demonstrates the Web SDK's functionality. The example app is located in the `react-example/` directory and includes:
2715+
2716+
- Sample implementation of all major SDK features
2717+
- Interactive UI for testing API endpoints
2718+
- Complete integration examples for in-app messaging, embedded messages, and more
2719+
2720+
To run the example application:
2721+
2722+
```bash
2723+
cd react-example
2724+
yarn install
2725+
yarn start
2726+
```
2727+
2728+
## E2E Testing
2729+
2730+
The React example application includes comprehensive end-to-end tests using Playwright. These tests validate the SDK's functionality in a real browser environment.
2731+
2732+
📖 **For detailed instructions on running and writing E2E tests, see the [E2E Testing Guide](./react-example/e2e/README.md).**
2733+
2734+
Quick start:
2735+
```bash
2736+
cd react-example
2737+
yarn install
2738+
yarn playwright:install
2739+
yarn start # In one terminal
2740+
yarn playwright # In another terminal
2741+
```
2742+
27092743
# Contributing
27102744

27112745
Looking to contribute? Please see the [contributing instructions here](./CONTRIBUTING.md)

react-example/.eslintrc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,26 @@
33
"rules": {
44
"@typescript-eslint/no-empty-interface": "off",
55
"import/no-unresolved": "off",
6-
"react/react-in-jsx-scope": "off"
6+
"react/react-in-jsx-scope": "off",
7+
"import/no-extraneous-dependencies": ["error", {
8+
"devDependencies": [
9+
"**/*.test.ts",
10+
"**/*.test.tsx",
11+
"**/*.spec.ts",
12+
"**/*.spec.tsx",
13+
"**/playwright.config.ts",
14+
"**/jest.config.js",
15+
"**/webpack.config.js",
16+
"**/webpack.*.js",
17+
"e2e/**/*",
18+
"**/e2e/**/*"
19+
]
20+
}]
21+
},
22+
"settings": {
23+
"react": {
24+
"version": "detect"
25+
}
726
},
827
"ignorePatterns": ["node_modules/"]
928
}

react-example/e2e/README.md

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
# E2E Testing with Playwright
2+
3+
This directory contains end-to-end (E2E) tests for the Iterable Web SDK React example application using [Playwright](https://playwright.dev/).
4+
5+
## Table of Contents
6+
7+
- [Prerequisites](#prerequisites)
8+
- [Installation](#installation)
9+
- [Running Tests](#running-tests)
10+
- [Test Structure](#test-structure)
11+
- [Page Object Model](#page-object-model)
12+
- [Configuration](#configuration)
13+
- [Writing New Tests](#writing-new-tests)
14+
- [Debugging Tests](#debugging-tests)
15+
- [CI/CD](#cicd)
16+
17+
## Prerequisites
18+
19+
Before running the E2E tests, ensure you have:
20+
21+
1. **Node.js**: Version 18.12.0 or higher (as specified in `package.json`)
22+
2. **React Example App Running**: The tests expect the application to be running on `http://localhost:8080`
23+
24+
## Installation
25+
26+
1. **Start the sample app** (from the SDK root directory):
27+
```bash
28+
yarn install:all && yarn start:all:react
29+
```
30+
This starts both the SDK and React sample app. Navigate to `http://localhost:8080` in your browser.
31+
32+
> **Note**: If port 8080 is taken, the app will run on the next available port (8081, 8082, etc.). Check the compilation logs for the specific port.
33+
34+
2. **Install Playwright browsers** (from the `react-example` directory):
35+
```bash
36+
yarn playwright:install
37+
```
38+
39+
## Running Tests
40+
41+
### Run E2E Tests
42+
43+
Once the application is running, you can execute the tests:
44+
45+
```bash
46+
# Run all tests headlessly
47+
yarn playwright
48+
49+
# Run tests with UI mode (interactive)
50+
yarn playwright:ui
51+
52+
# Run tests in debug mode
53+
yarn playwright:debug
54+
55+
# Run specific test file
56+
yarn playwright authentication.spec.ts
57+
58+
# Run tests in a specific browser
59+
yarn playwright --project=chromium
60+
```
61+
62+
## Test Structure
63+
64+
The E2E tests are organized as follows:
65+
66+
```
67+
e2e/
68+
├── README.md # This file
69+
├── authentication.spec.ts # Authentication and navigation tests
70+
├── uua-testing.spec.ts # UUA (User Update Actions) testing page tests
71+
└── page-objects/ # Page Object Model implementation
72+
├── BasePage.ts # Base page with common functionality
73+
├── components/ # Reusable component objects
74+
│ ├── LoginForm.ts # Login form interactions
75+
│ └── Navigation.ts # Navigation component interactions
76+
└── pages/ # Page-specific objects
77+
├── EmbeddedMsgsPage.ts # Embedded messages page
78+
├── EmbeddedPage.ts # Embedded page
79+
└── UUATestingPage.ts # UUA testing page
80+
```
81+
82+
## Page Object Model
83+
84+
This project uses the Page Object Model (POM) pattern to organize test code:
85+
86+
### BasePage
87+
- **Location**: `page-objects/BasePage.ts`
88+
- **Purpose**: Contains common functionality shared across all pages
89+
- **Features**: Cookie consent handling, page loading utilities, navigation access
90+
91+
### Components
92+
- **Navigation**: Handles navigation between different sections of the app
93+
- **LoginForm**: Manages user authentication flows
94+
95+
### Pages
96+
- **UUATestingPage**: Handles interactions with the UUA testing endpoints
97+
- **EmbeddedMsgsPage**: Manages embedded messages functionality
98+
- **EmbeddedPage**: Handles embedded message display and interactions
99+
100+
## Configuration
101+
102+
The Playwright configuration is defined in `playwright.config.ts` (in the `react-example` root):
103+
104+
### Key Settings:
105+
- **Base URL**: `http://localhost:8080`
106+
- **Test Directory**: `./e2e`
107+
- **Browsers**: Chromium, Firefox, WebKit
108+
- **Retry Strategy**: 2 retries on CI, 0 locally
109+
- **Test ID Attribute**: `data-test`
110+
- **Screenshots**: On failure only
111+
- **Video**: On first retry
112+
- **Trace**: On first retry
113+
114+
### Timeouts:
115+
- **Action Timeout**: 10 seconds
116+
- **Navigation Timeout**: 30 seconds
117+
118+
## Writing New Tests
119+
120+
### 1. Create a Test File
121+
122+
Create a new `.spec.ts` file in the `e2e` directory:
123+
124+
```typescript
125+
import { test, expect } from '@playwright/test';
126+
import { YourPageObject } from './page-objects/pages/YourPageObject';
127+
128+
test.describe('Your Feature', () => {
129+
let yourPage: YourPageObject;
130+
131+
test.beforeEach(async ({ page }) => {
132+
yourPage = new YourPageObject(page);
133+
await yourPage.goto();
134+
await yourPage.acceptCookies();
135+
});
136+
137+
test('should do something', async () => {
138+
// Your test logic here
139+
});
140+
});
141+
```
142+
143+
### 2. Create Page Objects
144+
145+
If testing a new page, create a corresponding page object:
146+
147+
```typescript
148+
// page-objects/pages/YourPageObject.ts
149+
import { Page, Locator, expect } from '@playwright/test';
150+
import { BasePage } from '../BasePage';
151+
152+
export class YourPageObject extends BasePage {
153+
readonly yourElement: Locator;
154+
155+
constructor(page: Page) {
156+
super(page);
157+
this.yourElement = page.getByTestId('your-element');
158+
}
159+
160+
async goto() {
161+
await this.page.goto('/your-route');
162+
await this.waitForPageLoad();
163+
}
164+
165+
async performAction() {
166+
await this.yourElement.click();
167+
}
168+
}
169+
```
170+
171+
### 3. Best Practices
172+
173+
- **Use `data-test` attributes** for element selection
174+
- **Extend BasePage** for new page objects
175+
- **Handle cookie consent** in `beforeEach` hooks
176+
- **Use meaningful test descriptions**
177+
- **Group related tests** in `describe` blocks
178+
- **Wait for elements** to be visible before interacting
179+
180+
## Debugging Tests
181+
182+
### Debug Mode
183+
```bash
184+
yarn playwright:debug
185+
```
186+
This opens the Playwright Inspector, allowing you to step through tests.
187+
188+
### UI Mode
189+
```bash
190+
yarn playwright:ui
191+
```
192+
Provides an interactive UI to run and debug tests.
193+
194+
### View Test Reports
195+
After running tests, view the HTML report:
196+
```bash
197+
npx playwright show-report
198+
```
199+
200+
### Screenshots and Videos
201+
Failed tests automatically capture:
202+
- Screenshots (in `test-results/`)
203+
- Videos (on retry)
204+
- Traces (on retry)
205+
206+
## CI/CD
207+
208+
The configuration is optimized for CI environments:
209+
210+
- **Parallel Execution**: Disabled on CI for stability
211+
- **Retries**: 2 retries on CI
212+
- **Fail Fast**: Tests fail if `test.only` is left in code
213+
- **Reporters**: HTML reports for detailed results
214+
215+
### Environment Variables
216+
- `CI`: Enables CI-specific settings when set to any truthy value
217+
218+
## Troubleshooting
219+
220+
### Common Issues
221+
222+
1. **Application not running**: Ensure the sample app is running and accessible at `http://localhost:8080`
223+
224+
2. **Timeouts**: If tests are timing out, check if the application is responsive and consider increasing timeout values
225+
226+
3. **Element not found**: Verify that `data-test` attributes exist on the target elements
227+
228+
4. **Browser installation**: Run `yarn playwright:install` if browsers are missing
229+
230+
### Getting Help
231+
232+
- Check the [Playwright documentation](https://playwright.dev/docs/intro)
233+
- Review existing test files for patterns and examples
234+
- Use `playwright:debug` mode to step through failing tests
235+
236+
## Available Test Scripts
237+
238+
From the `react-example` directory:
239+
240+
```bash
241+
yarn playwright # Run all tests headlessly
242+
yarn playwright:ui # Run with interactive UI
243+
yarn playwright:debug # Run in debug mode
244+
yarn playwright:install # Install Playwright browsers
245+
```
246+
247+
## Test Coverage
248+
249+
Current test files cover:
250+
251+
- **Authentication flows** (`authentication.spec.ts`)
252+
- **UUA testing endpoints** (`uua-testing.spec.ts`)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { test, expect } from '@playwright/test';
2+
import { BasePage } from './page-objects/BasePage';
3+
4+
test.describe('Authentication and Navigation', () => {
5+
let basePage: BasePage;
6+
7+
test.beforeEach(async ({ page }) => {
8+
basePage = new BasePage(page);
9+
await basePage.goto();
10+
});
11+
12+
test('should handle email input correctly', async () => {
13+
const testEmail = '[email protected]';
14+
15+
await basePage.loginForm.enterEmail(testEmail);
16+
await expect(basePage.loginForm.emailInput).toHaveValue(testEmail);
17+
});
18+
19+
test('should display all navigation links', async () => {
20+
await basePage.navigation.isNavigationVisible();
21+
});
22+
23+
test('should navigate to all sections correctly', async () => {
24+
await basePage.navigation.navigateToCommerce();
25+
await basePage.navigation.navigateToEvents();
26+
await basePage.navigation.navigateToUsers();
27+
await basePage.navigation.navigateToInApp();
28+
await basePage.navigation.navigateToEmbeddedMsgs();
29+
await basePage.navigation.navigateToEmbedded();
30+
await basePage.navigation.navigateToUUATesting();
31+
await basePage.navigation.navigateToHome();
32+
});
33+
34+
test('should maintain login state across navigation', async () => {
35+
const testEmail = '[email protected]';
36+
37+
// Enter email and attempt login
38+
await basePage.loginForm.loginWithEmail(testEmail);
39+
40+
// Navigate to different sections
41+
await basePage.navigation.navigateToCommerce();
42+
await basePage.navigation.navigateToHome();
43+
44+
// Verify email is still in the input field
45+
await expect(basePage.loginForm.emailInput).toHaveValue(testEmail);
46+
47+
// Verify error message is still visible
48+
const isErrorVisible = await basePage.loginForm.isErrorMessageVisible();
49+
expect(isErrorVisible).toBeTruthy();
50+
});
51+
});

0 commit comments

Comments
 (0)