Skip to content

Commit

Permalink
Fix semantics check
Browse files Browse the repository at this point in the history
  • Loading branch information
passsy committed Aug 17, 2023
1 parent 5f1614d commit 32bef76
Showing 1 changed file with 86 additions and 21 deletions.
107 changes: 86 additions & 21 deletions test/util/robot.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// ignore_for_file: avoid_print

import 'dart:async';
import 'dart:math' as math;

// ignore: depend_on_referenced_packages
import 'package:checks/src/checks.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -178,38 +181,30 @@ class WiredashTestRobot {
_spotPageView.spotSingle<Step1FeedbackMessage>().existsOnce();
await tester.enterText(find.byType(TextField), message);
await tester.pumpAndSettle();
await tester.waitUntil(
tester.getSemantics(
find.widgetWithText(TronButton, 'l10n.feedbackNextButton'),
),
matchesSemantics(
isEnabled: true,
isButton: true,
isFocusable: true,
hasEnabledState: true,
),
final button = spotSingle<TronButton>(
children: [spotSingleText('l10n.feedbackNextButton')],
);

// TODO find easier way to check if the button is clickable. Hit Testing?
await button.waitUntil(tester, (it) => it.isTappable(true));

expect(find.text('l10n.feedbackNextButton'), findsOneWidget);
expect(find.text('l10n.feedbackCloseButton'), findsOneWidget);
print('entered feedback message: $message');
}

Future<void> enterPromotionScoreMessage(String message) async {
final step = _spotPageView.spotSingle<PsStep2Message>()..existsOnce();
final done = step.spotSingleText('l10n.promoterScoreSubmitButton')
..existsOnce();
final done = step.spotSingle<TronButton>(
children: [spotSingleText('l10n.promoterScoreSubmitButton')],
)..existsOnce();
step.spotSingleText('l10n.promoterScoreBackButton').existsOnce();
await tester.enterText(find.byType(TextField), message);
await tester.pumpAndSettle();
await tester.waitUntil(
tester.getSemantics(done.finder),
matchesSemantics(
isEnabled: true,
isButton: true,
isFocusable: true,
hasEnabledState: true,
),
);

// TODO find easier way to check if the button is clickable. Hit Testing?
await done.waitUntil(tester, (it) => it.isTappable(true));

print('entered feedback message: $message');
}

Expand Down Expand Up @@ -468,6 +463,7 @@ class WiredashTestRobot {

SingleWidgetSelector<Widget> get _discard =>
_spotPageView.spotSingleText('l10n.feedbackDiscardButton');

SingleWidgetSelector<Widget> get _reallyDiscard =>
_spotPageView.spotSingleText('l10n.feedbackDiscardConfirmButton');

Expand Down Expand Up @@ -587,3 +583,72 @@ extension on Symbol {
.toString();
}
}

extension SpotWaitUntil<W extends Widget> on SingleWidgetSelector<W> {
Future<void> waitUntil(
WidgetTester tester,
void Function(SingleWidgetSnapshot<W>) matcher, {
Duration timeout = const Duration(seconds: 5),
}) async {
final ogStack = StackTrace.current;
final start = DateTime.now();
var attempt = 0;
while (true) {
attempt++;

final snapshot = this.snapshot();

final Object error;
final StackTrace stack;
try {
matcher(snapshot);
break;
} catch (e, s) {
error = e;
stack = s;
}

final now = DateTime.now();
final executingTime = start.difference(now).abs();
if (now.isAfter(start.add(timeout))) {
// Exit with error
print(ogStack);
print(stack);
throw 'Did not find $this after $timeout (attempt: $attempt)';
}

final duration =
Duration(milliseconds: math.pow(attempt, math.e).toInt());
if (executingTime > const Duration(seconds: 1) &&
duration > const Duration(seconds: 1)) {
// show continuous updates
print(
'Waiting for match (attempt: $attempt, @ $executingTime)\n'
'\tSelector: $this to match\n'
'\tException: $error',
);
}
if (attempt < 10) {
await tester.pumpAndSettle(duration);
} else {
await tester.pumpHardAndSettle(duration);
await tester.pump();
}
}
}
}

extension EffectiveTextMatcher on WidgetMatcher<TronButton> {
WidgetMatcher<TronButton> isTappable(bool value) {
return hasProp(
selector: (subject) => subject.context.nest<bool>(
() => ['is clickable"'],
(Element element) {
final widget = element.widget as TronButton;
return Extracted.value(widget.onTap != null);
},
),
match: (it) => it.equals(value),
);
}
}

0 comments on commit 32bef76

Please sign in to comment.