Newwebshop/tests/Unit/ProductTest.php

242 lines
7.6 KiB
PHP

<?php
/**
* Copyright seit 2024 Webshop System
*
* Unit-Tests für das Webshop-System
*
* @author Webshop System
* @license GPL v3
*/
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception;
class ProductTest extends TestCase
{
private $conn;
protected function setUp(): void
{
// Test-Datenbank-Verbindung
$connectionParams = [
'dbname' => getenv('DB_DATABASE') ?: 'freeshop_test',
'user' => getenv('DB_USERNAME') ?: 'freeshop_user',
'password' => getenv('DB_PASSWORD') ?: 'freeshop_password',
'host' => getenv('DB_HOST') ?: 'db',
'driver' => 'pdo_mysql',
'port' => getenv('DB_PORT') ?: 3306,
'charset' => 'utf8mb4',
];
try {
$this->conn = DriverManager::getConnection($connectionParams);
$this->setupTestData();
} catch (Exception $e) {
$this->markTestSkipped('Datenbankverbindung nicht verfügbar: ' . $e->getMessage());
}
}
protected function tearDown(): void
{
if ($this->conn) {
$this->cleanupTestData();
}
}
private function setupTestData()
{
// Test-Kategorie erstellen
$this->conn->executeStatement('
INSERT INTO ws_category (name, description, active)
VALUES (?, ?, ?)
', ['Test Kategorie', 'Test Beschreibung', 1]);
// Test-Produkte erstellen
$this->conn->executeStatement('
INSERT INTO ws_product (name, description, price, category_id, active)
VALUES (?, ?, ?, ?, ?)
', ['Test Produkt 1', 'Test Beschreibung 1', 19.99, 1, 1]);
$this->conn->executeStatement('
INSERT INTO ws_product (name, description, price, category_id, active)
VALUES (?, ?, ?, ?, ?)
', ['Test Produkt 2', 'Test Beschreibung 2', 29.99, 1, 1]);
}
private function cleanupTestData()
{
$this->conn->executeStatement('DELETE FROM ws_product WHERE name LIKE ?', ['Test Produkt%']);
$this->conn->executeStatement('DELETE FROM ws_category WHERE name = ?', ['Test Kategorie']);
}
public function testProductCreation()
{
$stmt = $this->conn->prepare('
INSERT INTO ws_product (name, description, price, category_id, active)
VALUES (?, ?, ?, ?, ?)
');
$result = $stmt->execute(['Test Produkt 3', 'Test Beschreibung 3', 39.99, 1, 1]);
$this->assertTrue($result);
// Prüfen ob Produkt erstellt wurde
$stmt = $this->conn->prepare('SELECT * FROM ws_product WHERE name = ?');
$stmt->execute(['Test Produkt 3']);
$product = $stmt->fetchAssociative();
$this->assertNotNull($product);
$this->assertEquals('Test Produkt 3', $product['name']);
$this->assertEquals(39.99, $product['price']);
$this->assertEquals(1, $product['active']);
}
public function testProductRetrieval()
{
$stmt = $this->conn->prepare('SELECT * FROM ws_product WHERE active = 1');
$stmt->execute();
$products = $stmt->fetchAllAssociative();
$this->assertGreaterThan(0, count($products));
foreach ($products as $product) {
$this->assertArrayHasKey('id', $product);
$this->assertArrayHasKey('name', $product);
$this->assertArrayHasKey('price', $product);
$this->assertEquals(1, $product['active']);
}
}
public function testProductUpdate()
{
// Produkt aktualisieren
$stmt = $this->conn->prepare('
UPDATE ws_product
SET name = ?, price = ?
WHERE name = ?
');
$result = $stmt->execute(['Aktualisiertes Produkt', 49.99, 'Test Produkt 1']);
$this->assertTrue($result);
// Prüfen ob Update erfolgreich war
$stmt = $this->conn->prepare('SELECT * FROM ws_product WHERE name = ?');
$stmt->execute(['Aktualisiertes Produkt']);
$product = $stmt->fetchAssociative();
$this->assertNotNull($product);
$this->assertEquals('Aktualisiertes Produkt', $product['name']);
$this->assertEquals(49.99, $product['price']);
}
public function testProductDeletion()
{
// Produkt löschen
$stmt = $this->conn->prepare('DELETE FROM ws_product WHERE name = ?');
$result = $stmt->execute(['Test Produkt 2']);
$this->assertTrue($result);
// Prüfen ob Produkt gelöscht wurde
$stmt = $this->conn->prepare('SELECT * FROM ws_product WHERE name = ?');
$stmt->execute(['Test Produkt 2']);
$product = $stmt->fetchAssociative();
$this->assertFalse($product);
}
public function testProductSearch()
{
$stmt = $this->conn->prepare('
SELECT * FROM ws_product
WHERE active = 1 AND (name LIKE ? OR description LIKE ?)
');
$stmt->execute(['%Test%', '%Test%']);
$products = $stmt->fetchAllAssociative();
$this->assertGreaterThan(0, count($products));
foreach ($products as $product) {
$this->assertTrue(
stripos($product['name'], 'Test') !== false ||
stripos($product['description'], 'Test') !== false
);
}
}
public function testProductPriceRange()
{
$stmt = $this->conn->prepare('
SELECT * FROM ws_product
WHERE active = 1 AND price BETWEEN ? AND ?
ORDER BY price ASC
');
$stmt->execute([10.00, 50.00]);
$products = $stmt->fetchAllAssociative();
$this->assertGreaterThan(0, count($products));
foreach ($products as $product) {
$this->assertGreaterThanOrEqual(10.00, $product['price']);
$this->assertLessThanOrEqual(50.00, $product['price']);
}
}
public function testProductCategoryRelationship()
{
$stmt = $this->conn->prepare('
SELECT p.*, c.name as category_name
FROM ws_product p
LEFT JOIN ws_category c ON p.category_id = c.id
WHERE p.active = 1
');
$stmt->execute();
$products = $stmt->fetchAllAssociative();
$this->assertGreaterThan(0, count($products));
foreach ($products as $product) {
$this->assertArrayHasKey('category_name', $product);
$this->assertNotNull($product['category_name']);
}
}
public function testProductValidation()
{
// Test mit ungültigen Daten
$stmt = $this->conn->prepare('
INSERT INTO ws_product (name, description, price, category_id, active)
VALUES (?, ?, ?, ?, ?)
');
// Leerer Name sollte fehlschlagen
$this->expectException(Exception::class);
$stmt->execute(['', 'Test Beschreibung', 19.99, 1, 1]);
}
public function testProductPagination()
{
$page = 1;
$perPage = 2;
$offset = ($page - 1) * $perPage;
$stmt = $this->conn->prepare('
SELECT * FROM ws_product
WHERE active = 1
ORDER BY id ASC
LIMIT ? OFFSET ?
');
$stmt->execute([$perPage, $offset]);
$products = $stmt->fetchAllAssociative();
$this->assertLessThanOrEqual($perPage, count($products));
}
}