NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

GooglePlaces::fake() nahradí živého klienta zaznamenávajúcim GooglePlacesFake a vráti ho — bez Http::fake() a bez živých (platených) volaní. Nič sa nedostane ku Google: každé volanie sa zaznamená a odpoveď pochádza z toho, čo ste pripravili metódami with*():

use RoundlyConsulting\GooglePlaces\DataTransferObjects\AutocompletePrediction;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\AutocompleteQuery;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\Place;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

$fake = GooglePlaces::fake();

$fake->withAutocomplete([new AutocompletePrediction('Café Roma', 'p1', ['cafe'])]);
$fake->withDetails(new Place('Café Roma'));

// ...exercise code that calls the facade...

$fake->assertAutocompleted(fn (AutocompleteQuery $q) => $q->input === 'Café');
$fake->assertDetailsRequested('p1');
$fake->assertNothingGeocoded();

Fake je PlacesClient nasadený za fasádu aj za väzbu v kontajneri, takže ho zasiahnu klienti vložení cez konštruktor, session(), matrix(), photo() (vrátane save(), ktorý zapíše pripravené bajty), stránkované vyhľadávanie, príkaz google-places:check aj geolokačný driver google_places.

Príprava výsledkov

PrípravaPre metódyAk nie je pripravené
withAutocomplete(array $predictions)autocomplete()Prázdna kolekcia.
withDetails(?Place $place)details()null.
withGeocode(array $results)geocode()Prázdna kolekcia.
withGeocodeAddress(array $results)geocodeAddress()Prázdna kolekcia.
withTextSearch(array $places)textSearch(), textSearchPaginated()Prázdne; paginátor vráti jednu stránku.
withNearbySearch(array $places)nearbySearch(), nearbySearchPaginated()Prázdne; paginátor vráti jednu stránku.
withFindPlace(?Place $place)findPlace()null.
withDistance(Distance|MultipleDistances $distance)distance()Nulová Distance.
withMatrix(DistanceMatrix $matrix)computeMatrix(), matrix()->…()Prázdna matica s rozmermi podľa dopytu.
withPhoto(string $bytes, ?string $uri = null)photoContents(), photoUri(), photo()->…Prázdne bajty; falošná URL bez kľúča zostavená z názvu fotografie.
withPhotoUrl(string $url)photoUrl()URL média zostavená z názvu fotografie.
withCheck(array $results)check(), google-places:checkTri zdravé výsledky.

Asercie

Každé volanie sa zaznamená ako jeho query objekt — skalárne hodnoty sa najprv prevedú na príslušnú triedu dopytu. Asercia bez callbacku prejde, ak k volaniu vôbec došlo; s callbackom musí zodpovedať aspoň jeden zaznamenaný dopyt:

AserciaPrejde, keď
assertAutocompleted(fn (AutocompleteQuery $q) => $q->input === 'Café')Volanie autocomplete (zodpovedajúce callbacku).
assertDetailsRequested('p1')Volanie details; reťazec porovná place id, callback dostane DetailsQuery.
assertGeocoded(fn (ReverseGeocodingQuery $q) => $q->location->latitude === 48.1486)Spätné geokódovanie.
assertAddressGeocoded('Hlavné námestie 1, Bratislava')Priame geokódovanie; reťazec porovná adresu.
assertTextSearched(fn (TextSearchQuery $q) => $q->textQuery === 'pizza')Textové vyhľadávanie, vrátane stránkovaného.
assertNearbySearched(fn (NearbySearchQuery $q) => $q->radius === 1500)Okolité vyhľadávanie, vrátane stránkovaného.
assertFindPlaceRequested(fn (string $text) => $text === 'Eiffel Tower')Volanie findPlace() — callback dostane len hľadaný text, nie preferovanú polohu.
assertDistanceRequested(fn (DistanceQuery $q) => $q->type === TravelMode::Driving)Volanie distance().
assertMatrixComputed(fn (MatrixQuery $q) => count($q->origins) === 2)Matica, cez computeMatrix() alebo matrix()->…().
assertPhotoRequested('places/p1/photos/a')Bajty alebo URL fotografie bez kľúča; callback dostane PhotoQuery (contents je pri URL false).
assertChecked()Prebehol check() — priamo alebo cez google-places:check.
assertNothingAutocompleted()Žiadne volanie autocomplete.
assertNothingGeocoded()Žiadne spätné geokódovanie.
assertNothingRequested()Žiadne volanie, okrem photoUrl() a vytvorenia handles.

