This commit is contained in:
J. A. Messias 2025-01-13 16:11:06 -03:00
parent 08016c53b8
commit a8c7897eff
19 changed files with 735 additions and 588 deletions

View File

@ -1,2 +1,2 @@
gradle 8.10.2 gradle 8.10.2
kotlin 2.0.20 kotlin 1.8.22

View File

@ -53,9 +53,15 @@ android {
versionName flutterVersionName versionName flutterVersionName
multiDexEnabled true multiDexEnabled true
consumerProguardFiles 'proguard-rules.pro' consumerProguardFiles 'proguard-rules.pro'
testInstrumentationRunner "pl.leancode.patrol.PatrolJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: "true"
} }
testOptions {
execution "ANDROIDX_TEST_ORCHESTRATOR"
}
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true coreLibraryDesugaringEnabled true
@ -94,6 +100,8 @@ android {
debug { debug {
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
minifyEnabled false
shrinkResources false
} }
} }
} }
@ -113,6 +121,11 @@ dependencies {
} }
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
androidTestUtil "androidx.test:orchestrator:1.5.1"
// androidTestImplementation 'androidx.test:runner:1.4.0'
// androidTestImplementation 'androidx.test:rules:1.4.0'
} }
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'

View File

@ -0,0 +1,36 @@
package com.freaccess.hub;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import pl.leancode.patrol.PatrolJUnitRunner;
@RunWith(Parameterized.class)
public class MainActivityTest {
private final String dartTestName;
public MainActivityTest(String dartTestName) {
this.dartTestName = dartTestName;
}
@Parameters(name = "{0}")
public static Object[] testCases() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
// replace "MainActivity.class" with "io.flutter.embedding.android.FlutterActivity.class"
// if in AndroidManifest.xml in manifest/application/activity you have
// android:name="io.flutter.embedding.android.FlutterActivity"
instrumentation.setUp(MainActivity.class);
instrumentation.waitForPatrolAppService();
return instrumentation.listDartTests();
}
@Test
public void runDartTest() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
instrumentation.runDartTest(dartTestName);
}
}

