test(app): nothing of one person reaches the next
Two guarantees of step 7 had no test. An open studyset closes when the person changes (here: the server revokes the session, and the app starts anew with another anonymous person), and the next person sees none of it. PersonScope shows the person's app once their data is open, says so when it can't be opened and then leaves no unhandled error behind (checked by removing the handler: the test fails), and closes the person's data when it goes away. testDependencies takes an optional openPerson for this, and the fake auth gateway can revoke the session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
b85485352c
commit
3fc51057f1
4 changed files with 112 additions and 12 deletions
|
|
@ -0,0 +1,71 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/dependencies/dependencies_scope.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/dependencies/person_dependencies.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/dependencies/person_scope.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/auth/model/auth_status.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/studyset/data/studyset_repository.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
import '../../support/fake_studyset_gateway.dart';
|
||||
import '../../support/test_dependencies.dart';
|
||||
|
||||
void main() {
|
||||
const person = SignedIn(authUserId: 'anonymous-1', isIdentified: false);
|
||||
|
||||
Future<void> showScope(
|
||||
WidgetTester tester,
|
||||
Future<PersonDependencies> Function() open,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
DependenciesScope(
|
||||
dependencies: testDependencies(openPerson: (_) => open()),
|
||||
child: const MaterialApp(
|
||||
home: PersonScope(person: person, child: Text('Home')),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
testWidgets("shows the person's app once their data is open", (
|
||||
tester,
|
||||
) async {
|
||||
await showScope(
|
||||
tester,
|
||||
() async => PersonDependencies(
|
||||
studysets: StudysetRepository(FakeStudysetGateway()),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Home'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets("says so when the person's data can't be opened", (
|
||||
tester,
|
||||
) async {
|
||||
await showScope(tester, () async => throw Exception('Disk full'));
|
||||
|
||||
expect(find.text("Couldn't open this device's data."), findsOneWidget);
|
||||
expect(find.text('Home'), findsNothing);
|
||||
|
||||
// Nothing was opened, so going away closes nothing and fails nothing.
|
||||
await tester.pumpWidget(const SizedBox());
|
||||
await tester.pump();
|
||||
});
|
||||
|
||||
testWidgets("closes the person's data when it goes away", (tester) async {
|
||||
var closed = false;
|
||||
await showScope(
|
||||
tester,
|
||||
() async => PersonDependencies(
|
||||
studysets: StudysetRepository(FakeStudysetGateway()),
|
||||
onDispose: () async => closed = true,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(const SizedBox());
|
||||
await tester.pump();
|
||||
|
||||
expect(closed, isTrue);
|
||||
});
|
||||
}
|
||||
|
|
@ -2,22 +2,28 @@ import 'package:flutter_test/flutter_test.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/dependencies/dependencies_scope.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/auth/widget/session_gate.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/studyset/widget/studyset_list_screen.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/studyset/widget/studyset_screen.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
import '../../../support/fake_auth_gateway.dart';
|
||||
import '../../../support/fake_studyset_gateway.dart';
|
||||
import '../../../support/test_dependencies.dart';
|
||||
|
||||
void main() {
|
||||
late FakeStudysetGateway gateway;
|
||||
|
||||
Future<void> showApp(WidgetTester tester) async {
|
||||
/// Shows the app; every person shares [gateway] unless [auth] is given, in
|
||||
/// which case each person gets data of their own.
|
||||
Future<void> showApp(WidgetTester tester, {FakeAuthGateway? auth}) async {
|
||||
tester.view.physicalSize = const Size(1200, 1600);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.reset);
|
||||
|
||||
await tester.pumpWidget(
|
||||
DependenciesScope(
|
||||
dependencies: testDependencies(studysetGateway: gateway),
|
||||
dependencies: auth == null
|
||||
? testDependencies(studysetGateway: gateway)
|
||||
: testDependencies(authGateway: auth),
|
||||
child: const MaterialApp(
|
||||
home: SessionGate(child: StudysetListScreen()),
|
||||
),
|
||||
|
|
@ -99,6 +105,22 @@ void main() {
|
|||
expect(gateway.deleted, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets('an open studyset closes when the person changes, and the next '
|
||||
'person sees none of it', (tester) async {
|
||||
final auth = FakeAuthGateway();
|
||||
await showApp(tester, auth: auth);
|
||||
await create(tester, 'Japanese');
|
||||
await open(tester, 'Japanese');
|
||||
expect(find.byType(StudysetScreen), findsOneWidget);
|
||||
|
||||
auth.revokeSession();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(StudysetScreen), findsNothing);
|
||||
expect(find.text('Japanese'), findsNothing);
|
||||
expect(find.text('No studysets yet.'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('a confirmed delete removes the studyset and closes it', (
|
||||
tester,
|
||||
) async {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ class FakeAuthGateway({var AuthStatus _status = const SignedOut()})
|
|||
_set(const SignedOut());
|
||||
}
|
||||
|
||||
/// Ends the session as when the server revokes this device's session.
|
||||
void revokeSession() => _set(const SignedOut());
|
||||
|
||||
void _set(AuthStatus status) {
|
||||
_status = status;
|
||||
_changes.add(status);
|
||||
|
|
|
|||
|
|
@ -11,13 +11,17 @@ import 'fake_studyset_gateway.dart';
|
|||
/// The app's dependencies with fakes instead of the server and the device's
|
||||
/// database; each test passes in only the fakes it looks at.
|
||||
///
|
||||
/// Every person gets [studysetGateway] (or a fresh fake of their own).
|
||||
/// Every person gets [studysetGateway] (or a fresh fake of their own), unless
|
||||
/// [openPerson] replaces how a person's dependencies are opened.
|
||||
Dependencies testDependencies({
|
||||
AuthGateway? authGateway,
|
||||
StudysetGateway? studysetGateway,
|
||||
OpenPerson? openPerson,
|
||||
}) => Dependencies(
|
||||
auth: AuthRepository(authGateway ?? FakeAuthGateway()),
|
||||
openPerson: (person) async {
|
||||
openPerson:
|
||||
openPerson ??
|
||||
(person) async {
|
||||
final studysets = StudysetRepository(
|
||||
studysetGateway ?? FakeStudysetGateway(),
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue