Skip to content

Commit 4e33975

Browse files
Ioan Zîcuioanzicu
authored andcommitted
E2E tests for Admin page: verify elements visibility on the page, add then delete a user
1 parent e6c9730 commit 4e33975

File tree

2 files changed

+198
-0
lines changed

2 files changed

+198
-0
lines changed

frontend/tests/admin.spec.ts

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { expect, test } from "@playwright/test";
2+
import { UserRole, verifyUserRow } from "./utils/admin";
3+
4+
5+
test.describe('Admin Page', () => {
6+
test.beforeEach(async ({ page }) => {
7+
await test.step("Open the admin page", async () => {
8+
await page.goto("/admin")
9+
})
10+
});
11+
12+
test("Admin tab table should be visible", async ({ page }) => {
13+
await test.step('Check elements visibility', async () => {
14+
await expect(page.getByRole('heading', { name: 'Users', level: 1 })).toBeVisible();
15+
await expect(page.getByText('Manage user accounts and permissions')).toBeVisible();
16+
await expect(page.getByRole('button', { name: 'Add User' })).toBeVisible();
17+
await expect(page.locator('th[data-slot="table-head"]')).toHaveText([
18+
'Full Name',
19+
'Email',
20+
'Role',
21+
'Status',
22+
'Actions'
23+
])
24+
});
25+
26+
await test.step('Check the user table', async () => {
27+
await verifyUserRow(page, 'N/A', 'admin@example.com', UserRole.SUPERUSER, 'Active', true);
28+
});
29+
})
30+
31+
32+
test('User Dialog should have all fields visible', async ({ page }) => {
33+
const addUserBtn = page.getByRole('button', { name: 'Add User' });
34+
35+
await test.step("Open the Dialog", async () => {
36+
await expect(addUserBtn).toBeVisible();
37+
await addUserBtn.click();
38+
});
39+
40+
const dialog = page.getByRole('dialog', { name: 'Add User' });
41+
42+
await test.step("Fill Inputs", async () => {
43+
await expect(dialog).toBeVisible();
44+
await expect(page.getByRole('heading', { name: 'Add User', level: 2 })).toBeVisible();
45+
await expect(dialog.getByText('Fill in the form below to add a new user')).toBeVisible();
46+
47+
const fields = ['Email', 'Full Name', 'Set Password', 'Confirm Password'];
48+
for (const field of fields) {
49+
await expect(dialog.getByLabel(field)).toBeVisible();
50+
await expect(dialog.locator('label[data-slot="form-label"]').filter({ hasText: field }))
51+
.toBeVisible();
52+
}
53+
54+
// Checkboxes
55+
await expect(dialog.getByRole('checkbox', { name: 'Is superuser?' })).toBeVisible();
56+
await expect(dialog.getByRole('checkbox', { name: 'Is active?' })).toBeVisible();
57+
});
58+
59+
await test.step("Close the Dialog", async () => {
60+
// Footer Buttons
61+
const cancelBtn = dialog.getByRole('button', { name: 'Cancel' });
62+
await expect(cancelBtn).toBeVisible();
63+
await expect(dialog.getByRole('button', { name: 'Save' })).toBeVisible();
64+
65+
// Close the dialog
66+
await cancelBtn.click();
67+
// Check if Add User button is visible after closing the dialog
68+
await expect(addUserBtn).toBeVisible();
69+
});
70+
});
71+
72+
73+
test('User Dialog should have all error fields visible', async ({ page }) => {
74+
const addUserBtn = page.getByRole('button', { name: 'Add User' });
75+
76+
await test.step("Open the Dialog", async () => {
77+
await expect(addUserBtn).toBeVisible();
78+
await addUserBtn.click();
79+
});
80+
81+
const dialog = page.getByRole('dialog', { name: 'Add User' });
82+
83+
await test.step("Trigger error messages", async () => {
84+
await expect(dialog).toBeVisible();
85+
86+
// Trigger error messages by clicking on input field
87+
await dialog.getByLabel('Email').click();
88+
await dialog.getByLabel('Set Password').click();
89+
await dialog.getByLabel('Confirm Password').click();
90+
91+
// Click Save to trigger error message on 'Confirm Password' field
92+
const saveBtn = dialog.getByRole('button', { name: 'Save' });
93+
await saveBtn.click();
94+
95+
// Check the error messages
96+
await expect(dialog.getByText('Invalid email address')).toBeVisible();
97+
await expect(dialog.getByText('Password is required')).toBeVisible();
98+
await expect(dialog.getByText('Please confirm your password')).toBeVisible();
99+
});
100+
101+
await test.step("Close the Dialog", async () => {
102+
const cancelBtn = dialog.getByRole('button', { name: 'Cancel' });
103+
await cancelBtn.click();
104+
// Check if Add User button is visible after closing the dialog
105+
await expect(dialog).toBeHidden();
106+
await expect(addUserBtn).toBeVisible();
107+
});
108+
});
109+
110+
111+
test('Admin should fill out the Add User form, save then delete it', async ({ page }) => {
112+
const email = 'becebal.burebista@example.com';
113+
const fullName = 'Decebal Burebista';
114+
const password = 'SecurePass123!';
115+
116+
const addUserBtn = page.getByRole('button', { name: 'Add User' });
117+
await expect(addUserBtn).toBeVisible();
118+
await addUserBtn.click();
119+
120+
const dialog = page.getByRole('dialog', { name: 'Add User' });
121+
await expect(dialog).toBeVisible();
122+
123+
await test.step("Fill out text and password fields", async () => {
124+
await dialog.getByLabel('Email').fill(email);
125+
await dialog.getByLabel('Full Name').fill(fullName);
126+
await dialog.locator('input[name="password"]').fill(password);
127+
await dialog.locator('input[name="confirm_password"]').fill(password);
128+
129+
// Toggle Checkboxes
130+
const superuserCheckbox = dialog.getByRole('checkbox', { name: 'Is superuser?' });
131+
const activeCheckbox = dialog.getByRole('checkbox', { name: 'Is active?' });
132+
133+
await superuserCheckbox.check();
134+
await activeCheckbox.check();
135+
136+
// Verify the data was entered correctly before saving
137+
await expect(dialog.getByLabel('Email')).toHaveValue(email);
138+
await expect(dialog.getByLabel('Full Name')).toHaveValue(fullName);
139+
await expect(dialog.getByLabel('Set Password')).toHaveValue(password);
140+
await expect(dialog.getByLabel('Confirm Password')).toHaveValue(password);
141+
await expect(superuserCheckbox).toBeChecked();
142+
await expect(activeCheckbox).toBeChecked();
143+
});
144+
145+
await test.step("Save the User", async () => {
146+
const saveButton = dialog.getByRole('button', { name: 'Save' });
147+
await saveButton.click();
148+
149+
// Verify the dialog closes
150+
await expect(dialog).toBeHidden();
151+
await expect(addUserBtn).toBeVisible();
152+
});
153+
154+
await test.step("Check the new user in the user table", async () => {
155+
await verifyUserRow(page, fullName, email, UserRole.SUPERUSER, 'Active');
156+
});
157+
158+
await test.step("Cleanup", async () => {
159+
const userRow = page.getByRole('row').filter({ hasText: email });
160+
161+
// Click the "ellipsis" trigger inside that row
162+
await userRow.getByRole('button', { name: 'menu' }).or(userRow.locator('[data-slot="dropdown-menu-trigger"]')).click();
163+
164+
// Click "Delete User" from the menu that appears globally
165+
await page.getByRole('menuitem', { name: 'Delete User' }).click();
166+
167+
// Confirm the deletion in the resulting dialog
168+
const confirmDialog = page.getByRole('dialog');
169+
await confirmDialog.getByRole('button', { name: 'Delete' }).click();
170+
});
171+
});
172+
});

frontend/tests/utils/admin.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { expect, Page } from "@playwright/test";
2+
3+
export enum UserRole {
4+
SUPERUSER = 'Superuser',
5+
USER = 'User'
6+
}
7+
8+
9+
export async function verifyUserRow(page: Page, name: string, email: string, role: UserRole, status: string, createUser: boolean = false) {
10+
const row = page.getByRole('row').filter({ hasText: name });
11+
await expect(row.getByText(name)).toBeVisible();
12+
13+
if (createUser) {
14+
await expect(row.locator('[data-slot="badge"]', { hasText: 'You' })).toBeVisible();
15+
}
16+
17+
await expect(row.getByText(email)).toBeVisible();
18+
const roleBadge = row.locator('[data-slot="badge"]').filter({ hasText: role });
19+
await expect(roleBadge).toBeVisible();
20+
21+
if (role === UserRole.SUPERUSER) {
22+
await expect(roleBadge).toHaveClass(/bg-primary/);
23+
}
24+
25+
await expect(row.getByText(status)).toBeVisible();
26+
}

0 commit comments

Comments
 (0)