Samotné session(), matrix() a photo() sa nezaznamenávajú — zaznamenajú sa volania, ktoré handles vykonajú. Volania v session sa zapíšu ako bežné autocomplete a details s tokenom session v dopyte, overujte preto $q->sessionToken. Fake nikdy nevyhodí výnimku.

Zostavenie falošných výsledkov

Výsledky sú obyčajné DTO, takže ich zostavíte priamo:

use RoundlyConsulting\GooglePlaces\DataTransferObjects\Distance;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\DistanceQuery;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\Geometry;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\Location;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\ReverseGeocodingResult;
use RoundlyConsulting\GooglePlaces\Enums\TravelMode;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

it('quotes a delivery time for a typed address', function () {
    $fake = GooglePlaces::fake();

    $point = new Location(48.1435, 17.1089);

    $fake->withGeocodeAddress([
        new ReverseGeocodingResult(
            address: 'Hlavné námestie 1, 811 01 Bratislava, Slovakia',
            placeId: 'p1',
            geometry: new Geometry($point, $point, $point),
            types: ['street_address'],
        ),
    ]);
    $fake->withDistance(new Distance('4.2 km', 4200, '12m', 720, TravelMode::Driving));

    // ...call the code under test...

    $fake->assertAddressGeocoded('Hlavné námestie 1, Bratislava');
    $fake->assertDistanceRequested(fn (DistanceQuery $q) => $q->type === TravelMode::Driving);
    $fake->assertNothingAutocompleted();
});

Kontrola, že sa nevolalo

use RoundlyConsulting\GooglePlaces\DataTransferObjects\Place;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\TextSearchQuery;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

it('renders the cached page without calling Google', function () {
    $fake = GooglePlaces::fake();

    $this->get('/places/cached')->assertOk();

    $fake->assertNothingRequested();   // no lookup, photo request or check at all
});

it('searches by text and never geocodes', function () {
    $fake = GooglePlaces::fake()->withTextSearch([new Place('Pizza Roma')]);

    $this->get('/search?q=pizza')->assertOk();

    $fake->assertTextSearched(fn (TextSearchQuery $q) => $q->textQuery === 'pizza');
    $fake->assertNothingAutocompleted();
    $fake->assertNothingGeocoded();
});

Fotografie

Bajty pripravte cez withPhoto() a fake skombinujte so Storage::fake():

use Illuminate\Support\Facades\Storage;
use RoundlyConsulting\GooglePlaces\DataTransferObjects\PhotoQuery;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

it('stores the hero photo', function () {
    Storage::fake('public');
    $fake = GooglePlaces::fake()->withPhoto('JPEG-BYTES');

    GooglePlaces::photo('places/p1/photos/a', 1200, 800)->save('public', 'p1.jpg');

    Storage::disk('public')->assertExists('p1.jpg');
    $fake->assertPhotoRequested(fn (PhotoQuery $q) => $q->name === 'places/p1/photos/a' && $q->maxWidth === 1200);
});

Kontrola stavu API

use RoundlyConsulting\GooglePlaces\DataTransferObjects\ApiCheckResult;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

config(['google-places.key' => 'test-key']);   // the command refuses to run without a key

$fake = GooglePlaces::fake()->withCheck([
    new ApiCheckResult('Places API (New)', true, 'Reachable and authorized.'),
    new ApiCheckResult('Routes API', false, 'Unreachable: timeout'),
    new ApiCheckResult('Geocoding API', true, 'Reachable and authorized.'),
]);

$this->artisan('google-places:check')->assertFailed();

$fake->assertChecked();

Testovanie so skutočným klientom

Ak chcete otestovať zostavenie požiadavky, klasifikáciu chýb, cache či rate limiting, ponechajte skutočného klienta a nahraďte radšej HTTP vrstvu:

use Illuminate\Support\Facades\Http;
use RoundlyConsulting\GooglePlaces\Exceptions\PlacesException;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

config(['google-places.key' => 'test-key', 'google-places.rate_limits.places.enabled' => false]);

Http::fake([
    'places.googleapis.com/v1/places:searchText' => Http::response([
        'error' => [
            'status' => 'INVALID_ARGUMENT',
            'message' => 'API key not valid.',
            'details' => [['@type' => 'type.googleapis.com/google.rpc.ErrorInfo', 'reason' => 'API_KEY_INVALID']],
        ],
    ], 400),
]);

try {
    GooglePlaces::textSearch('coffee');
} catch (PlacesException $e) {
    expect($e->isDenied())->toBeTrue()
        ->and($e->isInvalidRequest())->toBeFalse()
        ->and($e->googleReason())->toBe('API_KEY_INVALID');
}

Vlastnú testovaciu sadu balíka spustíte v jeho repozitári:

composer test

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.