157 lines
4.9 KiB
Dart
157 lines
4.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:kooltap/l10n/app_localizations.dart';
|
|
import 'package:kooltap/models/bar_tab.dart';
|
|
import 'package:kooltap/models/tab_item.dart';
|
|
import 'package:kooltap/services/admin_pin_service.dart';
|
|
import 'package:kooltap/services/bar_tab_service.dart';
|
|
import 'package:kooltap/services/pin_lock_service.dart';
|
|
import 'package:kooltap/viewmodels/admin_pin_view_model.dart';
|
|
import 'package:kooltap/viewmodels/bar_screen_view_model.dart';
|
|
import 'package:kooltap/views/dialogs/edit_tab_dialog.dart';
|
|
import 'package:mocktail/mocktail.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
class MockBarTabService extends Mock implements BarTabService {}
|
|
|
|
class MockAdminPinService extends Mock implements AdminPinService {}
|
|
|
|
BarTab _tab({required bool withItems}) {
|
|
return BarTab(
|
|
id: 'tab-1',
|
|
customerName: 'John',
|
|
openedAt: DateTime(2026),
|
|
items: [
|
|
if (withItems)
|
|
const TabItem(
|
|
id: 'item-1',
|
|
tabId: 'tab-1',
|
|
productId: 'beer',
|
|
productName: 'Beer',
|
|
quantity: 2,
|
|
unitPriceInCents: 250,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
void main() {
|
|
late MockBarTabService barTabService;
|
|
late MockAdminPinService adminPinService;
|
|
late AdminPinViewModel adminPinViewModel;
|
|
|
|
setUp(() {
|
|
barTabService = MockBarTabService();
|
|
adminPinService = MockAdminPinService();
|
|
adminPinViewModel = AdminPinViewModel(adminPinService: adminPinService);
|
|
|
|
when(() => barTabService.deleteTab(any())).thenAnswer((_) async {});
|
|
when(() => adminPinService.hasPin()).thenAnswer((_) async => true);
|
|
when(() => adminPinService.verifyPin('1234')).thenAnswer((_) async => true);
|
|
when(
|
|
() => adminPinService.verifyPin('0000'),
|
|
).thenAnswer((_) async => false);
|
|
});
|
|
|
|
Future<void> openDialog(WidgetTester tester, BarTab tab) async {
|
|
await adminPinViewModel.load();
|
|
|
|
await tester.pumpWidget(
|
|
MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider<BarScreenViewModel>(
|
|
create: (_) => BarScreenViewModel(barTabService: barTabService),
|
|
),
|
|
ChangeNotifierProvider<AdminPinViewModel>.value(
|
|
value: adminPinViewModel,
|
|
),
|
|
],
|
|
child: MaterialApp(
|
|
locale: const Locale('en'),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: Builder(
|
|
builder: (context) => Scaffold(
|
|
body: ElevatedButton(
|
|
onPressed: () => confirmDeleteTab(context, tab),
|
|
child: const Text('Open'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('Open'));
|
|
await tester.pumpAndSettle();
|
|
}
|
|
|
|
Future<void> confirmWithPin(WidgetTester tester, String? pin) async {
|
|
if (pin != null) await tester.enterText(find.byType(TextField), pin);
|
|
await tester.tap(find.widgetWithText(FilledButton, 'Delete'));
|
|
await tester.pumpAndSettle();
|
|
}
|
|
|
|
testWidgets('deletes an empty tab without asking for a PIN', (tester) async {
|
|
await openDialog(tester, _tab(withItems: false));
|
|
|
|
expect(find.byType(TextField), findsNothing);
|
|
await confirmWithPin(tester, null);
|
|
|
|
verify(() => barTabService.deleteTab('tab-1')).called(1);
|
|
});
|
|
|
|
testWidgets('deletes a tab with drinks after the right admin PIN', (
|
|
tester,
|
|
) async {
|
|
await openDialog(tester, _tab(withItems: true));
|
|
await confirmWithPin(tester, '1234');
|
|
|
|
verify(() => barTabService.deleteTab('tab-1')).called(1);
|
|
expect(adminPinViewModel.isUnlocked, false);
|
|
});
|
|
|
|
testWidgets('keeps a tab with drinks after a wrong admin PIN', (
|
|
tester,
|
|
) async {
|
|
await openDialog(tester, _tab(withItems: true));
|
|
await confirmWithPin(tester, '0000');
|
|
|
|
verifyNever(() => barTabService.deleteTab(any()));
|
|
});
|
|
|
|
testWidgets('keeps a tab with drinks while the PIN is locked out', (
|
|
tester,
|
|
) async {
|
|
when(
|
|
() => adminPinService.verifyPin(any()),
|
|
).thenThrow(const PinLockedOutException(Duration(minutes: 1)));
|
|
|
|
await openDialog(tester, _tab(withItems: true));
|
|
await confirmWithPin(tester, '1234');
|
|
|
|
verifyNever(() => barTabService.deleteTab(any()));
|
|
});
|
|
|
|
testWidgets('cancelling deletes nothing', (tester) async {
|
|
await openDialog(tester, _tab(withItems: true));
|
|
await tester.tap(find.text('Cancel'));
|
|
await tester.pumpAndSettle();
|
|
|
|
verifyNever(() => barTabService.deleteTab(any()));
|
|
});
|
|
|
|
testWidgets('does not ask for a PIN when no admin PIN is set', (
|
|
tester,
|
|
) async {
|
|
when(() => adminPinService.hasPin()).thenAnswer((_) async => false);
|
|
|
|
await openDialog(tester, _tab(withItems: true));
|
|
|
|
expect(find.byType(TextField), findsNothing);
|
|
await confirmWithPin(tester, null);
|
|
|
|
verify(() => barTabService.deleteTab('tab-1')).called(1);
|
|
});
|
|
}
|