Files
cxyz/cxyz-android/test/source_flags_test.dart
T
nsrb a7c6058540 Add cxyz Android project structure and initial configuration
- Introduced a new Flutter project for the cxyz Android manga/comic reader, including essential files such as pubspec.yaml, AndroidManifest.xml, and Gradle configuration.
- Added .gitignore files to exclude unnecessary files and directories for both the main project and Android-specific files.
- Implemented initial README.md with project description, features, setup instructions, and API details for ComicLand, MangaRead, and MangaTown.
- Configured analysis options and dependencies in pubspec.yaml to support Flutter development.
- Established a pnpm workspace and lockfile for dependency management.
- Included various Android resources such as icons, styles, and launch backgrounds for a complete application setup.
2026-08-29 17:50:31 +07:00

167 lines
5.0 KiB
Dart

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');
});
});
}