198 lines
6.3 KiB
Dart
198 lines
6.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import 'package:fuel_tax_tracker/screens/data_settings_screen.dart';
|
|
import 'package:fuel_tax_tracker/services/app_state.dart';
|
|
import 'package:fuel_tax_tracker/services/cloud/cloud_storage_provider.dart';
|
|
import 'package:fuel_tax_tracker/services/cloud_sync_service.dart';
|
|
import 'package:fuel_tax_tracker/services/database_service.dart';
|
|
import 'package:fuel_tax_tracker/widgets/backup_reminder.dart';
|
|
|
|
/// Covers the "your data isn't backed up" nudge shown after saving a fuel
|
|
/// entry with no cloud backup configured — see
|
|
/// `ConfirmFuelEntryScreen._save`. The dialog and the spotlight it can lead
|
|
/// to (`showBackupReminderDialog`/`openCloudBackupSetup`) are tested here
|
|
/// as standalone functions rather than through a full save, matching
|
|
/// settings_purge_test.dart's convention of not exercising actions that
|
|
/// need an initialized database.
|
|
void main() {
|
|
setUp(() {
|
|
SharedPreferences.setMockInitialValues({});
|
|
});
|
|
|
|
group('showBackupReminderDialog', () {
|
|
Future<bool?> openDialog(WidgetTester tester) async {
|
|
bool? result;
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () async => result = await showBackupReminderDialog(context),
|
|
child: const Text('open'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.tap(find.text('open'));
|
|
await tester.pumpAndSettle();
|
|
return result;
|
|
}
|
|
|
|
testWidgets('shows the warning with both actions', (tester) async {
|
|
await openDialog(tester);
|
|
|
|
expect(find.text("Your Data Isn't Backed Up"), findsOneWidget);
|
|
expect(find.text('Not Now'), findsOneWidget);
|
|
expect(find.text('Set Up Backup'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Not Now resolves false and closes the dialog', (tester) async {
|
|
bool? result;
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () async => result = await showBackupReminderDialog(context),
|
|
child: const Text('open'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.tap(find.text('open'));
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.tap(find.text('Not Now'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(result, isFalse);
|
|
expect(find.text("Your Data Isn't Backed Up"), findsNothing);
|
|
});
|
|
|
|
testWidgets('Set Up Backup resolves true and closes the dialog', (tester) async {
|
|
bool? result;
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () async => result = await showBackupReminderDialog(context),
|
|
child: const Text('open'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.tap(find.text('open'));
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.tap(find.text('Set Up Backup'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(result, isTrue);
|
|
expect(find.text("Your Data Isn't Backed Up"), findsNothing);
|
|
});
|
|
});
|
|
|
|
group('openCloudBackupSetup', () {
|
|
testWidgets('pushes Settings > Data with the cloud storage card spotlighted',
|
|
(tester) async {
|
|
final appState = AppState()..isLoading = false;
|
|
|
|
await tester.pumpWidget(
|
|
ChangeNotifierProvider.value(
|
|
value: appState,
|
|
child: MaterialApp(
|
|
home: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () => openCloudBackupSetup(context),
|
|
child: const Text('open'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('open'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byType(DataSettingsScreen), findsOneWidget);
|
|
expect(find.text('Back Up to the Cloud'), findsOneWidget);
|
|
expect(find.widgetWithText(FilledButton, 'Got It'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('dismissing the spotlight leaves the Data screen up', (tester) async {
|
|
final appState = AppState()..isLoading = false;
|
|
|
|
await tester.pumpWidget(
|
|
ChangeNotifierProvider.value(
|
|
value: appState,
|
|
child: MaterialApp(
|
|
home: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () => openCloudBackupSetup(context),
|
|
child: const Text('open'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.tap(find.text('open'));
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.tap(find.widgetWithText(FilledButton, 'Got It'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Back Up to the Cloud'), findsNothing, reason: 'spotlight dismissed');
|
|
expect(find.byType(DataSettingsScreen), findsOneWidget, reason: 'still on the Data screen');
|
|
});
|
|
});
|
|
|
|
group('AppState.hasCloudBackupConfigured', () {
|
|
test('false with no cloud provider connected at all', () {
|
|
final appState = AppState();
|
|
expect(appState.hasCloudBackupConfigured, isFalse);
|
|
});
|
|
|
|
test('false when a provider is connected but no folder has been chosen', () {
|
|
final appState = AppState()
|
|
..cloudSync = CloudSyncService(provider: _FakeProvider(), databaseService: DatabaseService());
|
|
|
|
expect(appState.hasCloudBackupConfigured, isFalse);
|
|
});
|
|
|
|
test('true once a backup folder has been configured', () {
|
|
final appState = AppState()
|
|
..cloudSync =
|
|
(CloudSyncService(provider: _FakeProvider(), databaseService: DatabaseService())
|
|
..configure('folder-id'));
|
|
|
|
expect(appState.hasCloudBackupConfigured, isTrue);
|
|
});
|
|
});
|
|
}
|
|
|
|
class _FakeProvider implements CloudStorageProvider {
|
|
@override
|
|
CloudProviderId get id => CloudProviderId.googleDrive;
|
|
|
|
@override
|
|
String get displayName => 'Fake Provider';
|
|
|
|
@override
|
|
bool get isSignedIn => true;
|
|
|
|
@override
|
|
String? get accountLabel => 'tester@example.com';
|
|
|
|
@override
|
|
Future<bool> attemptSilentSignIn() async => true;
|
|
|
|
@override
|
|
Future<String> signIn() async => accountLabel!;
|
|
|
|
@override
|
|
Future<void> signOut() async {}
|
|
|
|
@override
|
|
CloudStorageSession beginSession() => throw UnimplementedError();
|
|
}
|