@@ -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" , ( ) => ( {
@@ -56,6 +57,7 @@ import {
56
57
Auth ,
57
58
ConfirmationResult ,
58
59
AuthProvider ,
60
+ TotpSecret ,
59
61
} from "firebase/auth" ;
60
62
import { hasBehavior , getBehavior } from "./behaviors" ;
61
63
import { handleFirebaseError } from "./errors" ;
@@ -1051,3 +1053,91 @@ describe("signInWithProvider", () => {
1051
1053
expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "idle" ] ] ) ;
1052
1054
} ) ;
1053
1055
} ) ;
1056
+
1057
+ describe ( "generateTotpQrCode" , ( ) => {
1058
+ beforeEach ( ( ) => {
1059
+ vi . clearAllMocks ( ) ;
1060
+ } ) ;
1061
+
1062
+ it ( "should generate QR code successfully with authenticated user" , ( ) => {
1063
+ const mockUI = createMockUI ( {
1064
+ auth :
{ currentUser :
{ email :
"[email protected] " } } as Auth ,
1065
+ } ) ;
1066
+ const mockSecret = {
1067
+ generateQrCodeUrl :
vi . fn ( ) . mockReturnValue ( "otpauth://totp/[email protected] ?secret=ABC123&issuer=TestApp" ) ,
1068
+ } as unknown as TotpSecret ;
1069
+
1070
+ const result = generateTotpQrCode ( mockUI , mockSecret ) ;
1071
+
1072
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "[email protected] " , undefined ) ;
1073
+ expect ( result ) . toMatch ( / ^ d a t a : i m a g e \/ g i f ; b a s e 6 4 , / ) ;
1074
+ } ) ;
1075
+
1076
+ it ( "should generate QR code with custom account name and issuer" , ( ) => {
1077
+ const mockUI = createMockUI ( {
1078
+ auth :
{ currentUser :
{ email :
"[email protected] " } } as Auth ,
1079
+ } ) ;
1080
+ const mockSecret = {
1081
+ generateQrCodeUrl : vi . fn ( ) . mockReturnValue ( "otpauth://totp/CustomAccount?secret=ABC123&issuer=CustomIssuer" ) ,
1082
+ } as unknown as TotpSecret ;
1083
+
1084
+ const result = generateTotpQrCode ( mockUI , mockSecret , "CustomAccount" , "CustomIssuer" ) ;
1085
+
1086
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "CustomAccount" , "CustomIssuer" ) ;
1087
+ expect ( result ) . toMatch ( / ^ d a t a : i m a g e \/ g i f ; b a s e 6 4 , / ) ;
1088
+ } ) ;
1089
+
1090
+ it ( "should use user email as account name when no custom account name provided" , ( ) => {
1091
+ const mockUI = createMockUI ( {
1092
+ auth :
{ currentUser :
{ email :
"[email protected] " } } as Auth ,
1093
+ } ) ;
1094
+ const mockSecret = {
1095
+ generateQrCodeUrl :
vi . fn ( ) . mockReturnValue ( "otpauth://totp/[email protected] ?secret=ABC123" ) ,
1096
+ } as unknown as TotpSecret ;
1097
+
1098
+ generateTotpQrCode ( mockUI , mockSecret ) ;
1099
+
1100
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "[email protected] " , undefined ) ;
1101
+ } ) ;
1102
+
1103
+ it ( "should use empty string as account name when user has no email" , ( ) => {
1104
+ const mockUI = createMockUI ( {
1105
+ auth : { currentUser : { email : null } } as Auth ,
1106
+ } ) ;
1107
+ const mockSecret = {
1108
+ generateQrCodeUrl : vi . fn ( ) . mockReturnValue ( "otpauth://totp/?secret=ABC123" ) ,
1109
+ } as unknown as TotpSecret ;
1110
+
1111
+ generateTotpQrCode ( mockUI , mockSecret ) ;
1112
+
1113
+ expect ( mockSecret . generateQrCodeUrl ) . toHaveBeenCalledWith ( "" , undefined ) ;
1114
+ } ) ;
1115
+
1116
+ it ( "should throw error when user is not authenticated" , ( ) => {
1117
+ const mockUI = createMockUI ( {
1118
+ auth : { currentUser : null } as Auth ,
1119
+ } ) ;
1120
+ const mockSecret = {
1121
+ generateQrCodeUrl : vi . fn ( ) ,
1122
+ } as unknown as TotpSecret ;
1123
+
1124
+ expect ( ( ) => generateTotpQrCode ( mockUI , mockSecret ) ) . toThrow (
1125
+ "User must be authenticated to generate a TOTP QR code"
1126
+ ) ;
1127
+ expect ( mockSecret . generateQrCodeUrl ) . not . toHaveBeenCalled ( ) ;
1128
+ } ) ;
1129
+
1130
+ it ( "should throw error when currentUser is undefined" , ( ) => {
1131
+ const mockUI = createMockUI ( {
1132
+ auth : { currentUser : undefined } as unknown as Auth ,
1133
+ } ) ;
1134
+ const mockSecret = {
1135
+ generateQrCodeUrl : vi . fn ( ) ,
1136
+ } as unknown as TotpSecret ;
1137
+
1138
+ expect ( ( ) => generateTotpQrCode ( mockUI , mockSecret ) ) . toThrow (
1139
+ "User must be authenticated to generate a TOTP QR code"
1140
+ ) ;
1141
+ expect ( mockSecret . generateQrCodeUrl ) . not . toHaveBeenCalled ( ) ;
1142
+ } ) ;
1143
+ } ) ;
0 commit comments