Skip to content

Commit 2382b30

Browse files
Merge pull request #1236 from objectstack-ai/copilot/fix-e2e-test-errors
fix(e2e): authenticate before testing sidebar visibility
2 parents 18d7894 + a65eb91 commit 2382b30

File tree

3 files changed

+56
-11
lines changed

3 files changed

+56
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929

3030
### Fixed
3131

32+
- **E2E sidebar tests failing due to missing auth** (`e2e`): The `sidebar-text-visibility.spec.ts` tests failed because the MSW mock environment returns `auth.enabled: true` in its discovery response, causing `AuthGuard` to redirect unauthenticated users to the login page where no sidebar exists. Added `e2e/helpers/auth.ts` with a `registerAndLogin()` helper that signs up a test user via the register form, and updated both sidebar tests to authenticate before asserting sidebar visibility.
33+
3234
- **Changesets release bump escalation** (`release`): Added `___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.onlyUpdatePeerDependentsWhenOutOfRange` in `.changeset/config.json` and moved internal `@object-ui/*` entries in `@object-ui/plugin-designer` from `peerDependencies` to `dependencies` to prevent minor release PRs from incorrectly escalating fixed-group packages to a major version.
3335

3436
- **Home page star/favorite not reactive** (`@object-ui/console`): Migrated `useFavorites` from standalone hook to React Context (`FavoritesProvider`) so all consumers (HomePage, AppCard, AppSidebar, UnifiedSidebar) share a single state instance. Previously, each component calling `useFavorites()` created independent state, so toggling a favorite in AppCard did not trigger re-render in HomePage. localStorage persistence is retained as the storage layer.

e2e/helpers/auth.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { Page } from '@playwright/test';
2+
import { CONSOLE_BASE } from './index';
3+
4+
/** Shared timeout for waiting on React rendering and MSW boot. */
5+
const REACT_READY_TIMEOUT = 30_000;
6+
7+
/**
8+
* Register a new test user and wait for redirect to the home page.
9+
*
10+
* MSW auth handlers run in-memory, so each browser context starts
11+
* without a session. This helper creates a fresh user via the
12+
* register form so that subsequent navigation hits authenticated
13+
* routes (HomeLayout with sidebar, etc.).
14+
*/
15+
export async function registerAndLogin(page: Page) {
16+
await page.goto(`${CONSOLE_BASE}/register`);
17+
18+
// Wait for React to mount and the register form to render
19+
await page.waitForFunction(
20+
() => (document.getElementById('root')?.children.length ?? 0) > 0,
21+
{ timeout: REACT_READY_TIMEOUT },
22+
);
23+
// Wait for the form inputs to be present (MSW boot + React render)
24+
await page.locator('input[type="email"]').waitFor({ state: 'visible', timeout: 15_000 });
25+
26+
// Fill in the registration form
27+
const ts = Date.now();
28+
await page.locator('input[type="text"]').fill('E2E Test User');
29+
await page.locator('input[type="email"]').fill(`e2e-${ts}@test.local`);
30+
await page.locator('input[type="password"]').first().fill('Test1234!');
31+
await page.locator('input[type="password"]').nth(1).fill('Test1234!');
32+
33+
// Submit and wait for navigation away from the register page
34+
await page.locator('button[type="submit"]').click();
35+
await page.waitForURL(/\/console\/(home|apps\/)/, { timeout: REACT_READY_TIMEOUT });
36+
}

e2e/sidebar-text-visibility.spec.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
import { test, expect } from '@playwright/test';
2-
import { waitForReactMount, CONSOLE_BASE } from './helpers';
2+
import { CONSOLE_BASE } from './helpers';
3+
import { registerAndLogin } from './helpers/auth';
4+
5+
/** Timeout for sidebar elements to become visible after auth + page render. */
6+
const SIDEBAR_VISIBLE_TIMEOUT = 15_000;
37

48
/**
59
* Sidebar text visibility tests
610
*
711
* These tests validate that the sidebar displays text correctly
812
* when toggled between collapsed (icon mode) and expanded states.
13+
*
14+
* The MSW mock environment requires authentication, so each test
15+
* registers a fresh user before navigating to the home page.
916
*/
1017

1118
test.describe('Sidebar Text Visibility', () => {
1219
test('should show all text labels when sidebar is expanded in icon mode', async ({ page }) => {
13-
await page.goto(`${CONSOLE_BASE}/`);
14-
await waitForReactMount(page);
20+
// registerAndLogin navigates to /register, signs up, and waits for the
21+
// redirect to /home — the page is already authenticated & on the home route.
22+
await registerAndLogin(page);
1523

16-
// Wait for sidebar to be visible
24+
// Wait for sidebar to be visible (page needs time to render after auth redirect)
1725
const sidebar = page.locator('[data-sidebar="sidebar"]').first();
18-
await expect(sidebar).toBeVisible();
26+
await expect(sidebar).toBeVisible({ timeout: SIDEBAR_VISIBLE_TIMEOUT });
1927

20-
// Find the sidebar toggle button
28+
// Find the sidebar toggle button (desktop trigger rendered by AppShell)
2129
const toggleButton = page.locator('[data-sidebar="trigger"]').first();
22-
await expect(toggleButton).toBeVisible();
30+
await expect(toggleButton).toBeVisible({ timeout: SIDEBAR_VISIBLE_TIMEOUT });
2331

2432
// Get the parent sidebar element that has data-state attribute
2533
const sidebarGroup = page.locator('.group[data-collapsible="icon"]').first();
@@ -92,14 +100,13 @@ test.describe('Sidebar Text Visibility', () => {
92100
});
93101

94102
test('should hide text labels when sidebar is collapsed in icon mode', async ({ page }) => {
95-
await page.goto(`${CONSOLE_BASE}/`);
96-
await waitForReactMount(page);
103+
await registerAndLogin(page);
97104

98105
const sidebar = page.locator('[data-sidebar="sidebar"]').first();
99-
await expect(sidebar).toBeVisible();
106+
await expect(sidebar).toBeVisible({ timeout: SIDEBAR_VISIBLE_TIMEOUT });
100107

101108
const toggleButton = page.locator('[data-sidebar="trigger"]').first();
102-
await expect(toggleButton).toBeVisible();
109+
await expect(toggleButton).toBeVisible({ timeout: SIDEBAR_VISIBLE_TIMEOUT });
103110

104111
const sidebarGroup = page.locator('.group[data-collapsible="icon"]').first();
105112

0 commit comments

Comments
 (0)