You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
407 lines
12 KiB
407 lines
12 KiB
import 'package:built_collection/built_collection.dart'; |
|
import 'package:flutter/material.dart'; |
|
import 'package:flutter_test/flutter_test.dart'; |
|
import 'package:mocktail/mocktail.dart'; |
|
import 'package:neon/blocs.dart'; |
|
import 'package:neon/models.dart'; |
|
import 'package:neon/theme.dart'; |
|
import 'package:neon/utils.dart'; |
|
import 'package:neon/widgets.dart'; |
|
import 'package:neon_dashboard/l10n/localizations.dart'; |
|
import 'package:neon_dashboard/src/widgets/widget.dart'; |
|
import 'package:neon_dashboard/src/widgets/widget_button.dart'; |
|
import 'package:neon_dashboard/src/widgets/widget_item.dart'; |
|
import 'package:nextcloud/dashboard.dart' as dashboard; |
|
import 'package:rxdart/rxdart.dart'; |
|
|
|
class MockAccountsBloc extends Mock implements AccountsBloc {} |
|
|
|
Widget wrapWidget(final AccountsBloc accountsBloc, final Widget child) => MaterialApp( |
|
localizationsDelegates: AppLocalizations.localizationsDelegates, |
|
supportedLocales: AppLocalizations.supportedLocales, |
|
home: Scaffold( |
|
backgroundColor: Colors.transparent, |
|
body: NeonProvider<AccountsBloc>.value( |
|
value: accountsBloc, |
|
child: child, |
|
), |
|
), |
|
); |
|
|
|
void main() { |
|
final accountsBloc = MockAccountsBloc(); |
|
when(() => accountsBloc.activeAccount).thenAnswer( |
|
(final invocation) => BehaviorSubject.seeded( |
|
Account( |
|
serverURL: Uri(), |
|
username: 'example', |
|
), |
|
), |
|
); |
|
|
|
group('Widget item', () { |
|
final item = dashboard.WidgetItem( |
|
(final b) => b |
|
..title = 'Widget item title' |
|
..subtitle = 'Widget item subtitle' |
|
..link = 'https://example.com/link' |
|
..iconUrl = 'https://example.com/iconUrl' |
|
..overlayIconUrl = 'https://example.com/overlayIconUrl' |
|
..sinceId = '', |
|
); |
|
|
|
testWidgets('Everything filled', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetItem( |
|
item: item, |
|
roundIcon: true, |
|
), |
|
), |
|
); |
|
|
|
expect(find.text('Widget item title'), findsOneWidget); |
|
expect(find.text('Widget item subtitle'), findsOneWidget); |
|
expect(find.byType(InkWell), findsOneWidget); |
|
expect( |
|
tester.widget(find.byType(InkWell)), |
|
isA<InkWell>().having( |
|
(final a) => a.onTap, |
|
'onTap is not null', |
|
isNotNull, |
|
), |
|
); |
|
expect(find.byType(NeonImageWrapper), findsOneWidget); |
|
expect( |
|
tester.widget(find.byType(NeonImageWrapper)), |
|
isA<NeonImageWrapper>().having( |
|
(final a) => a.borderRadius, |
|
'borderRadius is correct', |
|
BorderRadius.circular(largeIconSize), |
|
), |
|
); |
|
expect(find.byType(NeonCachedImage), findsNWidgets(2)); |
|
|
|
expect(find.byType(DashboardWidgetItem), matchesGoldenFile('goldens/widget_item.png')); |
|
}); |
|
|
|
testWidgets('Not round', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetItem( |
|
item: item, |
|
roundIcon: false, |
|
), |
|
), |
|
); |
|
|
|
expect( |
|
tester.widget(find.byType(NeonImageWrapper)), |
|
isA<NeonImageWrapper>().having( |
|
(final a) => a.borderRadius, |
|
'borderRadius is null', |
|
null, |
|
), |
|
); |
|
|
|
expect(find.byType(DashboardWidgetItem), matchesGoldenFile('goldens/widget_item_not_round.png')); |
|
}); |
|
|
|
testWidgets('Without link', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetItem( |
|
item: item.rebuild((final b) => b..link = ''), |
|
roundIcon: true, |
|
), |
|
), |
|
); |
|
|
|
expect( |
|
tester.widget(find.byType(InkWell)), |
|
isA<InkWell>().having( |
|
(final a) => a.onTap, |
|
'onTap is null', |
|
isNull, |
|
), |
|
); |
|
}); |
|
|
|
testWidgets('Without overlayIconUrl', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetItem( |
|
item: item.rebuild((final b) => b..overlayIconUrl = ''), |
|
roundIcon: true, |
|
), |
|
), |
|
); |
|
|
|
expect(find.byType(NeonCachedImage), findsOneWidget); |
|
}); |
|
}); |
|
|
|
group('Widget button', () { |
|
final button = dashboard.Widget_Buttons( |
|
(final b) => b |
|
..type = 'new' |
|
..text = 'Button' |
|
..link = 'https://example.com/link', |
|
); |
|
|
|
testWidgets('New', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetButton( |
|
button: button, |
|
), |
|
), |
|
); |
|
|
|
expect(find.byIcon(Icons.add), findsOneWidget); |
|
expect(find.text('Button'), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidgetButton), matchesGoldenFile('goldens/widget_button_new.png')); |
|
}); |
|
|
|
testWidgets('More', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetButton( |
|
button: button.rebuild((final b) => b.type = 'more'), |
|
), |
|
), |
|
); |
|
|
|
expect(find.byIcon(Icons.more_outlined), findsOneWidget); |
|
expect(find.text('Button'), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidgetButton), matchesGoldenFile('goldens/widget_button_more.png')); |
|
}); |
|
|
|
testWidgets('Setup', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetButton( |
|
button: button.rebuild((final b) => b.type = 'setup'), |
|
), |
|
), |
|
); |
|
|
|
expect(find.byIcon(Icons.launch), findsOneWidget); |
|
expect(find.text('Button'), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidgetButton), matchesGoldenFile('goldens/widget_button_setup.png')); |
|
}); |
|
|
|
testWidgets('Invalid', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidgetButton( |
|
button: button.rebuild((final b) => b.type = 'test'), |
|
), |
|
), |
|
); |
|
|
|
expect(find.byType(Icon), findsNothing); |
|
expect(find.text('Button'), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidgetButton), matchesGoldenFile('goldens/widget_button_invalid.png')); |
|
}); |
|
}); |
|
|
|
group('Widget', () { |
|
final item = dashboard.WidgetItem( |
|
(final b) => b |
|
..title = 'Widget item title' |
|
..subtitle = 'Widget item subtitle' |
|
..link = 'https://example.com/link' |
|
..iconUrl = 'https://example.com/iconUrl' |
|
..overlayIconUrl = 'https://example.com/overlayIconUrl' |
|
..sinceId = '', |
|
); |
|
final items = dashboard.WidgetItems( |
|
(final b) => b |
|
..items = BuiltList<dashboard.WidgetItem>.from([item]).toBuilder() |
|
..emptyContentMessage = '' |
|
..halfEmptyContentMessage = '', |
|
); |
|
final button = dashboard.Widget_Buttons( |
|
(final b) => b |
|
..type = 'new' |
|
..text = 'Button' |
|
..link = 'https://example.com/link', |
|
); |
|
final widget = dashboard.Widget( |
|
(final b) => b |
|
..id = 'id' |
|
..title = 'Widget title' |
|
..order = 0 |
|
..iconClass = '' |
|
..iconUrl = 'https://example.com/iconUrl' |
|
..widgetUrl = 'https://example.com/widgetUrl' |
|
..itemIconsRound = true |
|
..itemApiVersions = BuiltList<int>.from([1, 2]).toBuilder() |
|
..reloadInterval = 0 |
|
..buttons = BuiltList<dashboard.Widget_Buttons>.from([button]).toBuilder(), |
|
); |
|
|
|
testWidgets('Everything filled', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidget( |
|
widget: widget, |
|
items: items, |
|
), |
|
), |
|
); |
|
|
|
expect(find.text('Widget title'), findsOneWidget); |
|
expect(find.byType(InkWell), findsNWidgets(4)); |
|
expect( |
|
tester.widget(find.byType(InkWell).first), |
|
isA<InkWell>().having( |
|
(final a) => a.onTap, |
|
'onTap is not null', |
|
isNotNull, |
|
), |
|
); |
|
expect(find.byType(NeonImageWrapper), findsOneWidget); |
|
expect( |
|
tester.widget(find.byType(NeonImageWrapper)), |
|
isA<NeonImageWrapper>().having( |
|
(final a) => a.borderRadius, |
|
'borderRadius is correct', |
|
BorderRadius.circular(largeIconSize), |
|
), |
|
); |
|
expect(find.byType(NeonCachedImage), findsNWidgets(3)); |
|
expect(find.byType(DashboardWidgetItem), findsOneWidget); |
|
expect(find.bySubtype<FilledButton>(), findsOneWidget); |
|
expect(find.byIcon(Icons.add), findsOneWidget); |
|
expect(find.text('Button'), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidget), matchesGoldenFile('goldens/widget.png')); |
|
}); |
|
|
|
testWidgets('Without widgetUrl', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidget( |
|
widget: widget.rebuild((final b) => b.widgetUrl = ''), |
|
items: items, |
|
), |
|
), |
|
); |
|
|
|
expect( |
|
tester.widget(find.byType(InkWell).first), |
|
isA<InkWell>().having( |
|
(final a) => a.onTap, |
|
'onTap is null', |
|
isNull, |
|
), |
|
); |
|
}); |
|
|
|
testWidgets('Not round', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidget( |
|
widget: widget.rebuild((final b) => b.itemIconsRound = false), |
|
items: items, |
|
), |
|
), |
|
); |
|
|
|
expect( |
|
tester.widget(find.byType(NeonImageWrapper)), |
|
isA<NeonImageWrapper>().having( |
|
(final a) => a.borderRadius, |
|
'borderRadius is null', |
|
null, |
|
), |
|
); |
|
|
|
expect(find.byType(DashboardWidget), matchesGoldenFile('goldens/widget_not_round.png')); |
|
}); |
|
|
|
testWidgets('With halfEmptyContentMessage', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidget( |
|
widget: widget, |
|
items: items.rebuild((final b) => b.halfEmptyContentMessage = 'Half empty'), |
|
), |
|
), |
|
); |
|
|
|
expect(find.text('Half empty'), findsOneWidget); |
|
expect(find.byIcon(Icons.check), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidget), matchesGoldenFile('goldens/widget_with_half_empty.png')); |
|
}); |
|
|
|
testWidgets('With emptyContentMessage', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidget( |
|
widget: widget, |
|
items: items.rebuild((final b) => b.emptyContentMessage = 'Empty'), |
|
), |
|
), |
|
); |
|
|
|
expect(find.text('Empty'), findsOneWidget); |
|
expect(find.byIcon(Icons.check), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidget), matchesGoldenFile('goldens/widget_with_empty.png')); |
|
}); |
|
|
|
testWidgets('Without items', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidget( |
|
widget: widget, |
|
items: null, |
|
), |
|
), |
|
); |
|
|
|
expect(find.text('No entries'), findsOneWidget); |
|
expect(find.byIcon(Icons.check), findsOneWidget); |
|
|
|
expect(find.byType(DashboardWidget), matchesGoldenFile('goldens/widget_without_items.png')); |
|
}); |
|
|
|
testWidgets('Without buttons', (final tester) async { |
|
await tester.pumpWidget( |
|
wrapWidget( |
|
accountsBloc, |
|
DashboardWidget( |
|
widget: widget.rebuild((final b) => b.buttons.clear()), |
|
items: items, |
|
), |
|
), |
|
); |
|
|
|
expect(find.bySubtype<FilledButton>(), findsNothing); |
|
|
|
expect(find.byType(DashboardWidget), matchesGoldenFile('goldens/widget_without_buttons.png')); |
|
}); |
|
}); |
|
}
|
|
|