[verified] Publish ReelBox source under GPLv3
This commit is contained in:
commit
db2b505ca3
445 files changed
+105274
No files matched your search
@@ -0,0 +1,199 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:reelbox/data/api_service.dart';
|
||||
import 'package:reelbox/data/catalog_discovery.dart';
|
||||
import 'package:reelbox/data/models.dart';
|
||||
|
||||
class DiscoveryFixtureApi extends ApiService {
|
||||
final calls = <Map<String, dynamic>>[];
|
||||
dynamic response = <dynamic>[];
|
||||
@override
|
||||
Future<dynamic> get(String path, {Map<String, dynamic>? query}) async {
|
||||
calls.add({'path': path, 'query': query});
|
||||
return response;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TitleRecord>> bestRandom({
|
||||
bool byYear = false,
|
||||
int page = 1,
|
||||
}) async {
|
||||
final rows = discoveryRows(
|
||||
await get('fixture', query: {'action': 'best-rand-top', 'pageno': page}),
|
||||
);
|
||||
return CatalogPage(
|
||||
decodeTitles(rows),
|
||||
nextPage: rows.isEmpty ? null : page + 1,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TitleRecord>> search(
|
||||
String query, {
|
||||
int page = 1,
|
||||
bool english = false,
|
||||
}) async {
|
||||
final rows = discoveryRows(
|
||||
await get(
|
||||
'fixture',
|
||||
query: {
|
||||
'action': english ? 'search-movie-en' : 'search-movie',
|
||||
'q': query,
|
||||
'pageno': page,
|
||||
},
|
||||
),
|
||||
);
|
||||
return CatalogPage(
|
||||
decodeTitles(rows),
|
||||
nextPage: rows.isEmpty ? null : page + 1,
|
||||
);
|
||||
}
|
||||
|
||||
final posterIds = <int>[];
|
||||
@override
|
||||
Future<TitleRecord> poster(int id) async {
|
||||
posterIds.add(id);
|
||||
return TitleRecord(id: id, title: 'Hydrated $id');
|
||||
}
|
||||
|
||||
bool actorFails = false;
|
||||
@override
|
||||
Future<List<TitleRecord>> actorTitles(int id) async {
|
||||
if (actorFails) throw const ApiException('Unavailable');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
test(
|
||||
'thematic and franchise directories use distinct observed PHP routes',
|
||||
() async {
|
||||
final api = DiscoveryFixtureApi()
|
||||
..response = [
|
||||
{'id': 1, 'mazmon': 'Space'},
|
||||
];
|
||||
final service = CatalogDiscovery(api);
|
||||
final themes = await service.directory(
|
||||
DiscoveryDirectory.themes,
|
||||
page: 2,
|
||||
);
|
||||
expect(themes.single['title'], 'Space');
|
||||
// Live public mazmon ignores pageno and returns the entire directory.
|
||||
expect(themes.nextPage, isNull);
|
||||
expect(api.calls.last['path'], endsWith('/api-user/filmahang/star.php'));
|
||||
expect((api.calls.last['query'] as Map)['action'], 'mazmon');
|
||||
expect((api.calls.last['query'] as Map).containsKey('key'), isFalse);
|
||||
await service.directory(DiscoveryDirectory.franchises, page: 3);
|
||||
expect(api.calls.last['path'], endsWith('/api-user/newapi/like.php'));
|
||||
expect(api.calls.last['query'], {'action': 'colection', 'pageno': 3});
|
||||
},
|
||||
);
|
||||
|
||||
test('most-shared hydrates IDs once in order and keeps raw cursor', () async {
|
||||
final api = DiscoveryFixtureApi()
|
||||
..response = [
|
||||
{'id': '11'},
|
||||
{'id': '11'},
|
||||
{'id': 12},
|
||||
];
|
||||
final result = await CatalogDiscovery(api).sharedTitles(page: 7);
|
||||
expect(result.map((t) => t.id), [11, 12]);
|
||||
expect(api.posterIds, [11, 12]);
|
||||
expect(result.nextPage, 8);
|
||||
expect((api.calls.single['query'] as Map)['action'], 'share');
|
||||
expect((api.calls.single['query'] as Map).containsKey('key'), isFalse);
|
||||
});
|
||||
|
||||
test(
|
||||
'search filters apply locally without truncating raw page cursor',
|
||||
() async {
|
||||
final api = DiscoveryFixtureApi()
|
||||
..response = [
|
||||
{'id': 1, 'title': 'Film', 'type': 'movie', 'year': 2000},
|
||||
];
|
||||
final result = await CatalogDiscovery(api).search(
|
||||
'query',
|
||||
page: 4,
|
||||
filter: const DiscoverySearchFilter(kind: 'serie', minimumYear: 2020),
|
||||
);
|
||||
expect(result, isEmpty);
|
||||
expect(result.nextPage, 5);
|
||||
expect(api.calls.single['query'], {
|
||||
'action': 'search-movie',
|
||||
'q': 'query',
|
||||
'pageno': 4,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test('actor empty filmography uses paged name search rather than repeating actor request', () async {
|
||||
final api = DiscoveryFixtureApi()
|
||||
..response = [
|
||||
{'id': 1, 'title': 'Name result'},
|
||||
];
|
||||
final loader = ActorFilmography(
|
||||
CatalogDiscovery(api),
|
||||
id: 4,
|
||||
name: 'Actor',
|
||||
);
|
||||
await loader.load(1);
|
||||
await loader.load(2);
|
||||
expect(loader.usingNameFallback, isTrue);
|
||||
expect((api.calls.last['query'] as Map)['pageno'], 2);
|
||||
expect((api.calls.last['query'] as Map)['q'], 'Actor');
|
||||
});
|
||||
|
||||
test(
|
||||
'actor metadata handles nested role actor without using the role ID',
|
||||
() {
|
||||
final person = actorMetadata({
|
||||
'id': 90,
|
||||
'role': 'Lead',
|
||||
'actor': {
|
||||
'id': 7,
|
||||
'name': 'Person',
|
||||
'bio': 'Biography',
|
||||
'born': '1980',
|
||||
'height': '180',
|
||||
},
|
||||
});
|
||||
expect(person['id'], 7);
|
||||
expect(person['name'], 'Person');
|
||||
expect(person['role'], 'Lead');
|
||||
expect(person['bio'], 'Biography');
|
||||
},
|
||||
);
|
||||
|
||||
test('continuation selects only current non-trailer source not expired history URL', () {
|
||||
const sources = [
|
||||
MediaSource(url: 'https://video.example/trailer', quality: 'Trailer'),
|
||||
MediaSource(id: 3, url: 'https://video.example/current', quality: '720p'),
|
||||
];
|
||||
expect(
|
||||
currentHistorySource(sources, 'https://expired.example/file')?.id,
|
||||
3,
|
||||
);
|
||||
expect(currentHistorySource([], 'https://expired.example/file'), isNull);
|
||||
});
|
||||
|
||||
test(
|
||||
'legacy discovery retains raw continuation even for invisible rows',
|
||||
() async {
|
||||
final api = DiscoveryFixtureApi()
|
||||
..response = [
|
||||
{'id': 0, 'title': ''},
|
||||
];
|
||||
final result = await CatalogDiscovery(api).suggestions(page: 4);
|
||||
expect(result, isEmpty);
|
||||
expect(result.nextPage, 5);
|
||||
expect(api.calls.single['query'], {
|
||||
'action': 'best-rand-top',
|
||||
'pageno': 4,
|
||||
});
|
||||
api.response = [];
|
||||
expect(
|
||||
(await CatalogDiscovery(api).suggestions(page: 5)).nextPage,
|
||||
isNull,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user