createMock(\medoo::class); $mockDb->method('select') ->willReturnCallback(function ($table, $columns, $where) { if ($table === 'pp_shop_statuses') { return [ ['id' => 0, 'status' => 'Nowe'], ['id' => 4, 'status' => 'W realizacji'], ]; } return []; }); $repository = new OrderRepository($mockDb); $statuses = $repository->orderStatuses(); $this->assertIsArray($statuses); $this->assertSame('Nowe', $statuses[0]); $this->assertSame('W realizacji', $statuses[4]); } public function testOrderStatusDataReturnsBothNamesAndColors(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('select') ->willReturnCallback(function ($table, $columns, $where) { if ($table === 'pp_shop_statuses') { return [ ['id' => 0, 'status' => 'Nowe', 'color' => '#ff0000'], ['id' => 4, 'status' => 'W realizacji', 'color' => '#00ff00'], ['id' => 5, 'status' => 'Wysłane', 'color' => ''], ]; } return []; }); $repository = new OrderRepository($mockDb); $data = $repository->orderStatusData(); $this->assertArrayHasKey('names', $data); $this->assertArrayHasKey('colors', $data); $this->assertSame('Nowe', $data['names'][0]); $this->assertSame('W realizacji', $data['names'][4]); $this->assertSame('Wysłane', $data['names'][5]); $this->assertSame('#ff0000', $data['colors'][0]); $this->assertSame('#00ff00', $data['colors'][4]); $this->assertArrayNotHasKey(5, $data['colors']); } public function testOrderStatusDataFiltersInvalidHexColors(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('select') ->willReturn([ ['id' => 1, 'status' => 'OK', 'color' => '#abc'], ['id' => 2, 'status' => 'Bad', 'color' => 'red'], ['id' => 3, 'status' => 'XSS', 'color' => '#000" onclick="alert(1)'], ['id' => 4, 'status' => 'Valid', 'color' => '#AABBCC'], ]); $repository = new OrderRepository($mockDb); $data = $repository->orderStatusData(); $this->assertSame('#abc', $data['colors'][1]); $this->assertArrayNotHasKey(2, $data['colors']); $this->assertArrayNotHasKey(3, $data['colors']); $this->assertSame('#AABBCC', $data['colors'][4]); } public function testOrderStatusDataReturnsEmptyOnDbFailure(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('select')->willReturn(false); $repository = new OrderRepository($mockDb); $data = $repository->orderStatusData(); $this->assertSame([], $data['names']); $this->assertSame([], $data['colors']); } public function testNextAndPrevOrderIdReturnNullForInvalidInput(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new OrderRepository($mockDb); $this->assertNull($repository->nextOrderId(0)); $this->assertNull($repository->prevOrderId(0)); } public function testListForAdminReturnsItemsAndTotal(): void { $mockDb = $this->createMock(\medoo::class); $resultSetCount = new class { public function fetchAll(): array { return [[3]]; } }; $resultSetData = new class { public function fetchAll(): array { return [ [ 'id' => 11, 'number' => '2026/02/001', 'date_order' => '2026-02-15 10:00:00', 'client' => 'Jan Kowalski', 'order_email' => 'jan@example.com', 'address' => 'Testowa 1, 00-000 Warszawa', 'status' => 0, 'client_phone' => '111222333', 'transport' => 'Kurier', 'payment_method' => 'Przelew', 'summary' => '123.45', 'paid' => 1, 'total_orders' => 2, ], ]; } }; $callIndex = 0; $mockDb->method('query') ->willReturnCallback(function () use (&$callIndex, $resultSetCount, $resultSetData) { $callIndex++; return $callIndex === 1 ? $resultSetCount : $resultSetData; }); $repository = new OrderRepository($mockDb); $result = $repository->listForAdmin([], 'date_order', 'DESC', 1, 15); $this->assertSame(3, $result['total']); $this->assertCount(1, $result['items']); $this->assertSame(11, $result['items'][0]['id']); $this->assertSame('2026/02/001', $result['items'][0]['number']); $this->assertSame(2, $result['items'][0]['total_orders']); $this->assertSame(1, $result['items'][0]['paid']); } // --- Frontend method tests --- public function testFindIdByHashReturnsIdWhenFound(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get') ->with('pp_shop_orders', 'id', ['hash' => 'abc123']) ->willReturn('42'); $repository = new OrderRepository($mockDb); $this->assertSame(42, $repository->findIdByHash('abc123')); } public function testFindIdByHashReturnsNullWhenNotFound(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get')->willReturn(null); $repository = new OrderRepository($mockDb); $this->assertNull($repository->findIdByHash('nonexistent')); } public function testFindIdByHashReturnsNullForEmptyHash(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new OrderRepository($mockDb); $this->assertNull($repository->findIdByHash('')); $this->assertNull($repository->findIdByHash(' ')); } public function testFindHashByIdReturnsHashWhenFound(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get') ->with('pp_shop_orders', 'hash', ['id' => 42]) ->willReturn('abc123hash'); $repository = new OrderRepository($mockDb); $this->assertSame('abc123hash', $repository->findHashById(42)); } public function testFindHashByIdReturnsNullForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new OrderRepository($mockDb); $this->assertNull($repository->findHashById(0)); $this->assertNull($repository->findHashById(-1)); } public function testOrderDetailsFrontendByIdReturnsArrayWithProducts(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get') ->willReturn(['id' => 1, 'number' => '2026/02/001', 'coupon_id' => null]); $mockDb->method('select') ->willReturn([['product_id' => 10, 'name' => 'Test Product']]); $repository = new OrderRepository($mockDb); $result = $repository->orderDetailsFrontend(1); $this->assertIsArray($result); $this->assertSame(1, $result['id']); $this->assertIsArray($result['products']); $this->assertCount(1, $result['products']); } public function testOrderDetailsFrontendByHashReturnsArrayWithProducts(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get') ->willReturn(['id' => 5, 'number' => '2026/02/005', 'hash' => 'testhash']); $mockDb->method('select') ->willReturn([]); $repository = new OrderRepository($mockDb); $result = $repository->orderDetailsFrontend(null, 'testhash'); $this->assertIsArray($result); $this->assertSame(5, $result['id']); $this->assertIsArray($result['products']); } public function testOrderDetailsFrontendReturnsNullWhenNotFound(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get')->willReturn(null); $repository = new OrderRepository($mockDb); $this->assertNull($repository->orderDetailsFrontend(999)); $this->assertNull($repository->orderDetailsFrontend(null, 'nonexistent')); } public function testGenerateOrderNumberFormatsCorrectly(): void { $mockDb = $this->createMock(\medoo::class); $resultSet = new class { public function fetchAll(): array { return [[5]]; } }; $mockDb->method('query')->willReturn($resultSet); $repository = new OrderRepository($mockDb); $number = $repository->generateOrderNumber(); $expectedPrefix = date('Y/m') . '/'; $this->assertStringStartsWith($expectedPrefix, $number); $this->assertSame($expectedPrefix . '006', $number); } // --- Order product CRUD tests --- public function testGetOrderProductReturnsNullForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new OrderRepository($mockDb); $this->assertNull($repository->getOrderProduct(0)); $this->assertNull($repository->getOrderProduct(-1)); } public function testGetOrderProductReturnsArray(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get') ->with('pp_shop_order_products', '*', ['id' => 5]) ->willReturn(['id' => 5, 'order_id' => 1, 'name' => 'Test']); $repository = new OrderRepository($mockDb); $result = $repository->getOrderProduct(5); $this->assertIsArray($result); $this->assertSame(5, $result['id']); } public function testAddOrderProductReturnsNullForInvalidOrderId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('insert'); $repository = new OrderRepository($mockDb); $this->assertNull($repository->addOrderProduct(0, ['name' => 'Test'])); } public function testAddOrderProductInsertsAndReturnsId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once())->method('insert') ->with('pp_shop_order_products', $this->callback(function ($data) { return $data['order_id'] === 10 && $data['product_id'] === 5 && $data['name'] === 'Test Product' && $data['quantity'] === 2; })); $mockDb->method('id')->willReturn('99'); $repository = new OrderRepository($mockDb); $result = $repository->addOrderProduct(10, [ 'product_id' => 5, 'name' => 'Test Product', 'quantity' => 2, 'price_brutto' => 19.99, ]); $this->assertSame(99, $result); } public function testUpdateOrderProductReturnsFalseForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('update'); $repository = new OrderRepository($mockDb); $this->assertFalse($repository->updateOrderProduct(0, ['quantity' => 3])); } public function testUpdateOrderProductUpdatesFields(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once())->method('update') ->with('pp_shop_order_products', $this->callback(function ($data) { return $data['quantity'] === 3 && $data['price_brutto'] === 25.50; }), ['id' => 7]); $repository = new OrderRepository($mockDb); $result = $repository->updateOrderProduct(7, [ 'quantity' => 3, 'price_brutto' => 25.50, ]); $this->assertTrue($result); } public function testUpdateOrderProductReturnsFalseForEmptyData(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('update'); $repository = new OrderRepository($mockDb); $this->assertFalse($repository->updateOrderProduct(7, [])); } public function testDeleteOrderProductReturnsFalseForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('delete'); $repository = new OrderRepository($mockDb); $this->assertFalse($repository->deleteOrderProduct(0)); } public function testDeleteOrderProductCallsDelete(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once())->method('delete') ->with('pp_shop_order_products', ['id' => 12]); $repository = new OrderRepository($mockDb); $this->assertTrue($repository->deleteOrderProduct(12)); } public function testUpdateTransportCostDoesNothingForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('update'); $repository = new OrderRepository($mockDb); $repository->updateTransportCost(0, 15.0); } public function testUpdateTransportCostUpdatesOrder(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once())->method('update') ->with('pp_shop_orders', ['transport_cost' => 12.50], ['id' => 5]); $repository = new OrderRepository($mockDb); $repository->updateTransportCost(5, 12.50); } public function testGenerateOrderNumberStartsAt001(): void { $mockDb = $this->createMock(\medoo::class); $resultSet = new class { public function fetchAll(): array { return [[null]]; } }; $mockDb->method('query')->willReturn($resultSet); $repository = new OrderRepository($mockDb); $number = $repository->generateOrderNumber(); $expectedPrefix = date('Y/m') . '/'; $this->assertSame($expectedPrefix . '001', $number); } }