Unify workspace dropdowns; Update layouts (#458)

Unified Account and Workspace drop-downs; Layout updates, now header lives within the PageBody component; Sidebars now use floating variant
This commit is contained in:
Giancarlo Buomprisco
2026-03-11 14:45:42 +08:00
committed by GitHub
parent ca585e09be
commit 4bc8448a1d
530 changed files with 14398 additions and 11198 deletions

View File

@@ -4,7 +4,7 @@
"main": "index.js",
"scripts": {
"report": "playwright show-report",
"test": "playwright test --max-failures=1",
"test": "playwright test --max-failures=1 --workers=4",
"test:fast": "playwright test --max-failures=1 --workers=16",
"test:setup": "playwright test tests/auth.setup.ts",
"test:ui": "playwright test --ui"

View File

@@ -38,6 +38,8 @@ test.describe('Account Settings', () => {
await Promise.all([request, response]);
await page.locator('[data-test="workspace-dropdown-trigger"]').click();
await expect(account.getProfileName()).toHaveText(name);
});

View File

@@ -34,17 +34,17 @@ test.describe('Admin', () => {
await page.goto('/admin');
// Check all stat cards are present
await expect(page.getByRole('heading', { name: 'Users' })).toBeVisible();
await expect(page.getByText('Users', { exact: true })).toBeVisible();
await expect(
page.getByRole('heading', { name: 'Team Accounts' }),
page.getByText('Team Accounts', { exact: true }),
).toBeVisible();
await expect(
page.getByRole('heading', { name: 'Paying Customers' }),
page.getByText('Paying Customers', { exact: true }),
).toBeVisible();
await expect(page.getByRole('heading', { name: 'Trials' })).toBeVisible();
await expect(page.getByText('Trials', { exact: true })).toBeVisible();
// Verify stat values are numbers
const stats = await page.$$('.text-3xl.font-bold');

View File

@@ -31,8 +31,17 @@ export class AuthPageObject {
}
async signOut() {
await this.page.click('[data-test="account-dropdown-trigger"]');
await this.page.click('[data-test="account-dropdown-sign-out"]');
const trigger = this.page.locator(
'[data-test="workspace-dropdown-trigger"], [data-test="account-dropdown-trigger"]',
);
await trigger.click();
const signOutButton = this.page.locator(
'[data-test="workspace-sign-out"], [data-test="account-dropdown-sign-out"]',
);
await signOutButton.click();
}
async signIn(params: { email: string; password: string }) {

View File

@@ -4,7 +4,7 @@ import { expect, test } from '@playwright/test';
test.describe('Healthcheck endpoint', () => {
test('returns healthy status', async ({ request }) => {
const response = await request.get('/healthcheck');
const response = await request.get('/api/healthcheck');
expect(response.status()).toBe(200);

View File

@@ -46,7 +46,7 @@ export class InvitationsPageObject {
`[data-test="invite-member-form-item"]:nth-child(${nth}) [data-test="role-selector-trigger"]`,
);
await this.page.click(`[data-test="role-option-${invite.role}"]`);
await this.page.getByRole('option', { name: invite.role }).click();
if (index < invites.length - 1) {
await form.locator('[data-test="add-new-invite-button"]').click();

View File

@@ -36,13 +36,13 @@ export class TeamAccountsPageObject {
}
getTeamFromSelector(teamName: string) {
return this.page.locator(`[data-test="account-selector-team"]`, {
return this.page.locator('[data-test="workspace-team-item"]', {
hasText: teamName,
});
}
getTeams() {
return this.page.locator('[data-test="account-selector-team"]');
return this.page.locator('[data-test="workspace-team-item"]');
}
goToSettings() {
@@ -83,10 +83,11 @@ export class TeamAccountsPageObject {
openAccountsSelector() {
return expect(async () => {
await this.page.click('[data-test="account-selector-trigger"]');
await this.page.click('[data-test="workspace-dropdown-trigger"]');
await this.page.click('[data-test="workspace-switch-submenu"]');
return expect(
this.page.locator('[data-test="account-selector-content"]'),
this.page.locator('[data-test="workspace-switch-content"]'),
).toBeVisible();
}).toPass();
}
@@ -115,7 +116,7 @@ export class TeamAccountsPageObject {
async createTeam({ teamName, slug } = this.createTeamName()) {
await this.openAccountsSelector();
await this.page.click('[data-test="create-team-account-trigger"]');
await this.page.click('[data-test="create-team-trigger"]');
await this.page.fill(
'[data-test="create-team-form"] [data-test="team-name-input"]',
@@ -140,14 +141,15 @@ export class TeamAccountsPageObject {
await this.openAccountsSelector();
await expect(this.getTeamFromSelector(teamName)).toBeVisible();
// Close the selector
// Close the selector (Escape closes submenu, then parent dropdown)
await this.page.keyboard.press('Escape');
await this.page.keyboard.press('Escape');
}
async createTeamWithNonLatinName(teamName: string, slug: string) {
await this.openAccountsSelector();
await this.page.click('[data-test="create-team-account-trigger"]');
await this.page.click('[data-test="create-team-trigger"]');
await this.page.fill(
'[data-test="create-team-form"] [data-test="team-name-input"]',
@@ -177,7 +179,8 @@ export class TeamAccountsPageObject {
await this.openAccountsSelector();
await expect(this.getTeamFromSelector(teamName)).toBeVisible();
// Close the selector
// Close the selector (Escape closes submenu, then parent dropdown)
await this.page.keyboard.press('Escape');
await this.page.keyboard.press('Escape');
}
@@ -207,11 +210,10 @@ export class TeamAccountsPageObject {
}
async deleteAccount(email: string) {
await this.page.click('[data-test="delete-team-trigger"]');
await this.otp.completeOtpVerification(email);
await expect(async () => {
await this.page.click('[data-test="delete-team-trigger"]');
await this.otp.completeOtpVerification(email);
const click = this.page.click(
'[data-test="delete-team-form-confirm-button"]',
);

View File

@@ -88,7 +88,7 @@ test.describe('Team Accounts', () => {
await teamAccounts.createTeam();
await teamAccounts.openAccountsSelector();
await page.click('[data-test="create-team-account-trigger"]');
await page.click('[data-test="create-team-trigger"]');
await teamAccounts.tryCreateTeam('billing');
@@ -202,7 +202,7 @@ test.describe('Team Accounts', () => {
// Use non-Latin name to trigger the slug field visibility
await teamAccounts.openAccountsSelector();
await page.click('[data-test="create-team-account-trigger"]');
await page.click('[data-test="create-team-trigger"]');
await page.fill(
'[data-test="create-team-form"] [data-test="team-name-input"]',