mockService = $this->createMock(OrderAdminService::class); $this->mockOrderRepo = $this->createMock(OrderRepository::class); $this->controller = new OrdersApiController($this->mockService, $this->mockOrderRepo); $_SERVER['REQUEST_METHOD'] = 'GET'; $_GET = []; } protected function tearDown(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; $_GET = []; http_response_code(200); } // --- list --- public function testListReturnsOrders(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->mockOrderRepo->method('listForApi') ->willReturn([ 'items' => [ ['id' => 1, 'number' => '2026/01/001', 'status' => 0, 'paid' => 0, 'summary' => 99.99], ], 'total' => 1, 'page' => 1, 'per_page' => 50, ]); ob_start(); $this->controller->list(); $output = ob_get_clean(); $json = json_decode($output, true); $this->assertSame('ok', $json['status']); $this->assertCount(1, $json['data']['items']); $this->assertSame(1, $json['data']['total']); } public function testListRejectsPostMethod(): void { $_SERVER['REQUEST_METHOD'] = 'POST'; ob_start(); $this->controller->list(); $output = ob_get_clean(); $this->assertSame(405, http_response_code()); } public function testListPassesFiltersToRepository(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; $_GET['status'] = '4'; $_GET['paid'] = '1'; $_GET['page'] = '2'; $_GET['per_page'] = '25'; $this->mockOrderRepo->expects($this->once()) ->method('listForApi') ->with( $this->callback(function ($filters) { return $filters['status'] === '4' && $filters['paid'] === '1'; }), 2, 25 ) ->willReturn(['items' => [], 'total' => 0, 'page' => 2, 'per_page' => 25]); ob_start(); $this->controller->list(); ob_get_clean(); } // --- get --- public function testGetReturnsOrder(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; $_GET['id'] = '42'; $this->mockOrderRepo->method('findForApi') ->with(42) ->willReturn([ 'id' => 42, 'number' => '2026/01/001', 'status' => 4, 'paid' => 1, 'summary' => 150.00, 'products' => [], 'statuses' => [], ]); ob_start(); $this->controller->get(); $output = ob_get_clean(); $json = json_decode($output, true); $this->assertSame('ok', $json['status']); $this->assertSame(42, $json['data']['id']); } public function testGetReturns404WhenOrderNotFound(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; $_GET['id'] = '999'; $this->mockOrderRepo->method('findForApi') ->with(999) ->willReturn(null); ob_start(); $this->controller->get(); $output = ob_get_clean(); $this->assertSame(404, http_response_code()); $json = json_decode($output, true); $this->assertSame('NOT_FOUND', $json['code']); } public function testGetReturns400WhenMissingId(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; ob_start(); $this->controller->get(); $output = ob_get_clean(); $this->assertSame(400, http_response_code()); } // --- change_status --- public function testChangeStatusUpdatesOrder(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_GET['id'] = '10'; $this->mockOrderRepo->method('findRawById') ->with(10) ->willReturn(['id' => 10, 'status' => 0]); $this->mockService->method('changeStatus') ->with(10, 5, false) ->willReturn(['result' => true]); // Simulate JSON body via php://input override is not possible in unit tests, // so we test the controller logic path via mock expectations ob_start(); $this->controller->change_status(); $output = ob_get_clean(); // Without a real php://input body, getJsonBody returns null → BAD_REQUEST $json = json_decode($output, true); $this->assertSame('error', $json['status']); $this->assertSame('BAD_REQUEST', $json['code']); } public function testChangeStatusReturns400WhenMissingId(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; ob_start(); $this->controller->change_status(); $output = ob_get_clean(); $this->assertSame(400, http_response_code()); } public function testChangeStatusRejectsGetMethod(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; $_GET['id'] = '10'; ob_start(); $this->controller->change_status(); $output = ob_get_clean(); $this->assertSame(405, http_response_code()); } // --- set_paid --- public function testSetPaidReturns404WhenOrderNotFound(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_GET['id'] = '999'; $this->mockOrderRepo->method('findRawById') ->with(999) ->willReturn(null); ob_start(); $this->controller->set_paid(); $output = ob_get_clean(); $this->assertSame(404, http_response_code()); } public function testSetPaidReturns400WhenMissingId(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; ob_start(); $this->controller->set_paid(); $output = ob_get_clean(); $this->assertSame(400, http_response_code()); } public function testSetPaidCallsServiceWhenOrderExists(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_GET['id'] = '10'; $this->mockOrderRepo->method('findRawById') ->with(10) ->willReturn(['id' => 10, 'paid' => 0]); $this->mockService->expects($this->once()) ->method('setOrderAsPaid') ->with(10, false); ob_start(); $this->controller->set_paid(); $output = ob_get_clean(); $json = json_decode($output, true); $this->assertSame('ok', $json['status']); $this->assertSame(1, $json['data']['paid']); } // --- set_unpaid --- public function testSetUnpaidReturns404WhenOrderNotFound(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_GET['id'] = '999'; $this->mockOrderRepo->method('findRawById') ->with(999) ->willReturn(null); ob_start(); $this->controller->set_unpaid(); $output = ob_get_clean(); $this->assertSame(404, http_response_code()); } public function testSetUnpaidCallsServiceWhenOrderExists(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_GET['id'] = '10'; $this->mockOrderRepo->method('findRawById') ->with(10) ->willReturn(['id' => 10, 'paid' => 1]); $this->mockService->expects($this->once()) ->method('setOrderAsUnpaid') ->with(10); ob_start(); $this->controller->set_unpaid(); $output = ob_get_clean(); $json = json_decode($output, true); $this->assertSame('ok', $json['status']); $this->assertSame(0, $json['data']['paid']); } }