22import { authMockFns } from '@sim/testing'
33import { beforeEach , describe , expect , it , vi } from 'vitest'
44
5- const { redirect, organizationContext } = vi . hoisted ( ( ) => ( {
5+ const { redirect, organizationContext, organizationAccess } = vi . hoisted ( ( ) => ( {
66 redirect : vi . fn ( ) ,
77 organizationContext : vi . fn ( ) ,
8+ organizationAccess : vi . fn ( ) ,
89} ) )
910vi . mock ( 'next/navigation' , ( ) => ( { redirect } ) )
1011vi . mock ( '@/lib/organizations/surface' , ( ) => ( {
1112 getOrganizationSurfaceContext : organizationContext ,
1213} ) )
13- vi . mock ( '@/ee/access-requests/components/my- access-requests' , ( ) => ( {
14- MyAccessRequests : ( ) => null ,
14+ vi . mock ( '@/ee/access-requests/components/access-requests-settings ' , ( ) => ( {
15+ AccessRequestsSettings : ( ) => null ,
1516} ) )
16- vi . mock ( '@/ee/access-requests/components/organization -access-requests ' , ( ) => ( {
17- OrganizationAccessRequests : ( ) => null ,
17+ vi . mock ( '@/lib/organizations/settings -access' , ( ) => ( {
18+ getOrganizationSettingsAccess : organizationAccess ,
1819} ) )
1920
2021import AccessRequestsPage from '@/app/access-requests/page'
21- import { MyAccessRequests } from '@/ee/access-requests/components/my- access-requests'
22+ import { AccessRequestsSettings } from '@/ee/access-requests/components/access-requests-settings '
2223
2324describe ( 'access request sign-in redirect' , ( ) => {
2425 beforeEach ( ( ) => {
2526 vi . clearAllMocks ( )
27+ organizationAccess . mockResolvedValue ( { isAdmin : false , isMember : true } )
2628 authMockFns . mockGetSession . mockResolvedValue ( null )
2729 redirect . mockImplementation ( ( ) => {
2830 throw new Error ( 'Redirect' )
@@ -92,7 +94,7 @@ describe('access request sign-in redirect', () => {
9294 ) . rejects . toThrow ( 'Redirect' )
9395 expect ( organizationContext ) . toHaveBeenCalledWith ( 'organization' , 'viewer' )
9496 const destination = new URL ( redirect . mock . calls [ 0 ] [ 0 ] , 'https://example.com' )
95- expect ( destination . pathname ) . toBe ( '/o/organization/access- requests' )
97+ expect ( destination . pathname ) . toBe ( '/o/organization/settings/ requests' )
9698 expect ( Object . fromEntries ( destination . searchParams ) ) . toEqual ( {
9799 view : 'catalog' ,
98100 requestId : 'request/a' ,
@@ -107,38 +109,90 @@ describe('access request sign-in redirect', () => {
107109 authMockFns . mockGetSession . mockResolvedValue ( { user : { id : 'viewer' } } )
108110 organizationContext . mockResolvedValue ( context )
109111 await AccessRequestsPage ( {
110- searchParams : Promise . resolve ( { organizationId : 'organization' } ) ,
112+ searchParams : Promise . resolve ( { organizationId : 'organization' , view : 'requests' } ) ,
111113 } )
112114 expect ( redirect ) . not . toHaveBeenCalled ( )
113115 }
114116 )
115117
116- it ( 'keeps authenticated administrator email links on the review surface ' , async ( ) => {
118+ it ( 'normalizes saved administrator email links without losing review state ' , async ( ) => {
117119 authMockFns . mockGetSession . mockResolvedValue ( { user : { id : 'viewer' } } )
118- await AccessRequestsPage ( {
119- searchParams : Promise . resolve ( {
120- organizationId : 'organization' ,
121- view : 'admin' ,
122- requestId : 'request' ,
123- } ) ,
120+ await expect (
121+ AccessRequestsPage ( {
122+ searchParams : Promise . resolve ( {
123+ organizationId : 'organization' ,
124+ view : 'admin' ,
125+ requestId : 'request' ,
126+ 'request-status' : 'declined' ,
127+ } ) ,
128+ } )
129+ ) . rejects . toThrow ( 'Redirect' )
130+ const destination = new URL ( redirect . mock . calls [ 0 ] [ 0 ] , 'https://example.com' )
131+ expect ( Object . fromEntries ( destination . searchParams ) ) . toEqual ( {
132+ organizationId : 'organization' ,
133+ view : 'review' ,
134+ 'request-id' : 'request' ,
135+ 'request-status' : 'declined' ,
124136 } )
125- expect ( redirect ) . not . toHaveBeenCalled ( )
126137 expect ( organizationContext ) . not . toHaveBeenCalled ( )
127138 } )
128139
140+ it ( 'routes reviewer links into organization settings when the shell is available' , async ( ) => {
141+ authMockFns . mockGetSession . mockResolvedValue ( { user : { id : 'viewer' } } )
142+ organizationContext . mockResolvedValue ( { searchAccess : { memberScoped : true } } )
143+ await expect (
144+ AccessRequestsPage ( {
145+ searchParams : Promise . resolve ( {
146+ organizationId : 'organization' ,
147+ view : 'review' ,
148+ 'request-id' : 'request' ,
149+ } ) ,
150+ } )
151+ ) . rejects . toThrow ( 'Redirect' )
152+ expect ( redirect ) . toHaveBeenCalledWith (
153+ '/o/organization/settings/requests?request-id=request&view=review'
154+ )
155+ } )
156+
157+ it . each ( [ undefined , 'invalid' , [ 'requests' , 'review' ] ] ) (
158+ 'keeps invalid or old requester links on My requests: %j' ,
159+ async ( view ) => {
160+ authMockFns . mockGetSession . mockResolvedValue ( { user : { id : 'viewer' } } )
161+ await expect (
162+ AccessRequestsPage ( {
163+ searchParams : Promise . resolve ( {
164+ organizationId : 'organization' ,
165+ requestId : 'request' ,
166+ view,
167+ } ) ,
168+ } )
169+ ) . rejects . toThrow ( 'Redirect' )
170+ const destination = new URL ( redirect . mock . calls [ 0 ] [ 0 ] , 'https://example.com' )
171+ expect ( destination . searchParams . get ( 'view' ) ) . toBe ( 'requests' )
172+ expect ( destination . searchParams . get ( 'requestId' ) ) . toBe ( 'request' )
173+ }
174+ )
175+
129176 it ( 'renders the standalone requester when the optional organization navigation lookup fails' , async ( ) => {
130177 authMockFns . mockGetSession . mockResolvedValue ( { user : { id : 'viewer' } } )
131178 organizationContext . mockRejectedValue ( new Error ( 'Organization context unavailable' ) )
132179
133180 const page = await AccessRequestsPage ( {
134- searchParams : Promise . resolve ( { organizationId : 'organization' , requestId : 'request' } ) ,
181+ searchParams : Promise . resolve ( {
182+ organizationId : 'organization' ,
183+ view : 'requests' ,
184+ requestId : 'request' ,
185+ } ) ,
135186 } )
136187
137188 expect ( redirect ) . not . toHaveBeenCalled ( )
138- expect ( page . props . children . type ) . toBe ( MyAccessRequests )
139- expect ( page . props . children . props ) . toEqual ( {
189+ expect ( page . props . children . props . children . props . children . props . children . type ) . toBe (
190+ AccessRequestsSettings
191+ )
192+ expect ( page . props . children . props . children . props . children . props . children . props ) . toEqual ( {
140193 scope : { kind : 'organization' , organizationId : 'organization' } ,
141194 standalone : true ,
195+ reviewOrganizationId : undefined ,
142196 } )
143197 } )
144198} )
0 commit comments