chore(client): 归档原型阶段新增文件(配置、主题、模型与测试)

为什么:上一批归档只覆盖了「已跟踪文件的修改」,原型阶段新增的文件(app_config、theme、
home_feed/play_ticket 模型、catalog_api、测试目录等)还是未入库状态 —— 而已入库的代码会 import 它们,
留在工作区会导致 HEAD 处的代码编译不过。一并归档,让 HEAD 自洽。

纯归档,无行为改动。
This commit is contained in:
Vicky committed 2026-10-15 17:53:45 +08:00
1 parent e1b98df509
commit feecc349a0
19 files changed
+2210

No files matched your search

@@ -0,0 +1,98 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:nontonki/core/data/models/drama.dart';
import 'package:nontonki/core/data/remote/api_client.dart';
import 'package:nontonki/pages/drama_detail/drama_detail_logic.dart';
import '../support/fake_watch_history.dart';
Drama _card(String id) => Drama(
id: id,
title: id,
synopsis: 'synopsis',
posterUrl: '/files/$id.jpg',
totalEpisodes: 3,
episodes: [
Episode(
id: '$id-1',
number: 1,
title: '第 1 集',
isFree: true,
videoUrl: '/files/$id-1.mp4',
),
],
);
Drama _detail(String id) => Drama(
id: id,
title: id,
synopsis: 'synopsis',
posterUrl: '/files/$id.jpg',
totalEpisodes: 3,
detailLoaded: true,
episodes: [
for (var number = 1; number <= 3; number++)
Episode(
id: '$id-$number',
number: number,
title: '第 $number 集',
isFree: true,
videoUrl: '/files/$id-$number.mp4',
),
],
);
void main() {
test('a list card is upgraded to the full episode list', () async {
var calls = 0;
final logic = DramaDetailLogic(
drama: _card('signal'),
history: FakeWatchHistory(),
);
await logic.load(() async {
calls++;
return _detail('signal');
});
expect(calls, 1);
expect(logic.loading, isFalse);
expect(logic.failed, isFalse);
expect(logic.drama.episodes, hasLength(3));
logic.dispose();
});
test('a failed load keeps the card and reports the reason', () async {
final logic = DramaDetailLogic(
drama: _card('signal'),
history: FakeWatchHistory(),
);
await logic.load(() async => throw const ApiException(500, '服务异常'));
expect(logic.failed, isTrue);
expect(logic.failureMessage, '服务异常');
expect(logic.drama.episodes, hasLength(1));
await logic.load(() async => throw StateError('offline'));
expect(logic.failed, isTrue);
expect(logic.failureMessage, isNull);
logic.dispose();
});
test('an already loaded detail skips the request', () async {
var calls = 0;
final logic = DramaDetailLogic(
drama: _detail('signal'),
history: FakeWatchHistory(),
);
await logic.load(() async {
calls++;
return _detail('signal');
});
expect(calls, 0);
expect(logic.drama.episodes, hasLength(3));
logic.dispose();
});
}