From 59ff9bdafbd548cdfa2150f28dfe8a5af884532d Mon Sep 17 00:00:00 2001 From: Abhishek S Lal Date: Mon, 12 Jan 2026 23:15:39 +0530 Subject: [PATCH] Bugfix/workspace name case mismatch (#6560) * fix: preserve workspace name casing in title bar (#6522) * fix: improve workspace display name handling in title bar --------- Co-authored-by: Uzairkazi695 --- .../src/components/AppTitleBar/index.js | 27 +++++++++---------- .../src/components/WorkspaceHome/index.js | 4 ++- .../src/utils/workspace-config.js | 2 +- .../default-workspace.spec.ts | 16 +++++------ .../default-workspace/migration.spec.ts | 12 ++++----- .../recovery-and-backup.spec.ts | 10 +++---- 6 files changed, 35 insertions(+), 36 deletions(-) diff --git a/packages/bruno-app/src/components/AppTitleBar/index.js b/packages/bruno-app/src/components/AppTitleBar/index.js index f2a621b29..0e40c9ea9 100644 --- a/packages/bruno-app/src/components/AppTitleBar/index.js +++ b/packages/bruno-app/src/components/AppTitleBar/index.js @@ -18,9 +18,9 @@ import ImportWorkspace from 'components/WorkspaceSidebar/ImportWorkspace'; import IconBottombarToggle from 'components/Icons/IconBottombarToggle/index'; import StyledWrapper from './StyledWrapper'; -import { toTitleCase } from 'utils/common/index'; import ResponseLayoutToggle from 'components/ResponsePane/ResponseLayoutToggle'; import { isMacOS, isWindowsOS, isLinuxOS } from 'utils/common/platform'; +import classNames from 'classnames'; const getOsClass = () => { if (isMacOS()) return 'os-mac'; @@ -29,6 +29,12 @@ const getOsClass = () => { return 'os-other'; }; +// Helper to get display name for workspace +export const getWorkspaceDisplayName = (name) => { + if (!name) return 'Untitled Workspace'; + return name; +}; + const AppTitleBar = () => { const dispatch = useDispatch(); const [isFullScreen, setIsFullScreen] = useState(false); @@ -115,7 +121,7 @@ const AppTitleBar = () => { const WorkspaceName = forwardRef((props, ref) => { return (
- {toTitleCase(activeWorkspace?.name) || 'Default Workspace'} + {getWorkspaceDisplayName(activeWorkspace?.name)}
); @@ -127,7 +133,7 @@ const AppTitleBar = () => { const handleWorkspaceSwitch = (workspaceUid) => { dispatch(switchWorkspace(workspaceUid)); - toast.success(`Switched to ${workspaces.find((w) => w.uid === workspaceUid)?.name}`); + toast.success(`Switched to ${getWorkspaceDisplayName(workspaces.find((w) => w.uid === workspaceUid)?.name)}`); }; const handleOpenWorkspace = async () => { @@ -178,7 +184,7 @@ const AppTitleBar = () => { return { id: workspace.uid, - label: toTitleCase(workspace.name), + label: getWorkspaceDisplayName(workspace.name), onClick: () => handleWorkspaceSwitch(workspace.uid), className: `workspace-item ${isActive ? 'active' : ''}`, rightSection: ( @@ -190,11 +196,7 @@ const AppTitleBar = () => { label={isPinned ? 'Unpin workspace' : 'Pin workspace'} size="sm" > - {isPinned ? ( - - ) : ( - - )} + {isPinned ? : } )} {isActive && } @@ -247,12 +249,7 @@ const AppTitleBar = () => {
{/* Left section: Home + Workspace */}
- + diff --git a/packages/bruno-app/src/components/WorkspaceHome/index.js b/packages/bruno-app/src/components/WorkspaceHome/index.js index db27824b0..4ec91aefe 100644 --- a/packages/bruno-app/src/components/WorkspaceHome/index.js +++ b/packages/bruno-app/src/components/WorkspaceHome/index.js @@ -11,6 +11,8 @@ import WorkspaceTabs from 'components/WorkspaceTabs'; import StyledWrapper from './StyledWrapper'; import Dropdown from 'components/Dropdown'; import { getRevealInFolderLabel } from 'utils/common/platform'; +import { getWorkspaceDisplayName } from 'components/AppTitleBar'; +import classNames from 'classnames'; const WorkspaceHome = () => { const dispatch = useDispatch(); @@ -208,7 +210,7 @@ const WorkspaceHome = () => {
) : ( - {activeWorkspace.name} + {getWorkspaceDisplayName(activeWorkspace.name)} )} diff --git a/packages/bruno-electron/src/utils/workspace-config.js b/packages/bruno-electron/src/utils/workspace-config.js index fadab0f08..78093a8a8 100644 --- a/packages/bruno-electron/src/utils/workspace-config.js +++ b/packages/bruno-electron/src/utils/workspace-config.js @@ -217,7 +217,7 @@ const readWorkspaceConfig = (workspacePath) => { const generateYamlContent = (config) => { const yamlLines = []; - const workspaceName = config.info?.name || config.name || 'Unnamed Workspace'; + const workspaceName = config.info?.name || config.name || 'Untitled Workspace'; const workspaceType = config.info?.type || config.type || WORKSPACE_TYPE; yamlLines.push(`opencollection: ${config.opencollection || OPENCOLLECTION_VERSION}`); diff --git a/tests/workspace/default-workspace/default-workspace.spec.ts b/tests/workspace/default-workspace/default-workspace.spec.ts index 4d94b1c5f..ad1757568 100644 --- a/tests/workspace/default-workspace/default-workspace.spec.ts +++ b/tests/workspace/default-workspace/default-workspace.spec.ts @@ -12,8 +12,8 @@ test.describe('Default Workspace', () => { await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); // Verify the workspace name is "My Workspace" in the title bar - const workspaceName = page.locator('.workspace-name'); - await expect(workspaceName).toContainText('My Workspace'); + const workspaceName = page.getByTestId('workspace-name'); + await expect(workspaceName).toHaveText('My Workspace'); await app.context().close(); await app.close(); @@ -28,7 +28,7 @@ test.describe('Default Workspace', () => { const app1 = await launchElectronApp({ userDataPath }); const page1 = await app1.firstWindow(); await page1.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page1.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page1.getByTestId('workspace-name')).toHaveText('My Workspace'); await app1.close(); @@ -36,7 +36,7 @@ test.describe('Default Workspace', () => { const app2 = await launchElectronApp({ userDataPath }); const page2 = await app2.firstWindow(); await page2.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page2.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page2.getByTestId('workspace-name')).toHaveText('My Workspace'); await app2.context().close(); await app2.close(); @@ -69,7 +69,7 @@ test.describe('Default Workspace', () => { await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); // Should show "My Workspace" - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Old directory should still exist (never deleted) expect(fs.existsSync(defaultWorkspacePath)).toBe(true); @@ -106,7 +106,7 @@ test.describe('Default Workspace', () => { const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Old corrupted file should still exist (never deleted) const oldContent = fs.readFileSync(path.join(defaultWorkspacePath, 'workspace.yml'), 'utf8'); @@ -150,7 +150,7 @@ docs: '' const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // New workspace should have been created const newWorkspacePath = path.join(userDataPath, 'default-workspace-1'); @@ -179,7 +179,7 @@ docs: '' const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // New workspace should have been created (default-workspace since non-existent doesn't block) const newWorkspacePath = path.join(userDataPath, 'default-workspace'); diff --git a/tests/workspace/default-workspace/migration.spec.ts b/tests/workspace/default-workspace/migration.spec.ts index b6ec9e34e..07bf9c906 100644 --- a/tests/workspace/default-workspace/migration.spec.ts +++ b/tests/workspace/default-workspace/migration.spec.ts @@ -35,7 +35,7 @@ test.describe('Default Workspace Migration', () => { await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); await test.step('Verify workspace UI', async () => { - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); }); await test.step('Verify workspace filesystem artifacts', async () => { @@ -87,7 +87,7 @@ test.describe('Default Workspace Migration', () => { const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Verify workspace.yml has both collections const workspacePath = path.join(userDataPath, 'default-workspace'); @@ -132,7 +132,7 @@ test.describe('Default Workspace Migration', () => { await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); // Verify default workspace is created - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Sample collection should NOT be created (because user has existing collections) const sampleCollection = page.locator('#sidebar-collection-name').getByText('Sample API Collection'); @@ -151,7 +151,7 @@ test.describe('Default Workspace Migration', () => { const app1 = await launchElectronApp({ userDataPath }); const page1 = await app1.firstWindow(); await page1.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page1.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page1.getByTestId('workspace-name')).toHaveText('My Workspace'); // Verify initial workspace was created const workspacePath = path.join(userDataPath, 'default-workspace'); @@ -165,7 +165,7 @@ test.describe('Default Workspace Migration', () => { const app2 = await launchElectronApp({ userDataPath }); const page2 = await app2.firstWindow(); await page2.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page2.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page2.getByTestId('workspace-name')).toHaveText('My Workspace'); // workspace.yml should NOT have been modified const currentYmlContent = fs.readFileSync(path.join(workspacePath, 'workspace.yml'), 'utf8'); @@ -188,7 +188,7 @@ test.describe('Default Workspace Migration', () => { const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Verify workspace was created const workspacePath = path.join(userDataPath, 'default-workspace'); diff --git a/tests/workspace/default-workspace/recovery-and-backup.spec.ts b/tests/workspace/default-workspace/recovery-and-backup.spec.ts index 123f59ffc..2fefc076f 100644 --- a/tests/workspace/default-workspace/recovery-and-backup.spec.ts +++ b/tests/workspace/default-workspace/recovery-and-backup.spec.ts @@ -183,7 +183,7 @@ docs: '' await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); // UI always shows "My Workspace" - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Should NOT create a new workspace expect(fs.existsSync(path.join(userDataPath, 'default-workspace-1'))).toBe(false); @@ -231,7 +231,7 @@ docs: '' const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Verify the correct workspace was selected (workspace-2) const prefs = JSON.parse(fs.readFileSync(path.join(userDataPath, 'preferences.json'), 'utf8')); @@ -295,7 +295,7 @@ docs: '' const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Verify workspace-1 was selected (not workspace-2 which is broken) const prefs = JSON.parse(fs.readFileSync(path.join(userDataPath, 'preferences.json'), 'utf8')); @@ -521,7 +521,7 @@ docs: '' const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Since path doesn't exist but we have a valid workspace, it should use it // OR create a new one recovering from the existing one @@ -603,7 +603,7 @@ docs: '' const page = await app.firstWindow(); await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 }); - await expect(page.locator('.workspace-name')).toContainText('My Workspace'); + await expect(page.getByTestId('workspace-name')).toHaveText('My Workspace'); // Verify workspace-1 was used (or workspace-2 was created recovering from workspace-1) const prefs = JSON.parse(fs.readFileSync(path.join(userDataPath, 'preferences.json'), 'utf8'));