202 lines
7.6 KiB
Dart
202 lines
7.6 KiB
Dart
import 'package:dio/dio.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:reelbox/app.dart';
|
|
import 'package:reelbox/data/api_service.dart';
|
|
import 'package:reelbox/data/models.dart';
|
|
import 'package:reelbox/state/app_state.dart';
|
|
import 'package:reelbox/ui/catalog.dart';
|
|
import 'package:reelbox/ui/library.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import 'api_service_test.dart' as fixtures;
|
|
import 'api_selector_test.dart' show iranBase;
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
setUp(() => SharedPreferences.setMockInitialValues({}));
|
|
|
|
fixtures.StubAdapter adapter() => fixtures.StubAdapter(
|
|
(r) => r.uri.path.contains('/first/')
|
|
? fixtures.jsonBody({'posters': []})
|
|
: fixtures.jsonBody([]),
|
|
);
|
|
|
|
for (final locale in ['en', 'fa']) {
|
|
testWidgets(
|
|
'settings hides connection details and preserves migrated library in $locale',
|
|
(tester) async {
|
|
final network = adapter();
|
|
final state = AppState(
|
|
api: ApiService(dio: Dio()..httpClientAdapter = network),
|
|
);
|
|
addTearDown(state.dispose);
|
|
await state.initialize(discover: false);
|
|
await state.updateSettings(state.prefs.copyWith(locale: locale));
|
|
const title = TitleRecord(id: 9, title: 'Saved title');
|
|
await state.toggleSaved(title);
|
|
await state.recordWatch(
|
|
title,
|
|
sourceUrl: 'https://media.example/film.mp4?token=exact',
|
|
positionSeconds: 12,
|
|
);
|
|
await state.createCollection('Keep collection');
|
|
final storedLibrary = (await SharedPreferences.getInstance()).getString(
|
|
AppState.storageKey,
|
|
);
|
|
var notifications = 0;
|
|
state.addListener(() => notifications++);
|
|
await tester.pumpWidget(
|
|
AppScope(
|
|
state: state,
|
|
child: const MaterialApp(home: SettingsPage()),
|
|
),
|
|
);
|
|
await tester.drag(find.byType(ListView), const Offset(0, -10000));
|
|
await tester.pumpAndSettle();
|
|
expect(state.api.baseUrl, iranBase);
|
|
expect(find.text(iranBase), findsNothing);
|
|
expect(find.byKey(const Key('catalog-api-endpoint')), findsNothing);
|
|
expect(
|
|
find.text(locale == 'en' ? 'Iran Catalogue' : 'فهرست ایران'),
|
|
findsNothing,
|
|
);
|
|
expect(find.byKey(const Key('catalog-api-selector')), findsNothing);
|
|
expect(find.text('Original API'), findsNothing);
|
|
expect(find.text('API اصلی'), findsNothing);
|
|
expect(find.text('Refresh API server'), findsNothing);
|
|
expect(notifications, 0);
|
|
expect(
|
|
network.requests,
|
|
isEmpty,
|
|
reason: 'Endpoint information must not probe or offer fallback',
|
|
);
|
|
expect(
|
|
(await SharedPreferences.getInstance()).getString(
|
|
AppState.storageKey,
|
|
),
|
|
storedLibrary,
|
|
);
|
|
final preferences = await SharedPreferences.getInstance();
|
|
await preferences.setString(
|
|
'reelbox.api-selection.v1',
|
|
'https://ninwinios.info/api/',
|
|
);
|
|
await preferences.setString(
|
|
'reelbox.trusted-api.v1',
|
|
'https://ninwinios.info/api/',
|
|
);
|
|
final restarted = AppState(
|
|
api: ApiService(dio: Dio()..httpClientAdapter = adapter()),
|
|
);
|
|
addTearDown(restarted.dispose);
|
|
await restarted.initialize(discover: false);
|
|
expect(preferences.getString(AppState.storageKey), storedLibrary);
|
|
expect(restarted.api.baseUrl, iranBase);
|
|
expect(restarted.saved.single.title, 'Saved title');
|
|
expect(
|
|
restarted.history.single.sourceUrl,
|
|
'https://media.example/film.mp4?token=exact',
|
|
);
|
|
expect(restarted.collections.single.name, 'Keep collection');
|
|
expect(restarted.locale, locale);
|
|
},
|
|
);
|
|
}
|
|
|
|
testWidgets(
|
|
'Iran-only catalogue normalizes a legacy views browse on first mount',
|
|
(tester) async {
|
|
final network = adapter();
|
|
final state = AppState(
|
|
api: ApiService(dio: Dio()..httpClientAdapter = network),
|
|
);
|
|
addTearDown(state.dispose);
|
|
await state.initialize(discover: false);
|
|
await tester.pumpWidget(
|
|
AppScope(
|
|
state: state,
|
|
child: const MaterialApp(home: BrowsePage(initialOrder: 'views')),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Most viewed'), findsNothing);
|
|
expect(find.text('Recently added'), findsOneWidget);
|
|
final iranRequests = network.requests.where(
|
|
(r) => r.uri.host == 'reelbox.dartty.top',
|
|
);
|
|
expect(iranRequests.any((r) => r.uri.path.contains('/created/')), isTrue);
|
|
expect(iranRequests.any((r) => r.uri.path.contains('/views/')), isFalse);
|
|
await tester.tap(find.byTooltip('Sort titles'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Most viewed'), findsNothing);
|
|
await tester.tap(find.text('Release year'));
|
|
await tester.pumpAndSettle();
|
|
await tester.pumpWidget(
|
|
AppScope(
|
|
state: state,
|
|
child: const MaterialApp(home: DiscoveryDirectoryPage()),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
final list = tester.widget<ListView>(find.byType(ListView));
|
|
final children =
|
|
(list.childrenDelegate as SliverChildListDelegate).children;
|
|
final titles = children
|
|
.whereType<ListTile>()
|
|
.map((tile) => (tile.title as Text).data)
|
|
.toList();
|
|
expect(titles, isNot(contains('Most-viewed movies')));
|
|
expect(titles, isNot(contains('Most-viewed series')));
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'catalogue tabs survive simplified settings without changing local library',
|
|
(tester) async {
|
|
final network = adapter();
|
|
final state = AppState(
|
|
api: ApiService(dio: Dio()..httpClientAdapter = network),
|
|
);
|
|
addTearDown(state.dispose);
|
|
await state.initialize(discover: false);
|
|
await state.updateSettings(state.prefs.copyWith(introCompleted: true));
|
|
await state.toggleSaved(const TitleRecord(id: 9, title: 'Saved title'));
|
|
await tester.pumpWidget(MyApp(state: state));
|
|
await tester.pumpAndSettle();
|
|
for (final tab in ['Browse', 'Search', 'Library', 'More']) {
|
|
await tester.tap(find.widgetWithText(NavigationDestination, tab));
|
|
await tester.pumpAndSettle();
|
|
}
|
|
await tester.tap(find.text('Settings'));
|
|
await tester.pumpAndSettle();
|
|
await tester.drag(find.byType(ListView), const Offset(0, -10000));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text(iranBase), findsNothing);
|
|
expect(find.byKey(const Key('catalog-api-endpoint')), findsNothing);
|
|
expect(find.byKey(const Key('catalog-api-selector')), findsNothing);
|
|
await tester.pageBack();
|
|
await tester.pumpAndSettle();
|
|
final iranRequests = network.requests
|
|
.where((r) => r.uri.origin == 'https://reelbox.dartty.top')
|
|
.toList();
|
|
expect(iranRequests.any((r) => r.uri.path.contains('/first/')), isTrue);
|
|
expect(
|
|
iranRequests.any((r) => r.uri.path.contains('/movie/by/filtres/')),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
iranRequests.any(
|
|
(r) => r.uri.queryParameters['action'] == 'search-trand',
|
|
),
|
|
isTrue,
|
|
);
|
|
expect(state.saved.single.title, 'Saved title');
|
|
await tester.tap(find.widgetWithText(NavigationDestination, 'Library'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Watchlist (1)'), findsOneWidget);
|
|
expect(tester.takeException(), isNull);
|
|
},
|
|
);
|
|
}
|