@@ -745,6 +745,149 @@ describe('core/strategies/email_and_password/createUserWithEmailAndPassword', ()
745
745
expect ( user . isAnonymous ) . to . be . false ;
746
746
} ) ;
747
747
} ) ;
748
+
749
+ context ( '#passwordPolicy' , ( ) => {
750
+ const TEST_MIN_PASSWORD_LENGTH = 6 ;
751
+ const TEST_ALLOWED_NON_ALPHANUMERIC_CHARS = [ '!' , '(' , ')' ] ;
752
+ const TEST_SCHEMA_VERSION = 1 ;
753
+
754
+ const TEST_TENANT_ID = 'tenant-id' ;
755
+ const TEST_REQUIRE_NUMERIC_TENANT_ID = 'other-tenant-id' ;
756
+
757
+ const PASSWORD_ERROR_MSG =
758
+ 'Firebase: The password does not meet the requirements. (auth/password-does-not-meet-requirements).' ;
759
+
760
+ const passwordPolicyResponse = {
761
+ customStrengthOptions : {
762
+ minPasswordLength : TEST_MIN_PASSWORD_LENGTH
763
+ } ,
764
+ allowedNonAlphanumericCharacters : TEST_ALLOWED_NON_ALPHANUMERIC_CHARS ,
765
+ schemaVersion : TEST_SCHEMA_VERSION
766
+ } ;
767
+ const passwordPolicyResponseRequireNumeric = {
768
+ customStrengthOptions : {
769
+ minPasswordLength : TEST_MIN_PASSWORD_LENGTH ,
770
+ containsNumericCharacter : true
771
+ } ,
772
+ allowedNonAlphanumericCharacters : TEST_ALLOWED_NON_ALPHANUMERIC_CHARS ,
773
+ schemaVersion : TEST_SCHEMA_VERSION
774
+ } ;
775
+ const cachedPasswordPolicy = {
776
+ customStrengthOptions : {
777
+ minPasswordLength : TEST_MIN_PASSWORD_LENGTH
778
+ } ,
779
+ allowedNonAlphanumericCharacters : TEST_ALLOWED_NON_ALPHANUMERIC_CHARS
780
+ } ;
781
+ const cachedPasswordPolicyRequireNumeric = {
782
+ customStrengthOptions : {
783
+ minPasswordLength : TEST_MIN_PASSWORD_LENGTH ,
784
+ containsNumericCharacter : true
785
+ } ,
786
+ allowedNonAlphanumericCharacters : TEST_ALLOWED_NON_ALPHANUMERIC_CHARS
787
+ } ;
788
+ let policyEndpointMock : mockFetch . Route ;
789
+ let policyEndpointMockWithTenant : mockFetch . Route ;
790
+ let policyEndpointMockWithOtherTenant : mockFetch . Route ;
791
+
792
+ beforeEach ( ( ) => {
793
+ policyEndpointMock = mockEndpointWithParams (
794
+ Endpoint . GET_PASSWORD_POLICY ,
795
+ { } ,
796
+ passwordPolicyResponse
797
+ ) ;
798
+ policyEndpointMockWithTenant = mockEndpointWithParams (
799
+ Endpoint . GET_PASSWORD_POLICY ,
800
+ {
801
+ tenantId : TEST_TENANT_ID
802
+ } ,
803
+ passwordPolicyResponse
804
+ ) ;
805
+ policyEndpointMockWithOtherTenant = mockEndpointWithParams (
806
+ Endpoint . GET_PASSWORD_POLICY ,
807
+ {
808
+ tenantId : TEST_REQUIRE_NUMERIC_TENANT_ID
809
+ } ,
810
+ passwordPolicyResponseRequireNumeric
811
+ ) ;
812
+ } ) ;
813
+
814
+ it ( 'does not update the cached password policy upon successful sign up when there is no existing policy cache' , async ( ) => {
815
+ await expect (
816
+ createUserWithEmailAndPassword ( auth , 'some-email' , 'some-password' )
817
+ ) . to . be . fulfilled ;
818
+
819
+ expect ( policyEndpointMock . calls . length ) . to . eq ( 0 ) ;
820
+ expect ( auth . _getPasswordPolicy ( ) ) . to . be . null ;
821
+ } ) ;
822
+
823
+ it ( 'does not update the cached password policy upon successful sign up when there is an existing policy cache' , async ( ) => {
824
+ await auth . _updatePasswordPolicy ( ) ;
825
+
826
+ await expect (
827
+ createUserWithEmailAndPassword ( auth , 'some-email' , 'some-password' )
828
+ ) . to . be . fulfilled ;
829
+
830
+ expect ( policyEndpointMock . calls . length ) . to . eq ( 1 ) ;
831
+ expect ( auth . _getPasswordPolicy ( ) ) . to . eql ( cachedPasswordPolicy ) ;
832
+ } ) ;
833
+
834
+ context ( 'handles password validation errors' , ( ) => {
835
+ beforeEach ( ( ) => {
836
+ mockEndpoint (
837
+ Endpoint . SIGN_UP ,
838
+ {
839
+ error : {
840
+ code : 400 ,
841
+ message : ServerError . PASSWORD_DOES_NOT_MEET_REQUIREMENTS
842
+ }
843
+ } ,
844
+ 400
845
+ ) ;
846
+ } ) ;
847
+
848
+ it ( 'updates the cached password policy when password does not meet backend requirements' , async ( ) => {
849
+ await auth . _updatePasswordPolicy ( ) ;
850
+ expect ( policyEndpointMock . calls . length ) . to . eq ( 1 ) ;
851
+ expect ( auth . _getPasswordPolicy ( ) ) . to . eql ( cachedPasswordPolicy ) ;
852
+
853
+ // Password policy changed after previous fetch.
854
+ policyEndpointMock . response = passwordPolicyResponseRequireNumeric ;
855
+ await expect (
856
+ createUserWithEmailAndPassword ( auth , 'some-email' , 'some-password' )
857
+ ) . to . be . rejectedWith ( FirebaseError , PASSWORD_ERROR_MSG ) ;
858
+
859
+ expect ( policyEndpointMock . calls . length ) . to . eq ( 2 ) ;
860
+ expect ( auth . _getPasswordPolicy ( ) ) . to . eql (
861
+ cachedPasswordPolicyRequireNumeric
862
+ ) ;
863
+ } ) ;
864
+
865
+ it ( 'does not update the cached password policy upon error if policy has not previously been fetched' , async ( ) => {
866
+ expect ( auth . _getPasswordPolicy ( ) ) . to . be . null ;
867
+
868
+ await expect (
869
+ createUserWithEmailAndPassword ( auth , 'some-email' , 'some-password' )
870
+ ) . to . be . rejectedWith ( FirebaseError , PASSWORD_ERROR_MSG ) ;
871
+
872
+ expect ( policyEndpointMock . calls . length ) . to . eq ( 0 ) ;
873
+ expect ( auth . _getPasswordPolicy ( ) ) . to . be . null ;
874
+ } ) ;
875
+
876
+ it ( 'does not update the cached password policy upon error if tenant changes and policy has not previously been fetched' , async ( ) => {
877
+ auth . tenantId = TEST_TENANT_ID ;
878
+ await auth . _updatePasswordPolicy ( ) ;
879
+ expect ( policyEndpointMockWithTenant . calls . length ) . to . eq ( 1 ) ;
880
+ expect ( auth . _getPasswordPolicy ( ) ) . to . eql ( cachedPasswordPolicy ) ;
881
+
882
+ auth . tenantId = TEST_REQUIRE_NUMERIC_TENANT_ID ;
883
+ await expect (
884
+ createUserWithEmailAndPassword ( auth , 'some-email' , 'some-password' )
885
+ ) . to . be . rejectedWith ( FirebaseError , PASSWORD_ERROR_MSG ) ;
886
+ expect ( policyEndpointMockWithOtherTenant . calls . length ) . to . eq ( 0 ) ;
887
+ expect ( auth . _getPasswordPolicy ( ) ) . to . be . undefined ;
888
+ } ) ;
889
+ } ) ;
890
+ } ) ;
748
891
} ) ;
749
892
750
893
describe ( 'core/strategies/email_and_password/signInWithEmailAndPassword' , ( ) => {
0 commit comments