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

Shops::fake()

Shops::fake() dosadí RoundlyConsulting\Shops\Testing\ShopsFake a vráti ho. Je to špión, nie atrapa: každá operácia naozaj prebehne — košíky, objednávky aj riadky zásob sú skutočné, udalosti sa spúšťajú a platba stále ide cez naviazaný PaymentGateway (predvolený NullPaymentGateway nič nestrhne). Každá zmena stavu sa zaznamená, či prišla cez fasádu, injektovaný ShopsManager (fake je jeho podtyp, takže ho dostanú aj injektované manažéry) alebo metódu modelu ako $cart->add() či $order->markPaid(). Volanie, ktoré vyhodí výnimku, sa nezaznamená.

use RoundlyConsulting\Shops\Cart\Cart;
use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Orders\Order;
use RoundlyConsulting\Shops\Products\ProductVariant;
use RoundlyConsulting\Shops\Testing\CartChange;

it('adds to the cart, checks out and charges', function () {
    Shops::fake();   // a spy — carts, orders and stock rows are still real

    $variant = ProductVariant::factory()->withEurPrice('1990')->withStock(5)->create();
    $cart = Cart::factory()->create();

    $this->post("/cart/{$cart->id}/items", ['variant' => $variant->id, 'quantity' => 2]);
    $this->post("/cart/{$cart->id}/checkout")->assertRedirect();

    $order = Order::query()->latest('id')->firstOrFail();

    Shops::assertCartChanged($cart, CartChange::Added);   // Added, Updated, Removed or Cleared
    Shops::assertOrderPlaced($cart);                      // the stock checkout reserves is part of this
    Shops::assertCharged($order);                         // and so are the transitions a charge makes
    Shops::assertNothingTransitioned();
    Shops::assertNothingStockAdjusted();
});

Zaznamenajú sa len volania vášho kódu: tovar, ktorý rezervuje vytvorenie objednávky, patrí k assertOrderPlaced(), a prechody stavu po úspešnej platbe patria k assertCharged(). Overovať môžete cez fasádu aj cez vrátený fake:

use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Inventory\Enums\StockReason;
use RoundlyConsulting\Shops\Orders\Enums\Status;
use RoundlyConsulting\Shops\Orders\Order;
use RoundlyConsulting\Shops\Products\ProductVariant;

it('ships an order and books a delivery', function () {
    $fake = Shops::fake();   // the ShopsFake — assert on it or on the facade

    $order = Order::factory()->paid()->create();
    $variant = ProductVariant::factory()->withStock(0)->create();

    $this->post("/admin/orders/{$order->number}/ship");
    $this->post("/admin/variants/{$variant->id}/receive", ['quantity' => 10]);

    $fake->assertTransitioned($order, Status::Fulfilled);   // any order / any status when omitted
    $fake->assertStockAdjusted($variant, delta: 10, reason: StockReason::Received);
    $fake->assertNothingPlaced();
    $fake->assertNothingCharged();
    $fake->assertNothingCartChanged();
});

Všetky asercie aj s ich negáciou:

AserciaNegáciaPrejde, keď
assertOrderPlaced(?Cart $cart = null)assertNothingPlaced()Ľubovoľná objednávka alebo objednávka z daného košíka.
assertCharged(?Order $order = null)assertNothingCharged()Ľubovoľná platba alebo platba danej objednávky — aj neúspešná.
assertTransitioned(?Order $order = null, ?Status $to = null)assertNothingTransitioned()Ľubovoľný prechod, zúžený podľa objednávky a/alebo cieľového stavu.
assertStockAdjusted(?ProductVariant $variant = null, ?int $delta = null, ?StockReason $reason = null)assertNothingStockAdjusted()Ľubovoľný zápis zásoby, zúžený podľa variantu, presnej zmeny a/alebo dôvodu.
assertCartChanged(?Cart $cart = null, ?CartChange $change = null)assertNothingCartChanged()Ľubovoľná zmena košíka, zúžená podľa košíka a/alebo CartChange (Added, Updated, Removed — aj update($item, 0) — Cleared).

Fake objekty sesterských balíkov sa dajú kombinovať: shops si každú akciu vyžiada pri každom volaní, takže Coupons::fake() uvidí uplatnenie kupónu pri vytvorení objednávky a Credits::fake() stiahnutie kreditu pri platbe.

Továrne modelov

Každý model balíka má továreň dostupnú cez Model::factory(). Používajte ich v testoch aj seederoch:

ModelPredvolené hodnotyStavy
Shops\ShopJedinečný názov firmy, bez menycurrency(string $currency)
Shops\TaxRateTrieda standard, 2000 bp, bez krajinydefault(), reduced(), forCountry(string $iso)
Products\ProductJedinečný názov, náhodné voliteľné published_at, predvolený variantwithPrice(string $price, string $currency = 'EUR'), withVariant(ProductVariantFactory $variant), published(), unpublished()
Products\ProductVariantNový produkt, náhodné SKU, cena v EUR alebo USD, sledovaný, zásoba 0–100withEurPrice(string $price), untracked(), withStock(int $stock)
Products\ProductOptionNový produkt, Size, Colour alebo Material—
Products\ProductOptionValueNová možnosť, jedinečné slovo—
Products\CategoryJedinečný názov, náhodné voliteľné published_atpublished(), unpublished()
Inventory\StockAdjustmentNový variant, +1–50 Received—
Cart\CartUUID token, EUR—
Cart\CartItemNový košík, cena v EUR, množstvo 1–5—
Orders\OrderStav New, poznámkawithStatus(Status $status), inProgress(), paid(), fulfilled(), canceled(), withDiscount(...)
Orders\ItemNová objednávka, cena v EUR alebo USD, množstvo 1–10withEurPrice(string $price), withUsdPrice(string $price)

Celý nákup bez fake v teste Pest — spúšťajte ho s načítanými publikovanými migráciami (RefreshDatabase):

use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Shops\Cart\Cart;
use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Orders\Events\OrderPlaced;
use RoundlyConsulting\Shops\Products\Product;
use RoundlyConsulting\Shops\Products\ProductVariant;

it('places an order and reserves stock', function () {
    Event::fake([OrderPlaced::class]);

    $product = Product::factory()
        ->published()
        ->withVariant(ProductVariant::factory()->withEurPrice('1990')->withStock(5))
        ->create();
    $variant = $product->variants()->first();

    $cart = Cart::factory()->create();   // EUR, guest token
    Shops::cart($cart)->add($variant, 2);

    $order = Shops::cart($cart)->checkout();

    expect($order->price->getSubtotal()->minor())->toBe('3980')
        ->and($variant->refresh()->availableStock())->toBe(3);

    Event::assertDispatched(OrderPlaced::class);
});

Ďalšie stavy:

use RoundlyConsulting\Shops\Orders\Order;
use RoundlyConsulting\Shops\Shops\Shop;
use RoundlyConsulting\Shops\Shops\TaxRate;

$shop = Shop::factory()->currency('EUR')->create();
TaxRate::factory()->for($shop)->default()->create();                // standard, 2000 bp
TaxRate::factory()->for($shop)->reduced()->forCountry('DE')->create();

$order = Order::factory()->paid()->create();                        // status columns only
$order = Order::factory()->withDiscount('500', 'EUR', couponCode: 'WELCOME10')->create();

Stavy továrne objednávok nastavujú stĺpce stavu priamo — nespúšťajú prechody, nerezervujú tovar ani nespúšťajú udalosti. Ak na vedľajších účinkoch záleží, použite metódy životného cyklu. Čísla objednávok sa pridelia pri vložení aj pod Event::fake().

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.