PluginProbe ʕ •ᴥ•ʔ
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More / 2.7.0
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More v2.7.0
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 / BulkRearmOnGrowthTest.php
reviews-feed / tests / Unit Last commit date
Doubles 1 month ago Providers 1 month ago BulkRearmOnGrowthTest.php 1 month ago BulkReviewsUpdateStuckStateTest.php 1 month ago ClearCacheRelayResetTest.php 1 month ago DeleteSourceRelayFailureTest.php 1 month ago ErrorHandlerFalsyOptionTest.php 1 month ago FeedCacheUpdateServiceTest.php 1 month ago FeedMalformedPayloadTest.php 1 month ago ForceKeylessRefetchTest.php 1 month ago LicenseDeactivateStaleStateTest.php 1 month ago MediaFinderMemoTest.php 1 month ago MultiSourceAggregationTest.php 1 month ago ReconcileMigratedLicenseRoutineTest.php 1 month ago ReconcileRemovalTest.php 1 month ago RegisterWebsiteRoutineTest.php 1 month ago RemoteRequestMemoTest.php 1 month ago ReviewAlertHeaderTotalsTest.php 1 month ago ReviewAlertPageTargetingTest.php 1 month ago ReviewAlertStarFillTest.php 1 month ago ShortcodeNeutralizationTest.php 1 month ago SiteMigrationRecoveryTest.php 1 month ago Smash1583HeaderParityTest.php 1 month ago Smash1631MultiLanguageBulkTest.php 1 month ago Smash1631UpdateSingleLangScopeTest.php 1 month ago Smash782BookingHeaderRatingTest.php 1 month ago Smash782CountryFlagEmojiTest.php 1 month ago Smash782ExternalRefreshCronTest.php 1 month ago Smash782ExtrasTemplateTest.php 1 month ago Smash782ReviewAlertProviderDataTest.php 1 month ago SourceIdLookupTest.php 1 month ago WpmlGetCurrentLanguageTest.php 1 month ago WpmlLanguageMappingTest.php 1 month ago
BulkRearmOnGrowthTest.php
141 lines
1 <?php
2
3 namespace SmashBalloon\Reviews\Tests\Unit;
4
5 use PHPUnit\Framework\TestCase;
6 use SmashBalloon\Reviews\Pro\Services\BulkUpdate\Bulk_Reviews_Update;
7
8 /**
9 * SMASH-1634 — change-driven re-arm of the one-shot paginated backfill.
10 *
11 * The bug: after a source's bulk history completes (`is_done`), it never re-runs,
12 * so review batches larger than the hourly incremental cap (Google/Yelp keyed
13 * API returns only the 5 newest bodies) never load without a manual "reset bulk
14 * history". `maybe_rearm_source()` re-opens ONE source's backfill when its
15 * upstream review count grows.
16 *
17 * These pin the exact contract, including the cost guards (seed-on-first-sight,
18 * key/provider gating) so the fix can't silently start a mass re-backfill.
19 *
20 * @group bulk-history
21 * @group smash-1634
22 */
23 class BulkRearmOnGrowthTest extends TestCase
24 {
25 protected function setUp(): void
26 {
27 parent::setUp();
28 global $wp_options_mock;
29 $wp_options_mock = [];
30 }
31
32 /** Keyed google/yelp needs an API key for the bulk (RapidAPI) path. */
33 private function withApiKey(string $provider = 'google'): void
34 {
35 global $wp_options_mock;
36 $wp_options_mock['sbr_apikeys'] = [$provider => 'TEST_KEY'];
37 }
38
39 private function seedBulk(array $state): void
40 {
41 global $wp_options_mock;
42 $wp_options_mock['sbr_bulk_sources'] = $state;
43 }
44
45 private function bulkState(string $account_id): array
46 {
47 global $wp_options_mock;
48 return $wp_options_mock['sbr_bulk_sources'][$account_id] ?? [];
49 }
50
51 /**
52 * First time we observe a completed source, we only SEED the baseline —
53 * we must NOT re-arm. This is the cost guard that stops deploying the fix
54 * from re-backfilling every existing source at once.
55 */
56 public function test_first_observation_seeds_baseline_without_rearm(): void
57 {
58 $this->withApiKey('google');
59 $id = 'ChIJ_SEED';
60 $this->seedBulk([$id => ['account_id' => $id, 'provider' => 'google', 'is_done' => true, 'page' => 3]]);
61
62 $rearmed = Bulk_Reviews_Update::maybe_rearm_source('google', $id, 233);
63
64 $this->assertFalse($rearmed, 'First sight of a done source must not re-arm.');
65 $state = $this->bulkState($id);
66 $this->assertTrue($state['is_done'], 'is_done must stay true on the seed pass.');
67 $this->assertSame(233, $state['last_total'], 'Baseline last_total must be seeded.');
68 }
69
70 /** No growth since the last backfill → no re-arm. */
71 public function test_no_growth_does_not_rearm(): void
72 {
73 $this->withApiKey('google');
74 $id = 'ChIJ_FLAT';
75 $this->seedBulk([$id => ['account_id' => $id, 'provider' => 'google', 'is_done' => true, 'page' => 3, 'last_total' => 233]]);
76
77 $this->assertFalse(Bulk_Reviews_Update::maybe_rearm_source('google', $id, 233));
78 $this->assertTrue($this->bulkState($id)['is_done'], 'Equal count must leave is_done untouched.');
79 }
80
81 /** THE FIX: upstream count grew → re-open the backfill for that source. */
82 public function test_growth_rearms_source(): void
83 {
84 $this->withApiKey('google');
85 $id = 'ChIJ_GROW';
86 $this->seedBulk([$id => ['account_id' => $id, 'provider' => 'google', 'is_done' => true, 'page' => 3, 'last_total' => 233]]);
87
88 $rearmed = Bulk_Reviews_Update::maybe_rearm_source('google', $id, 246);
89
90 $this->assertTrue($rearmed, 'Count growth must re-arm the source.');
91 $state = $this->bulkState($id);
92 $this->assertFalse($state['is_done'], 'Re-arm must clear is_done so the backfill re-runs.');
93 $this->assertSame(1, $state['page'], 'Re-arm must reset pagination to page 1 (matches the proven 1-indexed fresh init).');
94 $this->assertSame(246, $state['last_total'], 'Re-arm must record the new baseline (prevents re-loop).');
95 }
96
97 /** BC: a source still mid-backfill (is_done false) is left to the normal flow. */
98 public function test_not_done_source_is_untouched(): void
99 {
100 $this->withApiKey('google');
101 $id = 'ChIJ_RUNNING';
102 $this->seedBulk([$id => ['account_id' => $id, 'provider' => 'google', 'is_done' => false, 'page' => 1]]);
103
104 $this->assertFalse(Bulk_Reviews_Update::maybe_rearm_source('google', $id, 999));
105 $state = $this->bulkState($id);
106 $this->assertFalse($state['is_done']);
107 $this->assertArrayNotHasKey('last_total', $state, 'Running source must not be mutated.');
108 }
109
110 /** Cost guard: keyless (no API key) is not handled by this bulk service → never re-arm. */
111 public function test_no_api_key_never_rearms(): void
112 {
113 // no withApiKey()
114 $id = 'ChIJ_KEYLESS';
115 $this->seedBulk([$id => ['account_id' => $id, 'provider' => 'google', 'is_done' => true, 'page' => 3, 'last_total' => 100]]);
116
117 $this->assertFalse(Bulk_Reviews_Update::maybe_rearm_source('google', $id, 500));
118 $this->assertTrue($this->bulkState($id)['is_done'], 'Keyless source must be untouched.');
119 }
120
121 /** Guard: providers this bulk service doesn't own are ignored. */
122 public function test_non_google_yelp_provider_ignored(): void
123 {
124 $this->withApiKey('google');
125 $id = 'qa_booking';
126 $this->seedBulk([$id => ['account_id' => $id, 'provider' => 'booking', 'is_done' => true, 'page' => 3, 'last_total' => 10]]);
127
128 $this->assertFalse(Bulk_Reviews_Update::maybe_rearm_source('booking', $id, 50));
129 }
130
131 /** Guard: a zero/unknown current count is a no-op (don't act on missing data). */
132 public function test_zero_current_total_is_noop(): void
133 {
134 $this->withApiKey('google');
135 $id = 'ChIJ_ZERO';
136 $this->seedBulk([$id => ['account_id' => $id, 'provider' => 'google', 'is_done' => true, 'page' => 3, 'last_total' => 5]]);
137
138 $this->assertFalse(Bulk_Reviews_Update::maybe_rearm_source('google', $id, 0));
139 }
140 }
141