@@ -501,6 +501,211 @@ describe('Leaderboard API', () => {
501501 } ) ;
502502} ) ;
503503
504+ describe ( 'GET /dashboard/quests' , ( ) => {
505+ beforeAll ( async ( ) => {
506+ await setupTestDatabase ( ) ;
507+ } ) ;
508+
509+ afterAll ( async ( ) => {
510+ await teardownTestDatabase ( ) ;
511+ } ) ;
512+
513+ beforeEach ( async ( ) => {
514+ await clearTestData ( ) ;
515+ resetUserCounter ( ) ;
516+ } ) ;
517+
518+ it ( 'should only show personalized quests to the assigned user' , async ( ) => {
519+ const questGiver = await createTestUser ( { role : 'EDITOR' } ) ;
520+ const assignedPlayer = await createTestUser ( { role : 'PLAYER' , email : 'assigned@test.com' } ) ;
521+ const otherPlayer = await createTestUser ( { role : 'PLAYER' , email : 'other@test.com' } ) ;
522+
523+ // Create a global quest
524+ await createTestQuest ( questGiver . id , {
525+ title : 'Global Quest' ,
526+ status : 'AVAILABLE' ,
527+ bounty : 100
528+ } ) ;
529+
530+ // Create a personalized quest for assignedPlayer
531+ await createTestQuest ( questGiver . id , {
532+ title : 'Personalized Quest' ,
533+ status : 'AVAILABLE' ,
534+ bounty : 150 ,
535+ userId : assignedPlayer . id
536+ } ) ;
537+
538+ // Create a personalized quest for otherPlayer
539+ await createTestQuest ( questGiver . id , {
540+ title : 'Other Player Quest' ,
541+ status : 'AVAILABLE' ,
542+ bounty : 200 ,
543+ userId : otherPlayer . id
544+ } ) ;
545+
546+ // Assigned player should see global quest and their personalized quest
547+ const assignedPlayerToken = createTestToken ( assignedPlayer . id , assignedPlayer . email , assignedPlayer . role ) ;
548+ let response = await request ( app )
549+ . get ( '/dashboard/quests' )
550+ . set ( 'Authorization' , `Bearer ${ assignedPlayerToken } ` ) ;
551+
552+ expect ( response . status ) . toBe ( 200 ) ;
553+ expect ( response . body . data . quests ) . toHaveLength ( 2 ) ;
554+ const assignedPlayerTitles = response . body . data . quests . map ( ( q : any ) => q . title ) ;
555+ expect ( assignedPlayerTitles ) . toContain ( 'Global Quest' ) ;
556+ expect ( assignedPlayerTitles ) . toContain ( 'Personalized Quest' ) ;
557+ expect ( assignedPlayerTitles ) . not . toContain ( 'Other Player Quest' ) ;
558+
559+ // Other player should only see global quest and their own personalized quest
560+ const otherPlayerToken = createTestToken ( otherPlayer . id , otherPlayer . email , otherPlayer . role ) ;
561+ response = await request ( app )
562+ . get ( '/dashboard/quests' )
563+ . set ( 'Authorization' , `Bearer ${ otherPlayerToken } ` ) ;
564+
565+ expect ( response . status ) . toBe ( 200 ) ;
566+ expect ( response . body . data . quests ) . toHaveLength ( 2 ) ;
567+ const otherPlayerTitles = response . body . data . quests . map ( ( q : any ) => q . title ) ;
568+ expect ( otherPlayerTitles ) . toContain ( 'Global Quest' ) ;
569+ expect ( otherPlayerTitles ) . toContain ( 'Other Player Quest' ) ;
570+ expect ( otherPlayerTitles ) . not . toContain ( 'Personalized Quest' ) ;
571+ } ) ;
572+
573+ it ( 'admin should see all quests including personalized ones' , async ( ) => {
574+ const questGiver = await createTestUser ( { role : 'EDITOR' } ) ;
575+ const assignedPlayer = await createTestUser ( { role : 'PLAYER' , email : 'assigned@test.com' } ) ;
576+ const admin = await createTestUser ( { role : 'ADMIN' , email : 'admin@test.com' } ) ;
577+
578+ // Create a global quest
579+ await createTestQuest ( questGiver . id , {
580+ title : 'Global Quest' ,
581+ status : 'AVAILABLE' ,
582+ bounty : 100
583+ } ) ;
584+
585+ // Create a personalized quest
586+ await createTestQuest ( questGiver . id , {
587+ title : 'Personalized Quest' ,
588+ status : 'AVAILABLE' ,
589+ bounty : 150 ,
590+ userId : assignedPlayer . id
591+ } ) ;
592+
593+ const adminToken = createTestToken ( admin . id , admin . email , admin . role ) ;
594+ const response = await request ( app )
595+ . get ( '/dashboard/quests' )
596+ . set ( 'Authorization' , `Bearer ${ adminToken } ` ) ;
597+
598+ expect ( response . status ) . toBe ( 200 ) ;
599+ expect ( response . body . data . quests ) . toHaveLength ( 2 ) ;
600+ const titles = response . body . data . quests . map ( ( q : any ) => q . title ) ;
601+ expect ( titles ) . toContain ( 'Global Quest' ) ;
602+ expect ( titles ) . toContain ( 'Personalized Quest' ) ;
603+ } ) ;
604+
605+ it ( 'should exclude expired quests' , async ( ) => {
606+ const questGiver = await createTestUser ( { role : 'EDITOR' } ) ;
607+ const player = await createTestUser ( { role : 'PLAYER' } ) ;
608+ const token = createTestToken ( player . id , player . email , player . role ) ;
609+
610+ // Create a quest with past due date
611+ const pastDate = new Date ( ) ;
612+ pastDate . setDate ( pastDate . getDate ( ) - 1 ) ; // Yesterday
613+
614+ await createTestQuest ( questGiver . id , {
615+ title : 'Expired Quest' ,
616+ status : 'AVAILABLE' ,
617+ bounty : 100 ,
618+ dueDate : pastDate
619+ } ) ;
620+
621+ // Create a valid quest
622+ await createTestQuest ( questGiver . id , {
623+ title : 'Valid Quest' ,
624+ status : 'AVAILABLE' ,
625+ bounty : 100
626+ } ) ;
627+
628+ const response = await request ( app )
629+ . get ( '/dashboard/quests' )
630+ . set ( 'Authorization' , `Bearer ${ token } ` ) ;
631+
632+ expect ( response . status ) . toBe ( 200 ) ;
633+ expect ( response . body . data . quests ) . toHaveLength ( 1 ) ;
634+ expect ( response . body . data . quests [ 0 ] . title ) . toBe ( 'Valid Quest' ) ;
635+ } ) ;
636+
637+ it ( 'should support status filtering' , async ( ) => {
638+ const questGiver = await createTestUser ( { role : 'EDITOR' } ) ;
639+ const player = await createTestUser ( { role : 'PLAYER' } ) ;
640+ const token = createTestToken ( player . id , player . email , player . role ) ;
641+
642+ // Create quests with different statuses
643+ await createTestQuest ( questGiver . id , {
644+ title : 'Available Quest' ,
645+ status : 'AVAILABLE' ,
646+ bounty : 100
647+ } ) ;
648+
649+ await createTestQuest ( questGiver . id , {
650+ title : 'Claimed Quest' ,
651+ status : 'CLAIMED' ,
652+ claimedBy : player . id ,
653+ bounty : 200
654+ } ) ;
655+
656+ // Test filtering by AVAILABLE status
657+ let response = await request ( app )
658+ . get ( '/dashboard/quests?status=AVAILABLE' )
659+ . set ( 'Authorization' , `Bearer ${ token } ` ) ;
660+
661+ expect ( response . status ) . toBe ( 200 ) ;
662+ expect ( response . body . data . quests ) . toHaveLength ( 1 ) ;
663+ expect ( response . body . data . quests [ 0 ] . title ) . toBe ( 'Available Quest' ) ;
664+
665+ // Test filtering by CLAIMED status
666+ response = await request ( app )
667+ . get ( '/dashboard/quests?status=CLAIMED' )
668+ . set ( 'Authorization' , `Bearer ${ token } ` ) ;
669+
670+ expect ( response . status ) . toBe ( 200 ) ;
671+ expect ( response . body . data . quests ) . toHaveLength ( 1 ) ;
672+ expect ( response . body . data . quests [ 0 ] . title ) . toBe ( 'Claimed Quest' ) ;
673+ } ) ;
674+
675+ it ( 'should support search functionality' , async ( ) => {
676+ const questGiver = await createTestUser ( { role : 'EDITOR' } ) ;
677+ const player = await createTestUser ( { role : 'PLAYER' } ) ;
678+ const token = createTestToken ( player . id , player . email , player . role ) ;
679+
680+ // Create quests with different titles
681+ await createTestQuest ( questGiver . id , {
682+ title : 'Dragon Slayer Quest' ,
683+ status : 'AVAILABLE' ,
684+ bounty : 100
685+ } ) ;
686+
687+ await createTestQuest ( questGiver . id , {
688+ title : 'Treasure Hunt Quest' ,
689+ status : 'AVAILABLE' ,
690+ bounty : 200
691+ } ) ;
692+
693+ // Test search by title
694+ const response = await request ( app )
695+ . get ( '/dashboard/quests?search=dragon' ) // Using lowercase 'd' to test case-insensitivity
696+ . set ( 'Authorization' , `Bearer ${ token } ` ) ;
697+
698+ expect ( response . status ) . toBe ( 200 ) ;
699+ expect ( response . body . data . quests ) . toHaveLength ( 1 ) ;
700+ expect ( response . body . data . quests [ 0 ] . title ) . toBe ( 'Dragon Slayer Quest' ) ;
701+ } ) ;
702+
703+ it ( 'should require authentication' , async ( ) => {
704+ const response = await request ( app ) . get ( '/dashboard/quests' ) ;
705+ expect ( response . status ) . toBe ( 401 ) ;
706+ } ) ;
707+ } ) ;
708+
504709describe ( 'Reward Config API' , ( ) => {
505710 let adminUser : any ;
506711 let regularUser : any ;
0 commit comments