1+ import { Theme } from "@radix-ui/themes" ;
12import { render , screen } from "@testing-library/react" ;
23import userEvent from "@testing-library/user-event" ;
4+ import type { ReactElement } from "react" ;
35import { beforeEach , describe , expect , it , vi } from "vitest" ;
6+ import { ScopeReauthPrompt } from "./ScopeReauthPrompt" ;
47
5- vi . mock ( "@renderer/trpc/client" , ( ) => ( {
6- trpcClient : {
7- auth : {
8- getState : { query : vi . fn ( ) } ,
9- onStateChanged : { subscribe : vi . fn ( ( ) => ( { unsubscribe : vi . fn ( ) } ) ) } ,
10- getValidAccessToken : {
11- query : vi . fn ( ) . mockResolvedValue ( {
12- accessToken : "token" ,
13- apiHost : "https://us.posthog.com" ,
14- } ) ,
15- } ,
16- refreshAccessToken : {
17- mutate : vi . fn ( ) . mockResolvedValue ( {
18- accessToken : "token" ,
19- apiHost : "https://us.posthog.com" ,
20- } ) ,
21- } ,
22- login : {
23- mutate : vi . fn ( ) . mockResolvedValue ( {
24- state : {
25- status : "authenticated" ,
26- bootstrapComplete : true ,
27- cloudRegion : "us" ,
28- projectId : 1 ,
29- availableProjectIds : [ 1 ] ,
30- availableOrgIds : [ ] ,
31- hasCodeAccess : true ,
32- needsScopeReauth : false ,
33- } ,
34- } ) ,
35- } ,
36- signup : { mutate : vi . fn ( ) } ,
37- selectProject : { mutate : vi . fn ( ) } ,
38- redeemInviteCode : { mutate : vi . fn ( ) } ,
39- logout : {
40- mutate : vi . fn ( ) . mockResolvedValue ( {
41- status : "anonymous" ,
42- bootstrapComplete : true ,
43- cloudRegion : null ,
44- projectId : null ,
45- availableProjectIds : [ ] ,
46- availableOrgIds : [ ] ,
47- hasCodeAccess : null ,
48- needsScopeReauth : false ,
49- } ) ,
50- } ,
51- } ,
52- analytics : {
53- setUserId : { mutate : vi . fn ( ) . mockResolvedValue ( undefined ) } ,
54- resetUser : { mutate : vi . fn ( ) . mockResolvedValue ( undefined ) } ,
55- } ,
56- } ,
8+ const authState = {
9+ status : "anonymous" as const ,
10+ bootstrapComplete : true ,
11+ cloudRegion : null as "us" | "eu" | "dev" | null ,
12+ projectId : null ,
13+ availableProjectIds : [ ] ,
14+ availableOrgIds : [ ] ,
15+ hasCodeAccess : null ,
16+ needsScopeReauth : false ,
17+ } ;
18+
19+ const mockLoginMutateAsync = vi . fn ( ) ;
20+ const mockLogoutMutate = vi . fn ( ( ) => {
21+ authState . needsScopeReauth = false ;
22+ authState . cloudRegion = null ;
23+ } ) ;
24+
25+ vi . mock ( "@features/auth/hooks/authQueries" , ( ) => ( {
26+ useAuthStateValue : ( selector : ( state : typeof authState ) => unknown ) =>
27+ selector ( authState ) ,
5728} ) ) ;
5829
59- vi . mock ( "@utils/analytics" , ( ) => ( {
60- identifyUser : vi . fn ( ) ,
61- resetUser : vi . fn ( ) ,
62- track : vi . fn ( ) ,
30+ vi . mock ( "@features/auth/hooks/authMutations" , ( ) => ( {
31+ useLoginMutation : ( ) => ( {
32+ mutateAsync : mockLoginMutateAsync ,
33+ isPending : false ,
34+ } ) ,
35+ useLogoutMutation : ( ) => ( {
36+ mutate : mockLogoutMutate ,
37+ } ) ,
6338} ) ) ;
6439
6540vi . mock ( "@utils/logger" , ( ) => ( {
@@ -73,40 +48,18 @@ vi.mock("@utils/logger", () => ({
7348 } ,
7449} ) ) ;
7550
76- vi . mock ( "@utils/queryClient" , ( ) => ( {
77- queryClient : {
78- clear : vi . fn ( ) ,
79- setQueryData : vi . fn ( ) ,
80- removeQueries : vi . fn ( ) ,
81- } ,
82- } ) ) ;
83-
84- vi . mock ( "@stores/navigationStore" , ( ) => ( {
85- useNavigationStore : {
86- getState : ( ) => ( { navigateToTaskInput : vi . fn ( ) } ) ,
87- } ,
88- } ) ) ;
89-
90- import {
91- resetAuthStoreModuleStateForTest ,
92- useAuthStore ,
93- } from "@features/auth/stores/authStore" ;
94- import { Theme } from "@radix-ui/themes" ;
95- import type { ReactElement } from "react" ;
96- import { ScopeReauthPrompt } from "./ScopeReauthPrompt" ;
97-
9851function renderWithTheme ( ui : ReactElement ) {
9952 return render ( < Theme > { ui } </ Theme > ) ;
10053}
10154
10255describe ( "ScopeReauthPrompt" , ( ) => {
10356 beforeEach ( ( ) => {
104- localStorage . clear ( ) ;
105- resetAuthStoreModuleStateForTest ( ) ;
106- useAuthStore . setState ( {
107- needsScopeReauth : false ,
108- cloudRegion : null ,
109- } ) ;
57+ vi . clearAllMocks ( ) ;
58+ authState . status = "anonymous" ;
59+ authState . cloudRegion = null ;
60+ authState . projectId = null ;
61+ authState . hasCodeAccess = null ;
62+ authState . needsScopeReauth = false ;
11063 } ) ;
11164
11265 it ( "does not render dialog when needsScopeReauth is false" , ( ) => {
@@ -117,25 +70,34 @@ describe("ScopeReauthPrompt", () => {
11770 } ) ;
11871
11972 it ( "renders dialog when needsScopeReauth is true" , ( ) => {
120- useAuthStore . setState ( { needsScopeReauth : true , cloudRegion : "us" } ) ;
73+ authState . needsScopeReauth = true ;
74+ authState . cloudRegion = "us" ;
75+
12176 renderWithTheme ( < ScopeReauthPrompt /> ) ;
77+
12278 expect ( screen . getByText ( "Re-authentication required" ) ) . toBeInTheDocument ( ) ;
12379 } ) ;
12480
12581 it ( "disables Sign in button when cloudRegion is null" , ( ) => {
126- useAuthStore . setState ( { needsScopeReauth : true , cloudRegion : null } ) ;
82+ authState . needsScopeReauth = true ;
83+
12784 renderWithTheme ( < ScopeReauthPrompt /> ) ;
85+
12886 expect ( screen . getByRole ( "button" , { name : "Sign in" } ) ) . toBeDisabled ( ) ;
12987 } ) ;
13088
13189 it ( "enables Sign in button when cloudRegion is set" , ( ) => {
132- useAuthStore . setState ( { needsScopeReauth : true , cloudRegion : "us" } ) ;
90+ authState . needsScopeReauth = true ;
91+ authState . cloudRegion = "us" ;
92+
13393 renderWithTheme ( < ScopeReauthPrompt /> ) ;
94+
13495 expect ( screen . getByRole ( "button" , { name : "Sign in" } ) ) . not . toBeDisabled ( ) ;
13596 } ) ;
13697
13798 it ( "shows Log out button as an escape hatch when cloudRegion is null" , ( ) => {
138- useAuthStore . setState ( { needsScopeReauth : true , cloudRegion : null } ) ;
99+ authState . needsScopeReauth = true ;
100+
139101 renderWithTheme ( < ScopeReauthPrompt /> ) ;
140102
141103 const logoutButton = screen . getByRole ( "button" , { name : "Log out" } ) ;
@@ -145,14 +107,14 @@ describe("ScopeReauthPrompt", () => {
145107
146108 it ( "calls logout when Log out button is clicked" , async ( ) => {
147109 const user = userEvent . setup ( ) ;
148- useAuthStore . setState ( { needsScopeReauth : true , cloudRegion : null } ) ;
110+ authState . needsScopeReauth = true ;
111+
149112 renderWithTheme ( < ScopeReauthPrompt /> ) ;
150113
151114 await user . click ( screen . getByRole ( "button" , { name : "Log out" } ) ) ;
152115
153- const state = useAuthStore . getState ( ) ;
154- expect ( state . needsScopeReauth ) . toBe ( false ) ;
155- expect ( state . isAuthenticated ) . toBe ( false ) ;
156- expect ( state . cloudRegion ) . toBeNull ( ) ;
116+ expect ( mockLogoutMutate ) . toHaveBeenCalledTimes ( 1 ) ;
117+ expect ( authState . needsScopeReauth ) . toBe ( false ) ;
118+ expect ( authState . cloudRegion ) . toBeNull ( ) ;
157119 } ) ;
158120} ) ;
0 commit comments