import 'package:flutter_test/flutter_test.dart'; import 'package:cxyz_android/sources/source.dart'; import 'package:cxyz_android/sources/source_flags.dart'; import 'package:cxyz_android/sources/comicland/comicland_source.dart'; import 'package:cxyz_android/sources/mangaread/mangaread_source.dart'; import 'package:cxyz_android/sources/mangaread/urls.dart'; import 'package:cxyz_android/sources/mangatown/mangatown_source.dart'; import 'package:cxyz_android/sources/registry.dart'; void main() { group('parseEnabledSourceIds', () { test('default comicland token', () { expect(parseEnabledSourceIds('comicland'), {SourceId.comicland}); }); test('comma-separated both', () { expect( parseEnabledSourceIds('comicland,mangaread'), {SourceId.comicland, SourceId.mangaread}, ); }); test('mangaread only', () { expect(parseEnabledSourceIds('mangaread'), {SourceId.mangaread}); }); test('all enables every SourceId', () { expect(parseEnabledSourceIds('all'), SourceId.values.toSet()); expect(parseEnabledSourceIds('ALL'), SourceId.values.toSet()); expect(parseEnabledSourceIds('all,mangaread'), SourceId.values.toSet()); }); test('mangatown token', () { expect(parseEnabledSourceIds('mangatown'), {SourceId.mangatown}); }); test('ignores unknown and falls back when empty', () { expect(parseEnabledSourceIds(''), {SourceId.comicland}); expect(parseEnabledSourceIds('nope,also-bad'), {SourceId.comicland}); }); test('trims and is case-insensitive', () { expect( parseEnabledSourceIds(' MangaRead , ComicLand '), {SourceId.mangaread, SourceId.comicland}, ); }); }); group('SourceRegistry gating', () { test('registers only enabled ids', () { final reg = SourceRegistry( enabled: {SourceId.mangaread}, mangaRead: MangaReadSource(), ); expect(reg.all.map((s) => s.id), [SourceId.mangaread]); expect(reg.hasMultiple, isFalse); }); test('dual sources preserve declaration order', () { final reg = SourceRegistry( enabled: {SourceId.mangaread, SourceId.comicland}, comicLand: ComicLandSource(), mangaRead: MangaReadSource(), ); expect(reg.all.map((s) => s.id).toList(), [ SourceId.comicland, SourceId.mangaread, ]); expect(reg.hasMultiple, isTrue); }); test('all three sources preserve declaration order', () { final reg = SourceRegistry( enabled: { SourceId.mangatown, SourceId.mangaread, SourceId.comicland, }, comicLand: ComicLandSource(), mangaRead: MangaReadSource(), mangaTown: MangaTownSource(), ); expect(reg.all.map((s) => s.id).toList(), [ SourceId.comicland, SourceId.mangaread, SourceId.mangatown, ]); }); }); group('catalogMenus capabilities', () { test('ComicLand exposes newest, popular, official, uncensored, recommended, search', () { final kinds = ComicLandSource().catalogMenus.map((m) => m.kind).toList(); expect(kinds, [ CatalogMenuKind.latest, CatalogMenuKind.popular, CatalogMenuKind.official, CatalogMenuKind.uncensored, CatalogMenuKind.recommended, CatalogMenuKind.search, ]); expect( ComicLandSource().catalogMenus.first.title, 'Newest', ); }); test('MangaRead exposes latest and search only', () { final kinds = MangaReadSource().catalogMenus.map((m) => m.kind).toList(); expect(kinds, [ CatalogMenuKind.latest, CatalogMenuKind.search, ]); expect(kinds.contains(CatalogMenuKind.popular), isFalse); }); test('MangaTown exposes latest, hot variants, directory, search', () { final kinds = MangaTownSource().catalogMenus.map((m) => m.kind).toList(); expect(kinds, [ CatalogMenuKind.latest, CatalogMenuKind.popular, CatalogMenuKind.hotToday, CatalogMenuKind.hotWeek, CatalogMenuKind.hotMonth, CatalogMenuKind.directory, CatalogMenuKind.search, ]); }); }); group('mangaread urls', () { test('mangaSlugFromUrl', () { expect( mangaSlugFromUrl( 'https://www.mangaread.org/manga/the-chaebeols-youngest-son/chapter-560/', ), 'the-chaebeols-youngest-son', ); }); test('mangaBaseUrlFromListingUrl', () { expect( mangaBaseUrlFromListingUrl( 'https://www.mangaread.org/manga/foo-bar/chapter-1/', ), 'https://www.mangaread.org/manga/foo-bar/', ); }); test('listingUrlForSlug', () { expect( listingUrlForSlug('foo-bar'), 'https://www.mangaread.org/manga/foo-bar/', ); }); test('chapterNumberFromTitle', () { expect(chapterNumberFromTitle('Chapter 560'), '560'); expect(chapterNumberFromTitle('Ch. 12.5'), '12.5'); }); }); }