2026-10-21 19:49:18 +02:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
2026-10-21 10:42:55 +02:00
|
|
|
import 'package:clock/clock.dart';
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
|
import 'package:halkyon_app/halkyon_app.dart';
|
|
|
|
|
import 'package:halkyon_app/testing.dart';
|
2026-10-21 19:49:18 +02:00
|
|
|
import 'package:halkyon_ui/halkyon_ui.dart';
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
import 'package:material_ui/material_ui.dart';
|
|
|
|
|
|
|
|
|
|
/// A signed-in person's app as a test makes one: whose it is, and the
|
|
|
|
|
/// account's tiles in the app's own words.
|
|
|
|
|
class const _PersonApp(final SignedIn person) extends StatelessWidget {
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) => MaterialApp(
|
|
|
|
|
localizationsDelegates: testLocalizationsDelegates,
|
|
|
|
|
supportedLocales: HalkyonAppLocalizations.supportedLocales,
|
|
|
|
|
home: Scaffold(
|
|
|
|
|
body: ListView(
|
|
|
|
|
children: [
|
|
|
|
|
Text('App of ${person.authUserId}'),
|
|
|
|
|
const AccountTiles(
|
|
|
|
|
deleteMessage: 'Your notes are deleted everywhere.',
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
late FakeAuthGateway gateway;
|
|
|
|
|
late TestAppDependencies dependencies;
|
|
|
|
|
|
|
|
|
|
Future<void> start(WidgetTester tester, {InstanceChoice? choice}) async {
|
|
|
|
|
dependencies = TestAppDependencies(gateway: gateway);
|
|
|
|
|
final gate = AppScope(
|
|
|
|
|
dependencies: dependencies,
|
|
|
|
|
child: SessionGate(
|
|
|
|
|
look: (context) => (themeMode: ThemeMode.light, locale: null),
|
|
|
|
|
app: _PersonApp.new,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
await tester.pumpWidget(
|
|
|
|
|
AppFrameScope(
|
|
|
|
|
frame: testFrame(),
|
|
|
|
|
child: switch (choice) {
|
|
|
|
|
final choice? => InstanceScope(
|
|
|
|
|
notifier: choice,
|
|
|
|
|
checker: FakeInstanceChecker(),
|
|
|
|
|
countryNames: MemoryCountryNames(const {}),
|
|
|
|
|
subdivisionNames: const MemorySubdivisionNames({}),
|
|
|
|
|
child: gate,
|
|
|
|
|
),
|
|
|
|
|
null => gate,
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setUp(() => gateway = FakeAuthGateway());
|
|
|
|
|
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
testWidgets('says on which instance the account is signed in', (
|
|
|
|
|
tester,
|
|
|
|
|
) async {
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
await start(tester);
|
|
|
|
|
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
expect(find.text('Signed in on test.example.org'), findsOneWidget);
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
expect(
|
|
|
|
|
find.text('Switch account'),
|
|
|
|
|
findsNothing,
|
|
|
|
|
reason: 'no instances to switch among here',
|
|
|
|
|
);
|
|
|
|
|
expect(find.text('Sign out'), findsOneWidget);
|
|
|
|
|
expect(find.text('Delete account'), findsOneWidget);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWidgets('switching account lists the accounts on the device, the '
|
|
|
|
|
'instance in use named', (tester) async {
|
|
|
|
|
final instance = Instance.parse('learn.example.org')!;
|
|
|
|
|
final choice = InstanceChoice(
|
|
|
|
|
MemoryInstanceStore((current: instance, known: [instance])),
|
|
|
|
|
builtIn: instance,
|
|
|
|
|
forget: (instance) async {},
|
2026-10-21 18:15:14 +02:00
|
|
|
sharesStorage: (a, b) => false,
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
);
|
|
|
|
|
await choice.load(usedBefore: false);
|
|
|
|
|
await start(tester, choice: choice);
|
|
|
|
|
|
|
|
|
|
expect(find.text('Switch account'), findsOneWidget);
|
|
|
|
|
expect(find.text('learn.example.org'), findsWidgets);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Switch account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(find.text('Accounts'), findsOneWidget);
|
|
|
|
|
});
|
|
|
|
|
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
testWidgets('signing out asks nothing, deleting nothing', (tester) async {
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
await start(tester);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Sign out'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(find.text('Sign out?'), findsNothing);
|
|
|
|
|
expect(gateway.status, const SignedOut());
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
expect(gateway.accountDeletions, 0);
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWidgets("deleting the account asks first, in the app's words; Cancel "
|
|
|
|
|
'keeps it', (tester) async {
|
|
|
|
|
await start(tester);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
expect(find.text('Delete your account?'), findsOneWidget);
|
|
|
|
|
expect(find.text('Your notes are deleted everywhere.'), findsOneWidget);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Cancel'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
expect(gateway.accountDeletions, 0);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(gateway.accountDeletions, 1);
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
expect(find.text('Start on test.example.org:'), findsOneWidget);
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
});
|
|
|
|
|
|
2026-10-21 18:15:14 +02:00
|
|
|
testWidgets('deleting an identified account while the instance is out of '
|
|
|
|
|
'reach says so, and deletes nothing (the short reading)', (tester) async {
|
|
|
|
|
gateway = FakeAuthGateway(
|
feat(base,app)!: GitHub signs nobody in any more (ADR 0020, D36)
Every account signs in with SimpleLogin or a password now, so GitHub
goes from the module, the shared app package, Learn and Todo, ahead of
ADR 0017's GITHUB_SIGN_IN_ENDS.
- halkyon_base: no `gitHubSignIn` endpoint, GitHub identity provider or
GitHub refusals; no `githubClientId`/`githubClientSecret`, no
`GITHUB_SIGN_IN_ENDS` and no `forgetGitHubAccounts`; the register
loses `account-with-github`. `SignInWays.gitHub`, the basics'
`gitHubClientId` and `gitHubSignInEnds`, and `PasswordRefusal`'s
`signInAgain` and `noAddress` go. A first password takes a code
mailed to the person's own address; an account without one sets none
(`wrongCredentials`).
- Learn's server: `instance.info()` without `gitHubClientId`, the
pruning without GitHub, and `minimumAppBuild` 24, as builds up to 23
(v0.20.0) require `SignInWays.gitHub`: the server deploys with the
release of build 24.
- halkyon_app: no GitHub button or problems on the start screen, no
password offered after a GitHub sign-in, and `ServerpodAuthGateway`
without the browser half only GitHub used (`(client, base:)`). The
account section offers a first password only to an account with an
address. `LoopbackWebAuth` and the apps' schemes stay, SimpleLogin's
ways back.
- Learn's Profile lists no GitHub; the texts go (English, German).
- Serverpod's `serverpod_auth_idp_github_account` stays, as its
migrations make it; a row goes with its account, and ADR 0020's D36
gives operators the SQL to delete those left.
- deploy/: compose.yaml and .env.example without GitHub. The READMEs,
AGENTS.md files and ADR 0017 amended.
BREAKING CHANGE: builds up to 23 can't read the instance's answers
about an account's ways in; minimumAppBuild is 24.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 12:52:52 +01:00
|
|
|
status: const SignedIn(authUserId: 'person-2', isIdentified: true),
|
2026-10-21 18:15:14 +02:00
|
|
|
);
|
|
|
|
|
await start(tester);
|
|
|
|
|
dependencies.passwordGateway.failing = const PasswordFailed(
|
|
|
|
|
PasswordProblem.failed,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
find.text(
|
|
|
|
|
"Couldn't reach the instance. Check the connection and try again.",
|
|
|
|
|
),
|
|
|
|
|
findsOneWidget,
|
|
|
|
|
);
|
|
|
|
|
expect(gateway.accountDeletions, 0);
|
feat(base,app)!: GitHub signs nobody in any more (ADR 0020, D36)
Every account signs in with SimpleLogin or a password now, so GitHub
goes from the module, the shared app package, Learn and Todo, ahead of
ADR 0017's GITHUB_SIGN_IN_ENDS.
- halkyon_base: no `gitHubSignIn` endpoint, GitHub identity provider or
GitHub refusals; no `githubClientId`/`githubClientSecret`, no
`GITHUB_SIGN_IN_ENDS` and no `forgetGitHubAccounts`; the register
loses `account-with-github`. `SignInWays.gitHub`, the basics'
`gitHubClientId` and `gitHubSignInEnds`, and `PasswordRefusal`'s
`signInAgain` and `noAddress` go. A first password takes a code
mailed to the person's own address; an account without one sets none
(`wrongCredentials`).
- Learn's server: `instance.info()` without `gitHubClientId`, the
pruning without GitHub, and `minimumAppBuild` 24, as builds up to 23
(v0.20.0) require `SignInWays.gitHub`: the server deploys with the
release of build 24.
- halkyon_app: no GitHub button or problems on the start screen, no
password offered after a GitHub sign-in, and `ServerpodAuthGateway`
without the browser half only GitHub used (`(client, base:)`). The
account section offers a first password only to an account with an
address. `LoopbackWebAuth` and the apps' schemes stay, SimpleLogin's
ways back.
- Learn's Profile lists no GitHub; the texts go (English, German).
- Serverpod's `serverpod_auth_idp_github_account` stays, as its
migrations make it; a row goes with its account, and ADR 0020's D36
gives operators the SQL to delete those left.
- deploy/: compose.yaml and .env.example without GitHub. The READMEs,
AGENTS.md files and ADR 0017 amended.
BREAKING CHANGE: builds up to 23 can't read the instance's answers
about an account's ways in; minimumAppBuild is 24.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 12:52:52 +01:00
|
|
|
expect(find.text('App of person-2'), findsOneWidget);
|
2026-10-21 18:15:14 +02:00
|
|
|
});
|
|
|
|
|
|
2026-10-20 23:30:22 +02:00
|
|
|
testWidgets('deleting an account whose setup never finished asks for the '
|
|
|
|
|
'password and a code by mail', (tester) async {
|
|
|
|
|
// The first person the fake password gateway makes.
|
|
|
|
|
const person = '00000000-0000-4000-8000-000000000001';
|
|
|
|
|
gateway = FakeAuthGateway(
|
|
|
|
|
status: const SignedIn(authUserId: person, isIdentified: true),
|
|
|
|
|
);
|
|
|
|
|
await start(tester);
|
|
|
|
|
dependencies.passwordGateway.addAccount(
|
|
|
|
|
'anna@example.org',
|
|
|
|
|
password: 'correct horse',
|
|
|
|
|
crypto: dependencies.crypto,
|
|
|
|
|
finished: false,
|
|
|
|
|
);
|
|
|
|
|
dependencies.addresses.addresses[person] = 'anna@example.org';
|
|
|
|
|
Finder field(String label) => find.widgetWithText(TextField, label);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(find.textContaining('a code by mail confirms it'), findsOneWidget);
|
|
|
|
|
await tester.enterText(field('Current password'), 'correct horse');
|
|
|
|
|
await tester.tap(find.text('Email me a code'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
expect(
|
|
|
|
|
dependencies.passwordGateway.mailed.single.purpose,
|
|
|
|
|
MailCodePurpose.deletion,
|
|
|
|
|
);
|
|
|
|
|
expect(find.textContaining('anna@example.org'), findsOneWidget);
|
|
|
|
|
expect(gateway.accountDeletions, 0);
|
|
|
|
|
|
|
|
|
|
await tester.enterText(
|
|
|
|
|
field('Code from the email'),
|
|
|
|
|
dependencies.passwordGateway.codeFor('anna@example.org'),
|
|
|
|
|
);
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(gateway.accountDeletions, 1);
|
|
|
|
|
expect(
|
|
|
|
|
dependencies.passwordGateway.accounts,
|
|
|
|
|
isNot(contains('anna@example.org')),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
2026-10-21 10:42:55 +02:00
|
|
|
testWidgets("deleting an account whose authenticators' reset took effect "
|
|
|
|
|
'asks for a code by mail, as the instance takes it, and for the '
|
|
|
|
|
"address where this device doesn't know it", (tester) async {
|
|
|
|
|
// The first person the fake password gateway makes.
|
|
|
|
|
const person = '00000000-0000-4000-8000-000000000001';
|
|
|
|
|
gateway = FakeAuthGateway(
|
|
|
|
|
status: const SignedIn(authUserId: person, isIdentified: true),
|
|
|
|
|
);
|
|
|
|
|
await start(tester);
|
|
|
|
|
// Its authenticator still confirmed, the reset taken effect but not
|
|
|
|
|
// carried out (the third reading's fourth finding).
|
|
|
|
|
dependencies.passwordGateway
|
|
|
|
|
.addAccount(
|
|
|
|
|
'anna@example.org',
|
|
|
|
|
password: 'correct horse',
|
|
|
|
|
crypto: dependencies.crypto,
|
|
|
|
|
)
|
|
|
|
|
.authenticatorReset = clock.now().subtract(
|
|
|
|
|
const Duration(hours: 1),
|
|
|
|
|
);
|
|
|
|
|
Finder field(String label) => find.widgetWithText(TextField, label);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(find.textContaining('a code by mail confirms it'), findsOneWidget);
|
|
|
|
|
await tester.enterText(field('Current password'), 'correct horse');
|
|
|
|
|
await tester.enterText(field('Email address'), 'anna@example.org');
|
|
|
|
|
await tester.tap(find.text('Email me a code'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
expect(
|
|
|
|
|
dependencies.passwordGateway.mailed.single.purpose,
|
|
|
|
|
MailCodePurpose.deletion,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await tester.enterText(
|
|
|
|
|
field('Code from the email'),
|
|
|
|
|
dependencies.passwordGateway.codeFor('anna@example.org'),
|
|
|
|
|
);
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(gateway.accountDeletions, 1);
|
|
|
|
|
});
|
|
|
|
|
|
2026-10-20 21:59:42 +02:00
|
|
|
testWidgets('deleting an account with a password asks for it and a '
|
|
|
|
|
'code, which a wrong one fails, deleting nothing', (tester) async {
|
|
|
|
|
// The first person the fake password gateway makes.
|
|
|
|
|
const person = '00000000-0000-4000-8000-000000000001';
|
|
|
|
|
gateway = FakeAuthGateway(
|
|
|
|
|
status: const SignedIn(authUserId: person, isIdentified: true),
|
|
|
|
|
);
|
|
|
|
|
await start(tester);
|
|
|
|
|
dependencies.passwordGateway.addAccount(
|
|
|
|
|
'anna@example.org',
|
|
|
|
|
password: 'correct horse',
|
|
|
|
|
crypto: dependencies.crypto,
|
|
|
|
|
);
|
fix(auth): every call with a code after the password takes the address
Whoever guessed codes decided whether the owner was mailed (the re-review's
fourth finding): the address a sign-in sent was optional, so a guesser left
it out and no mail went, and a wait begun without a mail used up the one
mail there was. Every call carrying a code after the password or the phrase
proved (signing in, the phrase's reset, a change of password, a new phrase,
deletion) now takes the account's address and the language of its mails,
and is refused (wrongCredentials, as anything wrong after the password)
before any code is checked when the address isn't the account's; every
wait mails the owner, not only the first. The app sends the address the
person typed, or for changes while signed in the one this device signed in
with, and says so where it doesn't know it (addressUnknown).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 23:08:25 +02:00
|
|
|
// The address this device signed in with, which deleting sends.
|
|
|
|
|
dependencies.addresses.addresses[person] = 'anna@example.org';
|
2026-10-20 21:59:42 +02:00
|
|
|
Finder field(String label) => find.widgetWithText(TextField, label);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(gateway.accountDeletions, 0);
|
|
|
|
|
expect(field('Current password'), findsOneWidget);
|
|
|
|
|
await tester.enterText(field('Current password'), 'wrong horse');
|
|
|
|
|
await tester.enterText(
|
|
|
|
|
field('Code from your authenticator app'),
|
|
|
|
|
fakeTotpCode,
|
|
|
|
|
);
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
expect(
|
|
|
|
|
find.text("The address, the password or the code isn't right."),
|
|
|
|
|
findsOneWidget,
|
|
|
|
|
);
|
|
|
|
|
expect(gateway.accountDeletions, 0);
|
|
|
|
|
expect(dependencies.passwordGateway.accounts, contains('anna@example.org'));
|
|
|
|
|
|
|
|
|
|
await tester.enterText(field('Current password'), 'correct horse');
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(gateway.accountDeletions, 1);
|
|
|
|
|
expect(
|
|
|
|
|
dependencies.passwordGateway.accounts,
|
|
|
|
|
isNot(contains('anna@example.org')),
|
|
|
|
|
);
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
expect(find.text('Start on test.example.org:'), findsOneWidget);
|
2026-10-20 21:59:42 +02:00
|
|
|
});
|
|
|
|
|
|
2026-10-21 19:49:18 +02:00
|
|
|
testWidgets('while the account is deleted, the person stays in their app, '
|
|
|
|
|
'Delete account showing it is under way', (tester) async {
|
|
|
|
|
await start(tester);
|
|
|
|
|
gateway.deletionWaits = Completer();
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
// The spinner never settles while it runs.
|
|
|
|
|
await tester.pump();
|
|
|
|
|
await tester.pump(const Duration(milliseconds: 100));
|
|
|
|
|
|
|
|
|
|
expect(
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
find.text('App of person-1'),
|
2026-10-21 19:49:18 +02:00
|
|
|
findsOneWidget,
|
|
|
|
|
reason: 'never the launch screen in between',
|
|
|
|
|
);
|
|
|
|
|
expect(
|
|
|
|
|
find.descendant(
|
|
|
|
|
of: find.widgetWithText(ListTile, 'Delete account'),
|
|
|
|
|
matching: find.byType(ButtonLoadingIndicator),
|
|
|
|
|
),
|
|
|
|
|
findsOneWidget,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
gateway.deletionWaits!.complete();
|
|
|
|
|
await tester.pumpAndSettle();
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
expect(find.text('Start on test.example.org:'), findsOneWidget);
|
2026-10-21 19:49:18 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWidgets('a deletion the instance never got keeps the person in their '
|
|
|
|
|
'app, and says so once', (tester) async {
|
|
|
|
|
await start(tester);
|
|
|
|
|
gateway.deletionError = Exception('No connection');
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Delete account'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
await tester.tap(find.text('Delete account').last);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
find.text(
|
|
|
|
|
"Couldn't delete your account: the instance wasn't reached. "
|
|
|
|
|
'Try again.',
|
|
|
|
|
),
|
|
|
|
|
findsOneWidget,
|
|
|
|
|
);
|
feat(app)!: no anonymous accounts on the device (ADR 0020, D4, D25)
Every account has a way in, so the apps make no anonymous account any
more. The start screen shows whenever nobody is signed in, a first
start included, and offers SimpleLogin, a password and GitHub for those
who have it, with no start without an account. An instance out of reach
is said so, with Try again, and one offering no way to create an account
too. An anonymous account's session left from before is deleted as the
app starts (D25), falling back to signing out on the device.
What only anonymous accounts needed goes: signing in anonymously, the
signed-out mark, adding GitHub to an account and switching to a GitHub
account from the Profile tab (with its Cancel, the only one), an
anonymous device's own keys, the warning that signing out deletes the
account, and the texts about keeping progress. Settings says on which
instance the account is signed in. Learn's publishing, reports and
suggestions and its learner count no longer ask whether the person has
an identity: everyone signed in has one.
The server still offers anonymous sign-in until the next commit, so
older apps keep working until v0.20.0 raises the minimum build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 14:50:55 +02:00
|
|
|
expect(find.text('App of person-1'), findsOneWidget);
|
2026-10-21 19:49:18 +02:00
|
|
|
expect(gateway.status, isA<SignedIn>());
|
|
|
|
|
expect(find.byType(ButtonLoadingIndicator), findsNothing);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWidgets("a sign-out the device's storage failed keeps the person in "
|
|
|
|
|
'their app, and says so', (tester) async {
|
|
|
|
|
gateway = FakeAuthGateway(
|
feat(base,app)!: GitHub signs nobody in any more (ADR 0020, D36)
Every account signs in with SimpleLogin or a password now, so GitHub
goes from the module, the shared app package, Learn and Todo, ahead of
ADR 0017's GITHUB_SIGN_IN_ENDS.
- halkyon_base: no `gitHubSignIn` endpoint, GitHub identity provider or
GitHub refusals; no `githubClientId`/`githubClientSecret`, no
`GITHUB_SIGN_IN_ENDS` and no `forgetGitHubAccounts`; the register
loses `account-with-github`. `SignInWays.gitHub`, the basics'
`gitHubClientId` and `gitHubSignInEnds`, and `PasswordRefusal`'s
`signInAgain` and `noAddress` go. A first password takes a code
mailed to the person's own address; an account without one sets none
(`wrongCredentials`).
- Learn's server: `instance.info()` without `gitHubClientId`, the
pruning without GitHub, and `minimumAppBuild` 24, as builds up to 23
(v0.20.0) require `SignInWays.gitHub`: the server deploys with the
release of build 24.
- halkyon_app: no GitHub button or problems on the start screen, no
password offered after a GitHub sign-in, and `ServerpodAuthGateway`
without the browser half only GitHub used (`(client, base:)`). The
account section offers a first password only to an account with an
address. `LoopbackWebAuth` and the apps' schemes stay, SimpleLogin's
ways back.
- Learn's Profile lists no GitHub; the texts go (English, German).
- Serverpod's `serverpod_auth_idp_github_account` stays, as its
migrations make it; a row goes with its account, and ADR 0020's D36
gives operators the SQL to delete those left.
- deploy/: compose.yaml and .env.example without GitHub. The READMEs,
AGENTS.md files and ADR 0017 amended.
BREAKING CHANGE: builds up to 23 can't read the instance's answers
about an account's ways in; minimumAppBuild is 24.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 12:52:52 +01:00
|
|
|
status: const SignedIn(authUserId: 'person-2', isIdentified: true),
|
2026-10-21 19:49:18 +02:00
|
|
|
)..signOutError = Exception('The keyring is locked');
|
|
|
|
|
await start(tester);
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Sign out'));
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
find.text("Couldn't sign out on this device. Try again."),
|
|
|
|
|
findsOneWidget,
|
|
|
|
|
);
|
feat(base,app)!: GitHub signs nobody in any more (ADR 0020, D36)
Every account signs in with SimpleLogin or a password now, so GitHub
goes from the module, the shared app package, Learn and Todo, ahead of
ADR 0017's GITHUB_SIGN_IN_ENDS.
- halkyon_base: no `gitHubSignIn` endpoint, GitHub identity provider or
GitHub refusals; no `githubClientId`/`githubClientSecret`, no
`GITHUB_SIGN_IN_ENDS` and no `forgetGitHubAccounts`; the register
loses `account-with-github`. `SignInWays.gitHub`, the basics'
`gitHubClientId` and `gitHubSignInEnds`, and `PasswordRefusal`'s
`signInAgain` and `noAddress` go. A first password takes a code
mailed to the person's own address; an account without one sets none
(`wrongCredentials`).
- Learn's server: `instance.info()` without `gitHubClientId`, the
pruning without GitHub, and `minimumAppBuild` 24, as builds up to 23
(v0.20.0) require `SignInWays.gitHub`: the server deploys with the
release of build 24.
- halkyon_app: no GitHub button or problems on the start screen, no
password offered after a GitHub sign-in, and `ServerpodAuthGateway`
without the browser half only GitHub used (`(client, base:)`). The
account section offers a first password only to an account with an
address. `LoopbackWebAuth` and the apps' schemes stay, SimpleLogin's
ways back.
- Learn's Profile lists no GitHub; the texts go (English, German).
- Serverpod's `serverpod_auth_idp_github_account` stays, as its
migrations make it; a row goes with its account, and ADR 0020's D36
gives operators the SQL to delete those left.
- deploy/: compose.yaml and .env.example without GitHub. The READMEs,
AGENTS.md files and ADR 0017 amended.
BREAKING CHANGE: builds up to 23 can't read the instance's answers
about an account's ways in; minimumAppBuild is 24.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 12:52:52 +01:00
|
|
|
expect(find.text('App of person-2'), findsOneWidget);
|
2026-10-21 19:49:18 +02:00
|
|
|
});
|
|
|
|
|
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
testWidgets('speaks German', (tester) async {
|
|
|
|
|
await start(tester);
|
|
|
|
|
final german = lookupHalkyonAppLocalizations(const Locale('de'));
|
|
|
|
|
|
|
|
|
|
expect(german.accountSignedInOn('x'), 'Angemeldet auf x');
|
|
|
|
|
expect(german.accountSwitch, 'Konto wechseln');
|
|
|
|
|
expect(german.accountSignOut, 'Abmelden');
|
|
|
|
|
expect(german.accountDelete, 'Konto löschen');
|
|
|
|
|
expect(german.accountDeleteTitle, 'Dein Konto löschen?');
|
2026-10-21 19:49:18 +02:00
|
|
|
expect(
|
|
|
|
|
german.accountSignOutFailed,
|
|
|
|
|
'Abmelden auf diesem Gerät hat nicht geklappt. Versuch es noch einmal.',
|
|
|
|
|
);
|
|
|
|
|
expect(
|
|
|
|
|
german.accountDeleteFailed,
|
|
|
|
|
'Dein Konto wurde nicht gelöscht: Die Instanz war nicht erreichbar. '
|
|
|
|
|
'Versuch es noch einmal.',
|
|
|
|
|
);
|
refactor(halkyon_app): the account section, About, the language and countries' names, shared
What Learn and Todo each held now comes from halkyon_app:
- AccountTiles: whose account on which instance, switching, signing
out (asking first for an anonymous account, as it deletes it) and
deleting it (asking first), the app's own words passed in.
- showAppAbout: the app's name, version, icon and legalese as it gives
them, the source of what the instance runs (AppDependencies gains
sourceCodeUrl), the app's own parts, the licence list.
- resolveAppLocale: the first preferred language the app speaks, never
by country alone, British English otherwise.
- AssetCountryNames, the default of InstanceGate and InstanceScope:
Unicode CLDR 48.2's territory names in English and German
(tool/country_names.py, 7.6 KB), Hong Kong, Macao, Myanmar and
Palestine by their short names as Learn's world map has them, so
Todo says "Germany (EU)" where it said "DE (EU)".
Learn's texts read as before in every language; its About bloc and
gateway, its country names from the world map and the keys only the
moved code used are gone, as are Todo's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-19 23:51:52 +02:00
|
|
|
});
|
|
|
|
|
}
|