From 677cb5ddaf74f7f65c9045e9a84b2523b27d7752 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 28 Mar 2026 22:52:38 +0100 Subject: [PATCH 1/3] fix misleading notice #855 --- class-two-factor-core.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/class-two-factor-core.php b/class-two-factor-core.php index 7b57b868..2d7c2332 100644 --- a/class-two-factor-core.php +++ b/class-two-factor-core.php @@ -2132,7 +2132,9 @@ public static function user_two_factor_options( $user ) { self::add_error( new WP_Error( 'two_factor_suggest_backup', - __( 'To prevent being locked out of your account, consider enabling a backup method like Recovery Codes in case you lose access to your primary authentication method.', 'two-factor' ), + isset( $providers['Two_Factor_Backup_Codes'] ) + ? __( 'To prevent being locked out of your account, consider enabling a backup method like Recovery Codes in case you lose access to your primary authentication method.', 'two-factor' ) + : __( 'To prevent being locked out of your account, consider enabling an additional two-factor method in case you lose access to your primary authentication method.', 'two-factor' ), array( 'type' => 'warning', ) From 905be1fd3cedadd251c02f32742779d10fcf1a1f Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 16 Apr 2026 21:13:10 +0200 Subject: [PATCH 2/3] fix another misleading notice --- class-two-factor-core.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/class-two-factor-core.php b/class-two-factor-core.php index 2d7c2332..826fd6e0 100644 --- a/class-two-factor-core.php +++ b/class-two-factor-core.php @@ -2244,7 +2244,13 @@ private static function render_user_providers_form( $user, $providers ) { ?>

- +

From a782c2f2bc78c7a7c467d1d8561f5b635613c65a Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 21 Apr 2026 07:40:36 +0200 Subject: [PATCH 3/3] add tests by dknauss --- tests/class-two-factor-core.php | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/tests/class-two-factor-core.php b/tests/class-two-factor-core.php index c265f6aa..b0b472bb 100644 --- a/tests/class-two-factor-core.php +++ b/tests/class-two-factor-core.php @@ -159,6 +159,30 @@ private function do_redirect_callable( $callback ) { return $intercepted_url; } + /** + * Reset stored profile errors between tests. + */ + private function reset_profile_errors() { + $reflection = new ReflectionClass( Two_Factor_Core::class ); + $prop = $reflection->getProperty( 'profile_errors' ); + $prop->setAccessible( true ); + $prop->setValue( null, array() ); + } + + /** + * Render the user two-factor settings UI and return the markup. + * + * @param WP_User $user User instance. + * @return string + */ + private function render_user_two_factor_options( WP_User $user ) { + $this->reset_profile_errors(); + + ob_start(); + Two_Factor_Core::user_two_factor_options( $user ); + return ob_get_clean(); + } + /** * Verify adding hooks. * @@ -2157,6 +2181,71 @@ public function test_get_supported_providers_for_user() { $this->assertArrayHasKey( 'Two_Factor_Totp', $providers, 'TOTP provider is supported by default' ); } + /** + * Test user_two_factor_options output when backup codes are available. + * + * @covers Two_Factor_Core::user_two_factor_options + */ + public function test_user_two_factor_options_mentions_recovery_codes_when_backup_codes_are_available() { + $user = self::factory()->user->create_and_get(); + + Two_Factor_Core::enable_provider_for_user( $user->ID, 'Two_Factor_Email' ); + + try { + $output = $this->render_user_two_factor_options( $user ); + + $this->assertStringContainsString( + 'consider enabling a backup method like Recovery Codes', + $output + ); + $this->assertStringContainsString( + 'Configure a primary two-factor method along with a backup method, such as Recovery Codes', + $output + ); + $this->assertStringNotContainsString( + 'consider enabling an additional two-factor method', + $output + ); + } finally { + $this->reset_profile_errors(); + } + } + + /** + * Test user_two_factor_options output when backup codes are filtered out. + * + * @covers Two_Factor_Core::user_two_factor_options + */ + public function test_user_two_factor_options_uses_generic_wording_when_backup_codes_are_filtered_out() { + $filter = static function ( $providers ) { + unset( $providers['Two_Factor_Backup_Codes'] ); + return $providers; + }; + + add_filter( 'two_factor_providers', $filter ); + + try { + $user = self::factory()->user->create_and_get(); + + Two_Factor_Core::enable_provider_for_user( $user->ID, 'Two_Factor_Email' ); + + $output = $this->render_user_two_factor_options( $user ); + + $this->assertStringContainsString( + 'consider enabling an additional two-factor method', + $output + ); + $this->assertStringContainsString( + 'Configure a primary two-factor method along with an additional two-factor method', + $output + ); + $this->assertStringNotContainsString( 'Recovery Codes', $output ); + } finally { + remove_filter( 'two_factor_providers', $filter ); + $this->reset_profile_errors(); + } + } + /** * Test is_user_using_two_factor with enabled provider. *