PluginProbe ʕ •ᴥ•ʔ
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More / 2.6.7
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More v2.6.7
2.11.0 2.10.0 2.9.0 2.8.0 2.7.0 2.6.7 2.6.8 2.6.5 2.6.4 2.6.3 2.6.2 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 trunk 1.0 1.0.1 1.0.2 1.0.3 1.1 1.1.1 1.1.2 1.2.0 2.0 2.1.0 2.1.1 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1
reviews-feed / tests / Unit / ErrorHandlerFalsyOptionTest.php
reviews-feed / tests / Unit Last commit date
Doubles 2 months ago Providers 2 months ago BulkReviewsUpdateStuckStateTest.php 2 months ago ClearCacheRelayResetTest.php 2 months ago DeleteSourceRelayFailureTest.php 2 months ago ErrorHandlerFalsyOptionTest.php 2 months ago FeedCacheUpdateServiceTest.php 2 months ago FeedMalformedPayloadTest.php 2 months ago ForceKeylessRefetchTest.php 2 months ago LicenseDeactivateStaleStateTest.php 2 months ago MediaFinderMemoTest.php 2 months ago MultiSourceAggregationTest.php 2 months ago ReconcileMigratedLicenseRoutineTest.php 2 months ago ReconcileRemovalTest.php 2 months ago RegisterWebsiteRoutineTest.php 2 months ago RemoteRequestMemoTest.php 2 months ago ReviewAlertHeaderTotalsTest.php 2 months ago ReviewAlertPageTargetingTest.php 2 months ago ReviewAlertStarFillTest.php 2 months ago ShortcodeNeutralizationTest.php 2 months ago SiteMigrationRecoveryTest.php 2 months ago Smash1583HeaderParityTest.php 2 months ago SourceIdLookupTest.php 2 months ago WpmlGetCurrentLanguageTest.php 2 months ago WpmlLanguageMappingTest.php 2 months ago
ErrorHandlerFalsyOptionTest.php
129 lines
1 <?php
2
3 namespace SmashBalloon\Reviews\Tests\Unit;
4
5 use PHPUnit\Framework\TestCase;
6 use SmashBalloon\Reviews\Common\Helpers\SBR_Error_Handler;
7
8 /**
9 * Regression tests for SMASH-1544.
10 *
11 * On PHP 8, when the `sbr_errors` option row EXISTS in the DB but holds a
12 * falsy value (boolean false / '' — corrupted, legacy or third-party write),
13 * get_option('sbr_errors', []) returns that falsy value, NOT the [] default
14 * (the default only fires when the row is absent — see
15 * wp-includes/option.php). The handler then passed that bool to foreach()
16 * and array_push(), producing:
17 *
18 * PHP Warning: foreach() argument must be of type array|object, false given
19 * PHP Fatal error: Uncaught TypeError: array_push(): Argument #1 ($array)
20 * must be of type array, false given
21 *
22 * which took down the feed builder admin page and the WP-Cron cache update.
23 *
24 * These tests drive the falsy-stored-value path. failOnWarning="true" in
25 * phpunit.xml means even the foreach() warning fails the suite pre-fix.
26 *
27 * @group SMASH-1544
28 * @covers \SmashBalloon\Reviews\Common\Helpers\SBR_Error_Handler
29 */
30 class ErrorHandlerFalsyOptionTest extends TestCase
31 {
32 protected function setUp(): void
33 {
34 parent::setUp();
35 global $wp_options_mock;
36 $wp_options_mock = [];
37 }
38
39 protected function tearDown(): void
40 {
41 global $wp_options_mock;
42 $wp_options_mock = [];
43 parent::tearDown();
44 }
45
46 private function sampleError(): array
47 {
48 return [
49 'type' => 'connection',
50 'id' => 'feed_1',
51 'provider' => 'google',
52 'message' => 'API key missing',
53 ];
54 }
55
56 /**
57 * The exact customer condition: option row present, value === false.
58 * Pre-fix this fataled at array_push(false, ...). Post-fix it logs cleanly.
59 */
60 public function test_log_error_does_not_fatal_when_option_stored_as_false(): void
61 {
62 global $wp_options_mock;
63 $wp_options_mock['sbr_errors'] = false;
64
65 SBR_Error_Handler::log_error($this->sampleError());
66
67 $stored = SBR_Error_Handler::get_errors();
68 $this->assertIsArray($stored);
69 $this->assertCount(1, $stored);
70 $this->assertSame('feed_1', $stored[0]['id']);
71 }
72
73 /** Empty-string is the other falsy shape a corrupted option row can take. */
74 public function test_log_error_does_not_fatal_when_option_stored_as_empty_string(): void
75 {
76 global $wp_options_mock;
77 $wp_options_mock['sbr_errors'] = '';
78
79 SBR_Error_Handler::log_error($this->sampleError());
80
81 $this->assertCount(1, SBR_Error_Handler::get_errors());
82 }
83
84 /** get_errors() must always hand back an array, whatever the stored shape. */
85 public function test_get_errors_always_returns_array(): void
86 {
87 // `null` is deliberately omitted: the bootstrap get_option() stub uses
88 // `$wp_options_mock[$option] ?? $default`, so a stored null collapses to
89 // the [] default (same as "option not set") and would not exercise the
90 // is_array() coercion. The remaining falsy/non-array shapes do. SMASH-1544.
91 global $wp_options_mock;
92 foreach ([false, '', 0, 'not-an-array', 42] as $bad) {
93 $wp_options_mock['sbr_errors'] = $bad;
94 $this->assertIsArray(
95 SBR_Error_Handler::get_errors(),
96 'get_errors() must coerce non-array stored value to []'
97 );
98 }
99 }
100
101 /** check_error() must not trip foreach() on a falsy stored value. */
102 public function test_check_error_handles_falsy_option(): void
103 {
104 global $wp_options_mock;
105 $wp_options_mock['sbr_errors'] = false;
106
107 $this->assertSame('not_defined', SBR_Error_Handler::check_error($this->sampleError()));
108 }
109
110 /**
111 * BC: the normal path (option absent, then a real array) is unchanged.
112 * An existing caller relying on append-then-read still works.
113 */
114 public function test_existing_array_path_is_preserved(): void
115 {
116 // Option absent -> [] default -> first log creates the array.
117 SBR_Error_Handler::log_error($this->sampleError());
118
119 $second = $this->sampleError();
120 $second['id'] = 'feed_2';
121 SBR_Error_Handler::log_error($second);
122
123 $stored = SBR_Error_Handler::get_errors();
124 $this->assertCount(2, $stored);
125 $this->assertSame('feed_1', $stored[0]['id']);
126 $this->assertSame('feed_2', $stored[1]['id']);
127 }
128 }
129