open-design/apps/web/tests/components/WorkspaceTabsBar.test.tsx
Tom Huang c5d77a03bd
Some checks failed
nix-check / build (push) Failing after 2s
Garnet hemisphere (#1769)
* feat(chat-composer): enhance mention handling and input overlay

- Introduced a new overlay for inline mentions in the chat composer, improving user experience by visually indicating mentions as users type.
- Updated the `ChatComposer` component to manage mention entities and integrate them into the input field, allowing for better context and interaction.
- Enhanced the `AssistantMessage` component to support the display of plugin action panels based on the current project context, facilitating easier plugin management.
- Refactored related components to ensure consistent handling of project files and mentions across the application.

This update significantly improves the chat interaction model, making it more intuitive for users to engage with mentions and plugins.

* feat(plugin-management): enhance plugin action panels and UI components

- Updated the `AssistantMessage` component to include plugin action panels based on the latest project context, improving user interaction with generated plugins.
- Refactored the `PluginsView` to support detailed views for available marketplace entries, allowing users to access more information and actions for each plugin.
- Introduced new CSS styles for improved visual representation of plugin-related UI elements, enhancing overall user experience.
- Enhanced the `listPlugins` function to include an option for fetching hidden plugins, providing more flexibility in plugin management.

This update significantly improves the usability and functionality of the plugin management system, making it easier for users to interact with and manage their plugins.

* fix(assistant-message): refine plugin folder candidate selection logic

- Updated the `pluginFoldersTouchedThisTurn` function to improve the logic for selecting plugin folder candidates based on touched paths and message content.
- Introduced a new helper function, `pathMatchesFolderFileBasename`, to enhance the matching criteria for folder candidates.
- Added a check for explicit folder matches before falling back to a single candidate, improving accuracy in folder selection.
- Modified the `shouldRenderSlotAsText` function in `HomeHero` to include the name parameter, refining the rendering logic for slot text.

These changes enhance the functionality and reliability of the assistant message component in managing plugin folder candidates.

* feat(plugin-folder-actions): implement agent-routed CLI actions for plugin management

- Introduced a new `PluginFolderAgentAction` type to streamline actions related to plugin folders, including install, publish, and contribute.
- Updated the `DesignFilesPanel`, `FileWorkspace`, and `AssistantMessage` components to utilize the new agent action handling, improving user interaction with generated plugins.
- Refactored the action handling logic to send commands to the agent, enhancing the workflow for managing plugin folders.
- Added corresponding tests to ensure the new functionality works as expected and integrates seamlessly with existing components.

This update significantly enhances the plugin management experience by routing actions through the agent, allowing for a more cohesive and interactive user experience.

* Fix PR 1702 CI blockers

* Fix PR 1702 remaining CI checks

* Prebuild AGUI adapter after install

* Restore plugin project snapshot wiring

* feat(marketplace): refactor marketplace URL handling and enhance fetching logic

- Introduced new functions to normalize marketplace URLs and manage fetching of marketplace manifests, improving the reliability of marketplace integrations.
- Updated the server and plugin logic to utilize the new fetching mechanisms, ensuring consistent handling of marketplace data.
- Enhanced tests to cover new URL normalization and fetching scenarios, ensuring robustness in marketplace management.

This update significantly improves the marketplace experience by streamlining URL handling and enhancing data fetching capabilities.

* Fix project auto-send cleanup spec

* Reconcile run messages on cancel

* Use active design system as visual direction

* Fix active design system prompt wording

* feat(workspace-tabs): implement workspace tabs functionality and file attachment handling

- Introduced a new `WorkspaceTabsBar` component to manage workspace tabs, allowing users to navigate between different views (projects, marketplace, etc.).
- Enhanced file handling capabilities in the `HomeHero` and `EntryShell` components, enabling users to stage and attach files before project creation.
- Updated the `App` component to support auto-sending attachments alongside the first message in a project.
- Improved CSS styles for workspace tabs and attachment UI, ensuring a cohesive design and user experience.

This update significantly enhances the workspace navigation and file management features, providing users with a more intuitive and efficient workflow.

* refactor(workspace-tabs): streamline workspace tabs and UI components

- Removed unused components and actions from the `WorkspaceTabsBar` and `AppChromeHeader`, simplifying the codebase.
- Updated CSS styles for the workspace shell and tabs, enhancing visual consistency and reducing element sizes for a cleaner layout.
- Introduced a new client type detection mechanism to dynamically adjust the workspace shell's class, improving responsiveness.
- Added tests for the `WorkspaceTabsBar` to ensure proper navigation and tab management functionality.

These changes improve the overall performance and user experience of the workspace navigation system.

* Update critical e2e for entry modal flow

* Stabilize entry critical e2e flows

* fix(ui): adjust workspace tabs and header styles for improved layout

- Updated the CSS for workspace tabs and the app header, reducing element sizes and padding for a cleaner appearance.
- Introduced a new button in the `WorkspaceTabsBar` for quick access to the home tab, enhancing navigation.
- Minor adjustments to the layout and styles to ensure consistency across components.

These changes enhance the user interface and improve the overall user experience in the workspace navigation system.

* feat(workspace-tabs): implement pinned home tab functionality

- Added a new pinned home tab feature to the `WorkspaceTabsBar`, allowing the home tab to remain accessible during navigation.
- Updated tab management logic to collapse duplicate home tabs into a single pinned instance when restoring from local storage.
- Enhanced CSS styles for workspace tabs to accommodate the new pinned tab design.
- Updated tests to verify the behavior of the pinned home tab and its interaction with other tabs.

These changes improve navigation consistency and user experience within the workspace.

* refactor(workspace-tabs): enhance tab management and styling

- Updated CSS styles for workspace tabs, adjusting padding and flex properties for improved layout and consistency.
- Refactored tab creation logic to ensure unique IDs for project and marketplace tabs, enhancing navigation clarity.
- Removed deprecated functions related to pinned home tabs, streamlining the codebase.
- Improved test cases to verify independent behavior of home tabs during navigation.

These changes enhance the user experience by providing a more intuitive tab management system and a cleaner UI.

* style(workspace-tabs): update CSS for improved layout and visibility

- Adjusted CSS properties for workspace tabs, including overflow, position, and z-index to enhance layout and stacking context.
- Ensured consistent styling across tab components for better visual hierarchy.

These changes contribute to a more polished and user-friendly interface within the workspace.

* style(entry-layout): update CSS variables for improved layout consistency

- Replaced fixed width values with CSS variables for the entry rail to enhance flexibility.
- Adjusted padding and height properties for better visual alignment and spacing.
- Introduced a new background style for the entry main topbar to improve aesthetics.

These changes contribute to a more responsive and visually appealing layout in the entry view.

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: Eli <129168833+qiongyu1999@users.noreply.github.com>
2026-05-15 14:42:11 +08:00

132 lines
3.8 KiB
TypeScript

// @vitest-environment jsdom
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { WorkspaceTabsBar } from '../../src/components/WorkspaceTabsBar';
import { navigate, type Route } from '../../src/router';
import type { Project } from '../../src/types';
vi.mock('../../src/i18n', () => ({
useT: () => (key: string) => {
const labels: Record<string, string> = {
'app.brand': 'Open Design',
'common.close': 'Close',
'common.untitled': 'Untitled',
'entry.navDesignSystems': 'Design systems',
'entry.navHome': 'Home',
'entry.navProjects': 'Projects',
};
return labels[key] ?? key;
},
}));
vi.mock('../../src/router', async () => {
const actual = await vi.importActual<typeof import('../../src/router')>(
'../../src/router',
);
return {
...actual,
navigate: vi.fn(),
};
});
const homeRoute: Route = { kind: 'home', view: 'home' };
const projectRoute: Route = {
kind: 'project',
projectId: 'project-alpha',
conversationId: null,
fileName: null,
};
const project: Project = {
id: 'project-alpha',
name: 'Project Alpha',
skillId: null,
designSystemId: null,
createdAt: 1,
updatedAt: 1,
};
describe('WorkspaceTabsBar navigation semantics', () => {
beforeEach(() => {
window.localStorage.clear();
vi.clearAllMocks();
});
afterEach(() => {
cleanup();
});
it('keeps each new Home tab independent when one tab navigates', async () => {
const { rerender } = render(
<WorkspaceTabsBar route={homeRoute} projects={[project]} />,
);
expect(screen.getAllByRole('tab')).toHaveLength(1);
fireEvent.click(screen.getByRole('button', { name: 'New tab' }));
fireEvent.click(screen.getByRole('button', { name: 'New tab' }));
await waitFor(() => {
const labels = screen.getAllByRole('tab').map((tab) => tab.textContent ?? '');
expect(labels.filter((label) => label.includes('Home'))).toHaveLength(3);
});
expect(navigate).toHaveBeenCalledWith(homeRoute);
rerender(<WorkspaceTabsBar route={projectRoute} projects={[project]} />);
await waitFor(() => {
const tabs = screen.getAllByRole('tab');
const labels = tabs.map((tab) => tab.textContent ?? '');
expect(tabs).toHaveLength(3);
expect(labels.filter((label) => label.includes('Home'))).toHaveLength(2);
expect(labels.some((label) => label.includes('Project Alpha'))).toBe(true);
});
});
it('preserves restored Home tabs instead of collapsing them by route', async () => {
window.localStorage.setItem(
'open-design:workspace-tabs:v1',
JSON.stringify({
activeTabId: 'entry:home:old-two',
tabs: [
{
id: 'entry:home:old-one',
kind: 'entry',
view: 'home',
createdAt: 1,
lastActiveAt: 1,
},
{
id: 'entry:home:old-two',
kind: 'entry',
view: 'home',
createdAt: 2,
lastActiveAt: 2,
},
],
}),
);
render(<WorkspaceTabsBar route={homeRoute} projects={[project]} />);
await waitFor(() => {
const labels = screen.getAllByRole('tab').map((tab) => tab.textContent ?? '');
expect(labels.filter((label) => label.includes('Home'))).toHaveLength(2);
});
});
it('creates a replacement Home tab when the last tab is closed', async () => {
render(<WorkspaceTabsBar route={homeRoute} projects={[project]} />);
fireEvent.click(screen.getByRole('button', { name: 'Close' }));
await waitFor(() => {
const labels = screen.getAllByRole('tab').map((tab) => tab.textContent ?? '');
expect(labels).toHaveLength(1);
expect(labels[0]).toContain('Home');
});
expect(navigate).toHaveBeenCalledWith(homeRoute);
});
});