235 lines
8.0 KiB
Dart
235 lines
8.0 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:maibu_satabot_v2/core/app/app_user_cubit.dart';
|
|
import 'package:maibu_satabot_v2/core/di/injection.dart';
|
|
import 'package:maibu_satabot_v2/core/domain/entities/user_entity.dart';
|
|
import 'package:maibu_satabot_v2/core/localization/app_localizations.dart';
|
|
import 'package:maibu_satabot_v2/core/localization/locale_cubit.dart';
|
|
import 'package:maibu_satabot_v2/core/theme/AppTheme.dart';
|
|
import 'package:maibu_satabot_v2/core/update/update_cubit.dart';
|
|
import 'package:maibu_satabot_v2/core/update/update_state.dart';
|
|
import 'package:maibu_satabot_v2/core/update/version_check_service.dart';
|
|
import 'package:maibu_satabot_v2/features/main_container/domain/tab_config.dart';
|
|
import 'package:maibu_satabot_v2/features/main_container/presentation/cubit/tab_config_cubit.dart';
|
|
import 'package:maibu_satabot_v2/features/main_container/presentation/main_wrapper.dart';
|
|
import 'package:maibu_satabot_v2/features/v2/device_list/presentation/float_bar/cubit/float_bar_setting_cubit.dart';
|
|
import 'package:maibu_satabot_v2/features/v2/device_list/presentation/float_bar/view/float_bar_widget.dart';
|
|
import 'package:maibu_satabot_v2/features/v2/my/presentation/pages/my_page_v2.dart';
|
|
import 'package:maibu_satabot_v2/features/v2/my/presentation/pages/system_settings_page.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
const _admin = UserEntity(
|
|
userId: 'admin-id',
|
|
username: 'Admin',
|
|
nickname: 'Admin',
|
|
token: 'admin-test',
|
|
orgId: 1,
|
|
roleKey: 'admin',
|
|
);
|
|
|
|
const _member = UserEntity(
|
|
userId: 'member-id',
|
|
username: 'Member',
|
|
nickname: 'Member',
|
|
token: 'member-test',
|
|
orgId: 1,
|
|
roleKey: 'manager',
|
|
);
|
|
|
|
class _VersionService extends Fake implements VersionCheckService {
|
|
final started = Completer<void>();
|
|
final result = Completer<AppVersionInfo?>();
|
|
int checks = 0;
|
|
|
|
@override
|
|
Future<AppVersionInfo?> checkUpdate({
|
|
required String currentVersion,
|
|
required int currentVersionCode,
|
|
}) {
|
|
checks++;
|
|
started.complete();
|
|
return result.future;
|
|
}
|
|
}
|
|
|
|
class _Strings extends LocalizationsDelegate<AppLocalizations> {
|
|
const _Strings(this.value);
|
|
|
|
final AppLocalizations value;
|
|
|
|
@override
|
|
bool isSupported(Locale locale) => true;
|
|
|
|
@override
|
|
Future<AppLocalizations> load(Locale locale) => SynchronousFuture(value);
|
|
|
|
@override
|
|
bool shouldReload(_Strings old) => false;
|
|
}
|
|
|
|
class _ProfileBundle extends CachingAssetBundle {
|
|
static final png = base64Decode(
|
|
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR4nGNgAAIAAAUAAXpeqz8AAAAASUVORK5CYII=',
|
|
);
|
|
|
|
@override
|
|
Future<ByteData> load(String key) => key == 'assets/images/logo_me_bg.png'
|
|
? SynchronousFuture(ByteData.sublistView(png))
|
|
: rootBundle.load(key);
|
|
}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
test('non-admin tabs ignore the administrator configuration', () {
|
|
final config = TabConfig.defaultConfig()
|
|
.toggleItem('ai')
|
|
.toggleItem('device')
|
|
.toggleItem('work')
|
|
.toggleItem('me');
|
|
|
|
expect(config.navItemsForRole('admin').map((item) => item.id), ['ai']);
|
|
expect(config.settingItemsForRole('admin'), config.items);
|
|
for (final role in [null, 'personal', 'user', 'manager', 'siteManager']) {
|
|
final tabs = config.navItemsForRole(role);
|
|
expect(tabs.map((item) => item.id), ['device', 'work', 'me']);
|
|
expect(tabs.every((item) => item.isEnabled), isTrue);
|
|
expect(config.settingItemsForRole(role), tabs);
|
|
}
|
|
});
|
|
|
|
test(
|
|
'a pending administrator version check is discarded after switching users',
|
|
() async {
|
|
final users = AppUserCubit()..setAuth(_member);
|
|
final service = _VersionService();
|
|
final updates = UpdateCubit(service, users);
|
|
addTearDown(() async {
|
|
await updates.close();
|
|
await users.close();
|
|
});
|
|
|
|
await updates.checkUpdate();
|
|
expect(service.checks, 0);
|
|
expect(updates.state, isA<UpdateInitial>());
|
|
|
|
users.setAuth(_admin);
|
|
final check = updates.checkUpdate();
|
|
await service.started.future;
|
|
expect(updates.state, isA<UpdateChecking>());
|
|
|
|
users.setAuth(_member);
|
|
service.result.complete(null);
|
|
await check;
|
|
await Future<void>.delayed(Duration.zero);
|
|
expect(updates.state, isA<UpdateInitial>());
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'switching from admin locks tabs and hides float bar and updates',
|
|
(tester) async {
|
|
SharedPreferences.setMockInitialValues({});
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final users = AppUserCubit()..setAuth(_admin);
|
|
final tabs = TabConfigCubit(prefs)
|
|
..toggleTab('device')
|
|
..toggleTab('work');
|
|
final locale = LocaleCubit(prefs);
|
|
final service = _VersionService();
|
|
final updates = UpdateCubit(service, users);
|
|
sl.registerSingleton(FloatBarSettingService(prefs));
|
|
addTearDown(() async {
|
|
await sl.unregister<FloatBarSettingService>();
|
|
await updates.close();
|
|
await locale.close();
|
|
await tabs.close();
|
|
await users.close();
|
|
});
|
|
|
|
final strings = (await tester.runAsync(() async {
|
|
final value = AppLocalizations(AppLocalizations.chinese);
|
|
expect(await value.load(), isTrue);
|
|
return value;
|
|
}))!;
|
|
final bundle = _ProfileBundle();
|
|
final navigator = GlobalKey<NavigatorState>();
|
|
await tester.pumpWidget(
|
|
MultiBlocProvider(
|
|
providers: [
|
|
BlocProvider<AppUserCubit>.value(value: users),
|
|
BlocProvider<TabConfigCubit>.value(value: tabs),
|
|
BlocProvider<LocaleCubit>.value(value: locale),
|
|
BlocProvider<UpdateCubit>.value(value: updates),
|
|
],
|
|
child: MaterialApp(
|
|
navigatorKey: navigator,
|
|
theme: AppTheme.lightTheme,
|
|
locale: AppLocalizations.chinese,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
localizationsDelegates: [
|
|
_Strings(strings),
|
|
...GlobalMaterialLocalizations.delegates,
|
|
],
|
|
builder: (_, child) =>
|
|
DefaultAssetBundle(bundle: bundle, child: child!),
|
|
home: const MainWrapper(),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
expect(find.byType(MyPageV2), findsOneWidget);
|
|
expect(find.text('设备'), findsNothing);
|
|
|
|
navigator.currentState!.push<void>(
|
|
MaterialPageRoute(builder: (_) => const SystemSettingsPage()),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('AI'), findsOneWidget);
|
|
expect(
|
|
tester.widget<Switch>(find.byType(Switch).first).onChanged,
|
|
isNotNull,
|
|
);
|
|
final updatesTitle = find.text('版本更新');
|
|
await tester.scrollUntilVisible(
|
|
updatesTitle,
|
|
200,
|
|
scrollable: find.byType(Scrollable).first,
|
|
);
|
|
expect(updatesTitle, findsOneWidget);
|
|
|
|
users.setAuth(_member);
|
|
await FloatBarSettingService.setEnabled(true);
|
|
await tester.pumpAndSettle();
|
|
for (final label in ['设备', '作业', '我的']) {
|
|
expect(find.text(label), findsOneWidget);
|
|
}
|
|
for (final label in ['AI', '悬浮条', '版本更新']) {
|
|
expect(find.text(label), findsNothing);
|
|
}
|
|
final switches = tester.widgetList<Switch>(find.byType(Switch)).toList();
|
|
expect(switches, hasLength(3));
|
|
expect(
|
|
switches.every((toggle) => toggle.value && toggle.onChanged == null),
|
|
isTrue,
|
|
);
|
|
|
|
navigator.currentState!.pop();
|
|
await tester.pumpAndSettle();
|
|
expect(find.byType(MyPageV2), findsOneWidget);
|
|
expect(find.byType(FloatBarWidget), findsNothing);
|
|
for (final label in ['设备', '作业', '我的']) {
|
|
expect(find.text(label), findsOneWidget);
|
|
}
|
|
await tester.pumpWidget(const SizedBox.shrink());
|
|
},
|
|
);
|
|
}
|