Tkko / Flutter_Pinput

Flutter package to create Pin code input text field with every pixel customization possibility 🎨 with beautiful animations, iOS autofill, Android autofill
https://pub.dev/packages/pinput
MIT License
696 stars 172 forks source link

I have issue with test cases on pinput widget #140

Open yroza opened 11 months ago

yroza commented 11 months ago

Describe the bug I implemented patrol(https://patrol.leancode.co/) package for perform the integration testing in my current project. when I write the test cases for test the Pinput widget so I am not able to enter text in Pinput widget.

Screenshots Here is my code for test the pinput widget

image

Pinput version: [e.g. 1.1.10]

Result of: flutter doctor --verbose

Flutter (Channel stable, 3.7.4, on macOS 13.3.1 22E772610a darwin-arm64, locale en-IN) • Flutter version 3.7.4 on channel stable at /Users/yash/Documents/FlutterSdk/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision b4bce91dd0 (4 months ago), 2023-02-21 09:50:50 +0800 • Engine revision 248290d6d5 • Dart version 2.19.2 • DevTools version 2.20.1 [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) • Android SDK at /Users/yash/Library/Android/sdk • Platform android-33, build-tools 33.0.0 • ANDROID_HOME = /Users/yash/Users/yash/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 14.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14E222b • CocoaPods version 1.11.3 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.2) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) [✓] VS Code (version 1.78.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.66.0 [✓] Connected device (3 available) • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator) • macOS (desktop) • macos • darwin-arm64 • macOS 13.3.1 22E772610a darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 114.0.5735.106 [✓] HTTP Host Availability • All required HTTP hosts are available • No issues found!

Result of: patrol doctor

Patrol CLI version: 1.1.10 Program adb found in /Users/yash/Library/Android/sdk/platform-tools/adb Env var $ANDROID_HOME set to /Users/yash/Users/yash/Library/Android/sdk Program xcodebuild found in /usr/bin/xcodebuild Program ideviceinstaller found in /Users/yash/homebrew/bin/ideviceinstaller Program ios-deploy found in /Users/yash/homebrew/bin/ios-deploy

Smartphone (please complete the following information):

Additional context when I run the patrol develop command then I got this result

image
bartekpacia commented 10 months ago

Also reported in the Patrol repository: https://github.com/leancodepl/patrol/issues/1409

Tkko commented 10 months ago

Hey @yroza @bartekpacia, can you confirm that this code snippet works for you as well?

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinput/pinput.dart';

void main() {
  testWidgets('Can enter value', (WidgetTester tester) async {
    String? fieldValue;
    int called = 0;
    final controller = TextEditingController();
    final focusNode = FocusNode();

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Pinput(
            controller: controller,
            onChanged: (value) {
              fieldValue = value;
              called++;
            },
          ),
        ),
      ),
    );

    focusNode.requestFocus();
    await tester.pump();

    expect(fieldValue, isNull);
    expect(called, 0);

    await tester.enterText(find.byType(Pinput), '1111');
    await tester.testTextInput.receiveAction(TextInputAction.done);
    expect(fieldValue, equals('1111'));
    expect(called, 1);
  });
}
bartekpacia commented 10 months ago

Thanks @Tkko, this code works in a widget test (when run with flutter test test/pinput_test.dart).

When I run it in a real app on the device (with flutter run test/pinput_test.dart), it also works:

pinput_test.dart.webm

I had to modify your test slightly to use setState(), so the changes made are visible:

Test code ```dart import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinput/pinput.dart'; void main() { testWidgets('Can enter value', (tester) async { String? fieldValue; var called = 0; final controller = TextEditingController(); final focusNode = FocusNode(); await tester.pumpWidget( MaterialApp( home: Scaffold( body: StatefulBuilder( builder: (context, setState) { return Pinput( controller: controller, onChanged: (value) { setState(() { fieldValue = value; called++; }); }, ); }, ), ), ), ); focusNode.requestFocus(); await tester.pump(); expect(fieldValue, isNull); expect(called, 0); await tester.enterText(find.byType(Pinput), '1111'); await tester.pumpAndSettle(Duration(seconds: 2)); await tester.testTextInput.receiveAction(TextInputAction.done); await tester.pumpAndSettle(Duration(seconds: 2)); expect(fieldValue, equals('1111')); expect(called, 1); }); } ```
Tkko commented 10 months ago

@bartekpacia Perfect, I'm not sure how patrol works but Pinput uses an EditableText which is an underlying widget of TextField and CupertinoTextField so everything should work in the same way

bartekpacia commented 10 months ago

I'm curious whether you use a single EditableText for all of the number squares, or a single EditableText for each one of the number squares?

If you use a single EditableText for all, how does it work that you have a gap between the number squares?

Tkko commented 10 months ago

I use single EditableText Which is hidden under the boxes.

Screenshot 2023-06-28 at 12 15 30 PM

https://github.com/Tkko/Flutter_Pinput/blob/e34e5f2e2bf155d41569a49c342be0c740b4a159/lib/src/pinput_state.dart#L376

abdalmonem commented 1 week ago

For any one facing the same issue: add one duration to pump method before calling await tester.enterText(find.byType(Pinput), '1111'); example: await tester.pump(Duration(milliseconds: 500));