提交 Nontonki 短剧原型,准备推送到远程仓库。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
VickyandCursor committed 2026-10-13 16:23:08 +08:00
commit b1f6ce4bf9
148 files changed
+11175

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:nontonki/core/data/repositories/catalog_repository.dart';
import 'package:nontonki/core/data/models/drama.dart';
import 'package:nontonki/core/data/services/catalog_controller.dart';
void main() {
test(
'empty catalog is distinct from a failed load, and retry recovers',
() async {
final repo = ScriptedCatalogRepository();
final controller = CatalogController(repo);
await controller.load();
expect(controller.dramas, isEmpty);
expect(controller.error, isNull);
repo.fail = true;
await controller.load();
expect(controller.error, isNotNull);
repo.fail = false;
repo.items = await DemoCatalogRepository().fetchDramas();
await controller.load();
expect(controller.error, isNull);
expect(controller.dramas, hasLength(3));
expect(controller.dramas.first.episodes.length, 3);
},
);
}
class ScriptedCatalogRepository implements CatalogRepository {
bool fail = false;
List<Drama> items = const [];
@override
Future<List<Drama>> fetchDramas() async {
if (fail) throw StateError('offline');
return items;
}
}
+26
View File
@@ -0,0 +1,26 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:nontonki/core/data/repositories/catalog_repository.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
test('all mock entries reuse one bundled local demo video', () async {
final dramas = await DemoCatalogRepository().fetchDramas();
expect(dramas, hasLength(3));
expect(dramas.every((drama) => drama.episodes.length == 3), isTrue);
final paths = {
for (final drama in dramas)
for (final episode in drama.episodes) episode.assetPath,
};
expect(paths, {'assets/media/demo_clip.mp4'});
expect(
dramas.every(
(drama) => drama.episodes.every((episode) => episode.isFree),
),
isTrue,
);
final bytes = await rootBundle.load(paths.single);
expect(bytes.lengthInBytes, greaterThan(1000000));
});
}
+22
View File
@@ -0,0 +1,22 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:nontonki/pages/home/home_feed_sections.dart';
import 'package:nontonki/core/data/repositories/catalog_repository.dart';
void main() {
test(
'home categories filter demo dramas without changing their media',
() async {
final dramas = await DemoCatalogRepository().fetchDramas();
final sections = HomeFeedSections(dramas);
expect(sections.indicesFor(HomeFeedCategory.recommended), [0, 1, 2]);
expect(sections.indicesFor(HomeFeedCategory.animated), [0]);
expect(sections.indicesFor(HomeFeedCategory.liveAction), [1, 2]);
expect(sections.indicesFor(HomeFeedCategory.following), isEmpty);
expect(
sections.dramaAt(HomeFeedCategory.liveAction, 0).title,
'City Lights & Velvet Nights',
);
},
);
}