feca-mailshots-plugin/tests/integration/test_phase2_db_access.php

131 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
require_once dirname(__DIR__, 2) . '/feca_mailshots_plugin/src/autoload.php';
use FecaMailshots\Application\DataSourceService;
use FecaMailshots\Application\DslCompiler;
use FecaMailshots\Application\DslValidator;
use FecaMailshots\Domain\DslParser;
use FecaMailshots\Infrastructure\DatabaseSourceMetadataProvider;
use FecaMailshots\Infrastructure\Env;
use FecaMailshots\Infrastructure\PdoDatabaseRouter;
use FecaMailshots\Repository\MailshotRepository;
use FecaMailshots\Repository\MailshotQueryRepository;
Env::load(dirname(__DIR__, 2) . '/credentials/.env');
$host = getenv('MYSQL_TUNNEL_HOST');
if ($host === false || $host === '') {
$host = '127.0.0.1';
}
$port = getenv('MYSQL_TUNNEL_LOCAL_PORT');
if ($port === false || $port === '') {
$port = '13306';
}
$dbConfig = [
'MYSQL_HOST' => (string) $host,
'MYSQL_PORT' => (string) $port,
'MYSQL_USER' => Env::require('REMOTE_MYSQL_USER'),
'MYSQL_PASSWORD' => Env::require('REMOTE_MYSQL_PASSWORD'),
'MAILSHOTS_REMOTE_MYSQL_DB' => Env::require('MAILSHOTS_REMOTE_MYSQL_DB'),
'MEMBERS_REMOTE_MYSQL_DB' => Env::require('MEMBERS_REMOTE_MYSQL_DB'),
'FEN_REMOTE_MYSQL_DB' => Env::require('FEN_REMOTE_MYSQL_DB'),
];
$router = new PdoDatabaseRouter($dbConfig);
$metadata = new DatabaseSourceMetadataProvider($router);
$parser = new DslParser();
$validator = new DslValidator($metadata);
$compiler = new DslCompiler($metadata);
$queries = new MailshotQueryRepository($router);
$mailshots = new MailshotRepository($router);
$service = new DataSourceService($queries, $router, $parser, $validator, $compiler, $metadata, $mailshots);
$membersDb = $router->membersDbName();
$mailshotsDb = $router->mailshotsDbName();
$stmt = $router->membersPdo()->prepare(
'SELECT table_name FROM information_schema.tables WHERE table_schema = :schema AND table_name REGEXP :rx ORDER BY table_name ASC LIMIT 1'
);
$stmt->execute(['schema' => $membersDb, 'rx' => '^[A-Za-z][A-Za-z0-9_]*$']);
$firstTable = $stmt->fetchColumn();
if ($firstTable === false || $firstTable === null || $firstTable === '') {
fwrite(STDERR, "No usable tables found in MEMBERS db for integration preview test.\n");
exit(1);
}
$source = $membersDb . '.' . $firstTable;
$dsl = $source;
$validation = $service->validateDsl($dsl);
if (($validation['errors'] ?? []) !== []) {
fwrite(STDERR, "Validation failed for source {$source}: " . json_encode($validation['errors']) . "\n");
exit(1);
}
$preview = $service->preview($dsl, 5);
if (($preview['errors'] ?? []) !== []) {
fwrite(STDERR, "Preview failed for source {$source}: " . json_encode($preview['errors']) . "\n");
exit(1);
}
if (!isset($preview['count']) || !is_int($preview['count'])) {
fwrite(STDERR, "Preview response missing integer count.\n");
exit(1);
}
if (!isset($preview['columns']) || !is_array($preview['columns'])) {
fwrite(STDERR, "Preview response missing columns array.\n");
exit(1);
}
$name = 'phase2_db_access_' . gmdate('Ymd_His') . '_' . bin2hex(random_bytes(3));
$savedId = null;
try {
$save = $service->save(null, $name, $dsl);
if (($save['ok'] ?? false) !== true) {
fwrite(STDERR, "Save failed: " . json_encode($save) . "\n");
exit(1);
}
$savedId = (int) ($save['id'] ?? 0);
if ($savedId <= 0) {
fwrite(STDERR, "Save did not return a valid ID.\n");
exit(1);
}
$row = $queries->find($savedId);
if ($row === null) {
fwrite(STDERR, "Saved mailshot_queries row not found for ID {$savedId}.\n");
exit(1);
}
if (($row['name'] ?? '') !== $name || trim((string) ($row['dsl_text'] ?? '')) !== $dsl) {
fwrite(STDERR, "Saved row contents mismatch for ID {$savedId}.\n");
exit(1);
}
$service->delete($savedId);
$savedId = null;
echo "Phase 2 DB integration test passed\n";
echo "members_db={$membersDb}\n";
echo "mailshots_db={$mailshotsDb}\n";
echo "preview_source={$source}\n";
echo "preview_count=" . $preview['count'] . "\n";
} finally {
if ($savedId !== null) {
try {
$service->delete($savedId);
} catch (Throwable $e) {
fwrite(STDERR, "Cleanup warning for ID {$savedId}: {$e->getMessage()}\n");
}
}
}