createMock(\medoo::class); $repository = new ProducerRepository($mockDb); $result = $repository->find(0); $this->assertIsArray($result); $this->assertSame(0, $result['id']); $this->assertSame('', $result['name']); $this->assertSame(1, $result['status']); $this->assertNull($result['img']); $this->assertSame([], $result['languages']); } public function testFindNormalizesProducerData(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('get') ->with('pp_shop_producer', '*', ['id' => 5]) ->willReturn([ 'id' => '5', 'name' => 'Apple', 'status' => '1', 'img' => '/logo.png', ]); $mockDb->expects($this->once()) ->method('select') ->with('pp_shop_producer_lang', '*', ['producer_id' => 5]) ->willReturn([ [ 'lang_id' => 'pl', 'description' => 'Opis PL', 'data' => 'Dane PL', 'meta_title' => 'Meta PL', ], [ 'lang_id' => 'en', 'description' => 'Desc EN', 'data' => null, 'meta_title' => null, ], ]); $repository = new ProducerRepository($mockDb); $result = $repository->find(5); $this->assertSame(5, $result['id']); $this->assertSame('Apple', $result['name']); $this->assertSame(1, $result['status']); $this->assertSame('/logo.png', $result['img']); $this->assertArrayHasKey('pl', $result['languages']); $this->assertArrayHasKey('en', $result['languages']); $this->assertSame('Opis PL', $result['languages']['pl']['description']); $this->assertSame('Meta PL', $result['languages']['pl']['meta_title']); $this->assertNull($result['languages']['en']['meta_title']); } public function testSaveInsertsNewProducer(): void { $mockDb = $this->createMock(\medoo::class); $insertCalls = []; $mockDb->method('insert') ->willReturnCallback(function ($table, $row) use (&$insertCalls) { $insertCalls[] = ['table' => $table, 'row' => $row]; }); $mockDb->expects($this->once()) ->method('id') ->willReturn(42); $langs = [['id' => 'pl'], ['id' => 'en']]; $repository = new ProducerRepository($mockDb); $id = $repository->save( 0, 'Samsung', 1, '/samsung.png', ['pl' => 'Opis PL', 'en' => 'Desc EN'], ['pl' => 'Dane', 'en' => null], ['pl' => 'Meta PL', 'en' => 'Meta EN'], $langs ); $this->assertSame(42, $id); // 1st insert: pp_shop_producer $this->assertSame('pp_shop_producer', $insertCalls[0]['table']); $this->assertSame('Samsung', $insertCalls[0]['row']['name']); $this->assertSame(1, $insertCalls[0]['row']['status']); // 2nd and 3rd insert: pp_shop_producer_lang for each language $langInserts = array_filter($insertCalls, fn($c) => $c['table'] === 'pp_shop_producer_lang'); $this->assertCount(2, $langInserts); } public function testSaveUpdatesExistingProducer(): void { $mockDb = $this->createMock(\medoo::class); $updateRow = null; $mockDb->expects($this->atLeastOnce()) ->method('update') ->willReturnCallback(function ($table, $row, $where) use (&$updateRow) { if ($table === 'pp_shop_producer') { $updateRow = $row; $this->assertSame(['id' => 7], $where); } return true; }); $mockDb->expects($this->never())->method('id'); // get for translation id check $mockDb->method('get') ->willReturn(100); $langs = [['id' => 'pl']]; $repository = new ProducerRepository($mockDb); $id = $repository->save(7, 'Zaktualizowany', 0, null, ['pl' => 'Nowy opis'], ['pl' => null], ['pl' => 'Meta'], $langs); $this->assertSame(7, $id); $this->assertSame('Zaktualizowany', $updateRow['name']); $this->assertSame(0, $updateRow['status']); } public function testDeleteReturnsFalseForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('delete'); $repository = new ProducerRepository($mockDb); $this->assertFalse($repository->delete(0)); } public function testDeleteReturnsTrueOnSuccess(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('delete') ->with('pp_shop_producer', ['id' => 3]) ->willReturn(true); $repository = new ProducerRepository($mockDb); $this->assertTrue($repository->delete(3)); } public function testListForAdminWhitelistsSortAndPagination(): 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' => 'Test', 'status' => 1, 'img' => null, ]]; } }; }); $repository = new ProducerRepository($mockDb); $result = $repository->listForAdmin( [], 'name DESC; DROP TABLE pp_shop_producer; --', 'DESC; DELETE FROM pp_users; --', 1, 999 ); $this->assertCount(2, $queries); $dataSql = $queries[1]['sql']; $this->assertMatchesRegularExpression('/ORDER BY\s+p\.name\s+ASC,\s+p\.id\s+DESC/i', $dataSql); $this->assertStringNotContainsString('DROP TABLE', $dataSql); $this->assertMatchesRegularExpression('/LIMIT\s+100\s+OFFSET\s+0/i', $dataSql); } public function testAllProducersReturnsFormattedList(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('select') ->with('pp_shop_producer', ['id', 'name'], ['ORDER' => ['name' => 'ASC']]) ->willReturn([ ['id' => '1', 'name' => 'Apple'], ['id' => '2', 'name' => 'Samsung'], ]); $repository = new ProducerRepository($mockDb); $result = $repository->allProducers(); $this->assertCount(2, $result); $this->assertSame(1, $result[0]['id']); $this->assertSame('Apple', $result[0]['name']); $this->assertSame(2, $result[1]['id']); } public function testProducerProductsReturnsPaginatedResults(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('count') ->willReturn(30); $mockDb->expects($this->once()) ->method('select') ->willReturn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); $repository = new ProducerRepository($mockDb); $result = $repository->producerProducts(5, 12, 1); $this->assertArrayHasKey('products', $result); $this->assertArrayHasKey('ls', $result); $this->assertSame(3, $result['ls']); } public function testAllActiveProducersReturnsFullData(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->once()) ->method('select') ->with('pp_shop_producer', ['id', 'name', 'img'], [ 'status' => 1, 'ORDER' => ['name' => 'ASC'], ]) ->willReturn([ ['id' => '3', 'name' => 'Apple', 'img' => '/apple.png'], ['id' => '7', 'name' => 'Samsung', 'img' => null], ]); $repository = new ProducerRepository($mockDb); $result = $repository->allActiveProducers(); $this->assertCount(2, $result); $this->assertSame(3, $result[0]['id']); $this->assertSame('Apple', $result[0]['name']); $this->assertSame('/apple.png', $result[0]['img']); $this->assertSame(7, $result[1]['id']); $this->assertSame('Samsung', $result[1]['name']); $this->assertNull($result[1]['img']); } public function testAllActiveProducersReturnsEmptyOnNull(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('select')->willReturn(null); $repository = new ProducerRepository($mockDb); $result = $repository->allActiveProducers(); $this->assertSame([], $result); } public function testFindForFrontendReturnsNullForInvalidId(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->never())->method('get'); $repository = new ProducerRepository($mockDb); $this->assertNull($repository->findForFrontend(0, 'pl')); } public function testFindForFrontendReturnsNullWhenNotFound(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->method('get')->willReturn(null); $repository = new ProducerRepository($mockDb); $this->assertNull($repository->findForFrontend(99, 'pl')); } public function testFindForFrontendReturnsProducerWithLanguage(): void { $mockDb = $this->createMock(\medoo::class); $mockDb->expects($this->exactly(2)) ->method('get') ->willReturnOnConsecutiveCalls( ['id' => '5', 'name' => 'Sony', 'status' => '1', 'img' => '/sony.png'], ['lang_id' => 'pl', 'description' => 'Opis', 'data' => null, 'meta_title' => 'Sony PL'] ); $repository = new ProducerRepository($mockDb); $result = $repository->findForFrontend(5, 'pl'); $this->assertSame(5, $result['id']); $this->assertSame('Sony', $result['name']); $this->assertArrayHasKey('pl', $result['languages']); $this->assertSame('Sony PL', $result['languages']['pl']['meta_title']); } }