create([ 'title' => 'Prefetch Artwork', 'slug' => 'prefetch-artwork', 'hash' => 'aabbccddeeff00112233445566778899', 'file_path' => 'uploads/prefetch.jpg', ]); $queries = 0; DB::listen(function () use (&$queries): void { $queries++; }); $response = $this->getJson('/api/artworks/'.$artwork->id.'/page?prefetch=1') ->assertOk(); expect($queries)->toBe(1) ->and($response->json())->toHaveKeys(['id', 'title', 'slug', 'thumbs']) ->and($response->json('thumbs'))->toHaveKeys(['md', 'lg']) ->and($response->json('thumbs.xl'))->toBeNull() ->and($response->json('stats'))->toBeNull() ->and($response->json('thumbs.lg.url'))->toBe( 'https://cdn.skinbase.org/artworks/lg/aa/bb/aabbccddeeff00112233445566778899.webp' ); }); it('does not prefetch missing or unpublished artwork', function (): void { $unpublished = Artwork::factory()->unpublished()->create(); $this->getJson('/api/artworks/'.$unpublished->id.'/page?prefetch=1') ->assertNotFound(); $this->getJson('/api/artworks/999999/page?prefetch=1') ->assertNotFound(); }); it('keeps full page navigation data available separately from prefetch', function (): void { $artwork = Artwork::factory()->create([ 'slug' => 'full-navigation-artwork', ]); $this->getJson('/api/artworks/'.$artwork->id.'/page') ->assertOk() ->assertJsonStructure([ 'id', 'title', 'thumbs', 'user', 'categories', 'tags', 'stats', 'viewer', ]); }); it('measures the lightweight prefetch contract for guest and authenticated viewers', function (): void { $artwork = Artwork::factory()->create([ 'slug' => 'prefetch-measurement-artwork', 'hash' => 'aabbccddeeff00112233445566778899', ]); DB::enableQueryLog(); DB::flushQueryLog(); $guestPrefetch = $this->getJson('/api/artworks/'.$artwork->id.'/page?prefetch=1')->assertOk(); $guestPrefetchQueries = count(DB::getQueryLog()); DB::flushQueryLog(); $guestFull = $this->getJson('/api/artworks/'.$artwork->id.'/page')->assertOk(); $guestFullQueries = count(DB::getQueryLog()); DB::flushQueryLog(); $authPrefetch = $this->actingAs(User::factory()->create()) ->getJson('/api/artworks/'.$artwork->id.'/page?prefetch=1') ->assertOk(); $authPrefetchQueries = count(DB::getQueryLog()); DB::flushQueryLog(); $authFull = $this->getJson('/api/artworks/'.$artwork->id.'/page')->assertOk(); $authFullQueries = count(DB::getQueryLog()); DB::disableQueryLog(); fwrite(STDERR, sprintf( "M18B3 prefetch bytes/queries: guest=%d/%d auth=%d/%d; full guest=%d/%d auth=%d/%d\n", strlen((string) $guestPrefetch->getContent()), $guestPrefetchQueries, strlen((string) $authPrefetch->getContent()), $authPrefetchQueries, strlen((string) $guestFull->getContent()), $guestFullQueries, strlen((string) $authFull->getContent()), $authFullQueries, )); expect($guestPrefetchQueries)->toBe(1) ->and($authPrefetchQueries)->toBeLessThanOrEqual(2) ->and($guestPrefetch->json())->toEqual($authPrefetch->json()); });