DuplicatePreventionTest.php
1 week ago
EddItemTemplateBcTest.php
1 week ago
EddProviderGateTest.php
1 week ago
EddTitleRenderingBcTest.php
1 week ago
Smash782AirbnbUrlListingIdTest.php
1 week ago
Smash782BookingUrlHotelIdTest.php
1 week ago
EddItemTemplateBcTest.php
152 lines
| 1 | <?php |
| 2 | |
| 3 | namespace SmashBalloon\Reviews\Tests\Unit\Providers; |
| 4 | |
| 5 | use PHPUnit\Framework\TestCase; |
| 6 | |
| 7 | /** |
| 8 | * SMASH-1131 / PR #426 — BC pin for the templates/frontend/item.php provider-icon gate. |
| 9 | * |
| 10 | * The PR turns EDD into a SOURCE provider (alongside the legacy form-collector |
| 11 | * that lives at Forms/FormProviders/EddReviews.php). Both code paths store |
| 12 | * with `provider.name = 'edd'` in wp_sbr_reviews_posts: |
| 13 | * - Form-collected (existing): SubmissionsManager::transform_to_review() does |
| 14 | * NOT set $review['business'], $review['source']['url'] is empty. |
| 15 | * - Source-collected (new in PR #426): EDD::normalize_reviews() sets |
| 16 | * $post['business']['id'] = $download_id (EDD.php:500,683). |
| 17 | * |
| 18 | * The naked PR change removed 'edd' from item.php's $no_icon list — that would |
| 19 | * have visually regressed existing form-collected EDD reviews by suddenly |
| 20 | * rendering an EDD icon where they had none. The fix uses `business.id` as the |
| 21 | * source-vs-form discriminator, preserving the no-icon BC for form-collected |
| 22 | * while enabling the new icon for source-collected. |
| 23 | * |
| 24 | * These tests reproduce the item.php gate logic inline so we can exercise it |
| 25 | * without booting WordPress (the template body is non-class shared logic |
| 26 | * extracted into static helpers below). |
| 27 | */ |
| 28 | class EddItemTemplateBcTest extends TestCase |
| 29 | { |
| 30 | /** |
| 31 | * Reproduces the gate logic from templates/frontend/item.php lines 15-23 |
| 32 | * exactly. If item.php changes, this helper must change in lockstep — |
| 33 | * intentionally tight coupling so the test pins the contract. |
| 34 | * |
| 35 | * @param array $post Shape: ['provider' => ['name' => ...], 'business' => ['id' => ...], ...] |
| 36 | * @return bool Whether the provider icon should render. |
| 37 | */ |
| 38 | private static function shouldShowIcon(array $post): bool |
| 39 | { |
| 40 | $no_icon = ['wpforms', 'formidable', 'edd']; |
| 41 | $provider_name = $post['provider']['name'] ?? ''; |
| 42 | $is_edd_source = $provider_name === 'edd' && ! empty($post['business']['id'] ?? null); |
| 43 | return $provider_name !== '' && $provider_name !== 'none' |
| 44 | && (! in_array($provider_name, $no_icon, true) || $is_edd_source); |
| 45 | } |
| 46 | |
| 47 | public function test_form_collected_edd_review_does_not_show_icon(): void |
| 48 | { |
| 49 | // Shape produced by SubmissionsManager::transform_to_review() for an |
| 50 | // EDD form-collected review — no `business` key, `source.url` empty. |
| 51 | $post = [ |
| 52 | 'provider' => ['name' => 'edd', 'id' => 42], |
| 53 | 'source' => ['id' => 'sbr_collection_1', 'url' => ''], |
| 54 | 'review_id' => 'sub_abc123', |
| 55 | ]; |
| 56 | $this->assertFalse( |
| 57 | self::shouldShowIcon($post), |
| 58 | 'BC: form-collected EDD reviews (no business.id) must keep the legacy no-icon rendering' |
| 59 | ); |
| 60 | } |
| 61 | |
| 62 | public function test_source_collected_edd_review_shows_icon(): void |
| 63 | { |
| 64 | // Shape produced by EDD::normalize_reviews() for a source-collected |
| 65 | // EDD review — `business.id` populated with the download_id. |
| 66 | $post = [ |
| 67 | 'provider' => ['name' => 'edd', 'id' => '12345'], |
| 68 | 'business' => ['id' => 12345, 'name' => 'My Plugin Pro'], |
| 69 | 'source' => ['id' => '12345', 'url' => 'https://example.test/?p=12345'], |
| 70 | 'review_id' => 'comment_67', |
| 71 | ]; |
| 72 | $this->assertTrue( |
| 73 | self::shouldShowIcon($post), |
| 74 | 'Source-collected EDD reviews (business.id present) must render the EDD icon' |
| 75 | ); |
| 76 | } |
| 77 | |
| 78 | public function test_wpforms_review_does_not_show_icon(): void |
| 79 | { |
| 80 | // Pre-existing behavior — wpforms is a form-only provider with no |
| 81 | // source-mode, so it stays in $no_icon unconditionally. |
| 82 | $post = [ |
| 83 | 'provider' => ['name' => 'wpforms', 'id' => 1], |
| 84 | ]; |
| 85 | $this->assertFalse(self::shouldShowIcon($post)); |
| 86 | } |
| 87 | |
| 88 | public function test_formidable_review_does_not_show_icon(): void |
| 89 | { |
| 90 | $post = [ |
| 91 | 'provider' => ['name' => 'formidable', 'id' => 2], |
| 92 | ]; |
| 93 | $this->assertFalse(self::shouldShowIcon($post)); |
| 94 | } |
| 95 | |
| 96 | public function test_woocommerce_review_shows_icon(): void |
| 97 | { |
| 98 | // Sanity: WooCommerce is a real source provider — not in $no_icon, |
| 99 | // not affected by the EDD discriminator. Shows icon as before. |
| 100 | $post = [ |
| 101 | 'provider' => ['name' => 'woocommerce', 'id' => 'wc_123'], |
| 102 | 'source' => ['id' => 'wc_123', 'url' => 'https://example.test/product/foo/'], |
| 103 | ]; |
| 104 | $this->assertTrue(self::shouldShowIcon($post)); |
| 105 | } |
| 106 | |
| 107 | public function test_google_review_shows_icon(): void |
| 108 | { |
| 109 | // Sanity: Google source — always shows icon. |
| 110 | $post = [ |
| 111 | 'provider' => ['name' => 'google', 'id' => 'ChIJxxx'], |
| 112 | ]; |
| 113 | $this->assertTrue(self::shouldShowIcon($post)); |
| 114 | } |
| 115 | |
| 116 | public function test_provider_none_does_not_show_icon(): void |
| 117 | { |
| 118 | // Legacy "no provider" sentinel — must not render. |
| 119 | $post = [ |
| 120 | 'provider' => ['name' => 'none', 'id' => 0], |
| 121 | ]; |
| 122 | $this->assertFalse(self::shouldShowIcon($post)); |
| 123 | } |
| 124 | |
| 125 | public function test_missing_provider_does_not_show_icon(): void |
| 126 | { |
| 127 | // Defensive: malformed / partial post shapes must not crash + must |
| 128 | // fall through to "no icon" (safer than rendering broken alt-text). |
| 129 | $this->assertFalse(self::shouldShowIcon([])); |
| 130 | $this->assertFalse(self::shouldShowIcon(['provider' => []])); |
| 131 | $this->assertFalse(self::shouldShowIcon(['provider' => ['name' => '']])); |
| 132 | } |
| 133 | |
| 134 | public function test_edd_with_empty_business_id_stays_no_icon(): void |
| 135 | { |
| 136 | // Defensive: business present but business.id empty (zero, null, "") |
| 137 | // MUST be treated as form-collected — the discriminator only |
| 138 | // activates on a truthy, non-empty business.id (matches !empty() in |
| 139 | // the template). |
| 140 | foreach ([null, '', 0, '0', false] as $empty) { |
| 141 | $post = [ |
| 142 | 'provider' => ['name' => 'edd'], |
| 143 | 'business' => ['id' => $empty], |
| 144 | ]; |
| 145 | $this->assertFalse( |
| 146 | self::shouldShowIcon($post), |
| 147 | 'EDD review with empty business.id (' . var_export($empty, true) . ') must stay no-icon' |
| 148 | ); |
| 149 | } |
| 150 | } |
| 151 | } |
| 152 |