mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-11-11 19:54:00 +01:00
Text-free sync settings via ssui 0.7.0
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Bump sync_settings_ui 0.7.0 and github_device_auth 0.4.0 (glyph + spoken label). Guard covers the Sync settings screen; degraded sync gets its own warning glyph; tooltip delegate and copy button tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
edf6969949
commit
203e61d6ac
@ -115,7 +115,7 @@ extension _CaptureSyncBehaviour on _CaptureScreenState {
|
||||
final (icon, error) = !outcome.ok
|
||||
? (Icons.sync_problem, true)
|
||||
: outcome.degraded
|
||||
? (Icons.cloud_off, true)
|
||||
? (Icons.warning_amber, true)
|
||||
: (Icons.cloud_done, false);
|
||||
showCue(context, icon, spoken, error: error);
|
||||
}
|
||||
|
||||
12
pubspec.lock
12
pubspec.lock
@ -399,11 +399,11 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: github_device_auth
|
||||
ref: "github_device_auth-v0.3.2"
|
||||
resolved-ref: "4ccaba1bb3e495ef72d70c6a7e7d7ec98d755792"
|
||||
ref: "github_device_auth-v0.4.0"
|
||||
resolved-ref: "3084080d744c348a217727e26a6be838e7d5a4ff"
|
||||
url: "https://github.com/kuhyx/utils"
|
||||
source: git
|
||||
version: "0.3.2"
|
||||
version: "0.4.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1006,11 +1006,11 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: sync_settings_ui
|
||||
ref: "sync_settings_ui-v0.6.3"
|
||||
resolved-ref: eef7af4c86837ee82891493587ff3456297e5dea
|
||||
ref: "sync_settings_ui-v0.7.0"
|
||||
resolved-ref: "3084080d744c348a217727e26a6be838e7d5a4ff"
|
||||
url: "https://github.com/kuhyx/utils"
|
||||
source: git
|
||||
version: "0.6.3"
|
||||
version: "0.7.0"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.0.76+1
|
||||
version: 1.0.77+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.12.2
|
||||
@ -59,7 +59,7 @@ dependencies:
|
||||
github_device_auth:
|
||||
git:
|
||||
url: https://github.com/kuhyx/utils
|
||||
ref: github_device_auth-v0.3.2
|
||||
ref: github_device_auth-v0.4.0
|
||||
path: github_device_auth
|
||||
# One-tap Google ID token via the framework AccountManager chooser (FOSS,
|
||||
# no Play Services sign-in SDK). Used by the sync backend in lib/sync/.
|
||||
@ -97,7 +97,7 @@ dependencies:
|
||||
sync_settings_ui:
|
||||
git:
|
||||
url: https://github.com/kuhyx/utils
|
||||
ref: sync_settings_ui-v0.6.3
|
||||
ref: sync_settings_ui-v0.7.0
|
||||
path: sync_settings_ui
|
||||
url_launcher: 6.3.3
|
||||
uuid: 4.6.0
|
||||
|
||||
@ -203,7 +203,8 @@ void main() {
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 1)); // _delay(0) fires
|
||||
await tester.pump(); // token error throws → _error set
|
||||
expect(find.textContaining('nope'), findsOneWidget); // error rendered
|
||||
await tester.pump(const Duration(milliseconds: 300)); // dialog faded in
|
||||
expect(spoken('nope'), findsOneWidget); // error rendered (spoken glyph)
|
||||
|
||||
// Tap the "open on GitHub" action: copies the code and launches the URL.
|
||||
// _openPage awaits Clipboard.setData then the launcher's supportsMode +
|
||||
@ -213,7 +214,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(launcher.launched, 'https://github.com/login/device');
|
||||
|
||||
await tester.tap(find.text('Cancel'));
|
||||
await tester.tap(find.bySemanticsLabel('Cancel'));
|
||||
await tester.pumpAndSettle(); // finish the dialog pop animation
|
||||
expect(find.text('WXYZ-1234'), findsNothing); // dialog dismissed
|
||||
});
|
||||
|
||||
@ -24,6 +24,7 @@ import 'fake_note_repository.dart';
|
||||
import 'fake_secure_storage.dart';
|
||||
|
||||
import 'settings_screen_harness.dart';
|
||||
import 'text_free_guard.dart';
|
||||
|
||||
/// Stub file picker that returns a fixed in-memory file (no disk I/O, so the
|
||||
/// `_import` flow stays timer-free and deterministic under the widget tester).
|
||||
@ -101,7 +102,7 @@ void main() {
|
||||
|
||||
// _export does real file I/O on desktop, so drive it under runAsync.
|
||||
await tester.runAsync(() async {
|
||||
await tester.tap(find.text('Export notes'));
|
||||
await tester.tap(find.bySemanticsLabel('Export notes'));
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
});
|
||||
await tester.pump();
|
||||
@ -120,12 +121,12 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.runAsync(() async {
|
||||
await tester.tap(find.text('Export notes'));
|
||||
await tester.tap(find.bySemanticsLabel('Export notes'));
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
});
|
||||
await tester.pump();
|
||||
|
||||
expect(find.textContaining('Export failed'), findsOneWidget);
|
||||
expect(spoken('Export failed'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Import notes reads the picked file and merges', (
|
||||
@ -152,7 +153,7 @@ void main() {
|
||||
await tester.tap(find.byIcon(Icons.sync));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('Import notes'));
|
||||
await tester.tap(find.bySemanticsLabel('Import notes'));
|
||||
await tester.pump(); // openFile resolves (in-memory)
|
||||
await tester.pump(); // read + parse + merge + setState
|
||||
|
||||
@ -168,7 +169,7 @@ void main() {
|
||||
await tester.tap(find.byIcon(Icons.sync));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('Import notes'));
|
||||
await tester.tap(find.bySemanticsLabel('Import notes'));
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
|
||||
@ -186,11 +187,11 @@ void main() {
|
||||
await tester.tap(find.byIcon(Icons.sync));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('Import notes'));
|
||||
await tester.tap(find.bySemanticsLabel('Import notes'));
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
|
||||
expect(find.textContaining('Import failed'), findsOneWidget);
|
||||
expect(spoken('Import failed'), findsOneWidget);
|
||||
expect(await repo.listNotes(), isEmpty);
|
||||
});
|
||||
});
|
||||
|
||||
@ -26,6 +26,7 @@ import 'package:todo/sync/notes_markdown.dart';
|
||||
import 'package:todo/sync/sync_settings.dart';
|
||||
import 'package:todo/ui/github_mirror_screen.dart';
|
||||
import 'package:todo/ui/settings_screen.dart';
|
||||
import 'package:todo/ui/text_free_localizations.dart';
|
||||
|
||||
import 'fake_note_repository.dart';
|
||||
import 'fake_secure_storage.dart';
|
||||
@ -93,6 +94,8 @@ Future<FakeNoteRepository> pumpSettings(
|
||||
addTearDown(repo.close);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
// As in main.dart: Material's own button tooltips are blanked.
|
||||
localizationsDelegates: kTextFreeLocalizations,
|
||||
home: SettingsScreen(
|
||||
initial: initial,
|
||||
repository: repo,
|
||||
|
||||
30
test/text_free_localizations_test.dart
Normal file
30
test/text_free_localizations_test.dart
Normal file
@ -0,0 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:todo/ui/text_free_localizations.dart';
|
||||
|
||||
void main() {
|
||||
test('every button tooltip is blank', () {
|
||||
const l = TextFreeMaterialLocalizations();
|
||||
expect([
|
||||
l.backButtonTooltip,
|
||||
l.closeButtonTooltip,
|
||||
l.openAppDrawerTooltip,
|
||||
l.showMenuTooltip,
|
||||
l.moreButtonTooltip,
|
||||
l.deleteButtonTooltip,
|
||||
], everyElement(isEmpty));
|
||||
// Everything else is still the default English.
|
||||
expect(l.okButtonLabel, const DefaultMaterialLocalizations().okButtonLabel);
|
||||
});
|
||||
|
||||
test('the delegate loads them for English only, once', () async {
|
||||
final delegate = kTextFreeLocalizations.single;
|
||||
expect(delegate.isSupported(const Locale('en')), isTrue);
|
||||
expect(delegate.isSupported(const Locale('pl')), isFalse);
|
||||
expect(
|
||||
await delegate.load(const Locale('en')),
|
||||
isA<TextFreeMaterialLocalizations>(),
|
||||
);
|
||||
expect(delegate.shouldReload(delegate), isFalse);
|
||||
});
|
||||
}
|
||||
@ -83,6 +83,14 @@ void main() {
|
||||
expectNoChromeWords(t);
|
||||
});
|
||||
|
||||
testWidgets('sync settings paint no words', (t) async {
|
||||
await pumpSettings(t);
|
||||
await t.tap(find.bySemanticsLabel('Sync settings: Firebase'));
|
||||
await _frames(t);
|
||||
await _frames(t);
|
||||
expectNoChromeWords(t);
|
||||
});
|
||||
|
||||
testWidgets('GitHub sync and its test result paint no words', (t) async {
|
||||
await pumpMirror(
|
||||
t,
|
||||
|
||||
@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
@ -121,6 +122,24 @@ void main() {
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.bySemanticsLabel('Copy: $kAddLoginCommand'), findsOneWidget);
|
||||
|
||||
// The command is copied, not painted: the button puts it on the
|
||||
// clipboard (stubbed channel; the test host has no clipboard plugin).
|
||||
final copied = <Object?>[];
|
||||
final messenger =
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger;
|
||||
messenger.setMockMethodCallHandler(SystemChannels.platform, (call) async {
|
||||
if (call.method == 'Clipboard.setData') copied.add(call.arguments);
|
||||
return null;
|
||||
});
|
||||
addTearDown(
|
||||
() => messenger.setMockMethodCallHandler(SystemChannels.platform, null),
|
||||
);
|
||||
await tester.tap(find.bySemanticsLabel('Copy: $kAddLoginCommand'));
|
||||
await tester.pump();
|
||||
expect(copied, [
|
||||
{'text': kAddLoginCommand},
|
||||
]);
|
||||
});
|
||||
|
||||
testWidgets('closing the screen mid-test is harmless', (tester) async {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user