11import { userEvent } from "@testing-library/user-event" ;
22import { beforeEach , describe , expect , it , vi } from "vitest" ;
33import { TEST_ACCOUNT_A } from "~test/test-wallets.js" ;
4- import { render , waitFor } from "../../../../../../test/src/react-render.js" ;
4+ import {
5+ getByTestId ,
6+ render ,
7+ waitFor ,
8+ } from "../../../../../../test/src/react-render.js" ;
59import { TEST_CLIENT } from "../../../../../../test/src/test-clients.js" ;
610import { createWallet } from "../../../../../wallets/create-wallet.js" ;
711import type { ConnectLocale } from "../locale/types.js" ;
812import { SignatureScreen } from "./SignatureScreen.js" ;
13+ import { useActiveWallet } from "../../../../core/hooks/wallets/useActiveWallet.js" ;
914
1015const mockAuth = vi . hoisted ( ( ) => ( {
1116 doLogin : vi . fn ( ) . mockResolvedValue ( undefined ) ,
@@ -14,14 +19,12 @@ const mockAuth = vi.hoisted(() => ({
1419 isLoggedIn : vi . fn ( ) . mockResolvedValue ( true ) ,
1520} ) ) ;
1621
17- const wallet = createWallet ( "io.metamask" ) ;
18-
1922vi . mock ( "../../../../core/hooks/auth/useSiweAuth" , ( ) => ( {
2023 useSiweAuth : ( ) => mockAuth ,
2124} ) ) ;
2225
2326vi . mock ( "../../../../core/hooks/wallets/useActiveWallet" , ( ) => ( {
24- useActiveWallet : ( ) => wallet ,
27+ useActiveWallet : vi . fn ( ) . mockReturnValue ( createWallet ( "io.metamask" ) ) ,
2528} ) ) ;
2629
2730vi . mock ( "../../../../core/hooks/wallets/useActiveAccount" , ( ) => ( {
@@ -102,10 +105,9 @@ describe("SignatureScreen", () => {
102105 } ) ;
103106
104107 it ( "shows loading state when wallet is undefined" , async ( ) => {
105- // Override the mock to return undefined for this test
106108 vi . mocked ( useActiveWallet ) . mockReturnValueOnce ( undefined ) ;
107109
108- const { getByTestId } = render (
110+ const { queryByTestId } = render (
109111 < SignatureScreen
110112 onDone = { ( ) => { } }
111113 modalSize = "wide"
@@ -116,12 +118,12 @@ describe("SignatureScreen", () => {
116118 { setConnectedWallet : true } ,
117119 ) ;
118120
119- expect ( getByTestId ( "loading-screen ") ) . toBeInTheDocument ( ) ;
121+ expect ( queryByTestId ( "sign-in-button ") ) . not . toBeInTheDocument ( ) ;
120122 } ) ;
121123
122124 it ( "handles error state" , async ( ) => {
123125 mockAuth . doLogin . mockRejectedValueOnce ( new Error ( "Signing failed" ) ) ;
124- const { getByRole, getByText } = render (
126+ const { getByTestId , getByRole, getByText } = render (
125127 < SignatureScreen
126128 onDone = { ( ) => { } }
127129 modalSize = "wide"
@@ -132,7 +134,9 @@ describe("SignatureScreen", () => {
132134 { setConnectedWallet : true } ,
133135 ) ;
134136
135- const signInButton = getByRole ( "button" , { name : "Sign In" } ) ;
137+ const signInButton = await waitFor ( ( ) => {
138+ return getByTestId ( "sign-in-button" ) ;
139+ } ) ;
136140 await userEvent . click ( signInButton ) ;
137141
138142 // Should show error state
@@ -146,4 +150,142 @@ describe("SignatureScreen", () => {
146150 } ,
147151 ) ;
148152 } ) ;
153+
154+ describe ( "HeadlessSignIn" , ( ) => {
155+ const mockWallet = createWallet ( "inApp" ) ;
156+ beforeEach ( ( ) => {
157+ vi . mocked ( useActiveWallet ) . mockReturnValue ( mockWallet ) ;
158+ } ) ;
159+
160+ it ( "automatically triggers sign in on mount" , async ( ) => {
161+ render (
162+ < SignatureScreen
163+ onDone = { ( ) => { } }
164+ modalSize = "wide"
165+ connectLocale = { mockConnectLocale }
166+ client = { TEST_CLIENT }
167+ auth = { mockAuth }
168+ /> ,
169+ { setConnectedWallet : true } ,
170+ ) ;
171+
172+ await waitFor ( ( ) => {
173+ expect ( mockAuth . doLogin ) . toHaveBeenCalledTimes ( 1 ) ;
174+ } ) ;
175+ } ) ;
176+
177+ it ( "shows signing message during signing state" , async ( ) => {
178+ const { getByText } = render (
179+ < SignatureScreen
180+ onDone = { ( ) => { } }
181+ modalSize = "wide"
182+ connectLocale = { mockConnectLocale }
183+ client = { TEST_CLIENT }
184+ auth = { mockAuth }
185+ /> ,
186+ { setConnectedWallet : true } ,
187+ ) ;
188+
189+ await waitFor ( ( ) => {
190+ expect ( getByText ( "Signing" ) ) . toBeInTheDocument ( ) ;
191+ } ) ;
192+ } ) ;
193+
194+ it ( "shows error and retry button when signing fails" , async ( ) => {
195+ mockAuth . doLogin . mockRejectedValueOnce (
196+ new Error ( "Headless signing failed" ) ,
197+ ) ;
198+
199+ const { getByText, getByRole } = render (
200+ < SignatureScreen
201+ onDone = { ( ) => { } }
202+ modalSize = "wide"
203+ connectLocale = { mockConnectLocale }
204+ client = { TEST_CLIENT }
205+ auth = { mockAuth }
206+ /> ,
207+ { setConnectedWallet : true } ,
208+ ) ;
209+
210+ await waitFor (
211+ ( ) => {
212+ expect ( getByText ( "Headless signing failed" ) ) . toBeInTheDocument ( ) ;
213+ expect (
214+ getByRole ( "button" , { name : "Try Again" } ) ,
215+ ) . toBeInTheDocument ( ) ;
216+ } ,
217+ { timeout : 2000 } ,
218+ ) ;
219+ } ) ;
220+
221+ it ( "allows retry after failure" , async ( ) => {
222+ mockAuth . doLogin
223+ . mockRejectedValueOnce ( new Error ( "Failed first time" ) )
224+ . mockResolvedValueOnce ( undefined ) ;
225+
226+ const { getByRole, getByText } = render (
227+ < SignatureScreen
228+ onDone = { ( ) => { } }
229+ modalSize = "wide"
230+ connectLocale = { mockConnectLocale }
231+ client = { TEST_CLIENT }
232+ auth = { mockAuth }
233+ /> ,
234+ { setConnectedWallet : true } ,
235+ ) ;
236+
237+ // Wait for initial failure
238+ await waitFor (
239+ ( ) => {
240+ expect ( getByText ( "Failed first time" ) ) . toBeInTheDocument ( ) ;
241+ } ,
242+ { timeout : 2000 } ,
243+ ) ;
244+
245+ // Click retry
246+ const retryButton = getByRole ( "button" , { name : "Try Again" } ) ;
247+ await userEvent . click ( retryButton ) ;
248+
249+ // Should show loading again
250+ await waitFor ( ( ) => {
251+ expect ( getByText ( "Signing" ) ) . toBeInTheDocument ( ) ;
252+ } ) ;
253+
254+ // Should have called login twice
255+ expect ( mockAuth . doLogin ) . toHaveBeenCalledTimes ( 2 ) ;
256+ } ) ;
257+
258+ it ( "allows disconnecting wallet after failure" , async ( ) => {
259+ const mockDisconnect = vi . fn ( ) . mockResolvedValue ( undefined ) ;
260+ mockAuth . doLogin . mockRejectedValueOnce ( new Error ( "Failed" ) ) ;
261+ vi . mocked ( useActiveWallet ) . mockReturnValueOnce ( {
262+ ...createWallet ( "io.metamask" ) ,
263+ disconnect : mockDisconnect ,
264+ } ) ;
265+
266+ const { getByTestId } = render (
267+ < SignatureScreen
268+ onDone = { ( ) => { } }
269+ modalSize = "wide"
270+ connectLocale = { mockConnectLocale }
271+ client = { TEST_CLIENT }
272+ auth = { mockAuth }
273+ /> ,
274+ { setConnectedWallet : true } ,
275+ ) ;
276+
277+ // Wait for failure and click disconnect
278+ await waitFor (
279+ ( ) => {
280+ return getByTestId ( "disconnect-button" ) ;
281+ } ,
282+ { timeout : 2000 } ,
283+ ) . then ( ( button ) => userEvent . click ( button ) ) ;
284+
285+ // Should have attempted to disconnect
286+ await waitFor ( ( ) => {
287+ expect ( mockDisconnect ) . toHaveBeenCalled ( ) ;
288+ } ) ;
289+ } ) ;
290+ } ) ;
149291} ) ;
0 commit comments