1

I am trying to test a clipboard function in my app. When I press a button it should copy my text to the clipboard. When I try to test this functionality with a widget test, the future returned doesn't get resolved. Is there a way to mock the Clipboard.setData method?

Since my original code is quite large I made a reproducible widget test that has the same problem. The boolean dataCopied is false when I execute the expect().

testWidgets('test clipboard function', (WidgetTester tester) async {
    var dataCopied = false;
    await tester.pumpWidget(
      MaterialApp(
        home: Container(
          width: 10,
          height: 10,
          child: ElevatedButton(
            onPressed: (() {
              Clipboard.setData(ClipboardData(text: "test")).then((_) {
                dataCopied = true;
              });
            }),
            child: Text("Copy Text"),
          ),
        ),
      ),
    );

    await tester.tap(find.byType(ElevatedButton));
    expect(dataCopied, true);
  });
Stan
  • 629
  • 7
  • 18
  • I think the problem would be onPress is returning before `then` inside onPress is called. You might need to wait for few milliseconds before expecting data copy. – Rahul Jul 25 '21 at 12:36
  • You can either use await or then but the result is the same – Stan Jul 25 '21 at 13:34
  • yes. I understand. the `await tester.tap` doesn't wait for the onPress to complete. It waits for the tap operation to happen. So you need to provide some delay between `tester.tap` and `expect`. – Rahul Jul 25 '21 at 13:35
  • i used tester.pump() with a duration of 10 seconds still the future doesn't trigger – Stan Jul 25 '21 at 13:36
  • maybe adding `await Future.delayed(Duration(milliseconds: 100));` between both the lines. – Rahul Jul 25 '21 at 13:36
  • Unfortunately that doesn't work either – Stan Jul 25 '21 at 13:59
  • I think i might have found a solution since the flutter Clipboard class uses SystemChannel.platformed.invokeMethod() and I have found that a channel can be mocked https://stackoverflow.com/questions/43897734/how-can-i-mock-stub-out-a-flutter-platform-channel-plugin – Stan Jul 25 '21 at 14:03

1 Answers1

1

I found a solution. I checked the flutter source code and it seems the Clipboard class uses SystemChannels.platform to call the native clipboard function. From another post I saw that Channels can be mocked How can I mock/stub out a Flutter platform channel/plugin?

testWidgets('test clipboard function', (WidgetTester tester) async {
    var dataCopied = false;
    
    final List<MethodCall> log = <MethodCall>[];
    SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
      log.add(methodCall);
    });

    await tester.pumpWidget(
      MaterialApp(
        home: Container(
          width: 10,
          height: 10,
          child: ElevatedButton(
            onPressed: (() {
              Clipboard.setData(ClipboardData(text: "test")).then((_) {
                dataCopied = true;
              });
            }),
            child: Text("Copy Text"),
          ),
        ),
      ),
    );

    await tester.tap(find.byType(ElevatedButton));
    expect(dataCopied, true);
  });
Stan
  • 629
  • 7
  • 18