From 4c6d6882f76b6f9be2d081b9e2ab7f17d90215ad Mon Sep 17 00:00:00 2001 From: yungwenpeng Date: Thu, 10 Nov 2022 10:26:16 +0800 Subject: [PATCH] Modify testing for scenarios How to use: $ flutter drive --driver=test/test_driver/perf_driver.dart --target=test/scenarios/scenarios.dart -d chrome --- pubspec.lock | 61 ++++++++++++++++++- pubspec.yaml | 7 +++ test/scenarios/login.dart | 84 ++++++++++++++++++++++++++ test/scenarios/scenarios.dart | 7 +++ test/scenarios/userapi.dart | 97 +++++++++++++++++++++++++++++++ test/test_driver/perf_driver.dart | 3 + test/widget_test.dart | 3 + 7 files changed, 260 insertions(+), 2 deletions(-) create mode 100755 test/scenarios/login.dart create mode 100755 test/scenarios/scenarios.dart create mode 100755 test/scenarios/userapi.dart create mode 100755 test/test_driver/perf_driver.dart diff --git a/pubspec.lock b/pubspec.lock index de13bfb..201141b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.1.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.0" args: dependency: transitive description: @@ -182,7 +189,7 @@ packages: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.1.4" + version: "6.1.2" fixnum: dependency: transitive description: @@ -202,6 +209,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.2" + flutter_driver: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" flutter_lints: dependency: "direct dev" description: @@ -287,6 +299,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" glob: dependency: transitive description: @@ -301,6 +318,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.5" + http_mock_adapter: + dependency: "direct dev" + description: + name: http_mock_adapter + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" http_multi_server: dependency: transitive description: @@ -315,6 +346,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.1" + integration_test: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" intl: dependency: "direct main" description: @@ -414,7 +450,7 @@ packages: source: hosted version: "2.1.0" path: - dependency: transitive + dependency: "direct main" description: name: path url: "https://pub.dartlang.org" @@ -614,6 +650,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + sync_http: + dependency: transitive + description: + name: sync_http + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.1" term_glyph: dependency: transitive description: @@ -663,6 +706,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "9.0.0" watcher: dependency: transitive description: @@ -677,6 +727,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.0" + webdriver: + dependency: transitive + description: + name: webdriver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2c137dd..4ec7b75 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -27,6 +27,8 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: + integration_test: + sdk: flutter flutter: sdk: flutter flutter_localizations: @@ -47,8 +49,12 @@ dependencies: json_annotation: ^4.7.0 dio: ^4.0.6 jwt_decoder: ^2.0.1 + path: ^1.8.2 + http: ^0.13.5 dev_dependencies: + flutter_driver: + sdk: flutter flutter_test: sdk: flutter @@ -61,6 +67,7 @@ dev_dependencies: build_runner: ^2.3.2 freezed: ^2.2.0 json_serializable: ^6.5.3 + http_mock_adapter: ^0.3.3 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/scenarios/login.dart b/test/scenarios/login.dart new file mode 100755 index 0000000..cd4d9b4 --- /dev/null +++ b/test/scenarios/login.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:thingsboard_app/models/user_provider.dart'; +import 'package:thingsboard_app/pages/pages.dart'; + +Widget createLoginScreen() => ChangeNotifierProvider( + create: (context) => UserBaseProvider(), + child: const MaterialApp( + home: Login(), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: [ + Locale('en', ''), + ], + ), + ); + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('Login Page Widget Tests : ', () { + testWidgets('Testing if SingleChildScrollView shows up', (tester) async { + // Build the widget + await tester.pumpWidget(createLoginScreen()); + expect(find.byType(SingleChildScrollView), findsOneWidget); + }); + + testWidgets('Testing Scrolling', (tester) async { + await tester.pumpWidget(createLoginScreen()); + expect(find.widgetWithText(TextFormField, 'Username(email)'), + findsOneWidget); + // Scroll until the item to be found appears. + await tester.fling( + find.byType(SingleChildScrollView), const Offset(0, -200), 3000); + await tester.pumpAndSettle(); + expect(find.byIcon(Icons.login), findsWidgets); + }); + + testWidgets('validating error message when username input error', + (tester) async { + await tester.pumpWidget(createLoginScreen()); + /* + Steps: + 1. Enter 'test' into the username TextFormField + 2. Tap the login button + 3. Expect to show the snackbar on screen. + */ + await tester.enterText( + find.widgetWithText(TextFormField, 'Username(email)'), 'test'); + await tester.tap(find.byIcon(Icons.login)); + await tester.pumpAndSettle(); + expect(find.text('Please fix the errors in red before submitting.'), + findsOneWidget); + expect(find.text('Username(email) need @ character'), findsOneWidget); + }); + + testWidgets('validating error message when password input error', + (tester) async { + var inputText = '12'; + await tester.pumpWidget(createLoginScreen()); + /* + Steps: + 1. Enter 'test' into the password TextFormField + 2. Tap the visibility_off icon, verify inputText and visibility icon + 2. Tap the login button + 3. Expect to show the snackbar on screen. + */ + await tester.enterText( + find.widgetWithText(TextFormField, 'Password'), inputText); + await tester.tap(find.byIcon(Icons.visibility_off)); + expect(find.text(inputText), findsOneWidget); + await tester.pumpAndSettle(); + expect(find.byIcon(Icons.visibility), findsOneWidget); + await tester.tap(find.byIcon(Icons.login)); + await tester.pumpAndSettle(); + expect(find.text('Please fix the errors in red before submitting.'), + findsOneWidget); + expect(find.text('Minimum character length is 6'), findsOneWidget); + }); + }); +} diff --git a/test/scenarios/scenarios.dart b/test/scenarios/scenarios.dart new file mode 100755 index 0000000..10c0daa --- /dev/null +++ b/test/scenarios/scenarios.dart @@ -0,0 +1,7 @@ +import 'login.dart' as login; +import 'userapi.dart' as userapi; + +void main() { + //login.main(); + userapi.main(); +} diff --git a/test/scenarios/userapi.dart b/test/scenarios/userapi.dart new file mode 100755 index 0000000..d36b7a5 --- /dev/null +++ b/test/scenarios/userapi.dart @@ -0,0 +1,97 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:http/http.dart'; +import 'package:flutter_test/flutter_test.dart'; +//import 'package:dio/dio.dart'; +//import 'package:http_mock_adapter/http_mock_adapter.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + /*late Dio dio; + late DioAdapter dioAdapter; + Response response; + + group('RestApi Tests', () { + setUp(() { + dio = Dio(BaseOptions(baseUrl: 'http://localhost:3000')); + dioAdapter = DioAdapter( + dio: dio, + matcher: const FullHttpRequestMatcher(), + ); + }); + tearDown(() { + dioAdapter.close(); + dio.close(force: true); + }); + test('Testing getUser', () async { + const route = '/api/users?query=user1@test.com'; + const userInformation = { + "userName": "user1", + "email": "user1@test.com", + "role": "user" + }; + + dioAdapter.onGet(route, (server) { + server.reply(200, userInformation); + }); + response = await dio.get(route); + print(response.data); + expect(response.statusCode, 200); + expect(response.data, userInformation); + }); + });*/ + + late String apiUrl; + late String userName; + + group('RestAPI Test: ', () { + setUpAll(() { + HttpOverrides.global = null; + apiUrl = 'http://localhost:3000'; + userName = 'test@test.com'; + }); + + test('Testing signup', () async { + var userInformation = { + "userName": "test", + "email": userName, + "password": "string", + "role": "user" + }; + var client = Client(); + await client.delete(Uri.parse('$apiUrl/api/users/$userName')); + var response = await client.post( + Uri.parse('$apiUrl/api/users/signup'), + body: userInformation, + ); + client.close(); + final extractedData = json.decode(response.body); + expect(response.statusCode, 200); + expect(extractedData['email'], userName); + await Future.delayed(const Duration(seconds: 2)); + }); + + test('Testing getUser', () async { + var client = Client(); + var response = + await client.get(Uri.parse('$apiUrl/api/users?query=$userName')); + client.close(); + final extractedData = json.decode(response.body); + expect(response.statusCode, 200); + expect(extractedData['email'], userName); + await Future.delayed(const Duration(seconds: 5)); + }); + + test('Testing delete user', () async { + var client = Client(); + var response = + await client.delete(Uri.parse('$apiUrl/api/users/$userName')); + client.close(); + expect(response.statusCode, 200); + expect(response.body, 'OK'); + await Future.delayed(const Duration(seconds: 1)); + }); + }); +} diff --git a/test/test_driver/perf_driver.dart b/test/test_driver/perf_driver.dart new file mode 100755 index 0000000..8c57f7d --- /dev/null +++ b/test/test_driver/perf_driver.dart @@ -0,0 +1,3 @@ +import 'package:integration_test/integration_test_driver.dart'; + +Future main() async => await integrationDriver(); diff --git a/test/widget_test.dart b/test/widget_test.dart index f6bde38..99a32b3 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -5,6 +5,7 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. +import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -102,6 +103,8 @@ void main() { .getUrl(Uri.parse('$apiUrl/api/users?query=user1@test.com')); final HttpClientResponse response = await request.close(); + final stringData = await response.transform(utf8.decoder).join(); + print(stringData); expect(response.statusCode, 200); }); });