Testovanie
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:
| Asercia | Negácia | Prejde, 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:
| Model | Predvolené hodnoty | Stavy |
|---|---|---|
Shops\Shop | Jedinečný názov firmy, bez meny | currency(string $currency) |
Shops\TaxRate | Trieda standard, 2000 bp, bez krajiny | default(), reduced(), forCountry(string $iso) |
Products\Product | Jedinečný názov, náhodné voliteľné published_at, predvolený variant | withPrice(string $price, string $currency = 'EUR'), withVariant(ProductVariantFactory $variant), published(), unpublished() |
Products\ProductVariant | Nový produkt, náhodné SKU, cena v EUR alebo USD, sledovaný, zásoba 0–100 | withEurPrice(string $price), untracked(), withStock(int $stock) |
Products\ProductOption | Nový produkt, Size, Colour alebo Material | — |
Products\ProductOptionValue | Nová možnosť, jedinečné slovo | — |
Products\Category | Jedinečný názov, náhodné voliteľné published_at | published(), unpublished() |
Inventory\StockAdjustment | Nový variant, +1–50 Received | — |
Cart\Cart | UUID token, EUR | — |
Cart\CartItem | Nový košík, cena v EUR, množstvo 1–5 | — |
Orders\Order | Stav New, poznámka | withStatus(Status $status), inProgress(), paid(), fulfilled(), canceled(), withDiscount(...) |
Orders\Item | Nová objednávka, cena v EUR alebo USD, množstvo 1–10 | withEurPrice(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 kryptomienOdoslaní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.