Files
hash-wallet/integration_test/components/common_test_cases.dart
T
jwinterm f64ee19b0c fix(integration_test): repair compile after chain removal; robust key taps
integration_test/ has not compiled since 784a082f1 removed SOL/TRX/ZEC/DCR/
ZANO/Haven: common_test_flows.dart and common_test_constants.dart still
referenced WalletType.solana/.tron/.zano/.decred/.zcash/.haven and secrets that
were never generated, and wallet_keys_robot branched on .solana/.tron. Any
`flutter drive` over these components failed at kernel compile.

- common_test_flows.dart: drop removed chains from both wallet-type switches.
- common_test_constants.dart: default test wallet SOL -> WOW (Wownero-first;
  SOL no longer exists), with a real WOW address.
- wallet_keys_robot.dart: EVM-only branch (solana/tron gone).
- common_test_cases.dart tapItemByKey: wait for the widget (up to 20s) instead
  of pumping a flat 500ms then asserting. Screens behind an async transition
  (PIN-setup success button) were a coin flip; this makes the failure honest
  ("not there after 20s") and the pass reliable. Pump loop, not pumpAndSettle,
  since the dashboard sync animation never settles.
2026-08-02 21:29:40 -04:00

274 lines
8.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
class CommonTestCases {
WidgetTester tester;
CommonTestCases(this.tester);
Future<void> isSpecificPage<T>() async {
await tester.pumpAndSettle();
hasType<T>();
}
Future<void> tapItemByKey(
String key, {
bool shouldPumpAndSettle = true,
int pumpDuration = 100,
Duration timeout = const Duration(seconds: 20),
}) async {
final widgetFinder = find.byKey(ValueKey(key));
// Wait for the widget to actually appear rather than pumping a flat 500ms
// and hoping. Screens that arrive behind an async transition (PIN setup's
// success button is the usual offender) are otherwise a coin flip, and the
// failure reads as "key missing" rather than "key not there YET".
//
// Deliberately a pump loop, not pumpAndSettle: the dashboard runs a
// perpetual sync-indicator animation, so settling never completes there.
final deadline = DateTime.now().add(timeout);
while (!tester.any(widgetFinder) && DateTime.now().isBefore(deadline)) {
await tester.pump(const Duration(milliseconds: 100));
}
expect(tester.any(widgetFinder), true,
reason: 'Widget with key "$key" should be visible '
'(waited ${timeout.inSeconds}s)');
final widget = widgetFinder.first;
await tester.tap(widget, warnIfMissed: false);
shouldPumpAndSettle
? await tester.pumpAndSettle(Duration(milliseconds: pumpDuration))
: await tester.pump();
}
Future<void> tapItemByFinder(Finder finder, {bool shouldPumpAndSettle = true}) async {
await tester.tap(finder);
shouldPumpAndSettle ? await tester.pumpAndSettle() : await tester.pump();
}
void hasText(String text, {bool hasWidget = true}) {
final textWidget = find.text(text);
expect(textWidget, hasWidget ? findsOneWidget : findsNothing);
}
void hasTextAtLestOnce(String text, {bool hasWidget = true}) {
final textWidget = find.text(text);
expect(textWidget, hasWidget ? findsAny : findsNothing);
}
void hasType<T>() {
final typeWidget = find.byType(T);
expect(typeWidget, findsOneWidget);
}
bool isKeyPresent(String key) {
final typeWidget = find.byKey(ValueKey(key));
return typeWidget.tryEvaluate();
}
void hasValueKey(String key) {
final typeWidget = find.byKey(ValueKey(key));
expect(typeWidget, findsOneWidget);
}
Future<void> swipePage({bool swipeRight = true}) async {
await tester.drag(find.byType(PageView), Offset(swipeRight ? -300 : 300, 0));
await tester.pumpAndSettle();
}
Future<void> swipeByPageKey({required String key, bool swipeRight = true}) async {
await tester.drag(find.byKey(ValueKey(key)), Offset(swipeRight ? -300 : 300, 0));
await tester.pumpAndSettle();
}
Future<void> goBack() async {
tester.printToConsole('Routing back to previous screen');
final NavigatorState navigator = tester.state(find.byType(Navigator));
navigator.pop();
await tester.pumpAndSettle();
}
Future<void> startGesture(String key, Offset gestureOffset) async {
await tester.pumpAndSettle();
final hasKey = isKeyPresent(key);
tester.printToConsole("Has gestureKey: $hasKey");
if (!hasKey) return;
final gesture = await tester.startGesture(tester.getCenter(find.byKey(ValueKey(key))));
// Drag to the left
await gesture.moveBy(gestureOffset);
// End the gesture
await gesture.up();
await tester.pump();
}
Future<void> dragUntilVisible(
String childKey,
String parentKey, {
int maxScrolls = 100,
double scrollStep = 50.0,
int maxReverseScrolls = 50,
}) async {
await tester.pumpAndSettle();
final itemFinder = find.byKey(ValueKey(childKey));
final listFinder = find.byKey(ValueKey(parentKey));
// Check if the widget is already in the widget tree
if (tester.any(itemFinder)) {
// Widget is already built and in the tree
tester.printToConsole('Child is already present');
return;
}
// Find the Scrollable associated with the Parent Ad
final scrollableFinder = find.descendant(
of: listFinder,
matching: find.byType(Scrollable),
);
// Ensure that the Scrollable is found
expect(
scrollableFinder,
findsOneWidget,
reason: 'Scrollable descendant of the Parent Widget not found.',
);
// Get the initial scroll position
final scrollableState = tester.state<ScrollableState>(scrollableFinder);
double previousScrollPosition = scrollableState.position.pixels;
bool scrollDown = true;
bool reversedDirection = false;
bool found = false;
int reverseScrollCount = 0;
for (int scrolls = 0; scrolls < maxScrolls; scrolls++) {
await tester.pumpAndSettle();
// Check if the widget is visible
if (tester.any(itemFinder)) {
found = true;
break;
}
// Log current state for debugging
tester.printToConsole('Scrolling ${scrollDown ? 'down' : 'up'}, attempt $scrolls');
// Stop if reverse scroll limit is exceeded
if (!scrollDown && reverseScrollCount >= maxReverseScrolls) {
tester.printToConsole('Maximum reverse scrolls reached. Widget not found.');
break;
}
// Perform scrolling in the current direction
await tester.drag(
scrollableFinder,
scrollDown ? Offset(0, -scrollStep) : Offset(0, scrollStep),
);
await tester.pumpAndSettle();
// Update the scroll position after the drag
final currentScrollPosition = scrollableState.position.pixels;
if (currentScrollPosition == previousScrollPosition) {
// Cannot scroll further in the current direction
if (reversedDirection) {
// We've already tried both directions
tester.printToConsole('Reached the scroll limit in both directions. Widget not found.');
break;
} else {
// Reverse the scroll direction and reset reverse scroll count
scrollDown = !scrollDown;
reversedDirection = true;
reverseScrollCount = 0;
tester.printToConsole('Reached the end, reversing direction');
}
} else {
// Update scroll position and reverse scroll count, incrementing only for reverse scrolling
previousScrollPosition = currentScrollPosition;
if (!scrollDown) reverseScrollCount++;
}
}
if (!found) {
tester.printToConsole('Widget not found after $maxScrolls scrolls.');
}
}
Future<void> scrollItemIntoView(
String itemKeyId,
double scrollPixels,
String scrollableFinderKey,
) async {
final Finder itemFinder = find.byKey(ValueKey(itemKeyId));
final scrollableFinder = find.descendant(
of: find.byKey(ValueKey(scrollableFinderKey)),
matching: find.byType(Scrollable),
);
// Check if the item is already visible
if (tester.any(itemFinder)) {
tester.printToConsole('Item $itemKeyId is already visible');
return;
}
// Check if scrollable exists
if (!tester.any(scrollableFinder)) {
tester.printToConsole('Scrollable not found for $itemKeyId');
return;
}
try {
await tester.scrollUntilVisible(
itemFinder,
scrollPixels,
scrollable: scrollableFinder,
maxScrolls: 10,
);
// Wait for the scroll to complete
await tester.pumpAndSettle(Duration(milliseconds: 500));
// Verify the item is now visible
if (!tester.any(itemFinder)) {
tester.printToConsole('Item $itemKeyId not found after scrolling');
}
} catch (e) {
tester.printToConsole('Could not scroll to $itemKeyId: $e');
}
}
Future<void> enterText(String text, String editableTextKey) async {
final editableTextWidget = find.byKey(ValueKey((editableTextKey)));
await tester.enterText(editableTextWidget, text);
await tester.pumpAndSettle();
}
void findWidgetViaDescendant({
required FinderBase<Element> of,
required FinderBase<Element> matching,
}) {
final textWidget = find.descendant(of: of, matching: matching);
expect(textWidget, findsOneWidget);
}
Future<void> defaultSleepTime({int seconds = 2}) async =>
await Future.delayed(Duration(seconds: seconds));
Future<void> takeScreenshots(String screenshotName) async {
// Pausing this for now
// await (tester.binding as IntegrationTestWidgetsFlutterBinding).takeScreenshot(screenshotName);
}
}