Integration Test Preview allows tests on multiple screen sizes in a single e2e test run.

Overview

Integration Test Preview has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage (using Android and iOS platform UIs). This package is based upon the Integration Test Helper and Device Preview packages, and does much more with the combination of the two of them. It also allows for specific device size preview screenshots for the app stores, generated locally in your project path.

Integration Test Preview

Features

When running a test using a IntegrationTestPreview subclass, you can assign the devices that you want to test against (and take screenshots for). The following is an example of how you can test all your features end to end on multiple screen types:

import 'package:flutter_test/flutter_test.dart';
import 'package:device_frame/src/info/info.dart';
import 'package:device_frame/src/devices/devices.dart';
import 'package:integration_test_preview/integration_test_binding.dart';

import 'package:example/main.dart' as app;
import 'app_feature_groups.dart';

void main() async {

    final binding = IntegrationTestPreviewBinding.ensureInitialized();

    testWidgets('Testing end to end multi-screen integration', (WidgetTester tester) async {
      
          final main = app.setupMainWidget();
          final List<DeviceInfo> testDevices = [
            Devices.ios.iPhone12,
            Devices.android.samsungGalaxyNote20
          ];
          
          final integrationTestGroups = ScreenIntegrationTestGroups(binding);
          await integrationTestGroups.initializeDevices(testDevices, state: ScreenshotState.PREVIEW);
          await integrationTestGroups.initializeTests(tester, main);
          await integrationTestGroups.testDevicesEndToEnd();

      }, timeout: const Timeout(Duration(minutes: 3))
    );
    
}

Note: The testDevicesEndToEnd calls to your IntegrationTestPreview subclass implementation of testDeviceEndToEnd(DeviceInfo device).

Getting started

Note: This example uses another one of our packages. It's called the drawer_manager package, and can be found here for more details on how it works.

Install Provider, Drawer Manager & Integration Test Preview

  flutter pub get provider
  flutter pub get drawer_manager
  flutter pub get integration_test_preview

Or install Provider, Drawer Manager & Integration Test Preview (in pubspec.yaml)

    ...
    
dependencies:
  flutter:
    sdk: flutter

    ...

  provider: 6.0.2
  drawer_manager: 0.0.4
    
dev_dependencies:

  flutter_test:
    sdk: flutter

  integration_test:
    sdk: flutter

  integration_test_preview: 

Add Integration Test Driver file (test_driver/app_features_test.dart)

import 'dart:io';
import 'package:integration_test/integration_test_driver_extended.dart';

Future<void> main() => integrationDriver(
    onScreenshot: (String screenshotPath, List<int> screenshotBytes) async {
        
        final File image = File(screenshotPath);
        print('$image');

        final dir = image.parent;
        if(!await dir.exists()) await dir.create(recursive: true);

        image.writeAsBytesSync(screenshotBytes);
        
        return true;

    }
);

Usage

Create platforms file (lib/platforms.dart)

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class PlatformApp extends PlatformWidget {

  PlatformApp({
    Key? key,
    required MaterialApp androidApp,
    required CupertinoApp iosApp,
    required TargetPlatform defaultPlatform,
  }) : super(key: key,
      androidBuilder: (BuildContext context) => androidApp,
      iosBuilder:  (BuildContext context) => iosApp
    ) {
      PlatformWidget.setPlatform(defaultPlatform);
  }

}

class PlatformWidget extends StatefulWidget {
  
  static TargetPlatform? _defaultPlatform;

  static get platform {
      if(_defaultPlatform == null) {
        return TargetPlatform.android;
      }
      return _defaultPlatform;
  }

  static get isAndroid {
      return _defaultPlatform == TargetPlatform.android;
  }

  static get isIOS {
      return _defaultPlatform == TargetPlatform.iOS;
  }

  static void setPlatform(TargetPlatform platform) {
      _defaultPlatform = platform;
  }

