Skip to content

Commit 4f2f7f0

Browse files
authored
Merge pull request #13 from jerseysu/test-page-object
feat(IndexPage.ts): intro the page object pattern for the e2e test
2 parents 15a92ae + 2e784f5 commit 4f2f7f0

File tree

8 files changed

+154
-9
lines changed

8 files changed

+154
-9
lines changed

src/pages/Login.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ const Login = () => {
4040
id="email"
4141
label="Email Address"
4242
name="email"
43+
data-testid="email"
4344
autoFocus
45+
type="textbox"
4446
value={email}
4547
onChange={(e) => setEmail(e.target.value)}
4648
/>
@@ -51,8 +53,9 @@ const Login = () => {
5153
fullWidth
5254
id="password"
5355
name="password"
56+
data-testid="password"
5457
label="Password"
55-
type="password"
58+
type="textbox"
5659
value={password}
5760
onChange={(e) => {
5861
setPassword(e.target.value);
@@ -61,6 +64,7 @@ const Login = () => {
6164

6265
<Button
6366
component={Link}
67+
data-testid="loginButton"
6468
fullWidth
6569
to="/home"
6670
variant="contained"
@@ -71,7 +75,7 @@ const Login = () => {
7175

7276
<Grid container justifyContent={"flex-end"}>
7377
<Grid item>
74-
<Link to="/register">Don't have an account? Register</Link>
78+
<Link to="/register" data-testid="registerLink">Don't have an account? Register</Link>
7579
</Grid>
7680
</Grid>
7781
</Box>

src/pages/LoginSuccess.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const LoginSuccess = () => {
2424
<Avatar sx={{ m: 1, bgcolor: "primary.light" }}>
2525
<CheckCircle />
2626
</Avatar>
27-
<Typography variant="h5">LoginSuccess</Typography>
27+
<Typography variant="h5" data-testid='loginMessage'>LoginSuccess</Typography>
2828
<Link to="/">
2929
<img src="https://scontent.ftpe7-4.fna.fbcdn.net/v/t1.18169-9/998025_10151520012340920_1273035109_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=f798df&_nc_ohc=_HN2ki-NJdwQ7kNvgFA9NKO&_nc_ht=scontent.ftpe7-4.fna&oh=00_AYATB7lOPZlc2v0mq6-2OMdFrSwCoL3zV_-IVmRF3kUUjg&oe=66B450BD" alt="Jersey" width="500" height="600"></img>
3030
</Link>

src/pages/Register.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const Register = () => {
4242
fullWidth
4343
id="name"
4444
label="Name"
45+
data-testid="name"
4546
autoFocus
4647
value={name}
4748
onChange={(e) => setName(e.target.value)}
@@ -54,6 +55,7 @@ const Register = () => {
5455
fullWidth
5556
id="email"
5657
label="Email Address"
58+
data-testid="email"
5759
name="email"
5860
value={email}
5961
onChange={(e) => setEmail(e.target.value)}
@@ -65,7 +67,8 @@ const Register = () => {
6567
fullWidth
6668
name="password"
6769
label="Password"
68-
type="password"
70+
type="textbox"
71+
data-testid="password"
6972
id="password"
7073
value={password}
7174
onChange={(e) => setPassword(e.target.value)}
@@ -75,6 +78,7 @@ const Register = () => {
7578

7679
<Button
7780
component={Link}
81+
data-testid="registerButton"
7882
fullWidth
7983
to="/home"
8084
variant="contained"
@@ -85,7 +89,7 @@ const Register = () => {
8589

8690
<Grid container justifyContent="flex-end">
8791
<Grid item>
88-
<Link to="/login">Already have an account? Login</Link>
92+
<Link to="/login" data-testid="loginLink">Already have an account? Login</Link>
8993
</Grid>
9094
</Grid>
9195
</Box>

tests/indexPage.spec.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
import { test, expect } from '@playwright/test';
2+
import { IndexPage } from './pages/indexPage';
3+
import { WelcomePage } from './pages/welcomePage';
24

3-
test('has title', async ({ page }) => {
4-
await page.goto('/playwright-demo');
5+
test.describe('Login Page', () => {
6+
test('has title', async ({ page }) => {
7+
const indexPage = new IndexPage(page);
8+
await indexPage.goto();
59

6-
// Expect a title "to contain" a substring.
7-
await expect(page).toHaveTitle(/Jersey's Login Page/);
10+
// Expect a title "to contain" a substring.
11+
await expect(page).toHaveTitle(/Jersey's Login Page/);
12+
});
13+
14+
test('do login', async ({ page }) => {
15+
const indexPage = new IndexPage(page);
16+
await indexPage.goto();
17+
await indexPage.loginAction();
18+
19+
const welcomePage = new WelcomePage(page);
20+
const welcomeMsgText = await welcomePage.getWelcomeMsgText();
21+
22+
// Expect a welcome message LoginSuccess
23+
await expect(welcomeMsgText).toContain('LoginSuccess');
24+
});
825
});

tests/pages/indexPage.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { expect, type Locator, type Page } from '@playwright/test';
2+
3+
export class IndexPage {
4+
readonly page: Page;
5+
readonly email: Locator;
6+
readonly password: Locator;
7+
readonly loginButton: Locator;
8+
readonly registerLink: Locator;
9+
10+
constructor(page: Page) {
11+
this.page = page;
12+
this.email = page.locator('div[data-testid="email"] input');
13+
this.password = page.locator('div[data-testid="password"] input');
14+
this.loginButton = page.locator('a[data-testid="loginButton"]');
15+
this.registerLink = page.locator('a[data-testid="registerLink"]');
16+
}
17+
18+
async goto() {
19+
await this.page.goto('/react-playwright-demo');
20+
}
21+
22+
async fillEmail() {
23+
await this.email.fill('[email protected]');
24+
await expect(this.email).toBeVisible();
25+
}
26+
27+
async fillPassword() {
28+
// TODO: use the secret service.
29+
await this.password.fill('');
30+
await expect(this.password).toBeVisible();
31+
}
32+
33+
async loginAction() {
34+
await this.fillEmail();
35+
await this.fillPassword();
36+
await this.loginButton.click();
37+
}
38+
}

tests/pages/registerPage.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { expect, type Locator, type Page } from '@playwright/test';
2+
3+
export class RegisterPage {
4+
readonly page: Page;
5+
readonly name: Locator;
6+
readonly email: Locator;
7+
readonly password: Locator;
8+
readonly registerButton: Locator;
9+
readonly loginLink: Locator;
10+
11+
constructor(page: Page) {
12+
this.page = page;
13+
this.name = page.locator('div[data-testid="name"] input');
14+
this.email = page.locator('div[data-testid="email"] input');
15+
this.password = page.locator('div[data-testid="password"] input');
16+
this.registerButton = page.locator('a[data-testid="registerButton"]');
17+
this.loginLink = page.locator('a[data-testid="loginLink"]');
18+
}
19+
20+
async goto() {
21+
await this.page.goto('/react-playwright-demo/register');
22+
}
23+
24+
async fillName() {
25+
await this.name.fill('JerseyAwesome');
26+
await expect(this.name).toBeVisible();
27+
}
28+
29+
async fillEmail() {
30+
await this.email.fill('[email protected]');
31+
await expect(this.email).toBeVisible();
32+
}
33+
34+
async fillPassword() {
35+
// TODO: use the secret service.
36+
await this.password.fill('');
37+
await expect(this.password).toBeVisible();
38+
}
39+
40+
async registerAction() {
41+
await this.fillName();
42+
await this.fillEmail();
43+
await this.fillPassword();
44+
await this.registerButton.click();
45+
}
46+
}

tests/pages/welcomePage.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { type Locator, type Page } from '@playwright/test';
2+
3+
export class WelcomePage {
4+
readonly page: Page;
5+
readonly welcomeMsg: Locator;
6+
7+
constructor(page: Page) {
8+
this.page = page;
9+
this.welcomeMsg = page.locator('h5[data-testid="loginMessage"]');
10+
}
11+
12+
async goto() {
13+
await this.page.goto('/react-playwright-demo/home');
14+
}
15+
16+
async getWelcomeMsgText() {
17+
return await this.welcomeMsg.innerText();
18+
}
19+
}

tests/registerPage.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { test, expect } from '@playwright/test';
2+
import { RegisterPage } from './pages/registerPage';
3+
import { WelcomePage } from './pages/welcomePage';
4+
5+
test.describe('Register Page', () => {
6+
test('do register', async ({ page }) => {
7+
const registerPage = new RegisterPage(page);
8+
await registerPage.goto();
9+
await registerPage.registerAction();
10+
11+
const welcomePage = new WelcomePage(page);
12+
const welcomeMsgText = await welcomePage.getWelcomeMsgText();
13+
14+
// Expect a welcome message LoginSuccess
15+
await expect(welcomeMsgText).toContain('LoginSuccess');
16+
});
17+
});

0 commit comments

Comments
 (0)