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.
meshcore-client/test/screens/blocked_view_test.dart

150 lines
4.9 KiB

import 'package:drift/native.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:meshcore_open/connector/meshcore_connector.dart';
import 'package:meshcore_open/l10n/app_localizations.dart';
import 'package:meshcore_open/screens/settings/blocked_view.dart';
import 'package:meshcore_open/services/block_service.dart';
import 'package:meshcore_open/storage/drift/blob_store.dart';
import 'package:meshcore_open/storage/drift/offband_database.dart';
import 'package:meshcore_open/storage/prefs_manager.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// #938 (#507): the Blocked pane is per radio, and says so.
///
/// The gap this closes: with no radio connected the pane rendered "No blocked
/// users", which is indistinguishable from a connected radio with an empty
/// list. Since #471 made blocks per radio, that wording invited the reader to
/// conclude their blocks had been lost.
void main() {
late OffbandDatabase db;
setUp(() async {
SharedPreferences.setMockInitialValues({});
PrefsManager.reset();
await PrefsManager.initialize();
db = OffbandDatabase(NativeDatabase.memory());
BlobStore.overrideForTest(BlobStore(db));
});
tearDown(() async {
await db.close();
BlobStore.clearTestOverride();
});
Widget harness(BlockService block) => MultiProvider(
providers: [
ChangeNotifierProvider<BlockService>.value(value: block),
ChangeNotifierProvider<MeshCoreConnector>(
create: (_) => MeshCoreConnector(),
),
],
child: const MaterialApp(
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: Scaffold(body: BlockedView()),
),
);
group('the two empty states read differently', () {
testWidgets('no radio connected says so, and explains why', (t) async {
final block = BlockService();
await block.loadForDevice(null);
await t.pumpWidget(harness(block));
await t.pumpAndSettle();
expect(find.text('No radio connected'), findsOneWidget);
expect(
find.textContaining('Blocks belong to the radio that holds them'),
findsOneWidget,
reason: 'the reason matters: without it the pane looks like data loss',
);
expect(
find.text('No blocked users'),
findsNothing,
reason: 'this was the bug: both states said the same thing',
);
});
testWidgets('a connected radio with nothing blocked says THAT', (t) async {
final block = BlockService();
await block.loadForDevice('aa' * 16);
await t.pumpWidget(harness(block));
await t.pumpAndSettle();
expect(find.text('No blocked users'), findsOneWidget);
expect(find.text('No radio connected'), findsNothing);
});
});
group('per-radio isolation through the pane', () {
testWidgets('a block made on radio A is absent on radio B', (t) async {
final block = BlockService();
await block.loadForDevice('aa' * 16);
await block.block('deadbeef');
await t.pumpWidget(harness(block));
await t.pumpAndSettle();
expect(find.textContaining('deadbeef'), findsOneWidget);
// Switch radios, as the connector does on SELF_INFO.
await block.loadForDevice('bb' * 16);
await t.pumpAndSettle();
expect(
find.textContaining('deadbeef'),
findsNothing,
reason: 'radio A\'s block must not appear while radio B is connected',
);
expect(find.text('No blocked users'), findsOneWidget);
});
testWidgets('switching back restores radio A\'s list', (t) async {
final block = BlockService();
await block.loadForDevice('aa' * 16);
await block.block('deadbeef');
await block.loadForDevice('bb' * 16);
await block.loadForDevice('aa' * 16);
await t.pumpWidget(harness(block));
await t.pumpAndSettle();
expect(
find.textContaining('deadbeef'),
findsOneWidget,
reason: 'isolation is not deletion: A keeps its own list',
);
});
});
group('unblock sticks', () {
testWidgets('an unblock survives a radio switch and back', (t) async {
final block = BlockService();
await block.loadForDevice('aa' * 16);
await block.block('deadbeef');
await block.unblock('deadbeef');
await block.loadForDevice('bb' * 16);
await block.loadForDevice('aa' * 16);
await t.pumpWidget(harness(block));
await t.pumpAndSettle();
expect(
find.textContaining('deadbeef'),
findsNothing,
reason:
'the clear-sticks case from #507: the re-clear that kept '
'recurring was #471, and it must not come back',
);
});
});
}

Powered by TurnKey Linux.