- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
162 lines
5.5 KiB
PHP
162 lines
5.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Application\Campaign\ValueObjects\Campaign;
|
|
use App\Application\Campaign\ValueObjects\CampaignTrack;
|
|
|
|
describe('SpotifyCampaignService - Spotify ID Extraction', function () {
|
|
|
|
it('extracts Spotify ID from URI format (spotify:track:xxx)', function () {
|
|
$track = CampaignTrack::fromArray([
|
|
'id' => 'track_1',
|
|
'position' => 1,
|
|
'title' => 'Test Track',
|
|
'duration' => 180,
|
|
'preview_url' => null,
|
|
'spotify_uri' => 'spotify:track:track_id_123',
|
|
'isrc' => null,
|
|
]);
|
|
|
|
// Use reflection to test private method
|
|
$service = new \ReflectionClass(App\Application\Campaign\Services\SpotifyCampaignService::class);
|
|
$method = $service->getMethod('extractSpotifyId');
|
|
$method->setAccessible(true);
|
|
|
|
$extracted = $method->invoke(
|
|
$service->newInstanceWithoutConstructor(),
|
|
'spotify:track:track_id_123'
|
|
);
|
|
|
|
expect($extracted)->toBe('track_id_123');
|
|
});
|
|
|
|
it('extracts Spotify ID from URL format', function () {
|
|
$service = new \ReflectionClass(App\Application\Campaign\Services\SpotifyCampaignService::class);
|
|
$method = $service->getMethod('extractSpotifyId');
|
|
$method->setAccessible(true);
|
|
|
|
$extracted = $method->invoke(
|
|
$service->newInstanceWithoutConstructor(),
|
|
'https://open.spotify.com/track/url_track_id'
|
|
);
|
|
|
|
expect($extracted)->toBe('url_track_id');
|
|
});
|
|
|
|
it('returns ID if already just an ID', function () {
|
|
$service = new \ReflectionClass(App\Application\Campaign\Services\SpotifyCampaignService::class);
|
|
$method = $service->getMethod('extractSpotifyId');
|
|
$method->setAccessible(true);
|
|
|
|
$extracted = $method->invoke(
|
|
$service->newInstanceWithoutConstructor(),
|
|
'just_an_id_123'
|
|
);
|
|
|
|
expect($extracted)->toBe('just_an_id_123');
|
|
});
|
|
|
|
it('returns null for null input', function () {
|
|
$service = new \ReflectionClass(App\Application\Campaign\Services\SpotifyCampaignService::class);
|
|
$method = $service->getMethod('extractSpotifyId');
|
|
$method->setAccessible(true);
|
|
|
|
$extracted = $method->invoke(
|
|
$service->newInstanceWithoutConstructor(),
|
|
null
|
|
);
|
|
|
|
expect($extracted)->toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('Campaign Value Objects', function () {
|
|
|
|
it('creates campaign with tracks', function () {
|
|
$campaign = Campaign::fromArray([
|
|
'id' => '123',
|
|
'slug' => 'test-album',
|
|
'artist_name' => 'Test Artist',
|
|
'album_title' => 'Test Album',
|
|
'description' => 'Test description',
|
|
'artwork_url' => 'https://example.com/art.jpg',
|
|
'release_date' => '2024-12-01',
|
|
'total_saves' => 100,
|
|
'track_count' => 2,
|
|
'spotify_enabled' => true,
|
|
'apple_music_enabled' => true,
|
|
'spotify_uri' => 'spotify:album:abc123',
|
|
'apple_music_id' => 'apple123',
|
|
'tracks' => [
|
|
[
|
|
'id' => 'track_1',
|
|
'position' => 1,
|
|
'title' => 'Track 1',
|
|
'duration' => 180,
|
|
'preview_url' => null,
|
|
'spotify_uri' => 'spotify:track:track1',
|
|
'isrc' => 'US1234567890',
|
|
],
|
|
[
|
|
'id' => 'track_2',
|
|
'position' => 2,
|
|
'title' => 'Track 2',
|
|
'duration' => 200,
|
|
'preview_url' => null,
|
|
'spotify_uri' => 'spotify:track:track2',
|
|
'isrc' => 'US0987654321',
|
|
]
|
|
],
|
|
'status' => 'active',
|
|
]);
|
|
|
|
expect($campaign->id)->toBe('123');
|
|
expect($campaign->slug)->toBe('test-album');
|
|
expect($campaign->spotify_enabled)->toBeTrue();
|
|
expect($campaign->tracks)->toHaveCount(2);
|
|
expect($campaign->tracks[0]->title)->toBe('Track 1');
|
|
});
|
|
|
|
it('validates campaign status methods', function () {
|
|
$activeCampaign = Campaign::fromArray([
|
|
'id' => '1',
|
|
'slug' => 'active',
|
|
'artist_name' => 'Artist',
|
|
'album_title' => 'Album',
|
|
'description' => null,
|
|
'artwork_url' => null,
|
|
'release_date' => '2025-12-01',
|
|
'total_saves' => 0,
|
|
'track_count' => 0,
|
|
'spotify_enabled' => false,
|
|
'apple_music_enabled' => false,
|
|
'spotify_uri' => null,
|
|
'apple_music_id' => null,
|
|
'status' => 'active',
|
|
]);
|
|
|
|
expect($activeCampaign->isActive())->toBeTrue();
|
|
expect($activeCampaign->hasReleased())->toBeFalse();
|
|
});
|
|
|
|
it('creates campaign track value object', function () {
|
|
$track = CampaignTrack::fromArray([
|
|
'id' => 'track_123',
|
|
'position' => 1,
|
|
'title' => 'Amazing Song',
|
|
'duration' => 240,
|
|
'preview_url' => 'https://example.com/preview.mp3',
|
|
'spotify_id' => 'abc123',
|
|
'apple_music_id' => 'apple456',
|
|
]);
|
|
|
|
expect($track->id)->toBe('track_123');
|
|
expect($track->position)->toBe(1);
|
|
expect($track->title)->toBe('Amazing Song');
|
|
expect($track->duration)->toBe(240);
|
|
expect($track->spotify_id)->toBe('abc123');
|
|
expect($track->apple_music_id)->toBe('apple456');
|
|
});
|
|
});
|