test: decouple app fixtures from extension identities

This commit is contained in:
zarzet
2026-09-06 16:03:11 +07:00
parent ead2b9c0ab
commit 0e71003e12
23 changed files with 215 additions and 215 deletions
+2 -2
View File
@@ -15,7 +15,7 @@ DownloadHistoryItem _historyItem({
filePath: filePath,
service: 'test',
downloadedAt: downloadedAt,
spotifyId: 'spotify:track:same',
spotifyId: 'source-track-same',
isrc: 'SAMEISRC',
);
}
@@ -84,7 +84,7 @@ void main() {
totalCount: 2,
);
expect(state.getBySpotifyId('spotify:track:same')?.id, 'newest');
expect(state.getBySpotifyId('source-track-same')?.id, 'newest');
expect(state.getByIsrc('SAMEISRC')?.id, 'newest');
expect(
state.findByTrackAndArtist('Same Song', 'Same Artist')?.id,
@@ -8,43 +8,43 @@ void main() {
test('failed challenge attempts do not consume the granted retry', () {
final guard = DownloadVerificationRetryGuard();
guard.recordVerificationResult('item-1', 'tidal-web', granted: false);
guard.recordVerificationResult('item-1', 'provider-a', granted: false);
expect(guard.hasRetriedAfterGrant('item-1', 'tidal-web'), isFalse);
expect(guard.hasRetriedAfterGrant('item-1', 'provider-a'), isFalse);
});
test('completed grants allow only one automatic retry per service', () {
final guard = DownloadVerificationRetryGuard();
guard.recordVerificationResult('item-1', ' TIDAL-WEB ', granted: true);
guard.recordVerificationResult('item-1', ' PROVIDER-A ', granted: true);
expect(guard.hasRetriedAfterGrant('item-1', 'tidal-web'), isTrue);
expect(guard.hasRetriedAfterGrant('item-1', 'qobuz-web'), isFalse);
expect(guard.hasRetriedAfterGrant('item-2', 'tidal-web'), isFalse);
expect(guard.hasRetriedAfterGrant('item-1', 'provider-a'), isTrue);
expect(guard.hasRetriedAfterGrant('item-1', 'provider-b'), isFalse);
expect(guard.hasRetriedAfterGrant('item-2', 'provider-a'), isFalse);
});
test('manual retry clears every service marker for an item', () {
final guard = DownloadVerificationRetryGuard()
..recordVerificationResult('item-1', 'tidal-web', granted: true)
..recordVerificationResult('item-1', 'qobuz-web', granted: true)
..recordVerificationResult('item-2', 'tidal-web', granted: true);
..recordVerificationResult('item-1', 'provider-a', granted: true)
..recordVerificationResult('item-1', 'provider-b', granted: true)
..recordVerificationResult('item-2', 'provider-a', granted: true);
guard.clearItem('item-1');
expect(guard.hasRetriedAfterGrant('item-1', 'tidal-web'), isFalse);
expect(guard.hasRetriedAfterGrant('item-1', 'qobuz-web'), isFalse);
expect(guard.hasRetriedAfterGrant('item-2', 'tidal-web'), isTrue);
expect(guard.hasRetriedAfterGrant('item-1', 'provider-a'), isFalse);
expect(guard.hasRetriedAfterGrant('item-1', 'provider-b'), isFalse);
expect(guard.hasRetriedAfterGrant('item-2', 'provider-a'), isTrue);
});
test('queue cleanup retains markers only for remaining items', () {
final guard = DownloadVerificationRetryGuard()
..recordVerificationResult('removed', 'tidal-web', granted: true)
..recordVerificationResult('remaining', 'tidal-web', granted: true);
..recordVerificationResult('removed', 'provider-a', granted: true)
..recordVerificationResult('remaining', 'provider-a', granted: true);
guard.retainItems({'remaining'});
expect(guard.hasRetriedAfterGrant('removed', 'tidal-web'), isFalse);
expect(guard.hasRetriedAfterGrant('remaining', 'tidal-web'), isTrue);
expect(guard.hasRetriedAfterGrant('removed', 'provider-a'), isFalse);
expect(guard.hasRetriedAfterGrant('remaining', 'provider-a'), isTrue);
});
});
@@ -58,7 +58,7 @@ void main() {
final result = coordinator.waitForGrant(
itemId: 'item-1',
service: 'tidal-web',
service: 'provider-a',
startFlow: (cancellationSignal) async {
flowStarted.complete();
await cancellationSignal;
@@ -81,7 +81,7 @@ void main() {
final first = coordinator.waitForGrant(
itemId: 'item-1',
service: 'tidal-web',
service: 'provider-a',
startFlow: (cancellationSignal) async {
starts++;
await cancellationSignal;
@@ -93,7 +93,7 @@ void main() {
final second = coordinator.waitForGrant(
itemId: 'item-2',
service: 'tidal-web',
service: 'provider-a',
startFlow: (_) async {
starts++;
return true;
@@ -122,12 +122,12 @@ void main() {
final first = coordinator.waitForGrant(
itemId: 'item-1',
service: ' TIDAL-WEB ',
service: ' PROVIDER-A ',
startFlow: startFlow,
);
final second = coordinator.waitForGrant(
itemId: 'item-2',
service: 'tidal-web',
service: 'provider-a',
startFlow: startFlow,
);
+24 -24
View File
@@ -680,7 +680,7 @@ void main() {
test('round-trips json with service availability', () {
final track = Track.fromJson({
'id': 'spotify:track:1',
'id': 'source-track-1',
'name': 'Song',
'artistName': 'Artist',
'albumName': 'Album',
@@ -691,7 +691,7 @@ void main() {
expect(track.availability?.tidal, isTrue);
expect(track.availability?.qobuz, isFalse);
expect(track.availability?.deezerId, '31337');
expect(track.toJson()['id'], 'spotify:track:1');
expect(track.toJson()['id'], 'source-track-1');
expect(track.availability!.toJson()['deezer'], isTrue);
});
});
@@ -710,7 +710,7 @@ void main() {
final item = DownloadItem(
id: 'download-1',
track: sampleTrack(),
service: 'tidal',
service: 'provider-a',
createdAt: createdAt,
);
@@ -745,7 +745,7 @@ void main() {
final base = DownloadItem(
id: 'download-1',
track: sampleTrack(),
service: 'qobuz',
service: 'provider-b',
createdAt: DateTime.utc(2026),
filePath: '/music/stale.flac',
error: 'raw backend failure',
@@ -790,7 +790,7 @@ void main() {
'albumName': 'Album',
'duration': 1000,
},
'service': 'deezer',
'service': 'provider-a',
'status': 'failed',
'errorType': 'network',
'createdAt': '2026-05-04T10:00:00.000Z',
@@ -811,7 +811,7 @@ void main() {
final item = DownloadItem(
id: 'download-active',
track: sampleTrack(),
service: 'tidal',
service: 'provider-a',
createdAt: DateTime.utc(2026),
status: DownloadStatus.finalizing,
progress: 0.97,
@@ -937,7 +937,7 @@ void main() {
);
final updated = settings.copyWith(
defaultService: 'tidal',
defaultService: 'provider-a',
embedReplayGain: true,
embeddedCoverMaxDimension: 1000,
lyricsProviders: ['apple_music'],
@@ -950,7 +950,7 @@ void main() {
clearHomeFeedProvider: true,
);
expect(updated.defaultService, 'tidal');
expect(updated.defaultService, 'provider-a');
expect(updated.embedReplayGain, isTrue);
expect(updated.embeddedCoverMaxDimension, 1000);
expect(updated.lyricsProviders, ['apple_music']);
@@ -969,7 +969,7 @@ void main() {
test('round-trips json including recently added settings', () {
const settings = AppSettings(
defaultService: 'qobuz',
defaultService: 'provider-b',
storageMode: 'saf',
downloadTreeUri: 'content://tree/music',
downloadFallbackExtensionIds: ['ext.a', 'ext.b'],
@@ -996,7 +996,7 @@ void main() {
final decoded = AppSettings.fromJson(settings.toJson());
expect(decoded.defaultService, 'qobuz');
expect(decoded.defaultService, 'provider-b');
expect(decoded.storageMode, 'saf');
expect(decoded.downloadTreeUri, 'content://tree/music');
expect(decoded.downloadFallbackExtensionIds, ['ext.a', 'ext.b']);
@@ -1053,10 +1053,10 @@ void main() {
test('serializes all backend field names', () {
const payload = DownloadRequestPayload(
isrc: 'ISRC123',
service: 'tidal',
downloadProvider: 'tidal-web',
service: 'source-provider',
downloadProvider: 'download-provider',
providerTrackId: '123456789',
spotifyId: 'spotify:track:1',
spotifyId: 'source-track-1',
trackName: 'Song',
artistName: 'Artist',
albumName: 'Album',
@@ -1092,9 +1092,9 @@ void main() {
explicit: true,
albumType: 'compilation',
upc: '0012345678901',
tidalId: 'tidal-1',
qobuzId: 'qobuz-1',
deezerId: 'deezer-1',
tidalId: 'alternate-id-a',
qobuzId: 'alternate-id-b',
deezerId: 'alternate-id-c',
lyricsMode: 'sidecar',
useExtensions: true,
useFallback: true,
@@ -1114,10 +1114,10 @@ void main() {
expect(payload.toJson(), {
'contract_version': DownloadRequestPayload.nativeWorkerContractVersion,
'isrc': 'ISRC123',
'service': 'tidal',
'download_provider': 'tidal-web',
'service': 'source-provider',
'download_provider': 'download-provider',
'provider_track_id': '123456789',
'spotify_id': 'spotify:track:1',
'spotify_id': 'source-track-1',
'track_name': 'Song',
'artist_name': 'Artist',
'album_name': 'Album',
@@ -1153,9 +1153,9 @@ void main() {
'explicit': true,
'album_type': 'compilation',
'upc': '0012345678901',
'tidal_id': 'tidal-1',
'qobuz_id': 'qobuz-1',
'deezer_id': 'deezer-1',
'tidal_id': 'alternate-id-a',
'qobuz_id': 'alternate-id-b',
'deezer_id': 'alternate-id-c',
'lyrics_mode': 'sidecar',
'use_extensions': true,
'use_fallback': true,
@@ -1283,7 +1283,7 @@ void main() {
'albumType': 'album',
'explicit': true,
'upc': '4006381333931',
'comment': 'https://listen.tidal.com/album/1',
'comment': 'https://media.example/album/1',
'format': 'flac',
});
@@ -1302,7 +1302,7 @@ void main() {
expect(normalized['album_type'], 'album');
expect(normalized['explicit'], isTrue);
expect(normalized['upc'], '4006381333931');
expect(normalized['comment'], 'https://listen.tidal.com/album/1');
expect(normalized['comment'], 'https://media.example/album/1');
expect(normalized['audio_codec'], 'flac');
});
+3 -3
View File
@@ -31,11 +31,11 @@ void main() {
addTearDown(subscription.cancel);
final first = PlatformBridge.completeExtensionSessionGrant(
' qobuz-web ',
' provider-a ',
'grant-value',
);
final second = PlatformBridge.completeExtensionSessionGrant(
'QOBUZ-WEB',
'PROVIDER-A',
'grant-value',
);
@@ -48,7 +48,7 @@ void main() {
expect(callCount, 1);
expect(events, hasLength(1));
expect(events.single.extensionId, 'qobuz-web');
expect(events.single.extensionId, 'provider-a');
expect(events.single.success, isTrue);
});
}
+2 -2
View File
@@ -45,10 +45,10 @@ void main() {
test('prefers a known provider id over guessing from the resource id', () {
expect(
resolvePreferredMetadataProviderId(
'apple-music-ext',
'sample-provider',
'37i9dQZF1DXcBWIGoYBM5M',
),
'apple-music-ext',
'sample-provider',
);
});
@@ -20,7 +20,7 @@ void main() {
artistName: 'Artist',
albumName: 'Album',
filePath: r'Z:\missing\track.flac',
service: 'tidal-web',
service: 'provider-a',
downloadedAt: DateTime(2026),
duration: 250,
bitDepth: 16,
@@ -45,7 +45,7 @@ void main() {
expect(headerMeta, findsOneWidget);
expect(find.byType(ExplicitBadge), findsNWidgets(2));
expect(find.text('Explicit'), findsNothing);
for (final label in const ['16-bit/44.1kHz', '4:10', 'Tidal-web']) {
for (final label in const ['16-bit/44.1kHz', '4:10', 'Provider-a']) {
final text = tester.widget<Text>(
find.descendant(of: headerMeta, matching: find.text(label)),
);