diff --git a/pubspec.yaml b/pubspec.yaml index f3f7fce7..7f9aee13 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,8 +13,8 @@ topics: - nps environment: - sdk: ">=2.17.0 <4.0.0" - flutter: ">=3.0.0" + sdk: ">=3.0.0" + flutter: ">=3.10.0" dependencies: clock: ^1.1.0 @@ -36,7 +36,7 @@ dev_dependencies: flutter_test: sdk: flutter lint: '>=1.10.0 <3.0.0' - spot: '>=0.3.1 <0.5.0' + spot: '^0.6.0' test: ^1.21.0 transparent_image: ^2.0.0 diff --git a/test/feedback_flow_test.dart b/test/feedback_flow_test.dart index eea009a4..ee511930 100644 --- a/test/feedback_flow_test.dart +++ b/test/feedback_flow_test.dart @@ -39,7 +39,7 @@ void main() { // feedback is still available and not lost await robot.openWiredash(); - _larryPageView.spotSingleText('test message').existsOnce(); + _larryPageView.spotText('test message').existsOnce(); // when discarding feedback await robot.discardFeedback(); @@ -48,7 +48,7 @@ void main() { // it is no longer available await robot.openWiredash(); - _larryPageView.spotSingleText('test message').doesNotExist(); + _larryPageView.spotText('test message').doesNotExist(); }); testWidgets('Discard feedback disappears after 3s', (tester) async { @@ -59,7 +59,7 @@ void main() { await robot.discardFeedback(); final confirmDiscardButton = - _larryPageView.spotSingleText('l10n.feedbackDiscardConfirmButton'); + _larryPageView.spotText('l10n.feedbackDiscardConfirmButton'); confirmDiscardButton.existsOnce(); await tester.pumpAndSettle(const Duration(seconds: 3)); confirmDiscardButton.doesNotExist(); @@ -74,7 +74,7 @@ void main() { await robot.goToNextStep(); _larryPageView .spot() - .spotSingleText('l10n.feedbackStep1MessageErrorMissingMessage') + .spotText('l10n.feedbackStep1MessageErrorMissingMessage') .existsOnce(); // Entering a message allows continue diff --git a/test/util/robot.dart b/test/util/robot.dart index bb2240af..2e492482 100644 --- a/test/util/robot.dart +++ b/test/util/robot.dart @@ -133,9 +133,9 @@ class WiredashTestRobot { } Future openWiredash() async { - final feedbackText = spotSingle().spotSingleText('Feedback') + final feedbackText = spotSingle().spotText('Feedback') ..existsOnce(); - await _tap(feedbackText); + await act.tap(feedbackText); // process the event, wait for backdrop to appear in the widget tree await tester.pumpN(4); @@ -149,10 +149,9 @@ class WiredashTestRobot { } Future openPromoterScore() async { - final promoterScoreText = spotSingle() - .spotSingleText('Promoter Score') - ..existsOnce(); - await _tap(promoterScoreText); + final promoterScoreText = + spotSingle().spotText('Promoter Score')..existsOnce(); + await act.tap(promoterScoreText); // process the event, wait for backdrop to appear in the widget tree await tester.pumpN(4); @@ -179,9 +178,9 @@ class WiredashTestRobot { _spotPageView.spotSingle().existsOnce(); await tester.enterText(find.byType(TextField), message); await tester.pumpAndSettle(); - final button = spotSingle( - children: [spotSingleText('l10n.feedbackNextButton')], - ); + final button = spotSingle() + .withChild(spotText('l10n.feedbackNextButton')) + .single; // TODO find easier way to check if the button is clickable. Hit Testing? await button.waitUntil(tester, (it) => it.isTappable(true)); @@ -193,10 +192,11 @@ class WiredashTestRobot { Future enterPromotionScoreMessage(String message) async { final step = _spotPageView.spotSingle()..existsOnce(); - final done = step.spotSingle( - children: [spotSingleText('l10n.promoterScoreSubmitButton')], - )..existsOnce(); - step.spotSingleText('l10n.promoterScoreBackButton').existsOnce(); + final done = step + .spotSingle() + .withChild(spotText('l10n.promoterScoreSubmitButton')) + ..existsOnce(); + step.spotText('l10n.promoterScoreBackButton').existsOnce(); await tester.enterText(find.byType(TextField), message); await tester.pumpAndSettle(); @@ -216,8 +216,8 @@ class WiredashTestRobot { Future skipScreenshot() async { final step = _spotPageView.spotSingle() ..existsOnce(); - await _tap( - step.spotSingleText('l10n.feedbackStep3ScreenshotOverviewSkipButton'), + await act.tap( + step.spotText('l10n.feedbackStep3ScreenshotOverviewSkipButton'), ); await tester.pumpAndSettle(); await tester.pumpAndSettle(); @@ -234,10 +234,11 @@ class WiredashTestRobot { /// Actually calling [FeedbackModel.submitFeedback] Future submitFeedback() async { final step = _spotPageView.spotSingle()..existsOnce(); - await _tap( - step.spot( - children: [step.spotSingleText('l10n.feedbackStep6SubmitSubmitButton')], - ).last(), + await act.tap( + step + .spot() + .withChild(spotText('l10n.feedbackStep6SubmitSubmitButton')) + .last(), ); print('submit feedback'); await tester.pump(); @@ -245,7 +246,7 @@ class WiredashTestRobot { Future skipEmail() async { final step = _spotPageView.spotSingle()..existsOnce(); - await _tap(step.spotSingleText('l10n.feedbackNextButton')); + await act.tap(step.spotText('l10n.feedbackNextButton')); await tester.pumpAndSettle(); await tester.pumpAndSettle(); @@ -255,7 +256,7 @@ class WiredashTestRobot { Future submitEmailViaButton() async { final step = _spotPageView.spotSingle()..existsOnce(); - await _tap(step.spotSingleText('l10n.feedbackNextButton')); + await act.tap(step.spotText('l10n.feedbackNextButton')); await tester.pumpAndSettle(); final newStatus = services.feedbackModel.feedbackFlowStatus; @@ -272,7 +273,7 @@ class WiredashTestRobot { Future goToNextStep() async { final oldStatus = services.feedbackModel.feedbackFlowStatus; - await _tap(spotSingleText('l10n.feedbackNextButton')); + await act.tap(spotText('l10n.feedbackNextButton')); await tester.pumpAndSettle(); await tester.pumpAndSettle(); final newStatus = services.feedbackModel.feedbackFlowStatus; @@ -281,13 +282,14 @@ class WiredashTestRobot { Future goToPrevStep() async { final oldStatus = services.feedbackModel.feedbackFlowStatus; - final texts = spotTexts('l10n.feedbackBackButton'); + final texts = spot() + .whereText((text) => text.equals('l10n.feedbackBackButton')); final backdropStatus = services.backdropController.backdropStatus; if (backdropStatus == WiredashBackdropStatus.centered) { - await _tap(texts.last()); + await act.tap(texts.last()); } else { - await _tap(texts.first()); + await act.tap(texts.first()); } await tester.pumpAndSettle(); @@ -302,15 +304,15 @@ class WiredashTestRobot { step.spot().snapshot().discovered; if (noAttachmentsResult.isNotEmpty) { step.spot().existsOnce(); - final addScreenshotBtn = spotSingleText( + final addScreenshotBtn = spotText( 'l10n.feedbackStep3ScreenshotOverviewAddScreenshotButton', ); - await _tap(addScreenshotBtn); + await act.tap(addScreenshotBtn); } else { final gallery = step.spotSingle()..existsOnce(); final addAttachmentItem = gallery.spotSingle() ..existsOnce(); - await _tap(addAttachmentItem); + await act.tap(addAttachmentItem); } await tester.waitUntil(find.byType(ScreenshotBar), findsOneWidget); @@ -332,9 +334,8 @@ class WiredashTestRobot { print('Take screeshot'); // Click the screenshot button - await _tap( - screenshotBar - .spotSingleText('l10n.feedbackStep3ScreenshotBarCaptureButton'), + await act.tap( + screenshotBar.spotText('l10n.feedbackStep3ScreenshotBarCaptureButton'), ); while (services.feedbackModel.feedbackFlowStatus != FeedbackFlowStatus.screenshotDrawing) { @@ -342,9 +343,10 @@ class WiredashTestRobot { } // Wait for active "Save" button - final nextButton = screenshotBar.spotSingle( - children: [spotSingleText('l10n.feedbackStep3ScreenshotBarSaveButton')], - ).last(); + final nextButton = screenshotBar + .spotSingle() + .withChild(spotText('l10n.feedbackStep3ScreenshotBarSaveButton')) + .last(); try { await tester.waitUntil(nextButton.finder, findsOneWidget); @@ -363,15 +365,15 @@ class WiredashTestRobot { ); final screenshotBar = _spotBackdrop.spotSingle() ..existsOnce(); - await _tap( - screenshotBar.spotSingleText('l10n.feedbackStep3ScreenshotBarSaveButton'), + await act.tap( + screenshotBar.spotText('l10n.feedbackStep3ScreenshotBarSaveButton'), ); await tester.pumpHardAndSettle(const Duration(milliseconds: 100)); // wait until the animation is closed await tester.waitUntil( screenshotBar - .spotSingleText('l10n.feedbackStep3ScreenshotBarSaveButton') + .spotText('l10n.feedbackStep3ScreenshotBarSaveButton') .finder, findsNothing, ); @@ -393,7 +395,7 @@ class WiredashTestRobot { } Future selectLabel(String labelText) async { - await _tap(spotSingleText(labelText)); + await act.tap(spotText(labelText)); await tester.pumpAndSettle(); } @@ -423,7 +425,7 @@ class WiredashTestRobot { ) .first(); - await _tap(spotRatingCard(rating)); + await act.tap(spotRatingCard(rating)); await tester.pumpAndSettle(); /// automatically goes to next step @@ -434,9 +436,10 @@ class WiredashTestRobot { Future submitPromoterScore() async { final step = _spotPageView.spotSingle()..existsOnce(); - final submitButton = step.spot( - children: [spotSingleText('l10n.promoterScoreSubmitButton')], - ).last() + final submitButton = step + .spot() + .withChild(spotText('l10n.promoterScoreSubmitButton')) + .last() ..existsOnce(); final scrollable = spotSingle() .spotSingle() @@ -449,7 +452,7 @@ class WiredashTestRobot { -100, scrollable: scrollable.finder, ); - await _tap(submitButton); + await act.tap(submitButton); await tester.pumpAndSettle(); print('submit Promoter Score'); } @@ -461,20 +464,16 @@ class WiredashTestRobot { } } - Future _tap(SingleWidgetSelector spot) async { - await tester.tap(spot.finder); - } - SingleWidgetSelector get _discard => - _spotPageView.spotSingleText('l10n.feedbackDiscardButton'); + _spotPageView.spotText('l10n.feedbackDiscardButton'); SingleWidgetSelector get _reallyDiscard => - _spotPageView.spotSingleText('l10n.feedbackDiscardConfirmButton'); + _spotPageView.spotText('l10n.feedbackDiscardConfirmButton'); /// Starts discarding feedback, call [confirmDiscardFeedback] to confirm Future discardFeedback() async { _discard.existsOnce(); - await _tap(_discard); + await act.tap(_discard); await tester.pump(); _reallyDiscard.existsOnce(); } @@ -483,7 +482,7 @@ class WiredashTestRobot { Future confirmDiscardFeedback() async { _discard.doesNotExist(); _reallyDiscard.existsOnce(); - await _tap(_reallyDiscard); + await act.tap(_reallyDiscard); await tester.pump(); } } @@ -588,7 +587,7 @@ extension on Symbol { } } -extension SpotWaitUntil on SingleWidgetSelector { +extension SpotWaitUntil on WidgetSelector { Future waitUntil( WidgetTester tester, void Function(SingleWidgetSnapshot) matcher, { @@ -600,7 +599,7 @@ extension SpotWaitUntil on SingleWidgetSelector { while (true) { attempt++; - final snapshot = this.snapshot(); + final snapshot = single.snapshot(); final Object error; final StackTrace stack; @@ -645,10 +644,9 @@ extension SpotWaitUntil on SingleWidgetSelector { extension EffectiveTextMatcher on WidgetMatcher { WidgetMatcher isTappable(bool value) { return hasProp( - selector: (subject) => subject.context.nest( + widgetSelector: (subject) => subject.context.nest( () => ['is clickable"'], - (Element element) { - final widget = element.widget as TronButton; + (TronButton widget) { return Extracted.value(widget.onTap != null); }, ),