From b6ea858c9b7edc59e440654cfcfc701287fde823 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Mon, 15 Jun 2026 20:11:37 +0200 Subject: [PATCH] test(10-03): add failing BreadcrumbBar tests (RED) - 10 Vitest unit tests covering showRoot, rootLabel, navigate emits - Tests segments shape {id?, label} (not {id, name}) - Covers ellipsis collapse for >4 segments, no-id static segments - AppIcon stubbed via global.stubs for isolated rendering --- .../ui/__tests__/BreadcrumbBar.test.js | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 frontend/src/components/ui/__tests__/BreadcrumbBar.test.js diff --git a/frontend/src/components/ui/__tests__/BreadcrumbBar.test.js b/frontend/src/components/ui/__tests__/BreadcrumbBar.test.js new file mode 100644 index 0000000..9d9b6be --- /dev/null +++ b/frontend/src/components/ui/__tests__/BreadcrumbBar.test.js @@ -0,0 +1,116 @@ +import { describe, it, expect } from 'vitest' +import { mount } from '@vue/test-utils' +import BreadcrumbBar from '../BreadcrumbBar.vue' + +const STUBS = { global: { stubs: { AppIcon: true } } } + +function seg(id, label) { return { id, label } } +function staticSeg(label) { return { label } } + +describe('BreadcrumbBar', () => { + it('renders rootLabel button when showRoot=true', () => { + const w = mount(BreadcrumbBar, { + props: { rootLabel: 'Home', segments: [] }, + ...STUBS, + }) + expect(w.find('button').text()).toBe('Home') + }) + + it('does NOT render root button when showRoot=false', () => { + const w = mount(BreadcrumbBar, { + props: { showRoot: false, segments: [staticSeg('Users')] }, + ...STUBS, + }) + expect(w.findAll('button').length).toBe(0) + }) + + it('clicking root button emits navigate(null)', async () => { + const w = mount(BreadcrumbBar, { + props: { segments: [] }, + ...STUBS, + }) + await w.find('button').trigger('click') + expect(w.emitted('navigate')).toBeTruthy() + expect(w.emitted('navigate')[0]).toEqual([null]) + }) + + it('last segment renders as a non-clickable ', () => { + const w = mount(BreadcrumbBar, { + props: { segments: [seg('a', 'A'), seg('b', 'B')] }, + ...STUBS, + }) + const text = w.text() + expect(text).toContain('B') + const buttonWithB = w.findAll('button').filter(b => b.text() === 'B') + expect(buttonWithB.length).toBe(0) + }) + + it('clicking intermediate segment emits navigate(segment.id)', async () => { + const w = mount(BreadcrumbBar, { + props: { segments: [seg('r1', 'Root'), seg('f1', 'Test')] }, + ...STUBS, + }) + const buttons = w.findAll('button') + const rootBtn = buttons.find(b => b.text() === 'Root') + await rootBtn.trigger('click') + expect(w.emitted('navigate')).toBeTruthy() + expect(w.emitted('navigate')[0]).toEqual(['r1']) + }) + + it('segments without id render as plain text even when intermediate', () => { + const w = mount(BreadcrumbBar, { + props: { + showRoot: false, + segments: [staticSeg('Admin'), staticSeg('Users')], + }, + ...STUBS, + }) + expect(w.findAll('button').length).toBe(0) + }) + + it('>4 segments collapse to first + ellipsis + last two', () => { + const segments = [ + seg('a', 'Alpha'), + seg('b', 'Beta'), + seg('c', 'Gamma'), + seg('d', 'Delta'), + seg('e', 'Epsilon'), + ] + const w = mount(BreadcrumbBar, { + props: { segments }, + ...STUBS, + }) + const text = w.text() + expect(text).toContain('Alpha') + expect(text).toContain('…') + expect(text).toContain('Delta') + expect(text).toContain('Epsilon') + expect(text).not.toContain('Beta') + expect(text).not.toContain('Gamma') + }) + + it('rootLabel defaults to "Home"', () => { + const w = mount(BreadcrumbBar, { + props: { segments: [] }, + ...STUBS, + }) + expect(w.find('button').text()).toBe('Home') + }) + + it('custom rootLabel "Cloud" renders correctly', () => { + const w = mount(BreadcrumbBar, { + props: { rootLabel: 'Cloud', segments: [] }, + ...STUBS, + }) + expect(w.find('button').text()).toBe('Cloud') + }) + + it('renders chevronRight separator between segments', () => { + const w = mount(BreadcrumbBar, { + props: { segments: [seg('a', 'A'), seg('b', 'B')] }, + ...STUBS, + }) + const appIcons = w.findAll('app-icon-stub') + expect(appIcons.length).toBeGreaterThanOrEqual(1) + }) +})