OpenFlutter / flutter_screenutil

Flutter screen adaptation, font adaptation, get screen information
https://pub.dartlang.org/packages/flutter_screenutil
Apache License 2.0
3.88k stars 494 forks source link

Widget test #394

Closed awaisjamil-vd closed 2 years ago

awaisjamil-vd commented 2 years ago

how can i widget test those widget that has screenutill? please guide

Mounir-Bouaiche commented 2 years ago

@awaisjamil-vd I think you can test functionality by wrapping whole app within MediaQuery to simulate different screen sizes. Note: Don't use MediaQueryData.fromWindow. A simple example: (You can use (GlobalKey().currentContext?.findRenderObject() as RenderBox).size to get a widget size, See tutorials).

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

void main() {
  testWidgets('Test Responsiveness', (WidgetTester tester) async {
    // Declare Sizes
    const Size designSize = Size(360, 640);
    const Size initialSize = designSize;
    const Size biggerSize = Size(480, 920);
    const Size smallerSize = Size(300, 560);

    // We'll use MediaQuery to simulate diffrent screen sizes
    MediaQueryData currentData = MediaQueryData(size: initialSize);
    const MediaQueryData biggerData = MediaQueryData(size: biggerSize);
    const MediaQueryData smallerData = MediaQueryData(size: smallerSize);

    // Used to find a widget. See [CommonFinders.byKey].
    final _key = UniqueKey();

    // Click on button. See code bellow.
    Future<int> tap() async {
      await tester.tap(find.byKey(_key));
      return tester.pumpAndSettle();
    }

    void testSize(Size size) {
      expect(1.w, equals(size.width / designSize.width));
      expect(1.h, equals(size.height / designSize.height));
      print('[OK] Size: $size, width: ${1.w}, height: ${1.h}');
    }

    await tester.pumpWidget(StatefulBuilder(
      builder: (BuildContext context, StateSetter setState) {
        return MediaQuery(
          data: currentData,
          child: ScreenUtilInit(
            useInheritedMediaQuery: true,
            designSize: designSize,
            builder: (_) => MaterialApp(
              home: Material(
                child: TextButton(
                  key: _key,
                  child: Text('Change Screen Size'),
                  onPressed: () {
                    setState(() {
                      currentData = currentData.size == initialSize
                          // First test is with bigger screen
                          ? biggerData
                          // Second with smaller screen
                          : smallerData;
                    });
                  },
                ),
              ),
            ),
          ),
        );
      },
    ));

    // Tests with initial screen size
    testSize(initialSize);

    // Click On button to simulate changing screen size
    await tap();
    // Tests with bigger screen size
    testSize(biggerSize);

    // Click On button to simulate changing screen size
    await tap();
    // Tests with smaller screen size
    testSize(smallerSize);
  });
}
github-actions[bot] commented 2 years ago

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] commented 2 years ago

This issue was closed because it has been inactive for 14 days since being marked as stale.

sejun2 commented 2 years ago

@awaisjamil-vd I think you can test functionality by wrapping whole app within MediaQuery to simulate different screen sizes. Note: Don't use MediaQueryData.fromWindow. A simple example: (You can use (GlobalKey().currentContext?.findRenderObject() as RenderBox).size to get a widget size, See tutorials).

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

void main() {
  testWidgets('Test Responsiveness', (WidgetTester tester) async {
    // Declare Sizes
    const Size designSize = Size(360, 640);
    const Size initialSize = designSize;
    const Size biggerSize = Size(480, 920);
    const Size smallerSize = Size(300, 560);

    // We'll use MediaQuery to simulate diffrent screen sizes
    MediaQueryData currentData = MediaQueryData(size: initialSize);
    const MediaQueryData biggerData = MediaQueryData(size: biggerSize);
    const MediaQueryData smallerData = MediaQueryData(size: smallerSize);

    // Used to find a widget. See [CommonFinders.byKey].
    final _key = UniqueKey();

    // Click on button. See code bellow.
    Future<int> tap() async {
      await tester.tap(find.byKey(_key));
      return tester.pumpAndSettle();
    }

    void testSize(Size size) {
      expect(1.w, equals(size.width / designSize.width));
      expect(1.h, equals(size.height / designSize.height));
      print('[OK] Size: $size, width: ${1.w}, height: ${1.h}');
    }

    await tester.pumpWidget(StatefulBuilder(
      builder: (BuildContext context, StateSetter setState) {
        return MediaQuery(
          data: currentData,
          child: ScreenUtilInit(
            useInheritedMediaQuery: true,
            designSize: designSize,
            builder: (_) => MaterialApp(
              home: Material(
                child: TextButton(
                  key: _key,
                  child: Text('Change Screen Size'),
                  onPressed: () {
                    setState(() {
                      currentData = currentData.size == initialSize
                          // First test is with bigger screen
                          ? biggerData
                          // Second with smaller screen
                          : smallerData;
                    });
                  },
                ),
              ),
            ),
          ),
        );
      },
    ));

    // Tests with initial screen size
    testSize(initialSize);

    // Click On button to simulate changing screen size
    await tap();
    // Tests with bigger screen size
    testSize(biggerSize);

    // Click On button to simulate changing screen size
    await tap();
    // Tests with smaller screen size
    testSize(smallerSize);
  });
}

In my case, it does not work now... flutter_screenutil version :: 5.5.4 flutter version :: 3.0.5

