11import { Header } from './Header'
22import './index'
3+ import { authn , authSession } from 'solid-logic'
4+
5+ type Listener = ( ) => void
6+ const mockSessionListeners = new Map < string , Set < Listener > > ( )
7+
8+ jest . mock ( 'solid-logic' , ( ) => ( {
9+ authn : {
10+ checkUser : jest . fn ( async ( ) => null ) ,
11+ currentUser : jest . fn ( ( ) => null )
12+ } ,
13+ authSession : {
14+ logout : jest . fn ( async ( ) => undefined ) ,
15+ events : {
16+ on : jest . fn ( ( event : string , handler : Listener ) => {
17+ if ( ! mockSessionListeners . has ( event ) ) mockSessionListeners . set ( event , new Set ( ) )
18+ mockSessionListeners . get ( event ) ?. add ( handler )
19+ } ) ,
20+ off : jest . fn ( ( event : string , handler : Listener ) => {
21+ mockSessionListeners . get ( event ) ?. delete ( handler )
22+ } ) ,
23+ emit : jest . fn ( ( event : string ) => {
24+ mockSessionListeners . get ( event ) ?. forEach ( handler => handler ( ) )
25+ } )
26+ }
27+ }
28+ } ) )
329
430describe ( 'SolidUIHeaderElement' , ( ) => {
531 beforeEach ( ( ) => {
632 document . body . innerHTML = ''
33+ jest . clearAllMocks ( )
34+ mockSessionListeners . clear ( )
35+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( null )
36+ ; ( authn . checkUser as jest . Mock ) . mockResolvedValue ( null )
737 Object . defineProperty ( window , 'open' , {
838 configurable : true ,
939 writable : true ,
@@ -77,6 +107,8 @@ describe('SolidUIHeaderElement', () => {
77107 expect ( signUpLink . getAttribute ( 'icon' ) ) . toBe ( 'https://example.com/signup-icon-top.svg' )
78108
79109 loginButton . dispatchEvent ( new CustomEvent ( 'login-success' , { bubbles : true , composed : true } ) )
110+ await Promise . resolve ( )
111+ await header . updateComplete
80112
81113 expect ( authActionSelected ) . toHaveBeenCalledWith ( {
82114 role : 'login'
@@ -105,6 +137,7 @@ describe('SolidUIHeaderElement', () => {
105137
106138 it ( 'uses a custom fallback avatar when no accountAvatar is configured' , async ( ) => {
107139 const header = new Header ( )
140+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( { uri : 'https://alice.example/profile/card#me' } )
108141
109142 header . authState = 'logged-in'
110143 header . accountAvatar = ''
@@ -123,6 +156,7 @@ describe('SolidUIHeaderElement', () => {
123156 it ( 'renders an accounts dropdown with avatar when logged in' , async ( ) => {
124157 const header = new Header ( )
125158 const accountMenuSelected = jest . fn ( )
159+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( { uri : 'https://alice.example/profile/card#me' } )
126160
127161 header . authState = 'logged-in'
128162 header . accountIcon = 'https://example.com/account-icon.svg'
@@ -173,6 +207,7 @@ describe('SolidUIHeaderElement', () => {
173207
174208 it ( 'does not render the logout icon on mobile layout' , async ( ) => {
175209 const header = new Header ( )
210+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( { uri : 'https://alice.example/profile/card#me' } )
176211 header . layout = 'mobile'
177212 header . authState = 'logged-in'
178213 header . logoutIcon = 'https://example.com/logout-icon.svg'
@@ -196,6 +231,7 @@ describe('SolidUIHeaderElement', () => {
196231
197232 it ( 'does not render account webid on mobile layout' , async ( ) => {
198233 const header = new Header ( )
234+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( { uri : 'https://alice.example/profile/card#me' } )
199235 header . layout = 'mobile'
200236 header . authState = 'logged-in'
201237 header . accountMenu = [
@@ -263,6 +299,7 @@ describe('SolidUIHeaderElement', () => {
263299
264300 it ( 'renders helpMenuList inside the help dropdown and dispatches events' , async ( ) => {
265301 const header = new Header ( )
302+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( { uri : 'https://alice.example/profile/card#me' } )
266303
267304 const helpMenuClicked = jest . fn ( )
268305
@@ -304,4 +341,35 @@ describe('SolidUIHeaderElement', () => {
304341
305342 window . open = originalWindowOpen
306343 } )
344+
345+ it ( 'derives auth state from session on connect' , async ( ) => {
346+ const header = new Header ( )
347+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( { uri : 'https://alice.example/profile/card#me' } )
348+
349+ document . body . appendChild ( header )
350+ await header . updateComplete
351+ await Promise . resolve ( )
352+ await header . updateComplete
353+
354+ expect ( authn . checkUser ) . toHaveBeenCalled ( )
355+ expect ( header . authState ) . toBe ( 'logged-in' )
356+ } )
357+
358+ it ( 'refreshes auth state when session events fire' , async ( ) => {
359+ const header = new Header ( )
360+ document . body . appendChild ( header )
361+ await header . updateComplete
362+
363+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( { uri : 'https://alice.example/profile/card#me' } )
364+ ; ( authSession . events as any ) . emit ( 'login' )
365+ await Promise . resolve ( )
366+ await header . updateComplete
367+ expect ( header . authState ) . toBe ( 'logged-in' )
368+
369+ ; ( authn . currentUser as jest . Mock ) . mockReturnValue ( null )
370+ ; ( authSession . events as any ) . emit ( 'logout' )
371+ await Promise . resolve ( )
372+ await header . updateComplete
373+ expect ( header . authState ) . toBe ( 'logged-out' )
374+ } )
307375} )
0 commit comments