PluginProbe ʕ •ᴥ•ʔ
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More / 2.11.0
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More v2.11.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 / MediaFinderMemoTest.php
reviews-feed / tests / Unit Last commit date
Doubles 1 week ago Providers 1 week ago BulkRearmOnGrowthTest.php 1 week ago BulkReviewsUpdateStuckStateTest.php 1 week ago ClearCacheRelayResetTest.php 1 week ago DeleteSourceRelayFailureTest.php 1 week ago ErrorHandlerFalsyOptionTest.php 1 week ago FeedCacheUpdateServiceTest.php 1 week ago FeedMalformedPayloadTest.php 1 week ago ForceKeylessRefetchTest.php 1 week ago LicenseDeactivateStaleStateTest.php 1 week ago MediaFinderMemoTest.php 1 week ago MultiSourceAggregationTest.php 1 week ago ReconcileMigratedLicenseRoutineTest.php 1 week ago ReconcileRemovalTest.php 1 week ago RegisterWebsiteRoutineTest.php 1 week ago RelaySlowEndpointsTest.php 1 week ago RemoteRequestMemoTest.php 1 week ago ReviewAlertHeaderTotalsTest.php 1 week ago ReviewAlertPageTargetingTest.php 1 week ago ReviewAlertStarFillTest.php 1 week ago ShortcodeNeutralizationTest.php 1 week ago SiteMigrationRecoveryTest.php 1 week ago Smash1130UsageTrackingHardeningTest.php 1 week ago Smash1130UsageTrackingHooksTest.php 1 week ago Smash1583HeaderParityTest.php 1 week ago Smash1631MultiLanguageBulkTest.php 1 week ago Smash1631UpdateSingleLangScopeTest.php 1 week ago Smash1706TripAdvisorPlaceIdTest.php 1 week ago Smash1756SchemaServiceTest.php 1 week ago Smash1785AvatarLocalUrlGuardTest.php 1 week ago Smash1785AvatarReHealTest.php 1 week ago Smash1795ReviewTextXssTest.php 1 week ago Smash1835TripAdvisorKeyShapeTest.php 1 week ago Smash1973WordpressOrgPlaceIdNullTest.php 1 week ago Smash1987NestedSourceErrorShapeTest.php 1 week ago Smash782BookingHeaderRatingTest.php 1 week ago Smash782CountryFlagEmojiTest.php 1 week ago Smash782ExternalRefreshCronTest.php 1 week ago Smash782ExtrasTemplateTest.php 1 week ago Smash782ReviewAlertProviderDataTest.php 1 week ago SourceIdLookupTest.php 1 week ago WpmlGetCurrentLanguageTest.php 1 week ago WpmlLanguageMappingTest.php 1 week ago
MediaFinderMemoTest.php
123 lines
1 <?php
2
3 namespace SmashBalloon\Reviews\Tests\Unit;
4
5 use PHPUnit\Framework\TestCase;
6 use SmashBalloon\Reviews\Pro\MediaFinder;
7
8 /**
9 * Unit tests for the per-request memoization on MediaFinder::search()
10 * (SMASH-1360 Phase 2 round 2).
11 *
12 * Pins the memo-key contract: same `(provider, primary_url)` within ONE PHP
13 * request collapses to the cached media-array. Different reviewers / different
14 * places / different providers get distinct keys.
15 *
16 * The wp_lhr_log captured on demo-wp2 2026-05-06 showed the customizer-side
17 * direct-to-Google scraping amplifier — 25 calls / 10 unique reviewers =
18 * 2.5× duplication ratio. Without this memo, every shortcode independently
19 * fetches each reviewer's `https://www.google.com/maps/contrib/...` profile.
20 * With this memo, identical (reviewer, place_id) pairs across shortcodes
21 * collapse to one fetch.
22 *
23 * @group memo
24 * @group SMASH-1360
25 */
26 class MediaFinderMemoTest extends TestCase
27 {
28 protected function setUp(): void
29 {
30 parent::setUp();
31 MediaFinder::flush_search_memo();
32 }
33
34 /**
35 * Helper: build a MediaFinder pre-populated with provider + primary_url.
36 * We use reflection because primary_url is private and normally set via
37 * `construct_url_from_post_and_source()`, which requires a real $post.
38 */
39 private function makeFinder(string $provider, string $primaryUrl): MediaFinder
40 {
41 $finder = new MediaFinder(['info' => '{"id":"X"}']);
42 $finder->set_provider($provider);
43
44 // primary_url is private; use reflection to set it.
45 $ref = new \ReflectionProperty(MediaFinder::class, 'primary_url');
46 $ref->setAccessible(true);
47 $ref->setValue($finder, $primaryUrl);
48
49 return $finder;
50 }
51
52 public function test_memo_key_collapses_for_same_provider_and_url(): void
53 {
54 $a = $this->makeFinder('google', 'https://www.google.com/maps/contrib/123/place/CHIJ_X');
55 $b = $this->makeFinder('google', 'https://www.google.com/maps/contrib/123/place/CHIJ_X');
56
57 $this->assertSame($a->search_memo_key(), $b->search_memo_key());
58 }
59
60 public function test_memo_key_differs_for_different_reviewers(): void
61 {
62 $a = $this->makeFinder('google', 'https://www.google.com/maps/contrib/AAA/place/CHIJ_X');
63 $b = $this->makeFinder('google', 'https://www.google.com/maps/contrib/BBB/place/CHIJ_X');
64
65 $this->assertNotSame($a->search_memo_key(), $b->search_memo_key());
66 }
67
68 public function test_memo_key_differs_for_different_places(): void
69 {
70 $a = $this->makeFinder('google', 'https://www.google.com/maps/contrib/123/place/CHIJ_AFI');
71 $b = $this->makeFinder('google', 'https://www.google.com/maps/contrib/123/place/CHIJ_GOOGLEPLEX');
72
73 $this->assertNotSame($a->search_memo_key(), $b->search_memo_key());
74 }
75
76 public function test_memo_key_differs_for_different_providers(): void
77 {
78 // Yelp + TripAdvisor have their own primary_url shapes; the memo must
79 // not collapse them with Google even if URLs were structurally similar.
80 $google = $this->makeFinder('google', 'https://www.google.com/maps/contrib/X/place/Y');
81 $yelp = $this->makeFinder('yelp', 'https://www.google.com/maps/contrib/X/place/Y'); // synthetic
82
83 $this->assertNotSame($google->search_memo_key(), $yelp->search_memo_key());
84 }
85
86 public function test_memo_key_returns_null_when_primary_url_empty(): void
87 {
88 $finder = $this->makeFinder('google', '');
89
90 $this->assertNull($finder->search_memo_key());
91 }
92
93 public function test_memo_key_is_deterministic_sha256(): void
94 {
95 $finder = $this->makeFinder('google', 'https://www.google.com/maps/contrib/X/place/Y');
96 $expected = hash('sha256', 'google|https://www.google.com/maps/contrib/X/place/Y');
97
98 $this->assertSame($expected, $finder->search_memo_key());
99 }
100
101 public function test_memo_key_handles_long_urls(): void
102 {
103 // Defensive — Google contributor IDs can be long, place_ids can be
104 // ~30 chars, plus query params. Memo key derivation must be stable
105 // regardless of URL length.
106 $longUrl = 'https://www.google.com/maps/contrib/' . str_repeat('1', 50)
107 . '/place/' . str_repeat('a', 60)
108 . '?hl=en&extra=1';
109 $finder = $this->makeFinder('google', $longUrl);
110
111 $this->assertNotNull($finder->search_memo_key());
112 // sha256 hex output is always 64 chars regardless of input length
113 $this->assertSame(64, strlen($finder->search_memo_key()));
114 }
115
116 public function test_flush_search_memo_clears_state(): void
117 {
118 // Test isolation contract — same as RemoteRequestMemoTest's flush_memo.
119 MediaFinder::flush_search_memo();
120 $this->assertTrue(true);
121 }
122 }
123