I changed screenUtilInit's builder method to (context, widget){} for run without context error, then it spit such errors.

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following assertion was thrown building MediaQuery(MediaQueryData(size: Size(360.0, 640.0), devicePixelRatio: 1.0, textScaleFactor: 1.0, platformBrightness: Brightness.light, padding: EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, alwaysUse24HourFormat: false, accessibleNavigation: false, highContrast: false, disableAnimations: false, invertColors: false, boldText: false, navigationMode: traditional, gestureSettings: DeviceGestureSettings(touchSlop: 18.0), displayFeatures: [])): dependOnInheritedWidgetOfExactType() or dependOnInheritedElement() was called before _ScreenUtilInitState.initState() completed. When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget. Typically references to inherited widgets should occur in widget build() methods. Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.

The relevant error-causing widget was: MediaQuery MediaQuery:file:///Users/satoshi/Documents/flutter_projects/flutter_pdfview/testtest/test/screen_util_test.dart:35:16

When the exception was thrown, this was the stack:

0 StatefulElement.dependOnInheritedElement. (package:flutter/src/widgets/framework.dart:5056:9)

1 StatefulElement.dependOnInheritedElement (package:flutter/src/widgets/framework.dart:5099:6)

2 Element.dependOnInheritedWidgetOfExactType (package:flutter/src/widgets/framework.dart:4218:14)

3 MediaQuery.maybeOf (package:flutter/src/widgets/media_query.dart:941:20)

4 _ScreenUtilInitState.newData (package:flutter_screenutil/src/screenutil_init.dart:69:31)

5 _ScreenUtilInitState.initState (package:flutter_screenutil/src/screenutil_init.dart:92:22)

6 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4942:57)

7 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4781:5)

... Normal element mounting (15 frames)

22 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3817:16)

23 Element.updateChild (package:flutter/src/widgets/framework.dart:3545:20)

24 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1202:16)

25 RenderObjectToWidgetElement.update (package:flutter/src/widgets/binding.dart:1179:5)

26 RenderObjectToWidgetElement.performRebuild (package:flutter/src/widgets/binding.dart:1193:7)

27 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)

28 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)

29 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1183:19)

30 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)

31 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)

32 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)

33 AutomatedTestWidgetsFlutterBinding.pump. (package:flutter_test/src/binding.dart:1050:9)

36 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)

37 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1037:27)

38 WidgetTester.pumpWidget. (package:flutter_test/src/widget_tester.dart:548:22)

41 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)

42 WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:545:27)

43 main. (file:///Users/satoshi/Documents/flutter_projects/flutter_pdfview/testtest/test/screen_util_test.dart:33:18)

44 main. (file:///Users/satoshi/Documents/flutter_projects/flutter_pdfview/testtest/test/screen_util_test.dart:6:38)

45 testWidgets.. (package:flutter_test/src/widget_tester.dart:170:29)

(elided 5 frames from dart:async and package:stack_trace) ════════════════════════════════════════════════════════════════════════════════════════════════════ Test failed. See exception logs above. The test description was: Test Responsiveness I'm actually learning how to test screenutil applied screens, but I'm frustrating now because even sample code does not work .... Could you please update sample code for people like me ? Thanks a lot !
sejun2 commented 2 years ago

Here I attach my code.

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

void main() {
  testWidgets('Test Responsiveness', (WidgetTester tester) async {
    // Declare Sizes
    const Size designSize = Size(360, 640);
    const Size initialSize = designSize;
    const Size biggerSize = Size(480, 920);
    const Size smallerSize = Size(300, 560);

    // We'll use MediaQuery to simulate diffrent screen sizes
    MediaQueryData currentData = const MediaQueryData(size: initialSize);
    const MediaQueryData biggerData = MediaQueryData(size: biggerSize);
    const MediaQueryData smallerData = MediaQueryData(size: smallerSize);

    // Used to find a widget. See [CommonFinders.byKey].
    final _key = UniqueKey();

    // Click on button. See code bellow.
    Future<int> tap() async {
      await tester.tap(find.byKey(_key));
      return tester.pumpAndSettle();
    }

    void testSize(Size size) {
      expect(1.w, equals(size.width / designSize.width));
      expect(1.h, equals(size.height / designSize.height));
      print('[OK] Size: $size, width: ${1.w}, height: ${1.h}');
    }

    await tester.pumpWidget(StatefulBuilder(
      builder: (BuildContext context, StateSetter setState) {
        return MediaQuery(
          data: currentData,
          child: ScreenUtilInit(
            useInheritedMediaQuery: true,
            designSize: designSize,
            builder: (_context, _widget) => MaterialApp(
              home: Material(
                child: TextButton(
                  key: _key,
                  child: const Text('Change Screen Size'),
                  onPressed: () {
                    setState(() {
                      currentData = currentData.size == initialSize
                      // First test is with bigger screen
                          ? biggerData
                      // Second with smaller screen
                          : smallerData;
                    });
                  },
                ),
              ),
            ),
          ),
        );
      },
    ));

    // Tests with initial screen size
    testSize(initialSize);

    // Click On button to simulate changing screen size
    await tap();
    // Tests with bigger screen size
    testSize(biggerSize);

    // Click On button to simulate changing screen size
    await tap();
    // Tests with smaller screen size
    testSize(smallerSize);
  });
}
canavci312 commented 2 years ago

I have the exact same issue with @sejun2 I thought it was related to flutter 3.3.0 since I didn't have this issue last week. But your version seems to be 3.0.5 and still failing. Can we get any help from the author?

sejun2 commented 2 years ago

@canavci312 After removing MediaQuery widget, then it works fine.

canavci312 commented 2 years ago

@canavci312 After removing MediaQuery widget, then it works fine.

yes it works after deleting it but everything overflows now :( they weren't overflowing before

ZG-123 commented 8 months ago

,但现在所有内容都溢出了:(它们之前没有溢出

Hello, I have also encountered the same test problem at present, this code will directly report an error, is there any good way to test widgets containing flutter_screenutil plug-in?