test(app): wait for what a timer brings, not a fixed time
All checks were successful
CI / check (push) Successful in 30m8s
CI / deploy (push) Has been skipped

CI failed on d5651c5b (run 165): the path editor's test waited 60 ms
for a save its 20 ms pause sets off, and on the runner, its CPU capped,
the timer had not fired yet. The code was the same that had passed on
the laptop.

- The path editor's test waits until the bloc has saved what was typed,
  as the step editor's test does.
- The study session's test waits until the deletion held through the
  session has gone, and the Linux Pomodoro platform's tests until the
  alert, the registration and the suggestion have come over D-Bus,
  through `eventually` (test/support), each where a fixed wait stood.
- Waits before checking that nothing happened stay as they are: a slow
  machine can only make those pass more easily.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-24 20:31:10 +02:00
commit 904b2e41b2
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
3 changed files with 17 additions and 14 deletions

View file

@ -92,16 +92,16 @@ void main() {
..add(const PathEditorEventTitleChanged('Particles '))
..add(const PathEditorEventSecondaryTitleChanged('助詞'))
..add(PathEditorEventDescriptionChanged(RichContent.plain('は and が')));
await Future<void>.delayed(const Duration(milliseconds: 60));
expect(
await stored(),
LearningPathContent(
final typed = LearningPathContent(
title: 'Particles',
secondaryTitle: '助詞',
description: RichContent.plain('は and が'),
),
);
// Waits for the save rather than a fixed time: on a busy machine the
// pause's timer fires late (CI, 24 Oct 2026, after 60 ms).
await until((s) => s.saved == typed);
expect(await stored(), typed);
});
test('closing saves what is unsaved; a blank title is never saved', () async {

View file

@ -12,6 +12,8 @@ import 'package:halkyon_learn_flutter/src/feature/pomodoro/widget/pomodoro_texts
import 'package:intl/date_symbol_data_local.dart';
import 'package:material_ui/material_ui.dart';
import '../../../support/eventually.dart';
/// A notification server, as GNOME's, noting what it was asked.
class _Notifications() extends DBusObject {
this : super(DBusObjectPath('/org/freedesktop/Notifications'));
@ -162,7 +164,7 @@ void main() {
);
await platform.show(notice(run));
await Future<void>.delayed(const Duration(milliseconds: 600));
await eventually(() => notifications.notified.isNotEmpty);
final alert = notifications.notified.single;
expect((alert[3] as DBusString).value, 'Time for a break');
@ -264,7 +266,7 @@ void main() {
await shell.close();
(watcher, shell) = await startWatcher();
await Future<void>.delayed(const Duration(milliseconds: 200));
await eventually(() => watcher.registered.isNotEmpty);
expect(watcher.registered, hasLength(1));
});
@ -287,11 +289,11 @@ void main() {
final suggestions = <bool>[];
final subscription = platform.suggestsTopBar.listen(suggestions.add);
addTearDown(subscription.cancel);
await Future<void>.delayed(const Duration(milliseconds: 100));
await eventually(() => suggestions.isNotEmpty);
expect(suggestions, [true]);
await platform.dismissTopBarSuggestion();
await Future<void>.delayed(const Duration(milliseconds: 100));
await eventually(() => suggestions.length > 1);
expect(suggestions, [true, false]);
expect(await newPlatform().suggestsTopBar.first, isFalse);
});

View file

@ -22,6 +22,7 @@ import 'package:halkyon_learn_flutter/src/feature/studyset/model/exam_plan.dart'
import 'package:halkyon_learn_flutter/src/feature/studyset/model/studyset_content.dart';
import 'package:halkyon_learn_flutter/src/feature/tag/data/tag_repository.dart';
import '../../../support/eventually.dart';
import '../../../support/fake_card_gateway.dart';
import '../../../support/fake_learning_path_gateway.dart';
import '../../../support/fake_review_gateway.dart';
@ -207,7 +208,7 @@ void main() {
await bloc.close();
});
await Future<void>.delayed(const Duration(milliseconds: 50));
await eventually(() => deletions.pending.isEmpty);
expect(
(await cards.cardsOf('japanese')).map((each) => each.content.front),