122 lines
3.6 KiB
Dart
122 lines
3.6 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:fruitshorts/core/data/models/drama.dart';
|
|
import 'package:fruitshorts/core/data/models/search_result.dart';
|
|
import 'package:fruitshorts/core/data/remote/api_exception.dart';
|
|
import 'package:fruitshorts/core/data/repositories/search_repository.dart';
|
|
import 'package:fruitshorts/pages/discover/discover_logic.dart';
|
|
|
|
import '../support/fake_watch_history.dart';
|
|
|
|
Drama _drama(String id, {String language = 'id'}) => Drama(
|
|
id: id,
|
|
title: id,
|
|
synopsis: 'synopsis',
|
|
posterUrl: '/files/$id.png',
|
|
language: language,
|
|
episodes: const [],
|
|
);
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
test(
|
|
'should_query_backend_and_render_results_when_search_text_changes',
|
|
() async {
|
|
final repository = _FakeSearchRepository(results: [_drama('velvet')]);
|
|
final logic = DiscoverLogic(
|
|
history: FakeWatchHistory(),
|
|
drama: _drama('signal'),
|
|
searchRepository: repository,
|
|
)..searchDebounce = Duration.zero;
|
|
|
|
logic.search.text = 'velvet';
|
|
logic.onSearchChanged();
|
|
await pumpEventQueue();
|
|
|
|
expect(repository.calls, [
|
|
(keyword: 'velvet', pageIndex: 1, pageSize: 20),
|
|
]);
|
|
expect(logic.searchLoading, isFalse);
|
|
expect(logic.visibleDramas(const []).single.id, 'velvet');
|
|
logic.dispose();
|
|
},
|
|
);
|
|
|
|
test('should_keep_server_results_when_text_only_loses_whitespace', () async {
|
|
final repository = _FakeSearchRepository(results: [_drama('velvet')]);
|
|
final logic = DiscoverLogic(
|
|
history: FakeWatchHistory(),
|
|
drama: _drama('signal'),
|
|
searchRepository: repository,
|
|
)..searchDebounce = Duration.zero;
|
|
|
|
logic.search.text = 'velvet ';
|
|
logic.onSearchChanged();
|
|
await pumpEventQueue();
|
|
logic.search.text = 'velvet';
|
|
logic.onSearchChanged();
|
|
await pumpEventQueue();
|
|
|
|
expect(repository.calls, hasLength(1));
|
|
expect(logic.visibleDramas(const []).single.id, 'velvet');
|
|
logic.dispose();
|
|
});
|
|
|
|
test('should_expose_error_message_when_search_fails', () async {
|
|
final logic = DiscoverLogic(
|
|
history: FakeWatchHistory(),
|
|
drama: _drama('signal'),
|
|
searchRepository: _FakeSearchRepository(
|
|
error: const ApiException(400, 'Keyword is invalid'),
|
|
),
|
|
)..searchDebounce = Duration.zero;
|
|
|
|
logic.search.text = '%%%';
|
|
logic.onSearchChanged();
|
|
await pumpEventQueue();
|
|
|
|
expect(logic.searchError, 'Keyword is invalid');
|
|
expect(logic.searchLoading, isFalse);
|
|
logic.dispose();
|
|
});
|
|
|
|
test('should_clear_server_results_when_search_text_is_empty', () async {
|
|
final repository = _FakeSearchRepository(results: [_drama('velvet')]);
|
|
final logic = DiscoverLogic(
|
|
history: FakeWatchHistory(),
|
|
drama: _drama('signal'),
|
|
searchRepository: repository,
|
|
)..searchDebounce = Duration.zero;
|
|
|
|
logic.search.text = 'velvet';
|
|
logic.onSearchChanged();
|
|
await pumpEventQueue();
|
|
logic.search.clear();
|
|
logic.onSearchChanged();
|
|
|
|
expect(logic.visibleDramas([_drama('local')]).single.id, 'local');
|
|
logic.dispose();
|
|
});
|
|
}
|
|
|
|
class _FakeSearchRepository implements SearchRepository {
|
|
_FakeSearchRepository({this.results = const [], this.error});
|
|
|
|
final List<Drama> results;
|
|
final ApiException? error;
|
|
final List<({String keyword, int pageIndex, int pageSize})> calls = [];
|
|
|
|
@override
|
|
Future<SearchResult> search(
|
|
String keyword, {
|
|
int pageIndex = 1,
|
|
int pageSize = 20,
|
|
}) async {
|
|
calls.add((keyword: keyword, pageIndex: pageIndex, pageSize: pageSize));
|
|
if (error != null) throw error!;
|
|
return SearchResult(total: results.length, list: results);
|
|
}
|
|
}
|