@@ -88,6 +88,12 @@ mock.module('@tinyclaw/config', () => ({
8888// ── Mock @tinyclaw/core ─────────────────────────────────────────────
8989
9090const mockIsAvailable = mock ( ( ) => Promise . resolve ( true ) ) ;
91+ const mockGenerateTotpSecret = mock ( ( ) => 'JBSWY3DPEHPK3PXP' ) ;
92+ const mockCreateTotpUri = mock ( ( ) => 'otpauth://totp/TinyClaw?secret=JBSWY3DPEHPK3PXP' ) ;
93+ const mockVerifyTotpCode = mock ( ( ) => Promise . resolve ( true ) ) ;
94+ const mockGenerateBackupCodes = mock ( ( ) => Array . from ( { length : 10 } , ( _ , i ) => `BACKUP${ String ( i ) . padStart ( 2 , '0' ) } ` ) ) ;
95+ const mockGenerateRecoveryToken = mock ( ( ) => 'RECOVERYTOKEN' . repeat ( 5 ) ) ;
96+ const mockSha256 = mock ( ( ) => Promise . resolve ( 'abc123' ) ) ;
9197
9298mock . module ( '@tinyclaw/core' , ( ) => ( {
9399 createOllamaProvider : mock ( ( ) => ( {
@@ -96,6 +102,49 @@ mock.module('@tinyclaw/core', () => ({
96102 DEFAULT_PROVIDER : 'ollama' ,
97103 DEFAULT_MODEL : 'kimi-k2.5:cloud' ,
98104 DEFAULT_BASE_URL : 'https://ollama.com' ,
105+ SECURITY_WARNING_TITLE : 'Security Warning' ,
106+ SECURITY_WARNING_BODY : 'Test body' ,
107+ SECURITY_LICENSE : 'Test license' ,
108+ SECURITY_WARRANTY : 'Test warranty' ,
109+ SECURITY_SAFETY_TITLE : 'Safety' ,
110+ SECURITY_SAFETY_PRACTICES : [ 'Practice 1' ] ,
111+ SECURITY_CONFIRM : 'Do you accept?' ,
112+ defaultModelNote : mock ( ( model : string ) => `Using ${ model } ` ) ,
113+ TOTP_SETUP_TITLE : 'TOTP Setup' ,
114+ TOTP_SETUP_BODY : 'Set up 2FA' ,
115+ BACKUP_CODES_INTRO : 'Save these codes' ,
116+ BACKUP_CODES_HINT : 'Keep them safe' ,
117+ RECOVERY_TOKEN_HINT : 'Store securely' ,
118+ generateTotpSecret : mockGenerateTotpSecret ,
119+ createTotpUri : mockCreateTotpUri ,
120+ verifyTotpCode : mockVerifyTotpCode ,
121+ generateBackupCodes : mockGenerateBackupCodes ,
122+ generateRecoveryToken : mockGenerateRecoveryToken ,
123+ sha256 : mockSha256 ,
124+ BACKUP_CODES_COUNT : 10 ,
125+ } ) ) ;
126+
127+ // ── Mock @tinyclaw/web ──────────────────────────────────────────────
128+
129+ mock . module ( '@tinyclaw/web' , ( ) => ( {
130+ createWebUI : mock ( ( ) => ( {
131+ start : mock ( ( ) => Promise . resolve ( ) ) ,
132+ stop : mock ( ( ) => Promise . resolve ( ) ) ,
133+ } ) ) ,
134+ } ) ) ;
135+
136+ // ── Mock qrcode ─────────────────────────────────────────────────────
137+
138+ mock . module ( 'qrcode' , ( ) => ( {
139+ default : {
140+ toString : mock ( ( ) => Promise . resolve ( '██ QR CODE ██' ) ) ,
141+ } ,
142+ } ) ) ;
143+
144+ // ── Mock child_process (prevents execSync clipboard calls) ──────────
145+
146+ mock . module ( 'child_process' , ( ) => ( {
147+ execSync : mock ( ( ) => { } ) ,
99148} ) ) ;
100149
101150// ── Mock @tinyclaw/heartware ────────────────────────────────────────
@@ -171,6 +220,12 @@ beforeEach(() => {
171220 mockConfigSet . mockClear ( ) ;
172221 mockConfigClose . mockClear ( ) ;
173222 mockIsAvailable . mockClear ( ) ;
223+ mockGenerateTotpSecret . mockClear ( ) ;
224+ mockCreateTotpUri . mockClear ( ) ;
225+ mockVerifyTotpCode . mockClear ( ) ;
226+ mockGenerateBackupCodes . mockClear ( ) ;
227+ mockGenerateRecoveryToken . mockClear ( ) ;
228+ mockSha256 . mockClear ( ) ;
174229 mockParseSeed . mockClear ( ) ;
175230 mockGenerateRandomSeed . mockClear ( ) ;
176231 mockGenerateSoul . mockClear ( ) ;
@@ -183,6 +238,12 @@ beforeEach(() => {
183238 mockText . mockImplementation ( ( ) => '' ) ;
184239 mockSelect . mockImplementation ( ( ) => 'keep' ) ;
185240 mockIsAvailable . mockImplementation ( ( ) => Promise . resolve ( true ) ) ;
241+ mockGenerateTotpSecret . mockImplementation ( ( ) => 'JBSWY3DPEHPK3PXP' ) ;
242+ mockCreateTotpUri . mockImplementation ( ( ) => 'otpauth://totp/TinyClaw?secret=JBSWY3DPEHPK3PXP' ) ;
243+ mockVerifyTotpCode . mockImplementation ( ( ) => Promise . resolve ( true ) ) ;
244+ mockGenerateBackupCodes . mockImplementation ( ( ) => Array . from ( { length : 10 } , ( _ , i ) => `BACKUP${ String ( i ) . padStart ( 2 , '0' ) } ` ) ) ;
245+ mockGenerateRecoveryToken . mockImplementation ( ( ) => 'RECOVERYTOKEN' . repeat ( 5 ) ) ;
246+ mockSha256 . mockImplementation ( ( ) => Promise . resolve ( 'abc123' ) ) ;
186247 mockParseSeed . mockImplementation ( ( input : unknown ) => {
187248 const n = Number ( input ) ;
188249 if ( ! input || isNaN ( n ) ) return 42 ;
0 commit comments