Skip to content

Commit e92c287

Browse files
committed
updates.
1 parent 27de654 commit e92c287

8 files changed

Lines changed: 148 additions & 56 deletions

File tree

e2e/auth/navigation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export async function navigateToUsers(
1616
return test.step('navigate to users', async () => {
1717
await page.goto(buildAuthUrl(region, projectId));
1818
await page.waitForURL(buildAuthUrlPattern(region, projectId));
19-
await page.waitForLoadState('domcontentloaded');
19+
await page.getByRole('heading', { name: 'Auth' }).waitFor({ state: 'visible' });
2020
});
2121
}
2222

@@ -29,7 +29,7 @@ export async function navigateToUser(
2929
return test.step(`navigate to user ${userId}`, async () => {
3030
await page.goto(buildAuthUrl(region, projectId, `/user-${userId}`));
3131
await page.waitForURL(buildAuthUrlPattern(region, projectId, `/user-${userId}`));
32-
await page.waitForLoadState('domcontentloaded');
32+
await page.getByText(userId).first().waitFor({ state: 'visible' });
3333
});
3434
}
3535

e2e/auth/users.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,6 @@ export async function updateUserName(
137137
await nameSection.locator('id=name').fill(newName);
138138
await nameSection.getByRole('button', { name: 'Update' }).click();
139139
await expect(page.getByText(/has been updated/i)).toBeVisible();
140-
141-
await page.reload();
142-
await page.waitForLoadState('domcontentloaded');
143140
await expect(page.locator('input[id="name"]')).toHaveValue(newName);
144141
});
145142
}
@@ -160,9 +157,6 @@ export async function updateUserEmail(
160157
await emailSection.locator('id=email').fill(newEmail);
161158
await emailSection.getByRole('button', { name: 'Update' }).click();
162159
await expect(page.getByText(/has been updated/i)).toBeVisible();
163-
164-
await page.reload();
165-
await page.waitForLoadState('domcontentloaded');
166160
await expect(page.locator('input[id="email"]')).toHaveValue(newEmail);
167161
});
168162
}
@@ -183,9 +177,6 @@ export async function updateUserPhone(
183177
await phoneSection.locator('id=phone').fill(newPhone);
184178
await phoneSection.getByRole('button', { name: 'Update' }).click();
185179
await expect(page.getByText(/has been updated/i)).toBeVisible();
186-
187-
await page.reload();
188-
await page.waitForLoadState('domcontentloaded');
189180
await expect(page.locator('input[id="phone"]')).toHaveValue(newPhone);
190181
});
191182
}
@@ -226,7 +217,7 @@ export async function updateUserStatus(
226217
await expect(page.getByText(/has been (blocked|unblocked)/i)).toBeVisible();
227218

228219
await page.reload();
229-
await page.waitForLoadState('domcontentloaded');
220+
await page.waitForLoadState('networkidle');
230221
if (!enabled) {
231222
await expect(page.getByText('blocked')).toBeVisible();
232223
} else {
@@ -267,9 +258,6 @@ export async function updateUserLabels(
267258
await expect(updateButton).toBeEnabled({ timeout: 5000 });
268259
await updateButton.click();
269260
await expect(page.getByText(/have been updated/i)).toBeVisible();
270-
271-
await page.reload();
272-
await page.waitForLoadState('domcontentloaded');
273261
const reloadedLabelsSection = page.locator('form').filter({
274262
has: page.getByRole('heading', { name: 'Labels' })
275263
});
@@ -363,9 +351,6 @@ export async function updateUserPrefs(
363351

364352
await prefsSection.getByRole('button', { name: 'Update' }).click();
365353
await expect(page.getByText(/Preferences have been updated/i)).toBeVisible();
366-
367-
await page.reload();
368-
await page.waitForLoadState('domcontentloaded');
369354
});
370355
}
371356

@@ -391,9 +376,6 @@ export async function updateUserMfa(
391376
await mfaSection.getByRole('button', { name: 'Update' }).click();
392377
await expect(page.getByText(/Multi-factor authentication has been/i)).toBeVisible();
393378
}
394-
395-
await page.reload();
396-
await page.waitForLoadState('domcontentloaded');
397379
const reloadedMfaSection = page.locator('form').filter({
398380
has: page.getByRole('heading', { name: 'Multi-factor authentication' })
399381
});

e2e/helpers/delete.ts

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { test, type Page, expect } from '@playwright/test';
2+
3+
export async function deleteProject(page: Page, region: string, projectId: string) {
4+
return test.step('delete project', async () => {
5+
await page.goto(`./project-${region}-${projectId}/settings`);
6+
7+
// Get the project name from the data attribute
8+
const projectName = await page.locator('[data-project-name]').textContent();
9+
10+
// Click the Delete button in the CardGrid actions section
11+
await page.getByRole('button', { name: 'Delete', exact: true }).click();
12+
13+
// Wait for modal to open
14+
const dialog = page.locator('dialog[open]');
15+
await expect(dialog).toBeVisible();
16+
17+
// Type the project name to confirm
18+
await dialog.locator('#project-name').fill(projectName?.trim() || '');
19+
20+
// Click the Delete button in the modal
21+
await dialog.getByRole('button', { name: 'Delete', exact: true }).click();
22+
23+
// Wait for navigation back to organization
24+
await page.waitForURL(/\/organization-[^/]+$/);
25+
});
26+
}
27+
28+
export async function deleteOrganization(page: Page, organizationId: string) {
29+
return test.step('delete organization', async () => {
30+
await page.goto(`./organization-${organizationId}/settings`);
31+
32+
// Get the organization name from the data attribute
33+
const organizationName = await page.locator('[data-organization-name]').textContent();
34+
35+
// Click the Delete button in the CardGrid actions section
36+
await page.getByRole('button', { name: 'Delete', exact: true }).click();
37+
38+
// Wait for modal to open
39+
const dialog = page.locator('dialog[open]');
40+
await expect(dialog).toBeVisible();
41+
42+
// Type the organization name to confirm
43+
await dialog.locator('#organization-name').fill(organizationName?.trim() || '');
44+
45+
// Click the Delete button in the modal
46+
await dialog.getByRole('button', { name: 'Delete', exact: true }).click();
47+
48+
// Wait for navigation away from organization (to account/organizations or onboarding)
49+
await page.waitForURL(/\/(account\/organizations|onboarding\/create-organization)/);
50+
});
51+
}
52+
53+
export async function deleteAccount(page: Page) {
54+
return test.step('delete account', async () => {
55+
await page.goto('./account');
56+
57+
// Click the Delete button in the CardGrid actions section
58+
await page.getByRole('button', { name: 'Delete', exact: true }).click();
59+
60+
// Wait for confirm modal to open
61+
const dialog = page.locator('dialog[open]');
62+
await expect(dialog).toBeVisible();
63+
64+
// Click the confirm button in the modal (no name typing required)
65+
await dialog.getByRole('button', { name: 'Delete', exact: true }).click();
66+
67+
// Wait for navigation to login page after account deletion
68+
await page.waitForURL(/login/);
69+
});
70+
}
71+
72+
export async function cleanupTestAccount(
73+
page: Page,
74+
region: string,
75+
projectId: string,
76+
organizationId: string
77+
) {
78+
return test.step('cleanup test account', async () => {
79+
try {
80+
await deleteProject(page, region, projectId);
81+
} catch (error) {
82+
console.log('Failed to delete project:', error);
83+
}
84+
85+
try {
86+
await deleteOrganization(page, organizationId);
87+
} catch (error) {
88+
console.log('Failed to delete organization:', error);
89+
}
90+
91+
try {
92+
await deleteAccount(page);
93+
} catch (error) {
94+
console.log('Failed to delete account:', error);
95+
}
96+
});
97+
}

e2e/journeys/auth-free.spec.ts

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,75 +17,76 @@ import {
1717
deleteUser
1818
} from '../auth/users';
1919
import { navigateToUsers } from '../auth/navigation';
20+
import { cleanupTestAccount } from '../helpers/delete';
2021

2122
test('auth flow - free tier', async ({ page }) => {
2223
await registerUserStep(page);
2324
const project = await createFreeProject(page);
2425

25-
const user = await createUser(page, 'nyc', project.id, {
26+
const user = await createUser(page, project.region, project.id, {
2627
name: 'Test User',
2728
email: 'testuser@example.com',
2829
phone: '+12345678901',
2930
password: 'password123'
3031
});
3132

3233
await test.step('verify user appears in list', async () => {
33-
await navigateToUsers(page, 'nyc', project.id);
34+
await navigateToUsers(page, project.region, project.id);
3435
await expect(page.getByText('Test User')).toBeVisible();
3536
await expect(page.getByText('testuser@example.com')).toBeVisible();
3637
});
3738

38-
const user2 = await createUser(page, 'nyc', project.id, {
39+
const user2 = await createUser(page, project.region, project.id, {
3940
name: 'Second User',
4041
email: 'second@second.com',
4142
password: 'password456'
4243
});
4344

44-
const user3 = await createUser(page, 'nyc', project.id, {
45+
const user3 = await createUser(page, project.region, project.id, {
4546
name: 'Third User',
4647
email: 'third@example.com',
4748
phone: '+13334445555',
4849
password: 'password789'
4950
});
5051

51-
await updateUserName(page, 'nyc', project.id, user.id, 'Updated Test User');
52-
await updateUserEmail(page, 'nyc', project.id, user.id, 'updated@example.com');
53-
await updateUserPhone(page, 'nyc', project.id, user.id, '+19876543210');
54-
await updateUserPassword(page, 'nyc', project.id, user.id, 'newpassword123');
52+
await updateUserName(page, project.region, project.id, user.id, 'Updated Test User');
53+
await updateUserEmail(page, project.region, project.id, user.id, 'updated@example.com');
54+
await updateUserPhone(page, project.region, project.id, user.id, '+19876543210');
55+
await updateUserPassword(page, project.region, project.id, user.id, 'newpassword123');
5556

56-
await updateUserStatus(page, 'nyc', project.id, user.id, false);
57+
await updateUserStatus(page, project.region, project.id, user.id, false);
5758
await test.step('verify blocked status', async () => {
58-
await navigateToUsers(page, 'nyc', project.id);
59+
await navigateToUsers(page, project.region, project.id);
5960
const userRow = page.locator('[role="row"]').filter({ hasText: 'Updated Test User' });
6061
await expect(userRow.getByText('blocked')).toBeVisible();
6162
});
6263

63-
await updateUserStatus(page, 'nyc', project.id, user.id, true);
64+
await updateUserStatus(page, project.region, project.id, user.id, true);
6465
await test.step('verify unblocked status', async () => {
65-
await navigateToUsers(page, 'nyc', project.id);
66+
await navigateToUsers(page, project.region, project.id);
6667
const userRow = page.locator('[role="row"]').filter({ hasText: 'Updated Test User' });
6768
await expect(userRow.getByText('blocked')).not.toBeVisible();
6869
});
6970

70-
await updateUserLabels(page, 'nyc', project.id, user.id, ['test', 'e2e', 'freeTier']);
71+
await updateUserLabels(page, project.region, project.id, user.id, ['test', 'e2e', 'freeTier']);
7172

7273
await test.step('search by name', async () => {
73-
await navigateToUsers(page, 'nyc', project.id);
74+
await navigateToUsers(page, project.region, project.id);
7475
await searchUser(page, 'Updated');
7576
await expect(page.getByText('Updated Test User')).toBeVisible();
7677
await expect(page.getByText('Second User')).not.toBeVisible();
7778
await expect(page.getByText('Third User')).not.toBeVisible();
7879
});
7980

8081
await test.step('search by email', async () => {
81-
await navigateToUsers(page, 'nyc', project.id);
82+
await navigateToUsers(page, project.region, project.id);
8283
await searchUser(page, 'updated@example.com');
8384
await expect(page.getByText('updated@example.com')).toBeVisible();
8485
await expect(page.getByText('second@second.com')).not.toBeVisible();
8586
});
8687

8788
await test.step('verify multiple users', async () => {
88-
await navigateToUsers(page, 'nyc', project.id);
89+
await navigateToUsers(page, project.region, project.id);
8990
await expect(page.getByText('Updated Test User')).toBeVisible();
9091
await expect(page.getByText('Second User')).toBeVisible();
9192
await expect(page.getByText('Third User')).toBeVisible();
@@ -95,40 +96,45 @@ test('auth flow - free tier', async ({ page }) => {
9596
const userRow = page.locator('[role="row"]').filter({ hasText: 'Updated Test User' });
9697
await expect(userRow.getByText('unverified')).toBeVisible();
9798

98-
await updateUserEmailVerification(page, 'nyc', project.id, user.id, true);
99-
await navigateToUsers(page, 'nyc', project.id);
99+
await updateUserEmailVerification(page, project.region, project.id, user.id, true);
100+
await navigateToUsers(page, project.region, project.id);
100101
await expect(userRow.getByText('verified email')).toBeVisible();
101102

102-
await updateUserPhoneVerification(page, 'nyc', project.id, user.id, true);
103-
await navigateToUsers(page, 'nyc', project.id);
103+
await updateUserPhoneVerification(page, project.region, project.id, user.id, true);
104+
await navigateToUsers(page, project.region, project.id);
104105
await expect(userRow.getByText('verified')).toBeVisible();
105106

106-
await updateUserPhoneVerification(page, 'nyc', project.id, user.id, false);
107-
await navigateToUsers(page, 'nyc', project.id);
107+
await updateUserPhoneVerification(page, project.region, project.id, user.id, false);
108+
await navigateToUsers(page, project.region, project.id);
108109
await expect(userRow.getByText('verified email')).toBeVisible();
109110
});
110111

111112
await test.step('test user preferences', async () => {
112-
await updateUserPrefs(page, 'nyc', project.id, user.id, {
113+
await updateUserPrefs(page, project.region, project.id, user.id, {
113114
theme: 'dark',
114115
language: 'en',
115116
timezone: 'UTC'
116117
});
117118
});
118119

119120
await test.step('test MFA toggle', async () => {
120-
await updateUserMfa(page, 'nyc', project.id, user.id, true);
121-
await updateUserMfa(page, 'nyc', project.id, user.id, false);
121+
await updateUserMfa(page, project.region, project.id, user.id, true);
122+
await updateUserMfa(page, project.region, project.id, user.id, false);
122123
});
123124

124-
await deleteUser(page, 'nyc', project.id, user.id);
125-
await deleteUser(page, 'nyc', project.id, user2.id);
126-
await deleteUser(page, 'nyc', project.id, user3.id);
125+
await deleteUser(page, project.region, project.id, user.id);
126+
await deleteUser(page, project.region, project.id, user2.id);
127+
await deleteUser(page, project.region, project.id, user3.id);
127128

128129
await test.step('verify users deleted', async () => {
129-
await navigateToUsers(page, 'nyc', project.id);
130+
await navigateToUsers(page, project.region, project.id);
130131
await expect(page.getByText('Updated Test User')).not.toBeVisible();
131132
await expect(page.getByText('Second User')).not.toBeVisible();
132133
await expect(page.getByText('Third User')).not.toBeVisible();
133134
});
135+
136+
// cleanup: delete project, organization, and account
137+
test.afterAll('tear down', async () => {
138+
await cleanupTestAccount(page, project.region, project.id, project.organizationId);
139+
})
134140
});

e2e/steps/free-project.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getOrganizationIdFromUrl, getProjectIdFromUrl } from '../helpers/url';
44
type Metadata = {
55
id: string;
66
organizationId: string;
7+
region: string;
78
};
89

910
export async function createFreeProject(page: Page): Promise<Metadata> {
@@ -13,7 +14,7 @@ export async function createFreeProject(page: Page): Promise<Metadata> {
1314
return getOrganizationIdFromUrl(page.url());
1415
});
1516

16-
const projectId = await test.step('create project', async () => {
17+
const { projectId, region } = await test.step('create project', async () => {
1718
await page.waitForURL(/\/organization-[^/]+/);
1819
await page.getByRole('button', { name: 'create project' }).first().click();
1920
const dialog = page.locator('dialog[open]');
@@ -34,11 +35,15 @@ export async function createFreeProject(page: Page): Promise<Metadata> {
3435
await page.waitForURL(new RegExp(`/project-${region}-[^/]+`));
3536
expect(page.url()).toContain(`/console/project-${region}-`);
3637

37-
return getProjectIdFromUrl(page.url());
38+
return {
39+
projectId: getProjectIdFromUrl(page.url()),
40+
region
41+
};
3842
});
3943

4044
return {
4145
id: projectId,
42-
organizationId
46+
organizationId,
47+
region
4348
};
4449
}

src/routes/(console)/account/delete.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
showDelete = false;
1717
addNotification({
1818
type: 'success',
19-
message: `Account was deleted `
19+
message: 'Account was deleted'
2020
});
2121
trackEvent(Submit.AccountDelete);
2222
} catch (e) {

src/routes/(console)/organization-[organization]/settings/+page.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@
8989
<AvatarGroup {avatars} total={$members.total} />
9090
</svelte:fragment>
9191
<svelte:fragment slot="title">
92-
<h6 class="u-bold u-trim-1" data-private>{$organization.name}</h6>
92+
<h6 class="u-bold u-trim-1" data-private data-organization-name>
93+
{$organization.name}
94+
</h6>
9395
</svelte:fragment>
9496
<p>{orgMembers}, {orgProjects}</p>
9597
</BoxAvatar>

0 commit comments

Comments
 (0)