  static void reassembleApplication() {
      WidgetsBinding.instance!.reassembleApplication();
  }

  const PlatformWidget({
    Key? key,
    required this.androidBuilder,
    required this.iosBuilder,
  }) : super(key: key);

  final WidgetBuilder androidBuilder;
  final WidgetBuilder iosBuilder;

  @override
  State<PlatformWidget> createState() => _PlatformWidgetState();
}

class _PlatformWidgetState extends State<PlatformWidget> {
  @override
  Widget build(context) {
    switch (PlatformWidget._defaultPlatform) {
      case TargetPlatform.android:
        return widget.androidBuilder(context);
      case TargetPlatform.iOS:      
        return widget.iosBuilder(context);        
      default:
        assert(false, 'Unexpected platform ${PlatformWidget._defaultPlatform}');
        return Container();
    }
  }
}

Create hello file (lib/hello.dart)

import 'package:flutter/material.dart';

class HelloPage extends StatelessWidget {

  final int position;
  
  const HelloPage({Key? key, required this.position}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        'Hello, Flutter $position!',
        key: Key('hello-page-text-$position'),
        textAlign: TextAlign.center,
        style: const TextStyle(
            color: Color(0xff0085E0),
            fontSize: 48,
            fontWeight: FontWeight.bold
        )
      ),
    );
  }
}

Create main file (lib/main.dart)

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:drawer_manager/drawer_manager.dart';

import 'platforms.dart';
import 'hello.dart';

void main() {
  runApp(setupMainWidget());
}

Widget setupMainWidget() {
  WidgetsFlutterBinding.ensureInitialized();
  return const MyApp();
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<DrawerManagerProvider>(
        create: (_) => DrawerManagerProvider(),
        child: PlatformApp(
            defaultPlatform: PlatformWidget.platform,
            androidApp: const MaterialApp(home: MyHomePage()),
            iosApp: const CupertinoApp(
                theme: CupertinoThemeData(brightness: Brightness.light),
                home: MyHomePage(),
            )
        )
      );
  }
}

class MyHomePage extends StatelessWidget {

  const MyHomePage({Key? key}) : super(key: key);

  String _getTitle(int index) {
      switch (index) {
        case 0: return 'Hello 1';
        case 1: return 'Hello 2';
        default: return '';
      }
  }

  Widget _getTitleWidget() {
    return Consumer<DrawerManagerProvider>(builder: (context, dmObj, _) {
      return Text(
        _getTitle(dmObj.selection),
        key: const Key('app-bar-text')
      );
    });
  }

  Widget _buildAndroidHomePage(BuildContext context) {

    final drawerSelections = [
      const HelloPage(position: 1),
      const HelloPage(position: 2),
    ];
    
    final manager = Provider.of<DrawerManagerProvider>(context, listen: false);

    return Scaffold(
        appBar: AppBar(title: _getTitleWidget()),
        body: manager.body,
        drawer: DrawerManager(
          context,
          drawerElements: [
            const DrawerHeader(
              decoration: BoxDecoration(color: Colors.blue),
              child: Padding(
                padding: EdgeInsets.only(bottom: 20),
                child: Icon(
                  Icons.account_circle,
                  color: Colors.blueGrey,
                  size: 96,
                ),
              ),
            ),
            DrawerTile(
              key: const Key('drawer-hello-1'),
              context: context,
              leading: const Icon(Icons.hail_rounded),
              title: Text(_getTitle(0)),
              onTap: () async {
                // RUN A BACKEND Hello, Flutter OPERATION
              },
            ),
            DrawerTile(
              key: const Key('drawer-hello-2'),
              context: context,
              leading: const Icon(Icons.hail_rounded),
              title: Text(_getTitle(1)),
              onTap: () async {
                // RUN A BACKEND Hello, Flutter OPERATION
              },
            )
          ],
          tileSelections: drawerSelections,
        ));
    }

