-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathprofile.spec.ts
More file actions
153 lines (128 loc) · 6.43 KB
/
Copy pathprofile.spec.ts
File metadata and controls
153 lines (128 loc) · 6.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { expect, test } from '@playwright/test';
import { VendureAdminClient } from '../../utils/vendure-admin-client.js';
test.describe('Profile', () => {
test('should display profile page with form fields', async ({ page }) => {
await page.goto('/profile');
await expect(page.getByTestId('page-heading')).toBeVisible();
// Verify form fields are present
await expect(page.getByText('First name')).toBeVisible();
await expect(page.getByText('Last name')).toBeVisible();
await expect(page.getByText('Email Address or identifier')).toBeVisible();
// "Password" appears as both a field label and an auth method badge,
// so scope to the field label to avoid strict mode violation
await expect(page.locator('[data-slot="field-label"]').getByText('Password')).toBeVisible();
// Verify Update button is present
await expect(page.getByRole('button', { name: 'Update' })).toBeVisible();
});
test('should update first name and persist', async ({ page }) => {
await page.goto('/profile');
await expect(page.getByTestId('page-heading')).toBeVisible();
// Find the first name input via field label
const firstNameField = page.locator('[data-slot="field"]').filter({
has: page.locator('[data-slot="field-label"]').getByText('First name', { exact: true }),
});
const firstNameInput = firstNameField.getByRole('textbox');
await expect(firstNameInput).toBeVisible();
// Store original value
const originalValue = await firstNameInput.inputValue();
// Set a new value
const newValue = originalValue === 'TestFirstName' ? 'Super' : 'TestFirstName';
await firstNameInput.fill(newValue);
// Click Update
await page.getByRole('button', { name: 'Update' }).click();
await expect(
page
.locator('[data-sonner-toast]')
.filter({ hasText: /updated/i })
.first(),
).toBeVisible({ timeout: 10_000 });
// Reload and verify persistence
await page.reload();
await expect(page.getByTestId('page-heading')).toBeVisible();
const reloadedField = page.locator('[data-slot="field"]').filter({
has: page.locator('[data-slot="field-label"]').getByText('First name', { exact: true }),
});
await expect(reloadedField.getByRole('textbox')).toHaveValue(newValue);
// Reset to original value
await reloadedField.getByRole('textbox').fill(originalValue);
await page.getByRole('button', { name: 'Update' }).click();
await expect(
page
.locator('[data-sonner-toast]')
.filter({ hasText: /updated/i })
.first(),
).toBeVisible({ timeout: 10_000 });
});
test('should show Update button disabled when no changes', async ({ page }) => {
await page.goto('/profile');
await expect(page.getByTestId('page-heading')).toBeVisible();
// The Update button should be disabled when no changes have been made
const updateButton = page.getByRole('button', { name: 'Update' });
await expect(updateButton).toBeDisabled();
// Make a change to enable the button
const firstNameField = page.locator('[data-slot="field"]').filter({
has: page.locator('[data-slot="field-label"]').getByText('First name', { exact: true }),
});
const firstNameInput = firstNameField.getByRole('textbox');
const originalValue = await firstNameInput.inputValue();
await firstNameInput.fill(originalValue + 'x');
// Button should now be enabled
await expect(updateButton).toBeEnabled();
// Reset to original value (don't submit)
await firstNameInput.fill(originalValue);
});
// #5037 — an admin without UpdateAdministrator permission must still be able to
// edit their own profile (the page uses updateActiveAdministrator, gated by Owner)
test('should allow an admin without UpdateAdministrator permission to update own profile', async ({
page,
browser,
}) => {
const suffix = Date.now();
const emailAddress = `restricted-${suffix}@test.com`;
const password = 'test-password';
const client = new VendureAdminClient(page);
await client.login();
const { createRole } = await client.gql(
`mutation ($input: CreateRoleInput!) { createRole(input: $input) { id } }`,
{
input: {
code: `restricted-${suffix}`,
description: 'No admin permissions',
permissions: ['ReadCatalog'],
},
},
);
await client.gql(
`mutation ($input: CreateAdministratorInput!) { createAdministrator(input: $input) { id } }`,
{
input: {
firstName: 'Restricted',
lastName: 'Admin',
emailAddress,
password,
roleIds: [createRole.id],
},
},
);
// Fresh context so we browse as the restricted admin, not the superadmin
const context = await browser.newContext({ storageState: { cookies: [], origins: [] } });
const restrictedPage = await context.newPage();
await restrictedPage.goto('/login');
await restrictedPage.getByPlaceholder('Email').fill(emailAddress);
await restrictedPage.getByPlaceholder('Password').fill(password);
await restrictedPage.getByRole('button', { name: 'Sign in' }).click();
await expect(restrictedPage).not.toHaveURL(/\/login/, { timeout: 15_000 });
await restrictedPage.goto('/profile');
const firstNameField = restrictedPage.locator('[data-slot="field"]').filter({
has: restrictedPage.locator('[data-slot="field-label"]').getByText('First name', { exact: true }),
});
await firstNameField.getByRole('textbox').fill('Renamed');
await restrictedPage.getByRole('button', { name: 'Update' }).click();
await expect(
restrictedPage.locator('[data-sonner-toast]').filter({ hasText: 'Successfully updated profile' }),
).toBeVisible({ timeout: 10_000 });
await restrictedPage.reload();
await expect(firstNameField.getByRole('textbox')).toHaveValue('Renamed');
await context.close();
});
});