presseportale/tests/Feature/LegacyPressReleaseDateImportTest.php
Kevin Adametz a0c2e663dc legacy: --since-Delta für legacy:import + Importer setzen Timestamps wieder korrekt
--since=<Zeitpunkt> schränkt den Quell-Scan auf Legacy-Zeilen ein, deren
created_at ODER updated_at im Fenster liegt (users/companies/contacts/
press-releases; Kategorien und link-associations bleiben ungefiltert).
Kombiniert mit --force werden geänderte Bestandszeilen aktualisiert —
damit dauert ein Tages-Delta Sekunden statt eines Volldurchlaufs über
150k+ Zeilen.

Dazu Bugfix, der den Delta erst rund macht: User-/Company-/Contact-
Importer übergaben created_at/updated_at innerhalb von updateOrCreate —
die Felder sind nicht fillable und wurden stillschweigend verworfen
(Live-Befund: NULL-Timestamps, bisher nur durch legacy:fix-timestamps
geheilt). Jetzt explizit per forceFill wie im PressReleaseImporter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 13:03:07 +00:00

242 lines
8.3 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
use App\Enums\PressReleaseStatus;
use App\Models\Category;
use App\Models\LegacyImportMap;
use App\Models\PressRelease;
use App\Models\User;
use App\Services\Import\ImportContext;
use App\Services\Import\PressReleaseImporter;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
/**
* Baut das minimale Legacy-Schema (press_release + leere Bild-/Kontakt-Pivots)
* und legt Kategorie + User samt Import-Map-Einträgen an, damit der Importer
* Kategorie und Autor auflösen kann (ohne Autor wird eine PM übersprungen).
*/
function seedLegacyPressReleaseSchema(): Category
{
Config::set('database.connections.mysql_presseecho', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
'foreign_key_constraints' => false,
]);
DB::purge('mysql_presseecho');
Schema::connection('mysql_presseecho')->create('press_release', function (Blueprint $table): void {
$table->integer('id')->primary();
$table->string('title')->nullable();
$table->string('language')->nullable();
$table->text('text')->nullable();
$table->string('backlink_url')->nullable();
$table->integer('category_id')->nullable();
$table->string('keywords')->nullable();
$table->integer('user_id')->nullable();
$table->integer('company_id')->nullable();
$table->string('status')->nullable();
$table->integer('hits')->nullable();
$table->integer('teaser_begin')->nullable();
$table->integer('teaser_end')->nullable();
$table->boolean('no_export')->nullable();
$table->dateTime('created_at')->nullable();
$table->dateTime('updated_at')->nullable();
$table->string('slug')->nullable();
});
Schema::connection('mysql_presseecho')->create('press_release_image', function (Blueprint $table): void {
$table->integer('id')->primary();
$table->integer('press_release_id');
});
Schema::connection('mysql_presseecho')->create('press_release_contact', function (Blueprint $table): void {
$table->integer('press_release_id');
$table->integer('contact_id');
});
$category = Category::factory()->withTranslations()->create();
LegacyImportMap::query()->create([
'legacy_portal' => 'presseecho',
'legacy_table' => 'category',
'legacy_id' => 500,
'target_table' => 'categories',
'target_id' => $category->id,
]);
$author = User::factory()->create();
LegacyImportMap::query()->create([
'legacy_portal' => 'presseecho',
'legacy_table' => 'sf_guard_user',
'legacy_id' => 700,
'target_table' => 'users',
'target_id' => $author->id,
]);
return $category;
}
test('a published release takes published_at from the legacy created_at, not updated_at', function () {
/** @var TestCase $this */
seedLegacyPressReleaseSchema();
// updated_at trägt im Altsystem den Massen-/Migrationsstempel (2026) – das
// darf NICHT als Veröffentlichungsdatum landen.
DB::connection('mysql_presseecho')->table('press_release')->insert([
'id' => 10,
'title' => 'Alte veröffentlichte Meldung',
'language' => 'de',
'text' => 'Inhalt',
'category_id' => 500,
'user_id' => 700,
'status' => 'published',
'hits' => 5,
'no_export' => false,
'created_at' => '2008-11-18 12:05:42',
'updated_at' => '2026-04-23 01:08:26',
'slug' => 'alte-meldung',
]);
app(PressReleaseImporter::class)->run(new ImportContext('presseecho', false, true));
$pr = PressRelease::withoutGlobalScopes()
->where('legacy_portal', 'presseecho')
->where('legacy_id', 10)
->firstOrFail();
expect($pr->status)->toBe(PressReleaseStatus::Published);
expect($pr->published_at?->format('Y-m-d H:i:s'))->toBe('2008-11-18 12:05:42');
expect($pr->created_at?->format('Y-m-d H:i:s'))->toBe('2008-11-18 12:05:42');
});
test('a non-published release has no published_at and keeps its legacy created_at', function () {
/** @var TestCase $this */
seedLegacyPressReleaseSchema();
DB::connection('mysql_presseecho')->table('press_release')->insert([
'id' => 11,
'title' => 'Entwurf',
'language' => 'de',
'text' => 'Inhalt',
'category_id' => 500,
'user_id' => 700,
'status' => 'new',
'no_export' => false,
'created_at' => '2010-03-01 09:00:00',
'updated_at' => '2026-04-23 01:08:26',
'slug' => 'entwurf',
]);
app(PressReleaseImporter::class)->run(new ImportContext('presseecho', false, true));
$pr = PressRelease::withoutGlobalScopes()
->where('legacy_portal', 'presseecho')
->where('legacy_id', 11)
->firstOrFail();
expect($pr->status)->toBe(PressReleaseStatus::Draft);
expect($pr->published_at)->toBeNull();
expect($pr->created_at?->format('Y-m-d H:i:s'))->toBe('2010-03-01 09:00:00');
});
test('a force re-import preserves the uuid and the publication date', function () {
/** @var TestCase $this */
seedLegacyPressReleaseSchema();
DB::connection('mysql_presseecho')->table('press_release')->insert([
'id' => 12,
'title' => 'Stabile Referenz',
'language' => 'de',
'text' => 'Inhalt',
'category_id' => 500,
'user_id' => 700,
'status' => 'published',
'no_export' => false,
'created_at' => '2009-04-08 15:43:42',
'updated_at' => '2026-04-21 22:07:40',
'slug' => 'stabile-referenz',
]);
app(PressReleaseImporter::class)->run(new ImportContext('presseecho', false, true));
$first = PressRelease::withoutGlobalScopes()
->where('legacy_portal', 'presseecho')->where('legacy_id', 12)->firstOrFail();
$originalUuid = $first->uuid;
// Zweiter --force-Lauf (Delta-Szenario): darf uuid nicht neu würfeln.
app(PressReleaseImporter::class)->run(new ImportContext('presseecho', false, true));
$second = PressRelease::withoutGlobalScopes()
->where('legacy_portal', 'presseecho')->where('legacy_id', 12)->firstOrFail();
expect($second->uuid)->toBe($originalUuid);
expect($second->published_at?->format('Y-m-d H:i:s'))->toBe('2009-04-08 15:43:42');
});
test('a since delta only scans legacy rows created or updated in the window', function () {
/** @var TestCase $this */
seedLegacyPressReleaseSchema();
DB::connection('mysql_presseecho')->table('press_release')->insert([
[
'id' => 20,
'title' => 'Alte unveränderte Meldung',
'language' => 'de',
'text' => 'Inhalt',
'category_id' => 500,
'user_id' => 700,
'status' => 'published',
'no_export' => false,
'created_at' => '2019-05-01 08:00:00',
'updated_at' => '2019-05-01 08:00:00',
'slug' => 'alt-unveraendert',
],
[
'id' => 21,
'title' => 'Heute neu angelegt',
'language' => 'de',
'text' => 'Inhalt',
'category_id' => 500,
'user_id' => 700,
'status' => 'published',
'no_export' => false,
'created_at' => '2026-07-20 09:00:00',
'updated_at' => '2026-07-20 09:00:00',
'slug' => 'heute-neu',
],
[
'id' => 22,
'title' => 'Alt, aber heute geändert',
'language' => 'de',
'text' => 'Inhalt',
'category_id' => 500,
'user_id' => 700,
'status' => 'published',
'no_export' => false,
'created_at' => '2012-01-15 10:00:00',
'updated_at' => '2026-07-20 10:30:00',
'slug' => 'alt-heute-geaendert',
],
]);
app(PressReleaseImporter::class)->run(new ImportContext(
'presseecho',
false,
true,
Carbon::parse('2026-07-20 00:00:00'),
));
$imported = PressRelease::withoutGlobalScopes()
->where('legacy_portal', 'presseecho')
->whereIn('legacy_id', [20, 21, 22])
->pluck('legacy_id')->sort()->values()->all();
expect($imported)->toBe([21, 22]);
});