mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 08:09:18 +02:00
Add integration tests (Phase 2: DatabaseExtended, ShareLinkExtended, RateLimitExtended) and controller validation tests (Phase 3: ThesisCreate, ThesisEdit, AutofocusField)
This commit is contained in:
142
tests/TestDatabase.php
Normal file
142
tests/TestDatabase.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TestDatabase — helper for integration tests that need a real SQLite database.
|
||||
*
|
||||
* Creates an in-memory SQLite database, loads the full schema + seed data,
|
||||
* and provides a Database instance connected to it. Teardown discards the DB.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Thin Database subclass that accepts a pre-built PDO connection.
|
||||
* Bypasses the normal path-based constructor.
|
||||
*/
|
||||
class TestDatabaseInstance extends Database
|
||||
{
|
||||
public function __construct(PDO $pdo)
|
||||
{
|
||||
// Inject PDO directly via reflection, then flag as ready
|
||||
$ref = new ReflectionProperty(Database::class, 'pdo');
|
||||
$ref->setAccessible(true);
|
||||
$ref->setValue($this, $pdo);
|
||||
|
||||
$pathRef = new ReflectionProperty(Database::class, 'dbPath');
|
||||
$pathRef->setAccessible(true);
|
||||
$pathRef->setValue($this, ':memory:');
|
||||
}
|
||||
}
|
||||
|
||||
class TestDatabase
|
||||
{
|
||||
private static ?PDO $pdo = null;
|
||||
private static ?Database $db = null;
|
||||
|
||||
/**
|
||||
* Get or create the shared test Database instance.
|
||||
* Uses an in-memory SQLite DB so tests are fast and isolated.
|
||||
*/
|
||||
public static function getInstance(): Database
|
||||
{
|
||||
if (self::$db === null) {
|
||||
self::$pdo = new PDO('sqlite::memory:');
|
||||
self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
self::$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
self::$pdo->exec('PRAGMA foreign_keys = ON');
|
||||
self::$pdo->exec('PRAGMA journal_mode = MEMORY');
|
||||
|
||||
// Load schema
|
||||
$schema = file_get_contents(APP_ROOT . '/storage/schema.sql');
|
||||
if ($schema === false) {
|
||||
throw new RuntimeException('Failed to read schema.sql');
|
||||
}
|
||||
self::$pdo->exec($schema);
|
||||
|
||||
// Create a Database wrapper injecting our PDO
|
||||
self::$db = new TestDatabaseInstance(self::$pdo);
|
||||
}
|
||||
|
||||
return self::$db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw PDO connection (for queries that bypass the Database class).
|
||||
*/
|
||||
public static function getPDO(): PDO
|
||||
{
|
||||
// Ensure the DB is booted
|
||||
self::getInstance();
|
||||
return self::$pdo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all test data between tests.
|
||||
* Preserves seed data (orientations, access types, etc.) but removes
|
||||
* any theses, authors, tags, share links etc. created during a test.
|
||||
*/
|
||||
public static function resetData(): void
|
||||
{
|
||||
$pdo = self::getPDO();
|
||||
// Order matters due to FK constraints
|
||||
$tables = [
|
||||
'file_access_audit',
|
||||
'file_access_sessions',
|
||||
'file_access_tokens',
|
||||
'file_access_requests',
|
||||
'thesis_files',
|
||||
'thesis_tags',
|
||||
'thesis_formats',
|
||||
'thesis_languages',
|
||||
'thesis_supervisors',
|
||||
'thesis_authors',
|
||||
'theses',
|
||||
'share_links',
|
||||
'tags',
|
||||
'authors',
|
||||
'supervisors',
|
||||
'admin_audit_log',
|
||||
'audit_log',
|
||||
];
|
||||
foreach ($tables as $table) {
|
||||
$pdo->exec("DELETE FROM $table");
|
||||
}
|
||||
// Re-seed tags (some tests rely on tags existing)
|
||||
try {
|
||||
$pdo->exec("DELETE FROM tags WHERE deleted_at IS NOT NULL");
|
||||
} catch (Exception $e) {
|
||||
// tags table already empty
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed some basic test data: an author, a thesis.
|
||||
* Returns [authorId, thesisId].
|
||||
*
|
||||
* @return array{0: int, 1: int}
|
||||
*/
|
||||
public static function seedBasicThesis(string $title = 'Test Thesis', string $authorName = 'Test Author', int $year = 2024): array
|
||||
{
|
||||
$pdo = self::getPDO();
|
||||
|
||||
// Insert author
|
||||
$pdo->prepare('INSERT INTO authors (name) VALUES (?)')->execute([$authorName]);
|
||||
$authorId = (int)$pdo->lastInsertId();
|
||||
|
||||
// Insert thesis
|
||||
$pdo->prepare(
|
||||
"INSERT INTO theses (title, year, identifier, is_published, objet) VALUES (?, ?, ?, 1, 'tfe')"
|
||||
)->execute([$title, $year, "$year-001"]);
|
||||
|
||||
$thesisId = (int)$pdo->lastInsertId();
|
||||
|
||||
// Link author
|
||||
$pdo->prepare('INSERT INTO thesis_authors (thesis_id, author_id) VALUES (?, ?)')
|
||||
->execute([$thesisId, $authorId]);
|
||||
|
||||
// Insert a cover file
|
||||
$pdo->prepare(
|
||||
"INSERT INTO thesis_files (thesis_id, file_type, file_path, file_name, file_size, mime_type) VALUES (?, 'cover', ?, ?, 0, 'image/jpeg')"
|
||||
)->execute([$thesisId, "documents/$year-001/cover.jpg", 'cover.jpg']);
|
||||
|
||||
return [$authorId, $thesisId];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user