  Widget _buildIosHomePage(BuildContext context) {

    return CupertinoTabScaffold(
        tabBar: CupertinoTabBar(
            items: [
                BottomNavigationBarItem(
                    label: _getTitle(0),
                    icon: const Icon(Icons.hail_rounded),
                ),
                BottomNavigationBarItem(
                    label: _getTitle(1),
                    icon: const Icon(Icons.hail_rounded),
                ),
            ],
        ),
        // ignore: avoid_types_on_closure_parameters
        tabBuilder: (BuildContext context, int index) {
            final title = _getTitle(index);
            switch (index) {
            case 0:
                return CupertinoTabView(
                    builder: (context) => const HelloPage(position: 1),
                );
            case 1:
                return CupertinoTabView(
                    builder: (context) => const HelloPage(position: 2),
                );
            default:
                assert(false, 'Unexpected tab');
                return Container();
            }
        },
    );
  }

  @override
  Widget build(context) {
    return PlatformWidget(
      androidBuilder: _buildAndroidHomePage,
      iosBuilder: _buildIosHomePage,
    );
  }

}

Import Flutter Test & Integration Test Preview (in integration_test/app_feature_groups.dart)

    ...
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:device_frame/src/info/info.dart';
import 'package:integration_test_preview/integration_test_preview.dart';

import 'package:example/platforms.dart';

Subclass IntegrationTestPreview (in integration_test/app_feature_groups.dart)

The Integration Test Preview supports platform specific implementations, for methods like the showHelloFlutter method. This method uses the Drawer for Android and accomodates the Android environment UI interations. And uses the Tab Bar for iOS and accomodates the iOS environment UI interations.

class ScreenIntegrationTestGroups extends IntegrationTestPreview {

    ScreenIntegrationTestGroups(binding) : super(binding);

    // ...

    @override
    Future<void> setupInitialData() async {
        // ...
    }

    @override
    Future<BuildContext> getBuildContext() async {
        if(await isPlatformAndroid()) {
          final elementType = find.byType(MaterialApp);
          return tester.element(elementType);
        } else {
          final elementType = find.byType(CupertinoApp);
          return tester.element(elementType);
        }
    }
    
    @override
    Future<void> togglePlatformUI(TargetPlatform platform) async {
        PlatformWidget.setPlatform(platform);
        PlatformWidget.reassembleApplication();
        await waitForUI(durationMultiple: 2);
    }
    
    @override
    Future<void> testDeviceEndToEnd(DeviceInfo device) async {

        await waitForUI(durationMultiple: 2);
        await testHelloFlutterFeature();

    }

    Future<void> showHelloFlutter({required int position}) async {
        print('Showing Hello, Flutter $position!');
        if(PlatformWidget.isAndroid) {
            await tapForTooltip('Open navigation menu');
            await tapForKey('drawer-hello-$position');
        } else {
            await tapWidget('Hello $position');
        }
        await waitForUI();
    }

    Future<void> setupScreenshot(String fileName) async {
        String platformType = PlatformWidget.isAndroid ? 'android' : 'ios';
        String screenshotPath = 'screenshots/$platformType/$fileName.png';
        print('Setting up screenshot: $screenshotPath');
        await takeScreenshot(screenshotPath);
    }

    Future<void> verifyAppBarText(String text) async {

        if(PlatformWidget.isAndroid) {
            await verifyTextForKey('app-bar-text', text);
        }
      
    }

    Future<void> testHelloFlutterFeature() async {
        await showHelloFlutter(position: 1);
        await verifyAppBarText('Hello 1');
        await verifyTextForKey('hello-page-text-1', 'Hello, Flutter 1!');
        await setupScreenshot('hello_flutter_1');

        await showHelloFlutter(position: 2);
        await verifyAppBarText('Hello 2');
        await verifyTextForKey('hello-page-text-2', 'Hello, Flutter 2!');
        await setupScreenshot('hello_flutter_2');
    }

