test: fix tests steps implement

This commit is contained in:
insleker 2025-09-01 10:20:57 +08:00
parent ad37861303
commit eb19022572
7 changed files with 50 additions and 14 deletions

View File

@ -1,4 +1,5 @@
# Non-Functional Requirements
* Package structure
* plz follow official [Package structure](https://docs.flutter.dev/app-architecture/case-study#package-structure) with a slight modification, put each `<FEATURE NAME>/`s in `features/` sub-directory under `ui/`.
* support multiple platforms (windows, linux, android, web)
* only FOSS libs can use
* recommend no more than 300 lines of code per file

View File

@ -2,3 +2,10 @@
* [MVVM](https://docs.flutter.dev/app-architecture/guide)
## Package structure
The repo structure follows official [Package structure](https://docs.flutter.dev/app-architecture/case-study#package-structure) with slight modifications.
* put each `<FEATURE NAME>/`s in `features/` sub-directory under `ui/`.
* `test/features/` contains BDD unit tests for each feature. It focuses on pure logic, therefore will not access `View` but `ViewModel` and `Model`.
* `test/widget/` contains UI widget(component) tests which focus on `View` of MVVM only.

View File

@ -4,7 +4,7 @@ Feature: App preferences
Given the settings screen is open
When the user selects the "<theme>" theme
Then the app UI updates to use the "<theme>" theme
And the preference {theme} is saved as {"<theme>"}
And the preference {'theme'} is saved as <theme>
Examples:
| theme |
@ -16,7 +16,7 @@ Feature: App preferences
Given the settings screen is open
When the user selects a supported language "<language>"
Then all visible texts are displayed in "<language>"
And the preference {language} is saved as {"<language>"}
And the preference {'language'} is saved as <language>
Examples:
| language |

View File

@ -10,4 +10,7 @@ Feature: internationalizing
Then the language falls back to the device locale
Scenario: Supported languages are available
Then the app supports languages {en, zh-TW, es}
Then the app supports languages
| 'en' |
| 'zh-TW' |
| 'es' |

View File

@ -17,4 +17,11 @@ Future<void> aSignatureImageIsSelected(WidgetTester tester) async {
.setImageBytes(Uint8List.fromList([1, 2, 3]));
// Allow provider scheduler to process queued updates fully
await tester.pumpAndSettle();
// Extra pump with a non-zero duration to flush zero-delay timers
await tester.pump(const Duration(milliseconds: 1));
// Teardown to avoid pending timers from Riverpod's scheduler
addTearDown(() {
TestWorld.container?.dispose();
TestWorld.container = null;
});
}

View File

@ -1,17 +1,33 @@
import 'package:bdd_widget_test/data_table.dart' as bdd;
import 'package:flutter_test/flutter_test.dart';
/// Usage: the app supports languages {en, zh-TW, es}
/// Usage: the app supports languages
/// | 'en' |
/// | 'zh-TW' |
/// | 'es' |
Future<void> theAppSupportsLanguages(
WidgetTester tester,
String languages,
dynamic languages,
) async {
// Normalize the example token string "{en, zh-TW, es}" into a set
final raw = languages.trim();
final inner =
raw.startsWith('{') && raw.endsWith('}')
? raw.substring(1, raw.length - 1)
: raw;
final expected = inner.split(',').map((s) => s.trim()).toSet();
// Accept either a DataTable from bdd_widget_test or a string like "{en, zh-TW, es}"
final Set<String> expected;
if (languages is bdd.DataTable) {
final lists = languages.asLists();
// Flatten ignoring header rows if any
final items = lists
.skipWhile((row) => row.any((e) => e.toString().contains('artist') || e.toString().contains('name')))
.expand((row) => row)
.map((e) => e.toString().replaceAll("'", '').trim())
.where((e) => e.isNotEmpty)
.toSet();
expected = items;
} else {
final raw = languages.toString().trim();
final inner = raw.startsWith('{') && raw.endsWith('}')
? raw.substring(1, raw.length - 1)
: raw;
expected = inner.split(',').map((s) => s.trim().replaceAll("'", '')).toSet();
}
// Keep this in sync with the app's supported locales
const actual = {'en', 'zh-TW', 'es'};

View File

@ -1,5 +1,7 @@
import 'package:flutter_test/flutter_test.dart';
import '_world.dart';
// Re-export tokens so tests that import this step have access to token symbols
export '_tokens.dart';
/// Usage: the preference {language} is saved as {"<language>"}
Future<void> thePreferenceIsSavedAs(