From 7489301195e03417d51c9f5b961e5ca03fa4641f Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Sat, 16 May 2026 20:51:48 +0200 Subject: [PATCH] feat(gui-v2): port AppTopbar + useBreadcrumb to TypeScript MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - useBreadcrumb composable: pure toBreadcrumbItems() helper + thin useRoute() wrapper; route-driven, no prop coupling - AppTopbar: hamburger→setMobileOpen, theme/density toggles→shell store, PrimeVue Breadcrumb/OverlayBadge/Popover/Avatar/Menu; replaces all manual document.mousedown listeners with PrimeVue built-in dismissal; notifications stubbed (useNotificationStore is a toast queue, not a feed — TODO TECH-WS-GUI-REDESIGN); sign-out→authStore.logout() - Unit tests: 10 breadcrumb + 6 AppTopbar assertions (16 total, all pass) Co-Authored-By: Claude Opus 4.7 --- .../src/components-v2/layout/AppTopbar.vue | 442 ++++++++++++++++++ .../layout/__tests__/AppTopbar.spec.ts | 224 +++++++++ .../__tests__/useBreadcrumb.spec.ts | 151 ++++++ apps/app/src/composables/useBreadcrumb.ts | 91 ++++ 4 files changed, 908 insertions(+) create mode 100644 apps/app/src/components-v2/layout/AppTopbar.vue create mode 100644 apps/app/src/components-v2/layout/__tests__/AppTopbar.spec.ts create mode 100644 apps/app/src/composables/__tests__/useBreadcrumb.spec.ts create mode 100644 apps/app/src/composables/useBreadcrumb.ts diff --git a/apps/app/src/components-v2/layout/AppTopbar.vue b/apps/app/src/components-v2/layout/AppTopbar.vue new file mode 100644 index 00000000..dc3a501a --- /dev/null +++ b/apps/app/src/components-v2/layout/AppTopbar.vue @@ -0,0 +1,442 @@ + + + + + diff --git a/apps/app/src/components-v2/layout/__tests__/AppTopbar.spec.ts b/apps/app/src/components-v2/layout/__tests__/AppTopbar.spec.ts new file mode 100644 index 00000000..eb183a2b --- /dev/null +++ b/apps/app/src/components-v2/layout/__tests__/AppTopbar.spec.ts @@ -0,0 +1,224 @@ +/** + * AppTopbar.spec.ts + * + * Strategy: mount with createPinia(); stub all PrimeVue components so we + * test only the wiring of store actions to user interactions. + * + * Assertions: + * 1. Hamburger click → shell.setMobileOpen(true) + * 2. Theme toggle click → shell.setTheme with flipped value (light→dark, dark→light) + * 3. Density toggle click → shell.setDensity with flipped value + * 4. User-menu Sign out command → authStore.logout called + * + * useBreadcrumb() calls useRoute() internally. We provide a minimal + * vue-router mock via vi.mock so the composable has a route to call. + */ + +import { createPinia, setActivePinia } from 'pinia' +import { mount } from '@vue/test-utils' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { useShellUiStore } from '@/stores/useShellUiStore' +import { useAuthStore } from '@/stores/useAuthStore' + +// --------------------------------------------------------------------------- +// Mock vue-router (useBreadcrumb calls useRoute internally) +// --------------------------------------------------------------------------- + +vi.mock('vue-router', () => ({ + useRoute: () => ({ + matched: [], + }), + useRouter: () => ({}), +})) + +// --------------------------------------------------------------------------- +// Import component AFTER mocks +// --------------------------------------------------------------------------- + +// eslint-disable-next-line import/first -- intentional: mocks must precede import +import AppTopbar from '@/components-v2/layout/AppTopbar.vue' + +// --------------------------------------------------------------------------- +// Stubs for PrimeVue components +// --------------------------------------------------------------------------- + +const globalStubs = { + Breadcrumb: { name: 'Breadcrumb', props: ['model'], template: '