    // ...

}

Setup IntegrationTestPreview Subclass (in integration_test/app_features.dart)

import 'package:flutter_test/flutter_test.dart';
import 'package:device_frame/src/info/info.dart';
import 'package:device_frame/src/devices/devices.dart';
import 'package:integration_test_preview/integration_test_binding.dart';

import 'package:example/main.dart' as app;
import 'app_feature_groups.dart';

void main() async {

    final binding = IntegrationTestPreviewBinding.ensureInitialized();

    testWidgets('Testing end to end multi-screen integration', (WidgetTester tester) async {
      
          final main = app.setupMainWidget();
          final List<DeviceInfo> testDevices = [
            Devices.ios.iPhone12,
            Devices.android.samsungGalaxyNote20
          ];
          
          final integrationTestGroups = ScreenIntegrationTestGroups(binding);
          await integrationTestGroups.initializeDevices(testDevices, state: ScreenshotState.PREVIEW);
          await integrationTestGroups.initializeTests(tester, main);
          await integrationTestGroups.testDevicesEndToEnd();

      }, timeout: const Timeout(Duration(minutes: 3))
    );
    
}

Run Driver on IntegrationTestPreview Subclass (using integration_test/app_features.dart)

    flutter drive -t integration_test/app_features.dart

Review the screenshot results

The screenshots used in setupScreenshot are generated after the test completes...

Integration Testing Screenshots

Android Hello 1

Android Hello 2

iOS Hello 1

iOS Hello 2

Additional information

Alternatively, you can run the example

The example project has 5 screens that have grouped integration tests:

Package Support

To support this repo, take a look at the SUPPORT.md file.

Package Documentation

To view the documentation on the package, follow this link

You might also like...

Getx and Dio APi-Integration - Flutter RestApi Integration using Dio

Getx and Dio APi-Integration - Flutter RestApi Integration using Dio

Flutter RestApi Integration using Dio. Click this image to find videos== //Crud

Nov 5, 2022

Flutter-fb-integration - Flutter And firebase integration Guide

Flutter-fb-integration - Flutter And firebase integration Guide

Quickstart Guide This project still use my firebase server config, if you want t

Feb 2, 2022

FLutter Api Integration - Flutter Rest API Integration

FLutter Api Integration - Flutter Rest API Integration

Flutter_Rest_Api_integration Flutter_Rest_Api_integration. Preview How To Use To

Feb 17, 2022

Doctor Consultation App in Flutter containing splash screen on boarding screen Routing state management Dash board Bottom navigation Decorated Drawer and Doctors Screen in the last.

Doctor Consultation App in Flutter containing splash screen on boarding screen  Routing  state management Dash board Bottom navigation Decorated Drawer and Doctors Screen in the last.

Online doctor Consultation App UI in Flutter Doctor Consultation App UI in Flutter Visit Website Features State Management Navigation Bar Responsive D

Jan 1, 2023

RelativeScale is a simple custom sizing system for flutter widgets to achieve the same physical sizes across different devices.

RelativeScale is a simple custom sizing system for flutter widgets to achieve the same physical sizes across different devices.

RelativeScale is a simple custom sizing system for flutter widgets to achieve the same physical sizes across different devices. Usage It is VERY easy

Nov 25, 2022

A CustomPaint example where we can draw with different colors and different stroke sizes

A CustomPaint example where we can draw with different colors and different stroke sizes

CustomPaint A CustomPaint example where we can draw with different colors and different stroke sizes. A Flutter application which runs on iOS, Android

Dec 27, 2021

Flutter Multi-platform allows developers to unleash their app to run on the wide variety of different platforms with little or no change.

Flutter Multi-platform allows developers to unleash their app to run on the wide variety of different platforms with little or no change.

Flutter Multi-platform sample Flutter Multi-platform allows developers to unleash their app to run on the wide variety of different platforms with lit