View File

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '2.0.20' // Replace with the latest version ext.kotlin_version = '1.8.22'
ext.gradle_version = '8.6.0' // Replace with the latest version ext.gradle_version = '8.6.0' // Replace with the latest version
ext.google_services_version = '4.4.2' // Replace with the latest version ext.google_services_version = '4.4.2' // Replace with the latest version
repositories { repositories {
@ -8,12 +8,14 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath "com.android.tools.build:gradle:$gradle_version" // Use a versão do Gradle que corresponde à sua configuração classpath "com.android.tools.build:gradle:$gradle_version"
// Use a versão do Gradle que corresponde à sua configuração
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:$google_services_version" // Google Services plugin classpath "com.google.gms:google-services:$google_services_version"
} // Google Services plugin
}
} }
allprojects { allprojects {
repositories { repositories {
google() google()

View File

@ -20,7 +20,7 @@ plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id 'com.android.application' version '8.6.0' apply false id 'com.android.application' version '8.6.0' apply false
id 'com.android.library' version '8.6.0' apply false id 'com.android.library' version '8.6.0' apply false
id 'org.jetbrains.kotlin.android' version '2.0.20' apply false id 'org.jetbrains.kotlin.android' version '1.8.22' apply false
// START: FlutterFire Configuration // START: FlutterFire Configuration
@ -29,8 +29,7 @@ plugins {
// id "org.jetbrains.kotlin.android" version "1.7.10" apply false // id "org.jetbrains.kotlin.android" version "1.7.10" apply false
// id "org.jetbrains.kotlin.android" version "1.8.10" apply false // id "org.jetbrains.kotlin.android" version "1.8.10" apply false
} }
include ":app" include ":app"

View File

@ -1,8 +1,10 @@
import 'dart:collection'; import 'dart:collection';
import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:hub/components/molecular_components/throw_exception/throw_exception_widget.dart';
import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/backend/api_requests/index.dart'; import 'package:hub/features/backend/api_requests/index.dart';
@ -16,6 +18,7 @@ import 'package:hub/initialization.dart';
import 'package:hub/main.dart'; import 'package:hub/main.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:patrol_finders/patrol_finders.dart';
part 'auth_test.dart'; part 'auth_test.dart';
part 'home_test.dart'; part 'home_test.dart';
@ -30,12 +33,15 @@ part 'storage_test.dart';
part 'utils_test.dart'; part 'utils_test.dart';
part 'welcome_test.dart'; part 'welcome_test.dart';
late PatrolTester $;
void main() { void main() {
//init integration test
IntegrationTestWidgetsFlutterBinding.ensureInitialized(); IntegrationTestWidgetsFlutterBinding.ensureInitialized();
// WelcomeTest.signInToSignUp(); // WelcomeTest.signInToSignUp();
// WelcomeTest.signUpToSignIn(); // WelcomeTest.signUpToSignIn();
// // //
// AuthenticationTest.signIn(); // AuthenticationTest.signIn();
// AuthenticationTest.signUp(); // AuthenticationTest.signUp();
// AuthenticationTest.signOut(); // AuthenticationTest.signOut();
@ -43,7 +49,7 @@ void main() {
// ModularizationTest.switchLicense(); // ModularizationTest.switchLicense();
// ModularizationTest.containLicense(); // ModularizationTest.containLicense();
// //
// MenuTest.navToEntries(); MenuTest.navToEntries();
// MenuTest.containEntries(); // MenuTest.containEntries();
// MenuTest.labels2AppbarConsistency(); // MenuTest.labels2AppbarConsistency();
// //

View File

@ -1,145 +1,143 @@
part of 'app_test.dart'; part of 'app_test.dart';
class AuthenticationTest { class AuthenticationTest {
static Future signIn() async { static Future<void> signIn() async {
_setUpUnlogged(); patrolWidgetTest(
testWidgets('Sign-In with erro@exemplo.com', // 'Sign-In with erro@exemplo.com',
(WidgetTester tester) async { (PatrolTester tester) async {
await tester.pumpWidget(const App()); $ = tester;
tester.printToConsole('AuthenticationTest - Navigate Sign-In'); final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
await _navigateToSignIn(tester); final Map<String, String> credentials = {
await _auth({ 'emailTextFormField': 'erro@exemplo.com',
'emailTextFormField': 'erro@exemplo.com', 'passwordTextFormField': '12345678',
'passwordTextFormField': '12345678' };
}, tester); await _unlogged();
await tester.pumpAndSettle(); await $.pumpWidgetAndSettle(const App());
await Future.delayed(const Duration(milliseconds: 500)); await Future.delayed(const Duration(milliseconds: 500));
return; await _navigateToSignIn($);
}); await _auth(credentials, $, throwsException);
_tearDown(); await Future.delayed(const Duration(milliseconds: 500));
},
);
_setUpUnlogged(); patrolWidgetTest(
testWidgets('Sign-In with email_app@exemplo.com', 'Sign-In with email_app@exemplo.com',
(WidgetTester tester) async { (PatrolTester tester) async {
await tester.pumpWidget(const App()); $ = tester;
tester.printToConsole('AuthenticationTest - Navigate Sign-In'); final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
await _navigateToSignIn(tester); final Map<String, String> credentials = {
await _auth({ 'emailTextFormField': 'email_app@exemplo.com',
'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678',
'passwordTextFormField': '12345678' };
}, tester); await _unlogged();
await Future.delayed(const Duration(milliseconds: 500)); await $.pumpWidgetAndSettle(const App());
return; await _navigateToSignIn($);
}); await _auth(credentials, $, throwsException);
_tearDown(); await Future.delayed(const Duration(milliseconds: 500));
},
);
} }
static Future signUp() async { static Future<void> signUp() async {
_setUpUnlogged(); patrolWidgetTest(
testWidgets('Sign Up - credenciais já registradas', 'Sign Up - credenciais já registradas',
(WidgetTester tester) async { (PatrolTester tester) async {
var credentials = { $ = tester;
'nameTextFormField': 'app', final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
'emailTextFormField': 'email_app@exemplo.com', final Map<String, String> credentials = {
'passwordTextFormField': '12345678' 'nameTextFormField': 'app',
}; 'emailTextFormField': 'email_app@exemplo.com',
'passwordTextFormField': '12345678',
};
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignUp($);
await _auth(credentials, $, throwsException);
await Future.delayed(const Duration(milliseconds: 500));
},
);
await tester.pumpWidget(const App()); patrolWidgetTest(
tester.printToConsole('AuthenticationTest - Navigate Sign-Up'); 'Sign Up - credenciais novas',
await _navigateToSignUp(tester); (PatrolTester tester) async {
await _auth(credentials, tester); $ = tester;
await tester.pumpAndSettle(); final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
await Future.delayed(const Duration(milliseconds: 500)); final name = _generateRandomString(7);
return; final email = '$name@example.com';
}); final password = '12345678';
_tearDown(); final Map<String, String> credentials = {
'nameTextFormField': name,
'emailTextFormField': email,
'passwordTextFormField': password,
};
_setUpUnlogged(); await _unlogged();
testWidgets('Sign Up - credenciais novas', //
(WidgetTester tester) async {
late Map<String, String> credentials;
var name = ff.randomString(7, 7, true, true, true); await $.pumpWidgetAndSettle(const App());
var email = '$name@example.com'; await _navigateToSignUp($);
var password = '12345678'; await _auth(credentials, $, throwsException);
credentials = {
'nameTextFormField': name,
'emailTextFormField': email,
'passwordTextFormField': password
};
await tester.pumpWidget(const App()); await Future.delayed(const Duration(milliseconds: 500));
tester.printToConsole('AuthenticationTest - Navigate Sign-Up'); },
await _navigateToSignUp(tester); );
await _auth(credentials, tester);
await Future.delayed(const Duration(milliseconds: 500));
return;
});
_tearDown();
} }
static Future signOut() async { static Future<void> signOut() async {
_setUpLogged(); patrolWidgetTest(
testWidgets('Deslogar da Conta', (WidgetTester tester) async { 'Deslogar da Conta',
await tester.pumpWidget(const App()); (PatrolTester tester) async {
final Finder drawerButton = find.byIcon(Icons.menu_rounded); $ = tester;
await tester.pumpAndSettle(); await _logged();
await tester.tap(drawerButton); await $.pumpWidgetAndSettle(const App());
await tester.pumpAndSettle(); await $.waitUntilVisible($(MenuStaggeredView));
final Finder signOutButton = find.byIcon(Icons.exit_to_app); await Future.delayed(const Duration(milliseconds: 500));
await tester.pumpAndSettle();
await tester.tap(signOutButton); await $(Icons.menu_rounded).tap();
await tester.pumpAndSettle(); await $.waitUntilVisible($(MenuListView));
await Future.delayed(const Duration(milliseconds: 500)); await $(Icons.exit_to_app)
return; .waitUntilVisible()
}); .tap(settlePolicy: SettlePolicy.trySettle);
_tearDown(); await Future.delayed(const Duration(milliseconds: 500));
},
);
} }
static Future recovery() async {} static Future<void> recovery() async {}
} }
Future<void> _auth( Future<void> _auth(
Map<String, dynamic> credentials, WidgetTester tester) async { Map<String, String> credentials,
await _enterCredentials(credentials, tester); PatrolTester $,
await _submit('SubmitButtonWidget', tester); PatrolFinder throwsException,
} ) async {
await _enterCredentials(credentials, $);
Future<void> _send( await _submit('SubmitButtonWidget', $, throwsException);
Map<String, dynamic> credentials, WidgetTester tester) async {
await _enterCredentials(credentials, tester);
await _submit('SendButtonWidget', tester);
} }
Future<void> _enterCredentials( Future<void> _enterCredentials(
Map<String, dynamic> credentials, WidgetTester tester) async { Map<String, String> credentials,
await tester.pumpAndSettle(); PatrolTester $,
) async {
for (var entry in credentials.entries) { for (var entry in credentials.entries) {
final Finder field = find.byKey(ValueKey<String>(entry.key)); await $(ValueKey(entry.key)).enterText(entry.value);
await tester.pumpAndSettle(); await $.pumpAndSettle();
expect(field, findsOneWidget);
await tester.enterText(field, entry.value);
await tester.pumpAndSettle();
} }
await tester.pumpAndSettle();
} }
Future<void> _submit(String key, WidgetTester tester) async { Future<void> _submit(
await tester.pumpAndSettle(); String key, PatrolTester $, PatrolFinder throwsException) async {
final Finder submitButton = find.byKey(ValueKey<String>(key)); await $(ValueKey(key)).tap();
await tester.pumpAndSettle(); if ($(ValueKey('ThrowExceptionWidget')).exists) {
if (submitButton.evaluate().isNotEmpty) { // expect(throwsException, findsOneWidget);
await tester.tap(submitButton); await $(ValueKey('ThrowExceptionWidget')).tap();
}
final Finder throwExceptionWidget =
find.byKey(const ValueKey<String>('ThrowExceptionWidget'));
if (throwExceptionWidget.evaluate().isNotEmpty) {
await tester.pumpAndSettle();
await tester.ensureVisible(throwExceptionWidget);
await tester.tap(throwExceptionWidget);
await tester.pumpAndSettle();
} else { } else {
await _navigateBackUsingSystemGesture(); _navigateBackUsingSystemGesture();
} }
} }
String _generateRandomString(int length) {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
final rand = Random();
return List.generate(length, (index) => chars[rand.nextInt(chars.length)])
.join();
}

View File

@ -2,69 +2,67 @@ part of 'app_test.dart';
class LocalsTest { class LocalsTest {
static Future setLocal() async { static Future setLocal() async {
_setUpLogged(); patrolWidgetTest(
testWidgets('Selecionar um local disponível', // 'Selecionar um local disponível', //
(WidgetTester tester) async { (PatrolTester tester) async {
await tester.pumpWidget(const App()); $ = tester;
await tester.pumpAndSettle(); await _logged();
await $.pumpWidget(const App());
await $.pumpAndSettle();
final Finder profileFinder = final Finder profileFinder =
find.byKey(const Key('AsyncLocalProfileComponentWidget_InkWell')); find.byKey(const Key('AsyncLocalProfileComponentWidget_InkWell'));
expect(profileFinder, findsOneWidget); expect(profileFinder, findsOneWidget);
await tester.tap(profileFinder); await $.tap(profileFinder);
await tester.pump(const Duration(seconds: 1)); await $.pump(const Duration(seconds: 1));
final Finder bottomSheetFinder = final Finder bottomSheetFinder =
find.byType(BottomArrowLinkedLocalsComponentWidget); find.byType(BottomArrowLinkedLocalsComponentWidget);
expect(bottomSheetFinder, findsOneWidget); expect(bottomSheetFinder, findsOneWidget);
await tester.ensureVisible(bottomSheetFinder); await $.pump(const Duration(seconds: 1));
await tester.pump(const Duration(seconds: 1));
final Finder listViewFinder = find.descendant( final Finder listViewFinder = find.descendant(
of: bottomSheetFinder, of: bottomSheetFinder,
matching: find.byType(ListView), matching: find.byType(ListView),
); );
expect(listViewFinder, findsOneWidget); expect(listViewFinder, findsOneWidget);
await tester.ensureVisible(listViewFinder); await $.pump(const Duration(seconds: 1));
await tester.pump(const Duration(seconds: 1));
final Finder entriesFinder = find.descendant( final Finder entriesFinder = find.descendant(
of: listViewFinder, of: listViewFinder,
matching: find.byType(CardItemTemplateComponentWidget), matching: find.byType(CardItemTemplateComponentWidget),
); );
expect(entriesFinder, findsWidgets); expect(entriesFinder, findsWidgets);
if (entriesFinder.evaluate().isNotEmpty) { if (entriesFinder.evaluate().isNotEmpty) {
await tester.ensureVisible(entriesFinder.first); await $.tap(entriesFinder.first);
await tester.tap(entriesFinder.first); await $.pumpAndSettle();
await tester.pumpAndSettle(); }
}
await Future.delayed(const Duration(milliseconds: 500)); await Future.delayed(const Duration(milliseconds: 500));
return; return;
}); },
_tearDown(); );
} }
static Future unlinkLocal() async { static Future unlinkLocal() async {
_setUpAllLogged(); patrolWidgetTest('Desvincular do local selecionado', //
(PatrolTester tester) async {
testWidgets('Desvincular do local selecionado', // $ = tester;
(WidgetTester tester) async { await _logged();
await tester.pumpWidget(const App()); await $.pumpWidget(const App());
await tester.pumpAndSettle(); await $.pumpAndSettle();
await tester.pump(const Duration(seconds: 1)); await $.pump(const Duration(seconds: 1));
final Finder gridView = find.byType(GridView); final Finder gridView = find.byType(GridView);
await tester.ensureVisible(gridView);
final Finder entries = find.descendant( final Finder entries = find.descendant(
of: gridView, of: gridView,
matching: find.byType(ButtonMenuItem), matching: find.byType(ButtonMenuItem),
); );
await tester.pumpAndSettle(); await $.pumpAndSettle();
expect(entries, findsWidgets); expect(entries, findsWidgets);
final Finder settings = find.descendant( final Finder settings = find.descendant(
of: gridView, of: gridView,
@ -72,28 +70,25 @@ class LocalsTest {
); );
expect(settings, findsOneWidget); expect(settings, findsOneWidget);
await tester.ensureVisible(settings); await $.tap(settings);
await tester.tap(settings); await $.pumpAndSettle();
await tester.pumpAndSettle();
final Finder unlinkButton = find.byIcon(Symbols.digital_out_of_home); final Finder unlinkButton = find.byIcon(Symbols.digital_out_of_home);
expect(unlinkButton, findsOneWidget); expect(unlinkButton, findsOneWidget);
await tester.ensureVisible(unlinkButton); await $.tap(unlinkButton);
await tester.tap(unlinkButton); await $.pumpAndSettle();
await tester.pumpAndSettle(); await $.tap(find.text('Sim'));
await tester.tap(find.text('Sim')); await $.pump();
await tester.pump(); await $.pump(const Duration(seconds: 1));
await tester.pump(const Duration(seconds: 1)); await $.pump();
await tester.pump();
final Finder bottomSheetFinder = final Finder bottomSheetFinder =
find.byType(BottomArrowLinkedLocalsComponentWidget); find.byType(BottomArrowLinkedLocalsComponentWidget);
await tester.pump(const Duration(seconds: 1)); await $.pump(const Duration(seconds: 1));
expect(bottomSheetFinder, findsOneWidget); expect(bottomSheetFinder, findsOneWidget);
await tester.pump(const Duration(seconds: 1)); await $.pump(const Duration(seconds: 1));
await tester.ensureVisible(bottomSheetFinder); await $.pump(const Duration(seconds: 1));
await tester.pump(const Duration(seconds: 1));
final Finder listViewFinder = find.descendant( final Finder listViewFinder = find.descendant(
of: bottomSheetFinder, of: bottomSheetFinder,
@ -101,8 +96,7 @@ class LocalsTest {
); );
expect(listViewFinder, findsOneWidget); expect(listViewFinder, findsOneWidget);
await tester.ensureVisible(listViewFinder); await $.pump(const Duration(seconds: 1));
await tester.pump(const Duration(seconds: 1));
final Finder entriesFinder = find.descendant( final Finder entriesFinder = find.descendant(
of: listViewFinder, of: listViewFinder,
@ -113,59 +107,61 @@ class LocalsTest {
return; return;
}); });
testWidgets('Desvincular de um local já desvinculado', // patrolWidgetTest(
(WidgetTester tester) async { 'Desvincular de um local já desvinculado', //
await tester.pumpWidget(const App()); (PatrolTester tester) async {
try { $ = tester;
await tester.pumpAndSettle( await $.pumpWidget(const App());
const Duration(seconds: 2), try {
EnginePhase.sendSemanticsUpdate, await $.pumpAndSettle(
const Duration(seconds: 2), // const Duration(seconds: 2),
); // EnginePhase.sendSemanticsUpdate,
throw Exception('Local está vinculado'); // const Duration(seconds: 2),
} catch (e) { );
await Future.delayed(const Duration(milliseconds: 500)); throw Exception('Local está vinculado');
return; } catch (e) {
} await Future.delayed(const Duration(milliseconds: 500));
}); return;
}
_tearDownAll(); },
);
} }
static Future attachLocal() async { static Future attachLocal() async {
_setUpAllLogged(); patrolWidgetTest(
'Selecionar um local disponível', //
(PatrolTester tester) async {
$ = tester;
await _logged();
await $.pumpWidget(const App());
late Map<String, String> credentials;
final PatrolFinder throwsException = $('');
testWidgets('Selecionar um local disponível', // var name = ff.randomString(7, 7, true, true, true);
(WidgetTester tester) async { var email = '$name@example.com';
await tester.pumpWidget(const App()); var password = '12345678';
late Map<String, String> credentials; credentials = {
'nameTextFormField': name,
'emailTextFormField': email,
'passwordTextFormField': password
};
var name = ff.randomString(7, 7, true, true, true); await $.pumpWidget(const App());
var email = '$name@example.com'; await _navigateToSignUp($);
var password = '12345678'; await _auth(credentials, $, throwsException);
credentials = { credentials = {
'nameTextFormField': name, 'emailTextFormField': email,
'emailTextFormField': email, 'passwordTextFormField': password
'passwordTextFormField': password };
}; await _auth(credentials, $, throwsException);
await tester.pumpWidget(const App()); await $.pumpAndSettle();
await _navigateToSignUp(tester); await StorageHelper() //
await _auth(credentials, tester); .set(ProfileStorageKey.clientUUID.key, '7');
credentials = { await $.pumpAndSettle();
'emailTextFormField': email, await Future.delayed(const Duration(milliseconds: 500));
'passwordTextFormField': password return;
}; },
await _auth(credentials, tester); );
await tester.pumpAndSettle();
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await tester.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 500));
return;
});
_tearDownAll();
} }
} }

View File

@ -2,173 +2,190 @@ part of 'app_test.dart';
class MenuTest { class MenuTest {
static Future labels2AppbarConsistency() async { static Future labels2AppbarConsistency() async {
_setUpAllLogged(); patrolWidgetTest(
testWidgets('As labels dos menuItems correspondem aos títulos das AppBars?', 'As labels dos menuItems correspondem aos títulos das AppBars?', //
(WidgetTester tester) async { (PatrolTester tester) async {
await tester.pumpWidget(const App()); $ = tester;
await tester.pumpAndSettle(); await _logged();
await $.pumpWidget(const App());
await $.pumpAndSettle();
final List<String> routes = MenuEntry.entries final List<String> routes = MenuEntry.entries
.where((entry) => entry.key != 'FRE-HUB-LOGOUT') .where((entry) => entry.key != 'FRE-HUB-LOGOUT')
.map((entry) => entry.route) .map((entry) => entry.route)
.toList(); .toList();
final List<String> titles = MenuEntry.entries final List<String> titles = MenuEntry.entries
.where((entry) => entry.key != 'FRE-HUB-LOGOUT') .where((entry) => entry.key != 'FRE-HUB-LOGOUT')
.map((entry) => entry.name) .map((entry) => entry.name)
.toList(); .toList();
tester.printToConsole(routes.toString()); final LinkedHashMap<String, String> routesTitles =
LinkedHashMap.fromIterables(
routes,
titles,
);
for (final entry in routesTitles.entries) {
final String route = entry.key;
final String title = entry.value;
if (route == '/petsPage') continue;
if (route == '/fastPassPage') continue;
if (route == '/reservation') continue;
await $.pumpAndSettle();
final LinkedHashMap<String, String> routesTitles = ff.navigatorKey.currentContext!.go(route);
LinkedHashMap.fromIterables( await $.pumpAndSettle();
routes,
titles,
);
for (final entry in routesTitles.entries) {
final String route = entry.key;
final String title = entry.value;
tester.printToConsole('Start: $title');
if (route == '/petsPage') continue;
if (route == '/fastPassPage') continue;
if (route == '/reservation') continue;
await tester.pumpAndSettle();
ff.navigatorKey.currentContext!.go(route); Future.delayed(const Duration(milliseconds: 500));
await tester.pumpAndSettle();
Future.delayed(const Duration(milliseconds: 500)); final Finder appBar = find.text(title);
await $.pumpAndSettle();
final Finder appBar = find.text(title); expect(appBar, findsOneWidget);
await tester.pumpAndSettle(); await $.pumpAndSettle();
expect(appBar, findsOneWidget); }
await tester.pumpAndSettle(); await Future.delayed(const Duration(milliseconds: 500));
tester.printToConsole('Finish: $title'); return;
} },
await Future.delayed(const Duration(milliseconds: 500)); );
return;
});
} }
static Future containEntries() async { static Future containEntries() async {
_setUpAllLogged(); patrolWidgetTest(
testWidgets('HomeMenu contém seus itens?', (WidgetTester tester) async { 'HomeMenu contém seus itens?', //
await tester.pumpWidget(const App()); (PatrolTester tester) async {
await tester.pumpAndSettle(); $ = tester;
await Future.delayed(const Duration(seconds: 1)); await _logged();
await $.pumpWidget(const App());
await $.pumpAndSettle();
await Future.delayed(const Duration(seconds: 1));
final Finder gridView = find.byType(GridView); final Finder gridView = find.byType(GridView);
await tester.pumpAndSettle(); await $.pumpAndSettle();
await tester.ensureVisible(gridView); await $.pumpAndSettle();
await tester.pumpAndSettle(); final Finder gridEntries = find.descendant(
final Finder gridEntries = find.descendant( of: gridView,
of: gridView, matching: find.byType(ButtonMenuItem),
matching: find.byType(ButtonMenuItem), );
); await $.pumpAndSettle();
await tester.pumpAndSettle(); expect(gridEntries, findsWidgets);
expect(gridEntries, findsWidgets);
final List<String?> menuKeys = gridEntries final List<String?> menuKeys = gridEntries
.evaluate() .evaluate()
.map((element) { .map((element) {
final key = element.widget.key; final key = element.widget.key;
if (key is ValueKey<String>) { if (key is ValueKey<String>) {
return key.value; return key.value;
} }
return null; return null;
}) })
.where((key) => key != null) .where((key) => key != null)
.toList(); .toList();
await tester.pumpAndSettle(); await $.pumpAndSettle();
final List<MenuEntry> entries = MenuEntry.entries; final List<MenuEntry> entries = MenuEntry.entries;
await tester.pumpAndSettle(); await $.pumpAndSettle();
final List<String> entriesKey = entries final List<String> entriesKey = entries
.where((entry) => entry.types.contains(MenuEntryType.Home)) .where((entry) => entry.types.contains(MenuEntryType.Home))
.map((entry) => entry.key) .map((entry) => entry.key)
.toList(); .toList();
await tester.pumpAndSettle(); await $.pumpAndSettle();
expect(entriesKey, containsAll(menuKeys)); expect(entriesKey, containsAll(menuKeys));
await Future.delayed(const Duration(milliseconds: 500)); await Future.delayed(const Duration(milliseconds: 500));
return; return;
}); },
);
testWidgets('DrawerMenu contém seus itens?', (WidgetTester tester) async { patrolWidgetTest(
await tester.pumpWidget(const App()); 'DrawerMenu contém seus itens?', //
await tester.pumpAndSettle(); (PatrolTester tester) async {
await Future.delayed(const Duration(seconds: 1)); $ = tester;
await _logged();
await $.pumpWidget(const App());
await $.pumpAndSettle();
await Future.delayed(const Duration(seconds: 1));
final Finder drawerButton = find.byIcon(Icons.menu_rounded); final Finder drawerButton = find.byIcon(Icons.menu_rounded);
await tester.pumpAndSettle(); await $.pumpAndSettle();
await tester.tap(drawerButton); await $.tap(drawerButton);
await tester.pumpAndSettle(); await $.pumpAndSettle();
final Finder gridView = find.byType(ListView); final Finder gridView = find.byType(ListView);
await tester.pumpAndSettle(); await $.pumpAndSettle();
await tester.ensureVisible(gridView); final Finder gridEntries = find.descendant(
await tester.pumpAndSettle(); of: gridView,
final Finder gridEntries = find.descendant( matching: find.byType(CardMenuItem),
of: gridView, );
matching: find.byType(CardMenuItem), await $.pumpAndSettle();
); expect(gridEntries, findsWidgets);
await tester.pumpAndSettle();
expect(gridEntries, findsWidgets);
final List<String?> menuKeys = gridEntries final List<String?> menuKeys = gridEntries
.evaluate() .evaluate()
.map((element) { .map((element) {
final key = element.widget.key; final key = element.widget.key;
if (key is ValueKey<String>) { if (key is ValueKey<String>) {
return key.value; return key.value;
} }
return null; return null;
}) })
.where((key) => key != null) .where((key) => key != null)
.toList(); .toList();
await tester.pumpAndSettle(); await $.pumpAndSettle();
final List<MenuEntry> entries = MenuEntry.entries; final List<MenuEntry> entries = MenuEntry.entries;
await tester.pumpAndSettle(); await $.pumpAndSettle();
final List<String> entriesKey = entries final List<String> entriesKey = entries
.where((entry) => entry.types.contains(MenuEntryType.Drawer)) .where((entry) => entry.types.contains(MenuEntryType.Drawer))
.map((entry) => entry.key) .map((entry) => entry.key)
.toList(); .toList();
await tester.pumpAndSettle(); await $.pumpAndSettle();
expect(entriesKey, containsAll(menuKeys)); expect(entriesKey, containsAll(menuKeys));
await Future.delayed(const Duration(milliseconds: 500)); await Future.delayed(const Duration(milliseconds: 500));
return; return;
}); },
_tearDownAll(); );
} }
static Future navToEntries() async { static Future navToEntries() async {
_setUpAllLogged(); patrolWidgetTest(
testWidgets('Navegação entre items do Menu', (WidgetTester tester) async { 'Navegação entre items do Menu',
tester = tester; (PatrolTester tester) async {
await tester.pumpWidget(const App()); $ = tester;
await tester.pumpAndSettle(); await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
final Finder gridView = find.byType(GridView); final PatrolFinder profile =
await tester.ensureVisible(gridView); $(const Key('AsyncLocalProfileComponentWidget_InkWell'));
final Finder gridEntries = find.descendant( await $(profile)
of: gridView, .waitUntilVisible()
matching: find.byType(ButtonMenuItem), .tap(settlePolicy: SettlePolicy.noSettle);
); await $.waitUntilVisible($(BottomArrowLinkedLocalsComponentWidget));
await tester.pumpAndSettle();
await Future.delayed(const Duration(seconds: 5));
expect(gridEntries, findsWidgets);
final int gridEntriesCount = gridEntries.evaluate().length; final PatrolFinder local = $('FRE ACCESS DEMO');
for (int i = 0; i < gridEntriesCount; i++) { await $(local)
await Future.delayed(const Duration(seconds: 1)); .waitUntilVisible()
await tester.tap(gridEntries.at(i)); .tap(settlePolicy: SettlePolicy.trySettle);
await tester.pumpAndSettle();
await Future.delayed(const Duration(seconds: 1)); await $.waitUntilVisible($(MenuStaggeredView));
await tester.tap(find.byIcon(Icons.keyboard_arrow_left));
await tester.pumpAndSettle(); final Finder gridView = find.byType(GridView);
await Future.delayed(const Duration(milliseconds: 500)); final Finder gridEntries = find.descendant(
return; of: gridView,
} matching: find.byType(ButtonMenuItem),
}); );
_tearDownAll(); await $.pumpAndSettle();
expect(gridEntries, findsWidgets);
final int gridEntriesCount = gridEntries.evaluate().length;
for (int i = 0; i < gridEntriesCount; i++) {
await tester.tap(gridEntries.at(i));
await tester.pumpAndSettle();
await Future.delayed(const Duration(seconds: 1));
await tester.tap(find.byIcon(Icons.keyboard_arrow_left));
await tester.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 500));
return;
}
},
);
} }
} }

View File

@ -2,49 +2,52 @@ part of 'app_test.dart';
class ModularizationTest { class ModularizationTest {
static Future containLicense() async { static Future containLicense() async {
_setUpLogged(); patrolWidgetTest('Os modulos de licença está sendo processados?',
testWidgets('Os modulos de licença está sendo processados?', (PatrolTester tester) async {
(WidgetTester tester) async { $ = tester;
await tester.pumpWidget(const App()); await _logged();
await tester.pumpAndSettle(); await $.pumpWidgetAndSettle(const App());
await Future.delayed(const Duration(seconds: 1)); await $.waitUntilVisible($(MenuStaggeredView));
await tester.pumpAndSettle();
final LicenseRepository licenseRepository = LicenseRepositoryImpl(); final LicenseRepository licenseRepository = LicenseRepositoryImpl();
final List<String> result = await licenseRepository.getLicense(); final List<String> result = await licenseRepository.getLicense();
expect(result, isNotEmpty); expect(result, isNotEmpty);
await tester.pumpAndSettle(); await $.pumpAndSettle();
final List<MenuEntry> entries = MenuEntry.entries; final List<MenuEntry> entries = MenuEntry.entries;
await tester.pumpAndSettle();
final List<String> entriesKey = entries final List<String> entriesKey = entries
.where((entry) => entry.types.contains(MenuEntryType.Home)) .where((entry) => entry.types.contains(MenuEntryType.Home))
.map((entry) => '{key: ${entry.key}}') .map((entry) => '{key: ${entry.key}}')
.toList(); .toList();
await tester.pumpAndSettle();
expect(result, containsAll(entriesKey)); expect(result, containsAll(entriesKey));
await Future.delayed(const Duration(milliseconds: 500));
return; return;
}); });
_tearDown();
} }
static Future switchLicense() async { static Future switchLicense() async {
_setUpLogged(); patrolWidgetTest(
testWidgets('Licença está sendo atualizada?', (WidgetTester tester) async { 'Licença está sendo atualizada?',
await tester.pumpWidget(const App()); (PatrolTester tester) async {
final Finder profile = $ = tester;
find.byKey(const Key('AsyncLocalProfileComponentWidget_InkWell')); await _logged();
await tester.pumpAndSettle();
await tester.tap(profile); await $.pumpWidgetAndSettle(const App());
await tester.pumpAndSettle(); await $.waitUntilVisible($(MenuStaggeredView));
final Finder local = find.text('FRE ACCESS DEMO');
await tester.pumpAndSettle(); final PatrolFinder profile =
await tester.tap(local); $(const Key('AsyncLocalProfileComponentWidget_InkWell'));
await tester.pumpAndSettle(); await $(profile)
await Future.delayed(const Duration(milliseconds: 500)); .waitUntilVisible()
return; .tap(settlePolicy: SettlePolicy.noSettle);
}); await $.waitUntilVisible($(BottomArrowLinkedLocalsComponentWidget));
_tearDown();
final PatrolFinder local = $('FRE ACCESS DEMO');
await $(local)
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.trySettle);
},
);
} }
} }

View File

@ -1,2 +1,27 @@
class PatrolTest { import 'dart:io';
}
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';
void main() {
patrolTest(
'counter state is the same after going to home and switching apps',
($) async {
// Replace later with your app's main widget
await $.pumpWidgetAndSettle(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('app')),
backgroundColor: Colors.blue,
),
),
);
expect($('app'), findsOneWidget);
if (!Platform.isMacOS) {
await $.native.pressHome();
}
},
);
}

View File

@ -0,0 +1,86 @@
// GENERATED CODE - DO NOT MODIFY BY HAND AND DO NOT COMMIT TO VERSION CONTROL
// ignore_for_file: type=lint, invalid_use_of_internal_member
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';
import 'package:patrol/src/native/contracts/contracts.dart';
import 'package:test_api/src/backend/invoker.dart';
// START: GENERATED TEST IMPORTS
import 'app_test.dart' as app_test;
// END: GENERATED TEST IMPORTS
Future<void> main() async {
// This is the entrypoint of the bundled Dart test.
//
// Its responsibilies are:
// * Running a special Dart test that runs before all the other tests and
// explores the hierarchy of groups and tests.
// * Hosting a PatrolAppService, which the native side of Patrol uses to get
// the Dart tests, and to request execution of a specific Dart test.
//
// When running on Android, the Android Test Orchestrator, before running the
// tests, makes an initial run to gather the tests that it will later run. The
// native side of Patrol (specifically: PatrolJUnitRunner class) is hooked
// into the Android Test Orchestrator lifecycle and knows when that initial
// run happens. When it does, PatrolJUnitRunner makes an RPC call to
// PatrolAppService and asks it for Dart tests.
//
// When running on iOS, the native side of Patrol (specifically: the
// PATROL_INTEGRATION_TEST_IOS_RUNNER macro) makes an initial run to gather
// the tests that it will later run (same as the Android). During that initial
// run, it makes an RPC call to PatrolAppSevice and asks it for Dart tests.
//
// Once the native runner has the list of Dart tests, it dynamically creates
// native test cases from them. On Android, this is done using the
// Parametrized JUnit runner. On iOS, new test case methods are swizzled into
// the RunnerUITests class, taking advantage of the very dynamic nature of
// Objective-C runtime.
//
// Execution of these dynamically created native test cases is then fully
// managed by the underlying native test framework (JUnit on Android, XCTest
// on iOS). The native test cases do only one thing - request execution of the
// Dart test (out of which they had been created) and wait for it to complete.
// The result of running the Dart test is the result of the native test case.
final nativeAutomator = NativeAutomator(config: NativeAutomatorConfig());
await nativeAutomator.initialize();
final binding = PatrolBinding.ensureInitialized(NativeAutomatorConfig());
final testExplorationCompleter = Completer<DartGroupEntry>();
// A special test to explore the hierarchy of groups and tests. This is a hack
// around https://github.com/dart-lang/test/issues/1998.
//
// This test must be the first to run. If not, the native side likely won't
// receive any tests, and everything will fall apart.
test('patrol_test_explorer', () {
// Maybe somewhat counterintuitively, this callback runs *after* the calls
// to group() below.
final topLevelGroup = Invoker.current!.liveTest.groups.first;
final dartTestGroup = createDartTestGroup(topLevelGroup,
tags: null,
excludeTags: null,
);
testExplorationCompleter.complete(dartTestGroup);
print('patrol_test_explorer: obtained Dart-side test hierarchy:');
reportGroupStructure(dartTestGroup);
});
// START: GENERATED TEST GROUPS
group('app_test', app_test.main);
// END: GENERATED TEST GROUPS
final dartTestGroup = await testExplorationCompleter.future;
final appService = PatrolAppService(topLevelDartTestGroup: dartTestGroup);
binding.patrolAppService = appService;
await runAppService(appService);
// Until now, the native test runner was waiting for us, the Dart side, to
// come alive. Now that we did, let's tell it that we're ready to be asked
// about Dart tests.
await nativeAutomator.markPatrolAppServiceReady();
await appService.testExecutionCompleted;
}

View File

@ -1,137 +1,58 @@
part of 'app_test.dart'; part of 'app_test.dart';
Future<void> _setUpLogged() async { Future<void> _logged() async {
setUp(() async { await initializeApp();
await initializeApp(); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.isLogged.value, 'true');
.set(SecureStorageKey.isLogged.value, 'true'); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.haveLocal.value, 'true');
.set(SecureStorageKey.haveLocal.value, 'true'); await StorageHelper() //
await StorageHelper() // .set(ProfileStorageKey.devUUID.key, 'b5c3818753e76d85');
.set(ProfileStorageKey.devUUID.key, 'b5c3818753e76d85'); await StorageHelper() //
await StorageHelper() // .set(ProfileStorageKey.userUUID.key, '649c45d7514a28.85876308');
.set(ProfileStorageKey.userUUID.key, '649c45d7514a28.85876308'); await StorageHelper() //
await StorageHelper() // .set(ProfileStorageKey.clientUUID.key, '7');
.set(ProfileStorageKey.clientUUID.key, '7'); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.email.value, 'email_app@exemplo.com');
.set(SecureStorageKey.email.value, 'email_app@exemplo.com'); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.password.value, '123456');
.set(SecureStorageKey.password.value, '123456'); await StorageHelper() //
await StorageHelper() // .set(LocalsStorageKey.isNewVersion.key, true);
.set(LocalsStorageKey.isNewVersion.key, true); await PhpGroup //
await PhpGroup.resopndeVinculo.call(tarefa: 'A'); .resopndeVinculo
await LicenseRepositoryImpl().resetLicense(); .call(tarefa: 'A');
}); await LicenseRepositoryImpl() //
.resetLicense();
} }
Future<void> _setUpUnlogged() async { Future<void> _unlogged() async {
setUp(() async { await initializeApp();
await initializeApp(); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.isLogged.value, 'false');
.set(SecureStorageKey.isLogged.value, 'false'); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.haveLocal.value, 'false');
.set(SecureStorageKey.haveLocal.value, 'false'); await StorageHelper() //
await StorageHelper() // .set(ProfileStorageKey.devUUID.key, '');
.set(ProfileStorageKey.devUUID.key, ''); await StorageHelper() //
await StorageHelper() // .set(ProfileStorageKey.userUUID.key, '');
.set(ProfileStorageKey.userUUID.key, ''); await StorageHelper() //
await StorageHelper() // .set(ProfileStorageKey.clientUUID.key, '');
.set(ProfileStorageKey.clientUUID.key, ''); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.email.value, '');
.set(SecureStorageKey.email.value, ''); await StorageHelper() //
await StorageHelper() // .set(SecureStorageKey.password.value, '');
.set(SecureStorageKey.password.value, ''); await StorageHelper() //
await StorageHelper() // .set(LocalsStorageKey.isNewVersion.key, true);
.set(LocalsStorageKey.isNewVersion.key, true);
});
} }
Future<void> _tearDownAll() async { Future<void> _navigateToSignIn(PatrolTester $) async {
tearDownAll(() async { final signInButton = $(#toggleSignInPage);
await StorageHelper().clean(Storage.databaseStorage); await signInButton.tap();
await StorageHelper().clean(Storage.secureStorage);
await StorageHelper().clean(Storage.sharedPreferences);
});
} }
Future<void> _tearDown() async { Future<void> _navigateToSignUp(PatrolTester $) async {
tearDown(() async { final signUpButton = $(#toggleSignUpPage);
await StorageHelper().clean(Storage.databaseStorage); await signUpButton.tap();
await StorageHelper().clean(Storage.secureStorage);
await StorageHelper().clean(Storage.sharedPreferences);
});
}
Future<void> _setUpAllLogged() async {
setUpAll(() async {
await initializeApp().then((_) async {
await StorageHelper() //
.set(SecureStorageKey.isLogged.value, 'true');
await StorageHelper() //
.set(SecureStorageKey.haveLocal.value, 'true');
await StorageHelper() //
.set(ProfileStorageKey.devUUID.key, 'b5c3818753e76d85');
await StorageHelper() //
.set(ProfileStorageKey.userUUID.key, '649c45d7514a28.85876308');
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await StorageHelper() //
.set(SecureStorageKey.email.value, 'email_app@exemplo.com');
await StorageHelper() //
.set(SecureStorageKey.password.value, '123456');
await StorageHelper() //
.set(LocalsStorageKey.isNewVersion.key, true);
await PhpGroup.resopndeVinculo.call(tarefa: 'A');
});
await LicenseRepositoryImpl().resetLicense();
});
}
Future<void> _setUpAllUnlogged() async {
setUpAll(() async {
await initializeApp().then((_) async {
await StorageHelper() //
.set(SecureStorageKey.isLogged.value, 'false');
await StorageHelper() //
.set(SecureStorageKey.haveLocal.value, 'false');
await StorageHelper() //
.set(ProfileStorageKey.devUUID.key, '');
await StorageHelper() //
.set(ProfileStorageKey.userUUID.key, '');
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '');
await StorageHelper() //
.set(SecureStorageKey.email.value, '');
await StorageHelper() //
.set(SecureStorageKey.password.value, '');
await StorageHelper() //
.set(LocalsStorageKey.isNewVersion.key, true);
});
});
}
Future<void> _navigateToSignIn(WidgetTester tester) async {
await tester.pumpAndSettle();
final Finder navToSignIn =
find.byKey(const ValueKey<String>('toggleSignInPage'));
await tester.pumpAndSettle();
expect(navToSignIn, findsOneWidget);
await tester.pumpAndSettle();
if (navToSignIn.evaluate().isNotEmpty) {
await tester.tap(navToSignIn);
await tester.pumpAndSettle();
}
}
Future<void> _navigateToSignUp(WidgetTester tester) async {
await tester.pumpAndSettle();
final Finder navToSignUp =
find.byKey(const ValueKey<String>('toggleSignUpPage'));
await tester.pumpAndSettle();
if (navToSignUp.evaluate().isNotEmpty) {
await tester.tap(navToSignUp);
await tester.pumpAndSettle();
}
} }
Future<void> _navigateBackUsingSystemGesture() async => Future<void> _navigateBackUsingSystemGesture() async =>

View File

@ -2,36 +2,28 @@ part of 'app_test.dart';
class WelcomeTest { class WelcomeTest {
static Future signInToSignUp() async { static Future signInToSignUp() async {
_setUpAllUnlogged(); patrolWidgetTest(
testWidgets('Sign-In to Sign-Up', (WidgetTester tester) async { 'Sign-In to Sign-Up',
await tester.pumpWidget(const App()); (PatrolTester tester) async {
tester.printToConsole('WelcomeTest - Navigate to Sign-Up to Sign-In'); $ = tester;
await tester.pumpAndSettle(); await _unlogged();
tester.printToConsole('WelcomeTest - Navigate Sign-In'); await $.pumpWidgetAndSettle(const App());
await _navigateToSignIn(tester); await _navigateToSignIn($);
tester.printToConsole('WelcomeTest - Navigate Sign-Up'); await _navigateToSignUp($);
await _navigateToSignUp(tester); },
await tester.pumpAndSettle(); );
await Future.delayed(const Duration(milliseconds: 500));
return;
});
_tearDownAll();
} }
static Future signUpToSignIn() async { static Future signUpToSignIn() async {
_setUpAllUnlogged(); patrolWidgetTest(
testWidgets('Sign-Up to Sign-In', (WidgetTester tester) async { 'Sign-Up to Sign-In',
await tester.pumpWidget(const App()); (PatrolTester tester) async {
tester.printToConsole('WelcomeTest - Navigate to Sign-In to Sign-Up'); $ = tester;
await tester.pumpAndSettle(); await _unlogged();
await _navigateToSignUp(tester); await $.pumpWidgetAndSettle(const App());
tester.printToConsole('WelcomeTest - Navigate Sign-Up'); await _navigateToSignUp($);
await _navigateToSignIn(tester); await _navigateToSignIn($);
tester.printToConsole('WelcomeTest - Navigate Sign-In'); },
await tester.pumpAndSettle(); );
await Future.delayed(const Duration(milliseconds: 500));
return;
});
_tearDownAll();
} }
} }

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:hub/features/menu/index.dart'; import 'package:hub/features/menu/index.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
class CardMenuItem extends MenuItem { class CardMenuItem extends MenuItem {
const CardMenuItem({ const CardMenuItem({
@ -35,11 +36,11 @@ class _MenuCardItemState extends State<CardMenuItem> {
onTap: _isProcessing onTap: _isProcessing
? null ? null
: () async { : () async {
setState(() { safeSetState(() {
_isProcessing = true; _isProcessing = true;
}); });
await widget.action.call(); await widget.action.call();
setState(() { safeSetState(() {
_isProcessing = false; _isProcessing = false;
}); });
}, },

View File

@ -9,7 +9,9 @@ import 'package:hub/features/module/index.dart';
abstract class LicenseRemoteDataSource { abstract class LicenseRemoteDataSource {
Future<bool> fetchLicenses(bool isNewVersion); Future<bool> fetchLicenses(bool isNewVersion);
Future<bool> cleanLicense(); Future<bool> cleanLicense();
Future<void> processLicense(); Future<void> processLicense();
} }
@ -70,7 +72,7 @@ class LicenseRemoteDataSourceImpl implements LicenseRemoteDataSource {
} catch (e, s) { } catch (e, s) {
log('Erro ao obter licenças: $e', stackTrace: s); log('Erro ao obter licenças: $e', stackTrace: s);
// return await setupLicense(DatabaseStorage.database, isNewVersion); // return await setupLicense(DatabaseStorage.database, isNewVersion);
return false; return true;
} }
} }

View File

@ -34,9 +34,11 @@ class LicenseRepositoryImpl implements LicenseRepository {
log('updateLicense'); log('updateLicense');
bool result = false; bool result = false;
final bool isNewVersion = await localDataSource.isNewVersion(); final bool isNewVersion = await localDataSource.isNewVersion();
result = await localDataSource.setupLicense(isNewVersion);
if (isNewVersion) { if (isNewVersion) {
result = await remoteDataSource.fetchLicenses(isNewVersion); result = await remoteDataSource.fetchLicenses(isNewVersion);
} else {
result = await localDataSource.setupLicense(isNewVersion);
} }
return result; return result;

View File

@ -350,6 +350,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.2" version: "7.0.2"
dispose_scope:
dependency: transitive
description:
name: dispose_scope
sha256: "48ec38ca2631c53c4f8fa96b294c801e55c335db5e3fb9f82cede150cfe5a2af"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
dropdown_button2: dropdown_button2:
dependency: "direct main" dependency: "direct main"
description: description:
@ -665,10 +673,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage name: flutter_secure_storage
sha256: c0f1abb088adddc193286ea91eedd71900ec5707ac86503a7ae09d88c9ffc22b sha256: f7eceb0bc6f4fd0441e29d43cab9ac2a1c5ffd7ea7b64075136b718c46954874
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.0-beta.2" version: "10.0.0-beta.4"
flutter_secure_storage_darwin:
dependency: transitive
description:
name: flutter_secure_storage_darwin
sha256: f226f2a572bed96bc6542198ebaec227150786e34311d455a7e2d3d06d951845
url: "https://pub.dev"
source: hosted
version: "0.1.0"
flutter_secure_storage_linux: flutter_secure_storage_linux:
dependency: "direct main" dependency: "direct main"
description: description:
@ -737,10 +753,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_svg name: flutter_svg
sha256: "54900a1a1243f3c4a5506d853a2b5c2dbc38d5f27e52a52618a8054401431123" sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.16" version: "2.0.17"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -904,10 +920,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: image_picker_android name: image_picker_android
sha256: aa6f1280b670861ac45220cc95adc59bb6ae130259d36f980ccb62220dc5e59f sha256: b62d34a506e12bb965e824b6db4fbf709ee4589cf5d3e99b45ab2287b008ee0c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.12+19" version: "0.8.12+20"
image_picker_for_web: image_picker_for_web:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1289,6 +1305,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
patrol:
dependency: "direct dev"
description:
name: patrol
sha256: f2b423122e63b1251fc31165ba1f7d85d60e22b4d20076ef39dcb47f83e35467
url: "https://pub.dev"
source: hosted
version: "3.13.2"
patrol_finders:
dependency: "direct dev"
description:
name: patrol_finders
sha256: "5a1e2b4c6636e89645fc596d68224cfe6cca28e11c855b98dd0df9bed0d80405"
url: "https://pub.dev"
source: hosted
version: "2.6.0"
patrol_log:
dependency: transitive
description:
name: patrol_log
sha256: ad5d7b759d16071ca16aa9b27eb4f106ce23079792d4312941874dbc33e795cb
url: "https://pub.dev"
source: hosted
version: "0.2.2"
percent_indicator: percent_indicator:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1501,10 +1541,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d" sha256: bf808be89fe9dc467475e982c1db6c2faf3d2acf54d526cd5ec37d86c99dbd84
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
shared_preferences_foundation: shared_preferences_foundation:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1834,18 +1874,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.4.0"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "3.1.4"
uuid: uuid:
dependency: "direct overridden" dependency: "direct overridden"
description: description:
@ -1970,10 +2010,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: b7e92f129482460951d96ef9a46b49db34bd2e1621685de26e9eaafd9674e7eb sha256: "4adc14ea9a770cc9e2c8f1ac734536bd40e82615bd0fa6b94be10982de656cc7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.16.3" version: "3.17.0"
win32: win32:
dependency: "direct overridden" dependency: "direct overridden"
description: description:
@ -2016,4 +2056,4 @@ packages:
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.6.0 <4.0.0" dart: ">=3.6.0 <4.0.0"
flutter: ">=3.24.0" flutter: ">=3.27.0"

View File

@ -125,6 +125,8 @@ dev_dependencies:
freezed: ^2.5.7 freezed: ^2.5.7
json_serializable: ^6.9.0 json_serializable: ^6.9.0
test: ^1.25.8 test: ^1.25.8
patrol: ^3.13.2
patrol_finders: ^2.6.0
flutter_launcher_icons: flutter_launcher_icons:
android: "launcher_icon" android: "launcher_icon"
@ -159,3 +161,9 @@ fonts:
fonts: fonts:
- asset: assets/fonts/menu.ttf - asset: assets/fonts/menu.ttf
patrol:
app_name: FRE ACCESS HUB
android:
package_name: com.freaccess.hub
ios:
bundle_id: br.com.freaccess.hub