feat(songs): track CCLI import metadata on songs table
This commit is contained in:
parent
fc2060b926
commit
73b7afcc2f
|
|
@ -16,6 +16,8 @@ class Song extends Model
|
|||
protected $fillable = [
|
||||
'ccli_id',
|
||||
'cts_song_id',
|
||||
'imported_from_ccli_at',
|
||||
'ccli_source_url',
|
||||
'title',
|
||||
'author',
|
||||
'copyright_text',
|
||||
|
|
@ -30,6 +32,7 @@ protected function casts(): array
|
|||
return [
|
||||
'has_translation' => 'boolean',
|
||||
'last_used_at' => 'datetime',
|
||||
'imported_from_ccli_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,4 +22,12 @@ public function definition(): array
|
|||
'last_used_at' => $this->faker->optional()->dateTimeBetween('-6 months', 'now'),
|
||||
];
|
||||
}
|
||||
|
||||
public function fromCcli(): self
|
||||
{
|
||||
return $this->state(fn (): array => [
|
||||
'imported_from_ccli_at' => now(),
|
||||
'ccli_source_url' => 'https://songselect.ccli.com/Songs/9999001',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class () extends Migration {
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('songs', function (Blueprint $table): void {
|
||||
$table->timestamp('imported_from_ccli_at')->nullable()->after('last_used_at');
|
||||
$table->string('ccli_source_url', 500)->nullable()->after('imported_from_ccli_at');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('songs', function (Blueprint $table): void {
|
||||
$table->dropColumn(['imported_from_ccli_at', 'ccli_source_url']);
|
||||
});
|
||||
}
|
||||
};
|
||||
54
tests/Feature/SongCcliMetadataTest.php
Normal file
54
tests/Feature/SongCcliMetadataTest.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Song;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('songs table has imported_from_ccli_at and ccli_source_url columns', function (): void {
|
||||
expect(Schema::hasColumn('songs', 'imported_from_ccli_at'))->toBeTrue();
|
||||
expect(Schema::hasColumn('songs', 'ccli_source_url'))->toBeTrue();
|
||||
});
|
||||
|
||||
test('imported_from_ccli_at defaults to null', function (): void {
|
||||
$song = Song::factory()->create();
|
||||
|
||||
expect($song->fresh()->imported_from_ccli_at)->toBeNull();
|
||||
});
|
||||
|
||||
test('ccli_source_url defaults to null', function (): void {
|
||||
$song = Song::factory()->create();
|
||||
|
||||
expect($song->fresh()->ccli_source_url)->toBeNull();
|
||||
});
|
||||
|
||||
test('imported_from_ccli_at casts to Carbon instance', function (): void {
|
||||
$song = Song::factory()->create(['imported_from_ccli_at' => '2026-05-10 12:00:00']);
|
||||
|
||||
expect($song->fresh()->imported_from_ccli_at)->toBeInstanceOf(Carbon::class);
|
||||
});
|
||||
|
||||
test('fromCcli factory state populates both fields', function (): void {
|
||||
$song = Song::factory()->fromCcli()->create();
|
||||
$fresh = $song->fresh();
|
||||
|
||||
expect($fresh->imported_from_ccli_at)->not->toBeNull();
|
||||
expect($fresh->imported_from_ccli_at)->toBeInstanceOf(Carbon::class);
|
||||
expect($fresh->ccli_source_url)->not->toBeNull();
|
||||
expect($fresh->ccli_source_url)->toContain('songselect.ccli.com');
|
||||
});
|
||||
|
||||
test('migration rolls back cleanly', function (): void {
|
||||
Artisan::call('migrate:rollback', ['--step' => 1]);
|
||||
|
||||
expect(Schema::hasColumn('songs', 'imported_from_ccli_at'))->toBeFalse();
|
||||
expect(Schema::hasColumn('songs', 'ccli_source_url'))->toBeFalse();
|
||||
|
||||
Artisan::call('migrate');
|
||||
|
||||
expect(Schema::hasColumn('songs', 'imported_from_ccli_at'))->toBeTrue();
|
||||
expect(Schema::hasColumn('songs', 'ccli_source_url'))->toBeTrue();
|
||||
});
|
||||
Loading…
Reference in a new issue