@@ -178,23 +178,23 @@ vi.mock('react-bootstrap', () => {
178178 Item : ( { children, ...props } : MockComponentProps ) => h ( 'button' , { ...props } , children ) ,
179179 } ;
180180
181- const Nav = ( { children, ... props } : MockComponentProps ) =>
182- h ( 'nav ' , { ... props } , children ) ;
181+ const Nav = ( { children, className } : MockComponentProps ) =>
182+ h ( 'div ' , { className } , children ) ;
183183
184- Nav . Link = ( { children, ... props } : MockComponentProps ) =>
185- h ( 'a' , { ... props } , children ) ;
184+ Nav . Link = ( { children, href , onClick , className } : MockComponentProps ) =>
185+ h ( 'a' , { href , onClick , className } , children ) ;
186186
187- const Navbar = ( { children, ... props } : MockComponentProps ) =>
188- h ( 'nav' , { ... props , className : 'navbar' } , children ) ;
187+ const Navbar = ( { children, id , hidden , className } : MockComponentProps ) =>
188+ h ( 'nav' , { id , hidden , className : className ? className : 'navbar' , role : 'navigation ' } , children ) ;
189189
190- Navbar . Brand = ( { children, ... props } : MockComponentProps ) =>
191- h ( 'a' , { ... props , className : 'navbar-brand' } , children ) ;
190+ Navbar . Brand = ( { children, href , className } : MockComponentProps ) =>
191+ h ( 'a' , { href , className : className ? className : 'navbar-brand' } , children ) ;
192192
193- Navbar . Toggle = ( { children, ... props } : MockComponentProps ) =>
194- h ( 'button' , { ... props , className : 'navbar-toggle' } , children ) ;
193+ Navbar . Toggle = ( { children, onClick , id , 'aria-controls' : ariaControls } : MockComponentProps & { 'aria-controls' ?: string } ) =>
194+ h ( 'button' , { onClick , id , 'aria-controls' : ariaControls , className : 'navbar-toggle' } , children ) ;
195195
196- Navbar . Collapse = ( { children, ... props } : MockComponentProps ) =>
197- h ( 'div' , { ... props , className : 'navbar-collapse' } , children ) ;
196+ Navbar . Collapse = ( { children, id , className } : MockComponentProps ) =>
197+ h ( 'div' , { id , className : className ? className : 'navbar-collapse' } , children ) ;
198198
199199 const InputGroup = ( { children, ...props } : MockComponentProps ) =>
200200 h ( 'div' , { ...props , className : 'input-group' } , children ) ;
@@ -286,15 +286,41 @@ vi.mock('react-bootstrap/Button', () => {
286286 } ;
287287} ) ;
288288
289- // Mock react-feather icons
289+ // Direct import path mocks for Nav and Navbar
290+ vi . mock ( 'react-bootstrap/Nav' , ( ) => {
291+ const Nav = ( { children, className } : MockComponentProps ) => h ( 'div' , { className } , children ) ;
292+ const NavWithStatics = Object . assign ( Nav , {
293+ Link : ( { children, href, onClick, className } : MockComponentProps ) =>
294+ h ( 'a' , { href, onClick, className } , children ) ,
295+ } ) ;
296+ return { default : NavWithStatics } ;
297+ } ) ;
298+
299+ vi . mock ( 'react-bootstrap/Navbar' , ( ) => {
300+ const Navbar = ( { children, id, hidden, className } : MockComponentProps ) =>
301+ h ( 'nav' , { id, hidden, className, role : 'navigation' } , children ) ;
302+ const NavbarWithStatics = Object . assign ( Navbar , {
303+ Brand : ( { children, href, className } : MockComponentProps ) => h ( 'a' , { href, className } , children ) ,
304+ Toggle : ( { children, onClick, id, 'aria-controls' : ariaControls } : MockComponentProps & { 'aria-controls' ?: string } ) =>
305+ h ( 'button' , { onClick, id, 'aria-controls' : ariaControls , className : 'navbar-toggle' } , children ) ,
306+ Collapse : ( { children, id, className } : MockComponentProps ) => h ( 'div' , { id, className } , children ) ,
307+ } ) ;
308+ return { default : NavbarWithStatics } ;
309+ } ) ;
310+
311+ // Mock react-feather icons (use non-SVG to avoid namespace issues in jsdom)
290312vi . mock ( 'react-feather' , ( ) => ( {
291- ChevronDown : ( ) => h ( 'svg' , { 'data-testid' : 'chevron-down' } ) ,
292- ChevronUp : ( ) => h ( 'svg' , { 'data-testid' : 'chevron-up' } ) ,
293- Edit : ( ) => h ( 'svg' , { 'data-testid' : 'edit-icon' } ) ,
294- Eye : ( ) => h ( 'svg' , { 'data-testid' : 'eye-icon' } ) ,
295- EyeOff : ( ) => h ( 'svg' , { 'data-testid' : 'eye-off-icon' } ) ,
296- Monitor : ( ) => h ( 'svg' , { 'data-testid' : 'monitor-icon' } ) ,
297- Trash2 : ( ) => h ( 'svg' , { 'data-testid' : 'trash-icon' , className : 'feather-trash-2' } ) ,
313+ ChevronDown : ( ) => h ( 'span' , { 'data-testid' : 'chevron-down' } ) ,
314+ ChevronUp : ( ) => h ( 'span' , { 'data-testid' : 'chevron-up' } ) ,
315+ Edit : ( ) => h ( 'span' , { 'data-testid' : 'edit-icon' } ) ,
316+ Eye : ( ) => h ( 'span' , { 'data-testid' : 'eye-icon' } ) ,
317+ EyeOff : ( ) => h ( 'span' , { 'data-testid' : 'eye-off-icon' } ) ,
318+ Monitor : ( ) => h ( 'span' , { 'data-testid' : 'monitor-icon' } ) ,
319+ Trash2 : ( ) => h ( 'span' , { 'data-testid' : 'trash-icon' , className : 'feather-trash-2' } ) ,
320+ Key : ( ) => h ( 'span' , { 'data-testid' : 'key-icon' } ) ,
321+ LogOut : ( ) => h ( 'span' , { 'data-testid' : 'logout-icon' } ) ,
322+ Server : ( ) => h ( 'span' , { 'data-testid' : 'server-icon' } ) ,
323+ User : ( ) => h ( 'span' , { 'data-testid' : 'user-icon' } ) ,
298324} ) ) ;
299325
300326// Mock i18next
@@ -365,19 +391,24 @@ vi.mock('./utils', () => ({
365391 storeSecretKeyInServiceWorker : vi . fn ( ) ,
366392 bc : { postMessage : vi . fn ( ) } ,
367393 isDebugMode : { value : false } ,
394+ resetSecret : vi . fn ( ) ,
395+ clearSecretKeyFromServiceWorker : vi . fn ( ) . mockResolvedValue ( undefined ) ,
396+ FRONTEND_URL : '' ,
368397} ) ) ;
369398
370399// Mock preact-iso
371400vi . mock ( 'preact-iso' , ( ) => ( {
372401 useLocation : ( ) => ( {
373402 route : vi . fn ( ) ,
403+ url : '/' ,
374404 } ) ,
375405} ) ) ;
376406
377407// Mock median-js-bridge
378408vi . mock ( 'median-js-bridge' , ( ) => ( {
379409 default : {
380410 isNativeApp : ( ) => false ,
411+ sidebar : { setItems : vi . fn ( ) } ,
381412 } ,
382413} ) ) ;
383414
@@ -403,9 +434,18 @@ vi.mock('./components/Circle', () => ({
403434 Circle : vi . fn ( ( ) => null ) ,
404435} ) ) ;
405436
406- // Mock Navbar component
407- vi . mock ( './components/Navbar' , ( ) => ( {
408- logout : vi . fn ( ) ,
437+ // Mock components/Navbar to stub logout but keep other exports real
438+ vi . mock ( './components/Navbar' , async ( importOriginal ) => {
439+ const actual = await importOriginal < typeof import ( './components/Navbar' ) > ( ) ;
440+ return {
441+ ...actual ,
442+ logout : vi . fn ( ) ,
443+ } ;
444+ } ) ;
445+
446+ // Also mock direct Alert import path used by components (Navbar imports './Alert')
447+ vi . mock ( './Alert' , ( ) => ( {
448+ showAlert : vi . fn ( ) ,
409449} ) ) ;
410450
411451// Mock PasswordComponent
0 commit comments