corentin_wakdo/tests/Unit/Order/OrderControllerTest.php
Imugiii 11071e6251
All checks were successful
CI / secret-scan (push) Successful in 8s
CI / php-lint (push) Successful in 20s
CI / static-tests (push) Successful in 42s
CI / js-tests (push) Successful in 30s
CI / secret-scan (pull_request) Successful in 8s
CI / php-lint (pull_request) Successful in 23s
CI / js-tests (pull_request) Successful in 24s
CI / static-tests (pull_request) Successful in 45s
feat(api): suivi public du statut commande GET /api/orders/{number} (P4)
2026-06-22 06:45:59 +00:00

174 lines
6.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Unit\Order;
use PHPUnit\Framework\TestCase;
use App\Controllers\OrderController;
use App\Core\Config;
use App\Core\Database;
use App\Core\DatabaseInterface;
use App\Core\Request;
use App\Tests\Support\FakeOrderDatabase;
/**
* Sous-classe de test : redefinit le hook db() pour injecter le double dedie, sans
* base reelle. orders() construit alors le vrai OrderRepository sur ce double, ce
* qui exerce le cablage complet controleur -> repository.
*/
final class TestOrderController extends OrderController
{
public function __construct(
Request $request,
Config $config,
Database $database,
private readonly FakeOrderDatabase $fakeDb,
) {
parent::__construct($request, $config, $database);
}
protected function db(): DatabaseInterface
{
return $this->fakeDb;
}
}
final class OrderControllerTest extends TestCase
{
private function controller(FakeOrderDatabase $db, string $body = '', string $path = '/api/orders'): TestOrderController
{
$request = new Request('POST', $path, [], ['content-type' => 'application/json'], $body, '203.0.113.5');
return new TestOrderController($request, new Config(), new Database(new Config()), $db);
}
/**
* @param array<string, mixed> $payload
*/
private function jsonBody(array $payload): string
{
return (string) json_encode($payload);
}
public function testCreateReturns201WithOrderNumber(): void
{
$db = new FakeOrderDatabase();
$db->products[12] = ['id' => 12, 'name' => 'Cheeseburger', 'price_cents' => 890, 'vat_rate' => 100, 'is_available' => 1];
$body = $this->jsonBody(['service_mode' => 'takeaway', 'items' => [['type' => 'product', 'product_id' => 12, 'quantity' => 1]]]);
$response = $this->controller($db, $body)->create();
self::assertSame(201, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('K100', $data['data']['order_number'] ?? null);
self::assertSame('pending_payment', $data['data']['status'] ?? null);
self::assertSame(890, $data['data']['total_ttc_cents'] ?? null);
}
public function testCreateUnknownProductReturns422(): void
{
$db = new FakeOrderDatabase();
$body = $this->jsonBody(['service_mode' => 'takeaway', 'items' => [['type' => 'product', 'product_id' => 999, 'quantity' => 1]]]);
$response = $this->controller($db, $body)->create();
self::assertSame(422, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('PRODUCT_UNAVAILABLE', $data['error']['code'] ?? null);
}
public function testCreateInvalidServiceModeReturns422(): void
{
$db = new FakeOrderDatabase();
$body = $this->jsonBody(['service_mode' => 'bogus', 'items' => [['type' => 'product', 'product_id' => 12, 'quantity' => 1]]]);
$response = $this->controller($db, $body)->create();
self::assertSame(422, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('INVALID_SERVICE_MODE', $data['error']['code'] ?? null);
}
public function testPayReturns200Paid(): void
{
$db = new FakeOrderDatabase();
$db->orderByNumber = ['id' => 100, 'order_number' => 'K100', 'total_ttc_cents' => 890, 'status' => 'pending_payment'];
$response = $this->controller($db, '', '/api/orders/K100/pay')->pay(['number' => 'K100']);
self::assertSame(200, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('paid', $data['data']['status'] ?? null);
self::assertSame('K100', $data['data']['order_number'] ?? null);
}
public function testPayUnknownReturns404(): void
{
$db = new FakeOrderDatabase();
$db->orderByNumber = null;
$response = $this->controller($db, '', '/api/orders/K404/pay')->pay(['number' => 'K404']);
self::assertSame(404, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('ORDER_NOT_FOUND', $data['error']['code'] ?? null);
}
public function testPayTerminalStatusReturns409(): void
{
$db = new FakeOrderDatabase();
$db->orderByNumber = ['id' => 100, 'order_number' => 'K100', 'total_ttc_cents' => 890, 'status' => 'delivered'];
$response = $this->controller($db, '', '/api/orders/K100/pay')->pay(['number' => 'K100']);
self::assertSame(409, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('INVALID_TRANSITION', $data['error']['code'] ?? null);
}
public function testShowReturnsOrderStatus(): void
{
$db = new FakeOrderDatabase();
$db->orderByNumber = ['id' => 100, 'order_number' => 'K100', 'total_ttc_cents' => 890, 'status' => 'paid'];
$response = $this->controller($db, '', '/api/orders/K100')->show(['number' => 'K100']);
self::assertSame(200, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('K100', $data['data']['order_number'] ?? null);
self::assertSame('paid', $data['data']['status'] ?? null);
self::assertSame(890, $data['data']['total_ttc_cents'] ?? null);
}
public function testShowUnknownReturns404(): void
{
$db = new FakeOrderDatabase();
$db->orderByNumber = null;
$response = $this->controller($db, '', '/api/orders/K404')->show(['number' => 'K404']);
self::assertSame(404, $response->status());
$data = json_decode($response->body(), true);
self::assertIsArray($data);
self::assertSame('ORDER_NOT_FOUND', $data['error']['code'] ?? null);
}
public function testShowEmptyNumberReturns404(): void
{
$db = new FakeOrderDatabase();
$db->orderByNumber = ['id' => 1, 'order_number' => 'K1', 'total_ttc_cents' => 100, 'status' => 'paid'];
// Numero vide : court-circuite avant toute lecture BDD (findByNumber renvoie null).
$response = $this->controller($db, '', '/api/orders/')->show(['number' => '']);
self::assertSame(404, $response->status());
}
}