createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new PaymentMethodRepository($mockDb); $this->assertNull($repository->find(0)); } public function testFindReturnsNullWhenNotFound(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', '*', ['id' => 10]) ->willReturn(null); $repository = new PaymentMethodRepository($mockDb); $this->assertNull($repository->find(10)); } public function testFindNormalizesData(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', '*', ['id' => 11]) ->willReturn([ 'id' => '11', 'name' => ' Przelew ', 'description' => null, 'status' => '1', 'apilo_payment_type_id' => '7', ]); $repository = new PaymentMethodRepository($mockDb); $result = $repository->find(11); $this->assertIsArray($result); $this->assertSame(11, $result['id']); $this->assertSame('Przelew', $result['name']); $this->assertSame('', $result['description']); $this->assertSame(1, $result['status']); $this->assertSame(7, $result['apilo_payment_type_id']); } public function testSaveUpdatesRowAndReturnsId(): void { $mockDb = $this->createMock(\medoo::class); $updateRow = null; $updateWhere = null; $mockDb->expects($this->once()) ->method('update') ->willReturnCallback(function ($table, $row, $where) use (&$updateRow, &$updateWhere) { $this->assertSame('pp_shop_payment_methods', $table); $updateRow = $row; $updateWhere = $where; return true; }); $repository = new PaymentMethodRepository($mockDb); $id = $repository->save(3, [ 'description' => ' test ', 'status' => 'on', 'apilo_payment_type_id' => '22', ]); $this->assertSame(3, $id); $this->assertSame('test', $updateRow['description']); $this->assertSame(1, $updateRow['status']); $this->assertSame(22, $updateRow['apilo_payment_type_id']); $this->assertNull($updateRow['min_order_amount']); $this->assertNull($updateRow['max_order_amount']); $this->assertSame(['id' => 3], $updateWhere); } public function testSavePreservesNonNumericApiloPaymentTypeId(): void { $mockDb = $this->createMock(\medoo::class); $updateRow = null; $mockDb->expects($this->once()) ->method('update') ->willReturnCallback(function ($table, $row) use (&$updateRow) { $this->assertSame('pp_shop_payment_methods', $table); $updateRow = $row; return true; }); $repository = new PaymentMethodRepository($mockDb); $repository->save(4, [ 'description' => 'X', 'status' => 1, 'apilo_payment_type_id' => 'CASH_ON_DELIVERY', ]); $this->assertSame('CASH_ON_DELIVERY', $updateRow['apilo_payment_type_id']); } public function testSaveReturnsNullForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('update'); $repository = new PaymentMethodRepository($mockDb); $this->assertNull($repository->save(0, ['status' => 1])); } public function testSavePersistsMinMaxOrderAmount(): void { $mockDb = $this->createMock(\medoo::class); $updateRow = null; $mockDb->expects($this->once()) ->method('update') ->willReturnCallback(function ($table, $row) use (&$updateRow) { $updateRow = $row; return true; }); $repository = new PaymentMethodRepository($mockDb); $repository->save(5, [ 'description' => 'test', 'status' => 1, 'apilo_payment_type_id' => '', 'min_order_amount' => '40.00', 'max_order_amount' => '1000.00', ]); $this->assertSame(40.0, $updateRow['min_order_amount']); $this->assertSame(1000.0, $updateRow['max_order_amount']); } public function testSaveConvertsEmptyMinMaxToNull(): void { $mockDb = $this->createMock(\medoo::class); $updateRow = null; $mockDb->expects($this->once()) ->method('update') ->willReturnCallback(function ($table, $row) use (&$updateRow) { $updateRow = $row; return true; }); $repository = new PaymentMethodRepository($mockDb); $repository->save(6, [ 'description' => 'test', 'status' => 1, 'apilo_payment_type_id' => '', 'min_order_amount' => '', 'max_order_amount' => '', ]); $this->assertNull($updateRow['min_order_amount']); $this->assertNull($updateRow['max_order_amount']); } public function testFindNormalizesMinMaxOrderAmount(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', '*', ['id' => 6]) ->willReturn([ 'id' => '6', 'name' => 'PayPo', 'description' => '', 'status' => '1', 'apilo_payment_type_id' => null, 'min_order_amount' => '40.00', 'max_order_amount' => '1000.00', ]); $repository = new PaymentMethodRepository($mockDb); $result = $repository->find(6); $this->assertSame(40.0, $result['min_order_amount']); $this->assertSame(1000.0, $result['max_order_amount']); } public function testFindNormalizesNullMinMaxOrderAmount(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', '*', ['id' => 7]) ->willReturn([ 'id' => '7', 'name' => 'Przelew', 'description' => '', 'status' => '1', 'apilo_payment_type_id' => null, 'min_order_amount' => null, 'max_order_amount' => null, ]); $repository = new PaymentMethodRepository($mockDb); $result = $repository->find(7); $this->assertNull($result['min_order_amount']); $this->assertNull($result['max_order_amount']); } public function testListForAdminWhitelistsSortAndDirection(): void { $mockDb = $this->createMock(\medoo::class); $queries = []; $mockDb->method('query') ->willReturnCallback(function ($sql, $params = []) use (&$queries) { $queries[] = ['sql' => $sql, 'params' => $params]; if (strpos($sql, 'COUNT(0)') !== false) { return new class { public function fetchAll() { return [[1]]; } }; } return new class { public function fetchAll() { return [[ 'id' => 1, 'name' => 'Przelew', 'description' => 'Opis', 'status' => 1, 'apilo_payment_type_id' => 5, ]]; } }; }); $repository = new PaymentMethodRepository($mockDb); $result = $repository->listForAdmin( [], 'name DESC; DROP TABLE pp_shop_payment_methods; --', 'DESC; DELETE FROM pp_users; --', 1, 999 ); $this->assertCount(2, $queries); $dataSql = $queries[1]['sql']; $this->assertMatchesRegularExpression('/ORDER BY\s+spm\.name\s+ASC,\s+spm\.id\s+ASC/i', $dataSql); $this->assertStringNotContainsString('DROP TABLE', $dataSql); $this->assertStringNotContainsString('DELETE FROM pp_users', $dataSql); $this->assertMatchesRegularExpression('/LIMIT\s+100\s+OFFSET\s+0/i', $dataSql); $this->assertSame(1, (int)$result['items'][0]['id']); } public function testAllActiveReturnsNormalizedRows(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('select') ->with('pp_shop_payment_methods', '*', [ 'status' => 1, 'ORDER' => ['id' => 'ASC'], ]) ->willReturn([ [ 'id' => '2', 'name' => ' PayU ', 'description' => '', 'status' => '1', 'apilo_payment_type_id' => null, ], ]); $repository = new PaymentMethodRepository($mockDb); $rows = $repository->allActive(); $this->assertCount(1, $rows); $this->assertSame(2, $rows[0]['id']); $this->assertSame('PayU', $rows[0]['name']); $this->assertSame(1, $rows[0]['status']); $this->assertNull($rows[0]['apilo_payment_type_id']); } public function testAllForAdminReturnsRowsIncludingInactive(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('select') ->with('pp_shop_payment_methods', '*', [ 'ORDER' => ['name' => 'ASC'], ]) ->willReturn([ [ 'id' => '1', 'name' => 'Przelew', 'description' => '', 'status' => '1', 'apilo_payment_type_id' => null, ], [ 'id' => '2', 'name' => 'PayPo', 'description' => '', 'status' => '0', 'apilo_payment_type_id' => null, ], ]); $repository = new PaymentMethodRepository($mockDb); $rows = $repository->allForAdmin(); $this->assertCount(2, $rows); $this->assertSame(1, $rows[0]['id']); $this->assertSame(2, $rows[1]['id']); $this->assertSame(0, $rows[1]['status']); } public function testFindActiveByIdReturnsNullForNotFound(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', '*', [ 'AND' => [ 'id' => 4, 'status' => 1, ], ]) ->willReturn(null); $repository = new PaymentMethodRepository($mockDb); $this->assertNull($repository->findActiveById(4)); } public function testFindKeepsNonNumericApiloPaymentTypeId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', '*', ['id' => 12]) ->willReturn([ 'id' => '12', 'name' => 'PayPo', 'description' => '', 'status' => '1', 'apilo_payment_type_id' => 'PAYPO_DEFERRED', ]); $repository = new PaymentMethodRepository($mockDb); $result = $repository->find(12); $this->assertIsArray($result); $this->assertSame('PAYPO_DEFERRED', $result['apilo_payment_type_id']); } public function testIsActiveNormalizesStatusValue(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', 'status', ['id' => 5]) ->willReturn('0'); $repository = new PaymentMethodRepository($mockDb); $this->assertSame(0, $repository->isActive(5)); } public function testGetApiloPaymentTypeIdHandlesNullAndInt(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->exactly(2)) ->method('get') ->willReturnOnConsecutiveCalls(null, '8'); $repository = new PaymentMethodRepository($mockDb); $this->assertNull($repository->getApiloPaymentTypeId(1)); $this->assertSame(8, $repository->getApiloPaymentTypeId(2)); } public function testGetApiloPaymentTypeIdReturnsStringForNonNumericValue(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', 'apilo_payment_type_id', ['id' => 3]) ->willReturn('BANK_TRANSFER'); $repository = new PaymentMethodRepository($mockDb); $this->assertSame('BANK_TRANSFER', $repository->getApiloPaymentTypeId(3)); } public function testIsActiveReturnsOneForActivePayment(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', 'status', ['id' => 2]) ->willReturn('1'); $repository = new PaymentMethodRepository($mockDb); $this->assertSame(1, $repository->isActive(2)); } public function testIsActiveReturnsZeroForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new PaymentMethodRepository($mockDb); $this->assertSame(0, $repository->isActive(0)); } public function testFindActiveByIdReturnsNormalizedData(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_payment_methods', '*', [ 'AND' => [ 'id' => 3, 'status' => 1, ], ]) ->willReturn([ 'id' => '3', 'name' => ' Przelew ', 'description' => 'Opis', 'status' => '1', 'apilo_payment_type_id' => '5', ]); $repository = new PaymentMethodRepository($mockDb); $result = $repository->findActiveById(3); $this->assertIsArray($result); $this->assertSame(3, $result['id']); $this->assertSame('Przelew', $result['name']); $this->assertSame(1, $result['status']); $this->assertSame(5, $result['apilo_payment_type_id']); } public function testFindActiveByIdReturnsNullForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new PaymentMethodRepository($mockDb); $this->assertNull($repository->findActiveById(0)); } public function testAllActiveReturnsEmptyOnNull(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('select')->willReturn(null); $repository = new PaymentMethodRepository($mockDb); $this->assertSame([], $repository->allActive()); } public function testGetApiloPaymentTypeIdReturnsNullForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new PaymentMethodRepository($mockDb); $this->assertNull($repository->getApiloPaymentTypeId(0)); } public function testForTransportReturnsEmptyForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('query'); $repository = new PaymentMethodRepository($mockDb); $this->assertSame([], $repository->forTransport(0)); } public function testForTransportReturnsRows(): void { $mockDb = $this->createMock(\medoo::class); $capturedParams = null; $mockDb->expects($this->once()) ->method('query') ->willReturnCallback(function ($sql, $params = []) use (&$capturedParams) { $this->assertStringContainsString('pp_shop_transport_payment_methods', $sql); $capturedParams = $params; return new class { public function fetchAll() { return [[ 'id' => '9', 'name' => 'Karta', 'description' => 'Opis', 'status' => 1, 'apilo_payment_type_id' => '4', ]]; } }; }); $repository = new PaymentMethodRepository($mockDb); $rows = $repository->forTransport(12); $this->assertSame([':transport_id' => 12], $capturedParams); $this->assertCount(1, $rows); $this->assertSame(9, $rows[0]['id']); $this->assertSame(4, $rows[0]['apilo_payment_type_id']); } }