pp-planer/tests/Feature/DatabaseSchemaTest.php
Thorsten Bus 57d54ec06b feat: Wave 1 Foundation - Database, OAuth, Sync, Files, Layout, Email (T2-T7)
T2: Database Schema + All Migrations
- 10 migrations: users extension, services, songs, song_groups, song_slides,
  song_arrangements, song_arrangement_groups, service_songs, slides, cts_sync_log
- 9 Eloquent models with relationships and casts
- 9 factory classes for testing
- Tests: DatabaseSchemaTest (2 tests, 26 assertions) 

T3: ChurchTools OAuth Provider
- Custom Socialite provider for ChurchTools OAuth2
- AuthController with redirect/callback/logout
- Replaced Breeze login with OAuth-only (German UI)
- Removed all Breeze register/password-reset pages
- Tests: OAuthTest (9 tests, 54 assertions) 

T4: CTS API Service + Sync Command
- ChurchToolsService wrapping 5pm-HDH/churchtools-api
- SyncChurchToolsCommand (php artisan cts:sync)
- SyncController for refresh button
- CCLI-based song matching
- Tests: ChurchToolsSyncTest (2 tests) 

T5: File Conversion Service
- FileConversionService with letterbox/pillarbox to 1920×1080
- ConvertPowerPointJob (queued) with LibreOffice + spatie/pdf-to-image
- ZIP extraction and recursive processing
- Thumbnail generation (320×180)
- Tests: FileConversionTest (2 tests, 21 assertions) 

T6: Shared Vue Components
- AuthenticatedLayout with nav, user info, refresh button
- useAutoSave composable (500ms debounce)
- FlashMessage, ConfirmDialog, LoadingSpinner components
- HandleInertiaRequests middleware with shared props
- Tests: SharedPropsTest (7 tests) 

T7: Email Configuration
- MissingSongRequest mailable (German)
- Email template with song info and service link
- SONG_REQUEST_EMAIL config
- Tests: MissingSongMailTest (2 tests, 10 assertions) 

All tests passing: 30/30 (233 assertions)
All UI text in German with 'Du' form
Wave 1 complete: 7/7 tasks 
2026-03-01 19:39:26 +01:00

64 lines
1.8 KiB
PHP

<?php
use App\Models\CtsSyncLog;
use App\Models\Service;
use App\Models\ServiceSong;
use App\Models\Slide;
use App\Models\Song;
use App\Models\SongArrangement;
use App\Models\SongArrangementGroup;
use App\Models\SongGroup;
use App\Models\SongSlide;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
uses(RefreshDatabase::class);
test('all expected database tables exist', function () {
$expectedTables = [
'users',
'password_reset_tokens',
'sessions',
'cache',
'cache_locks',
'jobs',
'job_batches',
'failed_jobs',
'services',
'songs',
'song_groups',
'song_slides',
'song_arrangements',
'song_arrangement_groups',
'service_songs',
'slides',
'cts_sync_log',
];
foreach ($expectedTables as $table) {
expect(Schema::hasTable($table))->toBeTrue("Table [{$table}] should exist.");
}
});
test('all factories create valid records', function () {
Service::factory()->create();
Song::factory()->create();
SongGroup::factory()->create();
SongSlide::factory()->create();
SongArrangement::factory()->create();
SongArrangementGroup::factory()->create();
ServiceSong::factory()->create();
Slide::factory()->create();
CtsSyncLog::factory()->create();
expect(Service::count())->toBeGreaterThan(0)
->and(Song::count())->toBeGreaterThan(0)
->and(SongGroup::count())->toBeGreaterThan(0)
->and(SongSlide::count())->toBeGreaterThan(0)
->and(SongArrangement::count())->toBeGreaterThan(0)
->and(SongArrangementGroup::count())->toBeGreaterThan(0)
->and(ServiceSong::count())->toBeGreaterThan(0)
->and(Slide::count())->toBeGreaterThan(0)
->and(CtsSyncLog::count())->toBeGreaterThan(0);
});