trypost/tests/Browser/SidebarMenuTest.php
Paulo Castellano f62b4bb4a5
Unify sidebar workspace and account menus (#240)
* Unify sidebar workspace and account menus.

Merge workspace switching, profile, billing, and language into one header dropdown, move notifications beside it, pin support links to the footer, and add Workspace Settings to the nav — without MCP or onboarding residual.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Remove Workspace Settings from the sidebar nav.

Settings already lives in the unified account menu; keep the workspace group free for items like MCP later.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Cover sidebar menu role gates in browser tests.

Assert account/workspace settings visibility for owner, admin, member, and self-hosted so the unified menu stays aligned with WorkspacePolicy.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Rename sidebar wait helper to avoid Pest browser collision.

waitForTestId was already declared in MobileEditorTest, which fataled the e2e suite when listing Browser tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add sidebar menu browser coverage for workspace viewers.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 21:33:16 -03:00

190 lines
5.6 KiB
PHP

<?php
declare(strict_types=1);
use App\Enums\UserWorkspace\Role;
use App\Models\User;
use App\Models\Workspace;
/**
* Wait for a data-testid element to mount and lay out. Pest browser assertions
* do not auto-wait on SPA paint.
*/
function waitForSidebarTestId(mixed $page, string $testId): void
{
$page->script(<<<JS
(async () => {
const sel = '[data-testid="{$testId}"]';
for (let i = 0; i < 100; i++) {
const el = document.querySelector(sel);
if (el && el.getBoundingClientRect().height > 0) return;
await new Promise((r) => setTimeout(r, 50));
}
})();
JS);
}
test('account owners see account and workspace settings in the sidebar menu', function () {
config(['trypost.self_hosted' => false]);
$user = User::factory()->create();
$workspace = Workspace::factory()->create([
'user_id' => $user->id,
'account_id' => $user->account_id,
]);
$workspace->members()->attach($user->id, ['role' => Role::Admin->value]);
$user->update(['current_workspace_id' => $workspace->id]);
subscribeAccount($user->account);
$this->actingAs($user);
$page = visit(route('app.calendar'));
waitForSidebarTestId($page, 'sidebar-workspace-menu');
$page->assertVisible('@sidebar-workspace-menu')
->click('@sidebar-workspace-menu');
waitForSidebarTestId($page, 'logout-button');
$page->assertVisible('@sidebar-menu-my-account')
->assertVisible('@sidebar-menu-account-settings')
->assertVisible('@sidebar-menu-workspace-settings')
->assertVisible('@logout-button');
});
test('account billing is hidden in the sidebar menu when self-hosted', function () {
config(['trypost.self_hosted' => true]);
$user = User::factory()->create();
$workspace = Workspace::factory()->create([
'user_id' => $user->id,
'account_id' => $user->account_id,
]);
$workspace->members()->attach($user->id, ['role' => Role::Admin->value]);
$user->update(['current_workspace_id' => $workspace->id]);
$this->actingAs($user);
$page = visit(route('app.calendar'));
waitForSidebarTestId($page, 'sidebar-workspace-menu');
$page->assertVisible('@sidebar-workspace-menu')
->click('@sidebar-workspace-menu');
waitForSidebarTestId($page, 'logout-button');
$page->assertVisible('@sidebar-menu-my-account')
->assertMissing('@sidebar-menu-account-settings')
->assertVisible('@sidebar-menu-workspace-settings');
});
test('workspace admins see workspace settings but not account billing', function () {
config(['trypost.self_hosted' => false]);
[
'owner' => $owner,
'member' => $admin,
'shared_workspaces' => [$workspace],
] = strandedMemberOnSharedAccount(
sharedWorkspaces: 1,
attachMember: true,
setMemberCurrent: true,
);
$workspace->members()->updateExistingPivot($admin->id, [
'role' => Role::Admin->value,
]);
subscribeAccount($owner->account);
$this->actingAs($admin->fresh());
$page = visit(route('app.calendar'));
waitForSidebarTestId($page, 'sidebar-workspace-menu');
$page->assertVisible('@sidebar-workspace-menu')
->click('@sidebar-workspace-menu');
waitForSidebarTestId($page, 'logout-button');
$page->assertVisible('@sidebar-menu-my-account')
->assertVisible('@sidebar-menu-workspace-settings')
->assertMissing('@sidebar-menu-account-settings')
->assertVisible('@logout-button');
});
test('workspace members do not see account or workspace settings in the sidebar menu', function () {
config(['trypost.self_hosted' => false]);
[
'owner' => $owner,
'member' => $member,
'shared_workspaces' => [$workspace],
] = strandedMemberOnSharedAccount(
sharedWorkspaces: 1,
attachMember: true,
setMemberCurrent: true,
);
$workspace->members()->updateExistingPivot($member->id, [
'role' => Role::Member->value,
]);
subscribeAccount($owner->account);
$this->actingAs($member->fresh());
$page = visit(route('app.calendar'));
waitForSidebarTestId($page, 'sidebar-workspace-menu');
$page->assertVisible('@sidebar-workspace-menu')
->click('@sidebar-workspace-menu');
waitForSidebarTestId($page, 'logout-button');
$page->assertVisible('@sidebar-menu-my-account')
->assertMissing('@sidebar-menu-account-settings')
->assertMissing('@sidebar-menu-workspace-settings')
->assertVisible('@logout-button');
});
test('workspace viewers do not see account or workspace settings in the sidebar menu', function () {
config(['trypost.self_hosted' => false]);
[
'owner' => $owner,
'member' => $viewer,
'shared_workspaces' => [$workspace],
] = strandedMemberOnSharedAccount(
sharedWorkspaces: 1,
attachMember: true,
setMemberCurrent: true,
);
$workspace->members()->updateExistingPivot($viewer->id, [
'role' => Role::Viewer->value,
]);
subscribeAccount($owner->account);
$this->actingAs($viewer->fresh());
$page = visit(route('app.calendar'));
waitForSidebarTestId($page, 'sidebar-workspace-menu');
$page->assertVisible('@sidebar-workspace-menu')
->click('@sidebar-workspace-menu');
waitForSidebarTestId($page, 'logout-button');
$page->assertVisible('@sidebar-menu-my-account')
->assertMissing('@sidebar-menu-account-settings')
->assertMissing('@sidebar-menu-workspace-settings')
->assertVisible('@logout-button');
});