Doubles
3 weeks ago
Providers
3 weeks ago
BulkRearmOnGrowthTest.php
3 weeks ago
BulkReviewsUpdateStuckStateTest.php
3 weeks ago
ClearCacheRelayResetTest.php
3 weeks ago
DeleteSourceRelayFailureTest.php
3 weeks ago
ErrorHandlerFalsyOptionTest.php
3 weeks ago
FeedCacheUpdateServiceTest.php
3 weeks ago
FeedMalformedPayloadTest.php
3 weeks ago
ForceKeylessRefetchTest.php
3 weeks ago
LicenseDeactivateStaleStateTest.php
3 weeks ago
MediaFinderMemoTest.php
3 weeks ago
MultiSourceAggregationTest.php
3 weeks ago
ReconcileMigratedLicenseRoutineTest.php
3 weeks ago
ReconcileRemovalTest.php
3 weeks ago
RegisterWebsiteRoutineTest.php
3 weeks ago
RemoteRequestMemoTest.php
3 weeks ago
ReviewAlertHeaderTotalsTest.php
3 weeks ago
ReviewAlertPageTargetingTest.php
3 weeks ago
ReviewAlertStarFillTest.php
3 weeks ago
ShortcodeNeutralizationTest.php
3 weeks ago
SiteMigrationRecoveryTest.php
3 weeks ago
Smash1583HeaderParityTest.php
3 weeks ago
Smash1631MultiLanguageBulkTest.php
3 weeks ago
Smash1631UpdateSingleLangScopeTest.php
3 weeks ago
Smash1706TripAdvisorPlaceIdTest.php
3 weeks ago
Smash1756SchemaServiceTest.php
3 weeks ago
Smash1785AvatarLocalUrlGuardTest.php
3 weeks ago
Smash1785AvatarReHealTest.php
3 weeks ago
Smash1795ReviewTextXssTest.php
3 weeks ago
Smash782BookingHeaderRatingTest.php
3 weeks ago
Smash782CountryFlagEmojiTest.php
3 weeks ago
Smash782ExternalRefreshCronTest.php
3 weeks ago
Smash782ExtrasTemplateTest.php
3 weeks ago
Smash782ReviewAlertProviderDataTest.php
3 weeks ago
SourceIdLookupTest.php
3 weeks ago
WpmlGetCurrentLanguageTest.php
3 weeks ago
WpmlLanguageMappingTest.php
3 weeks ago
Smash782BookingHeaderRatingTest.php
107 lines
| 1 | <?php |
| 2 | |
| 3 | namespace SmashBalloon\Reviews\Tests\Unit; |
| 4 | |
| 5 | use PHPUnit\Framework\TestCase; |
| 6 | use SmashBalloon\Reviews\Common\FeedDisplay; |
| 7 | |
| 8 | /** |
| 9 | * SMASH-782 follow-up (2026-07-08) — Booking feed-header rating. |
| 10 | * |
| 11 | * FeedDisplay::get_booking_header_rating() shows Booking's native 0-10 score |
| 12 | * ONLY for a booking-only feed (every source carries a numeric review_score). |
| 13 | * For a booking-only MULTI-source feed the aggregate must be COUNT-WEIGHTED by |
| 14 | * each hotel's review volume (review_count ?? total_rating), kept on the 0-10 |
| 15 | * scale — a high-volume hotel dominates a low-volume one. Previously it was an |
| 16 | * unweighted array_sum/count mean. Any non-Booking source disqualifies the |
| 17 | * feed (is_booking_only=false) so a mixed collection falls back to the 0-5 |
| 18 | * star average elsewhere. |
| 19 | * |
| 20 | * Uses reflection (newInstanceWithoutConstructor) because the method reads only |
| 21 | * its $businesses argument — no Feed/Parser/WP state — so the real constructor |
| 22 | * (which needs Feed+Parser and get_option) is not required. |
| 23 | */ |
| 24 | final class Smash782BookingHeaderRatingTest extends TestCase |
| 25 | { |
| 26 | private function fd(): FeedDisplay |
| 27 | { |
| 28 | return (new \ReflectionClass(FeedDisplay::class))->newInstanceWithoutConstructor(); |
| 29 | } |
| 30 | |
| 31 | /** @param array<int,array<string,mixed>> $sources */ |
| 32 | private function biz(array $sources): array |
| 33 | { |
| 34 | return array_map(static fn ($s) => ['info' => json_encode($s)], $sources); |
| 35 | } |
| 36 | |
| 37 | public function test_booking_only_multi_source_score_is_count_weighted(): void |
| 38 | { |
| 39 | $r = $this->fd()->get_booking_header_rating($this->biz([ |
| 40 | ['review_score' => 8.5, 'total_rating' => 12312, 'review_score_word' => 'Very good'], |
| 41 | ['review_score' => 7.8, 'total_rating' => 1935, 'review_score_word' => 'Good'], |
| 42 | ['review_score' => 8.6, 'total_rating' => 372, 'review_score_word' => 'Fabulous'], |
| 43 | ])); |
| 44 | $this->assertTrue($r['is_booking_only']); |
| 45 | // (8.5*12312 + 7.8*1935 + 8.6*372) / 14619 = 8.41 -> 8.4 (unweighted mean would be 8.3) |
| 46 | $this->assertSame(8.4, $r['score']); |
| 47 | } |
| 48 | |
| 49 | public function test_single_source_score_unchanged_bc(): void |
| 50 | { |
| 51 | $r = $this->fd()->get_booking_header_rating($this->biz([ |
| 52 | ['review_score' => 8.5, 'total_rating' => 12312, 'review_score_word' => 'Very good'], |
| 53 | ])); |
| 54 | $this->assertTrue($r['is_booking_only']); |
| 55 | $this->assertSame(8.5, $r['score']); |
| 56 | $this->assertSame('Very good', $r['word']); |
| 57 | } |
| 58 | |
| 59 | public function test_no_counts_falls_back_to_unweighted_mean(): void |
| 60 | { |
| 61 | $r = $this->fd()->get_booking_header_rating($this->biz([ |
| 62 | ['review_score' => 8.5], |
| 63 | ['review_score' => 7.8], |
| 64 | ['review_score' => 8.6], |
| 65 | ])); |
| 66 | $this->assertTrue($r['is_booking_only']); |
| 67 | // no usable count on any source -> unweighted (8.5+7.8+8.6)/3 = 8.3 |
| 68 | $this->assertSame(8.3, $r['score']); |
| 69 | } |
| 70 | |
| 71 | public function test_review_count_key_also_weights(): void |
| 72 | { |
| 73 | // some payloads carry review_count instead of total_rating |
| 74 | $r = $this->fd()->get_booking_header_rating($this->biz([ |
| 75 | ['review_score' => 9.0, 'review_count' => 1000], |
| 76 | ['review_score' => 5.0, 'review_count' => 0], |
| 77 | ])); |
| 78 | // 9.0*1000 + 5.0*0 = 9000 / 1000 = 9.0 |
| 79 | $this->assertSame(9.0, $r['score']); |
| 80 | } |
| 81 | |
| 82 | public function test_mixed_feed_is_not_booking_only(): void |
| 83 | { |
| 84 | $r = $this->fd()->get_booking_header_rating($this->biz([ |
| 85 | ['review_score' => 8.5, 'total_rating' => 12312], |
| 86 | ['rating' => 4.6, 'review_count' => 300], // a non-Booking source: no review_score |
| 87 | ])); |
| 88 | $this->assertFalse($r['is_booking_only']); |
| 89 | $this->assertSame(0.0, $r['score']); |
| 90 | } |
| 91 | |
| 92 | public function test_word_shown_only_when_uniform(): void |
| 93 | { |
| 94 | $same = $this->fd()->get_booking_header_rating($this->biz([ |
| 95 | ['review_score' => 8.0, 'total_rating' => 100, 'review_score_word' => 'Very good'], |
| 96 | ['review_score' => 8.4, 'total_rating' => 100, 'review_score_word' => 'Very good'], |
| 97 | ])); |
| 98 | $this->assertSame('Very good', $same['word']); |
| 99 | |
| 100 | $diff = $this->fd()->get_booking_header_rating($this->biz([ |
| 101 | ['review_score' => 8.0, 'total_rating' => 100, 'review_score_word' => 'Very good'], |
| 102 | ['review_score' => 9.2, 'total_rating' => 100, 'review_score_word' => 'Superb'], |
| 103 | ])); |
| 104 | $this->assertSame('', $diff['word']); |
| 105 | } |
| 106 | } |
| 107 |