Dec 31, 2022

Flutter plugin to get link preview meta-data

Flutter plugin to get link preview meta-data

link_preview A Rich Link Preview flutter plugin. Usage To use this plugin, add link_preview as a dependency in your pubspec.yaml file. Example import

Jun 23, 2021
Comments
  • Lessen dependency on Drawer and Device Preview

    Lessen dependency on Drawer and Device Preview

    I think a package like this is actually really needed in the Flutter ecosystem but the setup process is really too much. It would be great to see this simplified.

    It's also a bit weird that this package considers device_preview its surface of interaction (as in it specifically relies on it device_preview and the sidebar being there to function) rather than using something lower level such as implicitly resizing screen through integration_test and wrapping that image around device_frame if necessary.

    enhancement help wanted 
    opened by Nolence 2
  • Package won't publish

    Package won't publish

    The package won't publish due to the pubspec.yaml device_preview git reference.

    Screen Shot 2022-03-27 at 8 56 18 AM

    This is the current pubspec.yaml:

    name: integration_test_preview
    description: Integration Test Preview has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage (using Android and iOS platform UIs). This package is based upon the Integration Test Helper and Device Preview packages, and does much more with the combination of the two of them. It also allows for specific device size preview screenshots for the app stores, generated locally in your project path.
    version: 0.0.1
    homepage: https://github.com/the-mac/integration_test_preview
    
    environment:
      sdk: ">=2.15.1 <3.0.0"
      flutter: ">=1.17.0"
    
    dependencies:
    
      flutter:
        sdk: flutter
    
      flutter_test:
        sdk: flutter
    
      integration_test:
        sdk: flutter
      
      integration_test_helper: ^0.0.2
    
      device_preview:
        git:
          url: https://github.com/the-mac/flutter_device_preview.git
          path: device_preview/
          ref: master
    
    dev_dependencies:
      flutter_lints: ^1.0.0
    
    flutter:
    
    
    opened by cdm2012 1
  • Failed setup

    Failed setup

    The package installs but, when running I get the following error:

    
    Try correcting the name to the name of an existing setter, or defining a setter or field named 'waitForMilliseconds'.
            this.waitForMilliseconds = waitForMilliseconds;
                 ^^^^^^^^^^^^^^^^^^^
    
    
    opened by cdm2012 0
  • Smaller to larger device RenderFlow

    Smaller to larger device RenderFlow

    Although the test ends with a failure, the screenshots are still generated. But, when changing from a Medium Phone size to a Medium Tablet size, there is an RenderFlow exception when using a Row widget.

    
    I/flutter (27873): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
    I/flutter (27873): The following assertion was thrown during layout:
    I/flutter (27873): A RenderFlex overflowed by 155 pixels on the right.
    I/flutter (27873): 
    I/flutter (27873): The relevant error-causing widget was:
    I/flutter (27873):   Row
    I/flutter (27873):   Row:file:///.../lib/core/widgets/the_mac.dart:26:20
    I/flutter (27873): 
    I/flutter (27873): The overflowing RenderFlex has an orientation of Axis.horizontal.
    I/flutter (27873): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
    I/flutter (27873): black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
    I/flutter (27873): Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
    I/flutter (27873): RenderFlex to fit within the available space instead of being sized to their natural size.
    I/flutter (27873): This is considered an error condition because it indicates that there is content that cannot be
    I/flutter (27873): seen. If the content is legitimately bigger than the available space, consider clipping it with a
    I/flutter (27873): ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
    I/flutter (27873): like a ListView.
    I/flutter (27873): The specific RenderFlex in question is: RenderFlex#f4207 OVERFLOWING:
    I/flutter (27873):   creator: Row ← DecoratedBox ← ConstrainedBox ← Padding ← Container ← ResponsiveContainer ← Listener
    I/flutter (27873):     ← _GestureSemantics ← RawGestureDetector ← SocialButton ← Column ← MediaQuery ← ⋯
    I/flutter (27873):   parentData: <none> (can use size)
    I/flutter (27873):   constraints: BoxConstraints(w=292.0, h=100.0)
    I/flutter (27873):   size: Size(292.0, 100.0)
    I/flutter (27873):   direction: horizontal
    I/flutter (27873):   mainAxisAlignment: center
    I/flutter (27873):   mainAxisSize: min
    I/flutter (27873):   crossAxisAlignment: center
    I/flutter (27873):   textDirection: ltr
    I/flutter (27873):   verticalDirection: down
    I/flutter (27873): ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
    I/flutter (27873): ════════════════════════════════════════════════════════════════════════════════════════════════════
    I/flutter (27873): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
    I/flutter (27873): The following assertion was thrown during layout:
    I/flutter (27873): A RenderFlex overflowed by 104 pixels on the right.
    I/flutter (27873): 
    I/flutter (27873): The relevant error-causing widget was:
    I/flutter (27873):   Row
    I/flutter (27873):   Row:file:///.../lib/core/widgets/the_mac.dart:26:20
    I/flutter (27873): 
    I/flutter (27873): The overflowing RenderFlex has an orientation of Axis.horizontal.
    I/flutter (27873): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
    I/flutter (27873): black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
    I/flutter (27873): Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
    I/flutter (27873): RenderFlex to fit within the available space instead of being sized to their natural size.
    I/flutter (27873): This is considered an error condition because it indicates that there is content that cannot be
    I/flutter (27873): seen. If the content is legitimately bigger than the available space, consider clipping it with a
    I/flutter (27873): ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
    I/flutter (27873): like a ListView.
    I/flutter (27873): The specific RenderFlex in question is: RenderFlex#cb32a OVERFLOWING:
    I/flutter (27873):   creator: Row ← DecoratedBox ← ConstrainedBox ← Padding ← Container ← ResponsiveContainer ← Listener
    I/flutter (27873):     ← _GestureSemantics ← RawGestureDetector ← SocialButton ← Column ← MediaQuery ← ⋯
    I/flutter (27873):   parentData: <none> (can use size)
    I/flutter (27873):   constraints: BoxConstraints(w=292.0, h=100.0)
    I/flutter (27873):   size: Size(292.0, 100.0)
    I/flutter (27873):   direction: horizontal
    I/flutter (27873):   mainAxisAlignment: center
    I/flutter (27873):   mainAxisSize: min
    I/flutter (27873):   crossAxisAlignment: center
    I/flutter (27873):   textDirection: ltr
    I/flutter (27873):   verticalDirection: down
    I/flutter (27873): ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
    I/flutter (27873): ════════════════════════════════════════════════════════════════════════════════════════════════════
    I/flutter (27873): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
    I/flutter (27873): The following assertion was thrown during layout:
    I/flutter (27873): A RenderFlex overflowed by 120 pixels on the bottom.
    I/flutter (27873): 
    I/flutter (27873): The relevant error-causing widget was:
    I/flutter (27873):   Column
    I/flutter (27873):   Column:file:///.../lib/core/widgets/the_mac.dart:124:12
    I/flutter (27873): 
    I/flutter (27873): The overflowing RenderFlex has an orientation of Axis.vertical.
    I/flutter (27873): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
    I/flutter (27873): black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
    I/flutter (27873): Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
    I/flutter (27873): RenderFlex to fit within the available space instead of being sized to their natural size.
    I/flutter (27873): This is considered an error condition because it indicates that there is content that cannot be
    I/flutter (27873): seen. If the content is legitimately bigger than the available space, consider clipping it with a
    I/flutter (27873): ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
    I/flutter (27873): like a ListView.
    I/flutter (27873): The specific RenderFlex in question is: RenderFlex#6e864 relayoutBoundary=up3 OVERFLOWING:
    I/flutter (27873):   creator: Column ← MediaQuery ← Padding ← SafeArea ← Padding ← Stack ← DecoratedBox ←
    I/flutter (27873):     CupertinoPageScaffold ← PlatformWidget ← TheMACPage ← LayoutBuilder ← Semantics ← ⋯
    I/flutter (27873):   parentData: offset=Offset(0.0, 24.0) (can use size)
    I/flutter (27873):   constraints: BoxConstraints(0.0<=w<=412.0, 0.0<=h<=892.0)
    I/flutter (27873):   size: Size(412.0, 892.0)
    I/flutter (27873):   direction: vertical
    I/flutter (27873):   mainAxisAlignment: center
    I/flutter (27873):   mainAxisSize: max
    I/flutter (27873):   crossAxisAlignment: center
    I/flutter (27873):   verticalDirection: down
    I/flutter (27873): ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
    I/flutter (27873): ════════════════════════════════════════════════════════════════════════════════════════════════════
    
    

    Here is the source code that causes that error:

    
    import 'package:flutter/material.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:template_items/core/util/build_config.dart';
    
    import 'package:webview_flutter/webview_flutter.dart';
    import 'package:font_awesome_flutter/font_awesome_flutter.dart';
    import 'package:responsive_widgets_prefix/responsive_widgets_prefix.dart';
    
    import 'package:template_items/core/widgets/platforms.dart';
    
    Map launchResults = {};
    
    class SocialButton extends GestureDetector {
      SocialButton(String title, Color color, IconData icon, {Key? key, required Function() onTap})
          : super(
              key: key,
              onTap: onTap,
              child: ResponsiveContainer(
                height: 40,
                width: 350,
                margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 60),
                decoration: BoxDecoration(
                    color: color,
                    borderRadius: const BorderRadius.all(Radius.circular(10))
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    ResponsiveIcon(
                      icon,
                      color: Colors.white,
                    ),
                    ResponsiveContainer(
                      margin: const EdgeInsets.only(left: 20),
                      child: ResponsiveText(
                        title,
                        style: const TextStyle(
                            color: Colors.white,
                            fontSize: 18,
                            fontWeight: FontWeight.w400)
                        ),
                    ),
                  ],
                ),
              )
            );
    }
    
    class WebViewContainer extends StatelessWidget {
    
      final String webViewUrl;
    
      const WebViewContainer(this.webViewUrl, {Key? key}) : super(key: key);
    
      Widget _buildBody(BuildContext context) {
    
        return Container(
            child: WebView(
              initialUrl: webViewUrl,
              javascriptMode: JavascriptMode.unrestricted,
              onPageFinished: (url) {
                  print('url: $url');
                  launchResults[url] = true;
              },
              debuggingEnabled: false,
            ),
            decoration: BoxDecoration(
                border: Border.all(color: Colors.blue)
            )
        );
      }
    
      Widget _buildAndroid(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: _buildBody(context)
        );
      }
    
      Widget _buildIOS(BuildContext context) {
        return CupertinoPageScaffold(
          navigationBar: const CupertinoNavigationBar(),
          child: SafeArea(
            child: _buildBody(context)
          )
        );
      }
    
    
      @override
      Widget build(context) {
        return PlatformWidget(
          androidBuilder: _buildAndroid,
          iosBuilder: _buildIOS,
        );
      }
    }
    
    class TheMACPage extends StatelessWidget {
    
      static const facebookURL = 'https://m.facebook.com/groups/694991294608697/';
      static const githubURL = 'https://github.com/the-mac';
    
      const TheMACPage({Key? key}) : super(key: key);
    
    
      Widget _buildAndroid(BuildContext context) {
        return Scaffold(
          body: _buildBody(context)
        );
      }
    
      Widget _buildIOS(BuildContext context) {
        return CupertinoPageScaffold(
          backgroundColor: Colors.white,
          child: SafeArea(
            child: _buildBody(context)
          )
        );
      }
    
      Widget _buildBody(BuildContext context) {
        return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              const Padding(
                padding: EdgeInsets.symmetric(vertical: 16),
              ),
              Center(
                // margin: const EdgeInsets.only(top: 20, bottom: 20),
                child: ResponsiveText(
                  'Welcome to\nThe Mobile Apps Community!',
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                      color: Color(0xff0085E0),
                      fontSize: 28,
                      fontWeight: FontWeight.bold
                    )
                  ),
              ),
              const Padding(
                padding: EdgeInsets.symmetric(vertical: 16),
              ),
              ResponsiveImage.asset(
                'assets/images/the-mac-avatar.jpeg',
                width: 320
              ),
              const Padding(
                padding: EdgeInsets.symmetric(vertical: 16),
              ),
              SocialButton(
                'Check out our Facebook',
                const Color(0xff39579A),
                FontAwesomeIcons.facebookF,
                onTap: () async {
                    Navigator.push<void>(
                      context, MaterialPageRoute( builder: (BuildContext context) => const WebViewContainer(facebookURL))
                    );
                }
              ),
              SocialButton(
                'Check out our Github',
                Colors.black,
                FontAwesomeIcons.github,
                onTap: () async {
                    Navigator.push<void>(
                      context, MaterialPageRoute( builder: (BuildContext context) => const WebViewContainer(githubURL))
                    );
                }
              ),
            ],
        );
      }
    
      @override
      Widget build(context) {
        return PlatformWidget(
          androidBuilder: _buildAndroid,
          iosBuilder: _buildIOS,
        );
      }
    }
    
    
    
    opened by cdm2012 0
