Under the wordmark on a cobalt wash, two tiles as Proton's account page shows its services: the build's instance, chosen in one tap, and another, which unfolds the address to type. A ring from cobalt to copper, a glow and a tagline come in under the pointer, on the keyboard's focus, while pressed or open; without a mouse the taglines always show. The launch screen's "Halkyon" over "Learn" becomes BrandWordmark, which both show. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
158 lines
5.3 KiB
Dart
158 lines
5.3 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
||
import 'package:halkyon_learn_flutter/src/app/instance_gate.dart';
|
||
import 'package:halkyon_learn_flutter/src/app/person_app.dart';
|
||
import 'package:halkyon_learn_flutter/src/core/instance/instance.dart';
|
||
import 'package:halkyon_learn_flutter/src/core/instance/instance_choice.dart';
|
||
import 'package:halkyon_learn_flutter/src/feature/auth/widget/session_gate.dart';
|
||
import 'package:halkyon_learn_flutter/src/feature/settings/widget/settings_screen.dart';
|
||
import 'package:material_ui/material_ui.dart';
|
||
|
||
import '../support/fake_instance_checker.dart';
|
||
import '../support/memory_device_settings_store.dart';
|
||
import '../support/memory_instance_store.dart';
|
||
import '../support/pump_app.dart';
|
||
import '../support/test_dependencies.dart';
|
||
|
||
void main() {
|
||
final builtIn = Instance.parse('learn.halkyon.eu')!;
|
||
final other = Instance.parse('learn.example.org')!;
|
||
late MemoryInstanceStore store;
|
||
late List<Instance> opened;
|
||
late List<Instance> forgotten;
|
||
|
||
setUp(() {
|
||
store = MemoryInstanceStore();
|
||
opened = [];
|
||
forgotten = [];
|
||
});
|
||
|
||
/// Starts the app on a device that [usedBefore] the choice existed, with
|
||
/// [answering] instances answering a check.
|
||
Future<InstanceChoice> start(
|
||
WidgetTester tester, {
|
||
bool usedBefore = false,
|
||
Set<Instance> answering = const {},
|
||
}) async {
|
||
tester.view.physicalSize = const Size(412, 900);
|
||
tester.view.devicePixelRatio = 1;
|
||
addTearDown(tester.view.reset);
|
||
final choice = InstanceChoice(
|
||
store,
|
||
builtIn: builtIn,
|
||
forget: (instance) async => forgotten.add(instance),
|
||
);
|
||
await choice.load(usedBefore: usedBefore);
|
||
await tester.pumpWidget(
|
||
InstanceGate(
|
||
choice: choice,
|
||
checker: FakeInstanceChecker(answering),
|
||
deviceSettings: MemoryDeviceSettingsStore(),
|
||
open: (instance) async {
|
||
opened.add(instance);
|
||
return testDependencies();
|
||
},
|
||
app: SessionGate(app: (person) => PersonApp(person: person)),
|
||
),
|
||
);
|
||
await tester.pumpAndSettle();
|
||
return choice;
|
||
}
|
||
|
||
/// Opens Settings › Switch account, further down Settings.
|
||
Future<void> openSwitcher(WidgetTester tester) async {
|
||
await openTab(tester, 'Profile');
|
||
await tester.tap(find.byTooltip('Settings'));
|
||
await tester.pumpAndSettle();
|
||
await tester.scrollUntilVisible(
|
||
find.text('Switch account'),
|
||
200,
|
||
// Settings' list; its citation preview is a scroll view of its own.
|
||
scrollable: find
|
||
.descendant(
|
||
of: find.byType(SettingsScreen),
|
||
matching: find.byType(Scrollable),
|
||
)
|
||
.first,
|
||
);
|
||
// Built, but perhaps still below the window's edge.
|
||
await tester.ensureVisible(find.text('Switch account'));
|
||
await tester.pumpAndSettle();
|
||
await tester.tap(find.text('Switch account'));
|
||
await tester.pumpAndSettle();
|
||
}
|
||
|
||
testWidgets('a new install asks for the instance first, and opens the '
|
||
"build's in one tap", (tester) async {
|
||
await start(tester);
|
||
|
||
// The wordmark says it to screen readers.
|
||
expect(find.bySemanticsLabel('Welcome to Halkyon Learn'), findsOneWidget);
|
||
expect(opened, isEmpty, reason: 'nothing made anywhere yet');
|
||
expect(find.byType(TextField), findsNothing, reason: 'no address asked');
|
||
|
||
await tester.tap(find.text('learn.halkyon.eu'));
|
||
await tester.pumpAndSettle();
|
||
|
||
expect(opened, [builtIn]);
|
||
expect(tab('Home'), findsOneWidget);
|
||
});
|
||
|
||
testWidgets('another instance is checked before the app moves there', (
|
||
tester,
|
||
) async {
|
||
await start(tester, answering: {other});
|
||
|
||
await tester.tap(find.text('Another instance'));
|
||
await tester.pumpAndSettle();
|
||
expect(
|
||
FocusManager.instance.primaryFocus?.context
|
||
?.findAncestorWidgetOfExactType<TextField>(),
|
||
isNotNull,
|
||
reason: 'the address is typed at once',
|
||
);
|
||
|
||
await tester.enterText(find.byType(TextField), 'nowhere.example.org');
|
||
await tester.tap(find.text('Continue'));
|
||
await tester.pumpAndSettle();
|
||
expect(
|
||
find.text(
|
||
'No instance of Halkyon Learn answers at nowhere.example.org.',
|
||
),
|
||
findsOneWidget,
|
||
);
|
||
expect(opened, isEmpty);
|
||
|
||
await tester.enterText(find.byType(TextField), 'learn.example.org');
|
||
await tester.tap(find.text('Continue'));
|
||
await tester.pumpAndSettle();
|
||
expect(opened, [other]);
|
||
});
|
||
|
||
testWidgets('an install from before goes on without asking', (tester) async {
|
||
await start(tester, usedBefore: true);
|
||
|
||
expect(opened, [builtIn]);
|
||
expect(tab('Home'), findsOneWidget);
|
||
});
|
||
|
||
testWidgets('Settings switches between the accounts on the device, and '
|
||
'removes one not in use', (tester) async {
|
||
store = MemoryInstanceStore((current: builtIn, known: [builtIn, other]));
|
||
await start(tester);
|
||
await openSwitcher(tester);
|
||
expect(find.text('learn.halkyon.eu'), findsWidgets);
|
||
await tester.tap(find.text('learn.example.org'));
|
||
await tester.pumpAndSettle();
|
||
expect(opened, [builtIn, other]);
|
||
expect(tab('Home'), findsOneWidget, reason: 'a new app, on Home');
|
||
|
||
await openSwitcher(tester);
|
||
await tester.tap(find.byTooltip('Remove account'));
|
||
await tester.pumpAndSettle();
|
||
await tester.tap(find.widgetWithText(FilledButton, 'Remove'));
|
||
await tester.pumpAndSettle();
|
||
|
||
expect(forgotten, [builtIn]);
|
||
expect(store.kept?.known, [other]);
|
||
});
|
||
}
|