@@ -10,6 +10,7 @@ import {
10
10
signInWithCredential ,
11
11
signInAnonymously ,
12
12
signInWithProvider ,
13
+ generateTotpQrCode ,
13
14
} from "./auth" ;
14
15
15
16
vi . mock ( "firebase/auth" , ( ) => ( {
@@ -31,6 +32,7 @@ vi.mock("firebase/auth", () => ({
31
32
linkWithCredential : vi . fn ( ) ,
32
33
} ) ) ;
33
34
35
+
34
36
vi . mock ( "./behaviors" , ( ) => ( {
35
37
hasBehavior : vi . fn ( ) ,
36
38
getBehavior : vi . fn ( ) ,
@@ -56,6 +58,7 @@ import {
56
58
Auth ,
57
59
ConfirmationResult ,
58
60
AuthProvider ,
61
+ TotpSecret ,
59
62
} from "firebase/auth" ;
60
63
import { hasBehavior , getBehavior } from "./behaviors" ;
61
64
import { handleFirebaseError } from "./errors" ;
@@ -924,3 +927,87 @@ describe("signInWithProvider", () => {
924
927
expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "idle" ] ] ) ;
925
928
} ) ;
926
929
} ) ;
930
+
931
+ describe ( "generateTotpQrCode" , ( ) => {
932
+ beforeEach ( ( ) => {
933
+ vi . clearAllMocks ( ) ;
934
+ } ) ;
935
+
936
+ it ( "should generate QR code successfully with authenticated user" , ( ) => {
937
+ const mockUI = createMockUI ( {
938
+ auth :
{ currentUser :
{ email :
"[email protected] " } } as Auth ,
939
+ } ) ;
940
+ const mockSecret = {
941
+ generateQrCodeUrl :
vi . fn ( ) . mockReturnValue ( "otpauth://totp/[email protected] ?secret=ABC123&issuer=TestApp" ) ,
942
+ } as unknown as TotpSecret ;
943
+
944
+ const result = generateTotpQrCode ( mockUI , mockSecret ) ;
945
+
946
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "[email protected] " , undefined ) ;
947
+ expect ( result ) . toMatch ( / ^ d a t a : i m a g e \/ g i f ; b a s e 6 4 , / ) ;
948
+ } ) ;
949
+
950
+ it ( "should generate QR code with custom account name and issuer" , ( ) => {
951
+ const mockUI = createMockUI ( {
952
+ auth :
{ currentUser :
{ email :
"[email protected] " } } as Auth ,
953
+ } ) ;
954
+ const mockSecret = {
955
+ generateQrCodeUrl : vi . fn ( ) . mockReturnValue ( "otpauth://totp/CustomAccount?secret=ABC123&issuer=CustomIssuer" ) ,
956
+ } as unknown as TotpSecret ;
957
+
958
+ const result = generateTotpQrCode ( mockUI , mockSecret , "CustomAccount" , "CustomIssuer" ) ;
959
+
960
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "CustomAccount" , "CustomIssuer" ) ;
961
+ expect ( result ) . toMatch ( / ^ d a t a : i m a g e \/ g i f ; b a s e 6 4 , / ) ;
962
+ } ) ;
963
+
964
+ it ( "should use user email as account name when no custom account name provided" , ( ) => {
965
+ const mockUI = createMockUI ( {
966
+ auth :
{ currentUser :
{ email :
"[email protected] " } } as Auth ,
967
+ } ) ;
968
+ const mockSecret = {
969
+ generateQrCodeUrl :
vi . fn ( ) . mockReturnValue ( "otpauth://totp/[email protected] ?secret=ABC123" ) ,
970
+ } as unknown as TotpSecret ;
971
+
972
+ generateTotpQrCode ( mockUI , mockSecret ) ;
973
+
974
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "[email protected] " , undefined ) ;
975
+ } ) ;
976
+
977
+ it ( "should use empty string as account name when user has no email" , ( ) => {
978
+ const mockUI = createMockUI ( {
979
+ auth : { currentUser : { email : null } } as Auth ,
980
+ } ) ;
981
+ const mockSecret = {
982
+ generateQrCodeUrl : vi . fn ( ) . mockReturnValue ( "otpauth://totp/?secret=ABC123" ) ,
983
+ } as unknown as TotpSecret ;
984
+
985
+ generateTotpQrCode ( mockUI , mockSecret ) ;
986
+
987
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "" , undefined ) ;
988
+ } ) ;
989
+
990
+ it ( "should throw error when user is not authenticated" , ( ) => {
991
+ const mockUI = createMockUI ( {
992
+ auth : { currentUser : null } as Auth ,
993
+ } ) ;
994
+ const mockSecret = {
995
+ generateQrCodeUrl : vi . fn ( ) ,
996
+ } as unknown as TotpSecret ;
997
+
998
+ expect ( ( ) => generateTotpQrCode ( mockUI , mockSecret ) ) . toThrow ( "User must be authenticated to generate a TOTP QR code" ) ;
999
+ expect ( mockSecret . generateQrCodeUrl ) . not . toHaveBeenCalled ( ) ;
1000
+ } ) ;
1001
+
1002
+ it ( "should throw error when currentUser is undefined" , ( ) => {
1003
+ const mockUI = createMockUI ( {
1004
+ auth : { currentUser : undefined } as unknown as Auth ,
1005
+ } ) ;
1006
+ const mockSecret = {
1007
+ generateQrCodeUrl : vi . fn ( ) ,
1008
+ } as unknown as TotpSecret ;
1009
+
1010
+ expect ( ( ) => generateTotpQrCode ( mockUI , mockSecret ) ) . toThrow ( "User must be authenticated to generate a TOTP QR code" ) ;
1011
+ expect ( mockSecret . generateQrCodeUrl ) . not . toHaveBeenCalled ( ) ;
1012
+ } ) ;
1013
+ } ) ;
0 commit comments