Owner
The Mobile Applications Community
The Mobile Applications Community is where apps can be built using community resources.
The Mobile Applications Community
Integration test - Copy of the official Flutter integration test plugin

integration_test This package enables self-driving testing of Flutter code on de

null 0 Jan 5, 2022
Ouday 25 Dec 15, 2022
Android test task master - Create PIN code screen, authentication by PIN code screen and menu screen

Here is described test tasks for a android dev. Need to implement three screens:

null 3 Oct 4, 2022
Ozzie is your testing friend. Ozzie will take an screenshot during integration tests whenever you need. Ozzie will capture performance reports for you.

ozzie.flutter Ozzie is your testing friend. Ozzie will take an screenshot during integration tests whenever you need. Ozzie will capture performance r

Jorge Coca 40 Nov 3, 2022
An E-Commerce application developed on Flutter, which helps to run the app on Android / IOS / Windows's OS / MacOS / Web Browser from a single codebase

BuySmart An E-Commerce application developed on Flutter, which helps to run the app on Android / IOS / Windows's OS / MacOS / Web Browser from a singl

Sumit Kumar 11 Oct 10, 2022
Flutter Navigation - all types of navigation in flutter run main.tabBar.dart to see tabBar, and run main.dart to see the otheres

pop_up_bar A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if th

Michael Odumosu 0 Jan 1, 2022
PrivateFit is an E2E encrypted fitness application built on the atPlatform.

Private Fit Now for a little internet optimism Generated by the at_app CLI and Very Good CLI ?? A secure fitness app. Getting Started ?? This project

The Atsign Foundation 6 Oct 31, 2022
AI Library to create efficient Artificial Neural Networks. Computation uses SIMD (Single Instruction Multiple Data) to improve performance.

eneural_net eNeural.net / Dart is an AI Library for efficient Artificial Neural Networks. The library is portable (native, JS/Web, Flutter) and the co

null 21 Dec 29, 2022
Lite version of smart_select package, zero dependencies, an easy way to provide a single or multiple choice chips.

Lite version of smart_select package, zero dependencies, an easy way to provide a single or multiple choice chips. What's New in Version 2.x.x Added p

Irfan Vigma Taufik 97 Dec 15, 2022
null 0 Feb 2, 2022