This commit is contained in:
Hillel Coren 2019-08-21 18:25:58 +03:00
parent 435a532960
commit 34e56f95b1
8 changed files with 33 additions and 60 deletions

View File

@ -14,7 +14,6 @@ import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
import 'package:invoiceninja_flutter/ui/app/app_drawer_vm.dart'; import 'package:invoiceninja_flutter/ui/app/app_drawer_vm.dart';
import 'package:invoiceninja_flutter/ui/app/lists/selected_indicator.dart'; import 'package:invoiceninja_flutter/ui/app/lists/selected_indicator.dart';
import 'package:invoiceninja_flutter/utils/icons.dart'; import 'package:invoiceninja_flutter/utils/icons.dart';
import 'package:invoiceninja_flutter/utils/keys.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart';
@ -170,7 +169,6 @@ class AppDrawer extends StatelessWidget {
store.dispatch(ViewDashboard(context: context)), store.dispatch(ViewDashboard(context: context)),
), ),
DrawerTile( DrawerTile(
key: Key(ClientKeys.drawer),
company: company, company: company,
entityType: EntityType.client, entityType: EntityType.client,
icon: getEntityIcon(EntityType.client), icon: getEntityIcon(EntityType.client),
@ -186,7 +184,6 @@ class AppDrawer extends StatelessWidget {
}, },
), ),
DrawerTile( DrawerTile(
key: Key(ProductKeys.drawer),
company: company, company: company,
entityType: EntityType.product, entityType: EntityType.product,
icon: getEntityIcon(EntityType.product), icon: getEntityIcon(EntityType.product),
@ -316,7 +313,6 @@ class AppDrawer extends StatelessWidget {
), ),
// STARTER: menu - do not remove comment // STARTER: menu - do not remove comment
DrawerTile( DrawerTile(
key: Key(SettingsKeys.drawer),
company: company, company: company,
icon: FontAwesomeIcons.cog, icon: FontAwesomeIcons.cog,
title: localization.settings, title: localization.settings,
@ -344,14 +340,13 @@ class AppDrawer extends StatelessWidget {
class DrawerTile extends StatelessWidget { class DrawerTile extends StatelessWidget {
const DrawerTile({ const DrawerTile({
Key key,
@required this.company, @required this.company,
@required this.icon, @required this.icon,
@required this.title, @required this.title,
@required this.onTap, @required this.onTap,
this.onCreateTap, this.onCreateTap,
this.entityType, this.entityType,
}) : super(key: key); });
final CompanyEntity company; final CompanyEntity company;
final EntityType entityType; final EntityType entityType;
@ -381,7 +376,7 @@ class DrawerTile extends StatelessWidget {
isSelected: uiState.containsRoute(route), isSelected: uiState.containsRoute(route),
child: ListTile( child: ListTile(
dense: true, dense: true,
leading: Icon(icon, size: 22.0, key: ValueKey(title)), leading: Icon(icon, size: 22.0),
title: Tooltip(message: title, child: Text(title)), title: Tooltip(message: title, child: Text(title)),
onTap: onTap, onTap: onTap,
trailing: onCreateTap == null || !user.canCreate(entityType) trailing: onCreateTap == null || !user.canCreate(entityType)

View File

@ -6,7 +6,6 @@ import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/utils/keys.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart';
class LoginView extends StatefulWidget { class LoginView extends StatefulWidget {
@ -32,12 +31,6 @@ class _LoginState extends State<LoginView> {
static const String OTP_ERROR = 'OTP_REQUIRED'; static const String OTP_ERROR = 'OTP_REQUIRED';
static final ValueKey _emailKey = Key(LoginKeys.email);
static final ValueKey _passwordKey = Key(LoginKeys.password);
static final ValueKey _urlKey = Key(LoginKeys.url);
static final ValueKey _secretKey = Key(LoginKeys.secret);
static final ValueKey _oneTimePasswordKey = Key(LoginKeys.oneTimePassword);
final FocusNode _focusNode1 = new FocusNode(); final FocusNode _focusNode1 = new FocusNode();
bool _isSelfHosted = false; bool _isSelfHosted = false;
@ -134,7 +127,7 @@ class _LoginState extends State<LoginView> {
isOneTimePassword isOneTimePassword
? TextFormField( ? TextFormField(
controller: _oneTimePasswordController, controller: _oneTimePasswordController,
key: _oneTimePasswordKey, key: ValueKey(localization.oneTimePassword),
autocorrect: false, autocorrect: false,
decoration: InputDecoration( decoration: InputDecoration(
labelText: localization.oneTimePassword), labelText: localization.oneTimePassword),
@ -143,7 +136,7 @@ class _LoginState extends State<LoginView> {
children: <Widget>[ children: <Widget>[
TextFormField( TextFormField(
controller: _emailController, controller: _emailController,
key: _emailKey, key: ValueKey(localization.email),
autocorrect: false, autocorrect: false,
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: InputDecoration( decoration: InputDecoration(
@ -160,7 +153,7 @@ class _LoginState extends State<LoginView> {
), ),
TextFormField( TextFormField(
controller: _passwordController, controller: _passwordController,
key: _passwordKey, key: ValueKey(localization.password),
autocorrect: false, autocorrect: false,
autovalidate: _autoValidate, autovalidate: _autoValidate,
decoration: InputDecoration( decoration: InputDecoration(
@ -176,7 +169,7 @@ class _LoginState extends State<LoginView> {
_isSelfHosted _isSelfHosted
? TextFormField( ? TextFormField(
controller: _urlController, controller: _urlController,
key: _urlKey, key: ValueKey(localization.url),
autocorrect: false, autocorrect: false,
autovalidate: _autoValidate, autovalidate: _autoValidate,
decoration: InputDecoration( decoration: InputDecoration(
@ -191,7 +184,7 @@ class _LoginState extends State<LoginView> {
_isSelfHosted _isSelfHosted
? TextFormField( ? TextFormField(
controller: _secretController, controller: _secretController,
key: _secretKey, key: ValueKey(localization.secret),
autocorrect: false, autocorrect: false,
decoration: InputDecoration( decoration: InputDecoration(
labelText: localization.secret), labelText: localization.secret),
@ -232,7 +225,7 @@ class _LoginState extends State<LoginView> {
setState(() => _isSelfHosted = false), setState(() => _isSelfHosted = false),
child: Text(localization.hostedLogin)) child: Text(localization.hostedLogin))
: FlatButton( : FlatButton(
key: Key(LoginKeys.loginSelfHost), key: ValueKey(localization.selfhostLogin),
onPressed: () => onPressed: () =>
setState(() => _isSelfHosted = true), setState(() => _isSelfHosted = true),
child: Text(localization.selfhostLogin)), child: Text(localization.selfhostLogin)),

View File

@ -1,6 +1,5 @@
class AppKeys { class AppKeys {
static const String openAppDrawer = 'Open navigation menu'; static const String openAppDrawer = 'Open navigation menu';
static const String dashboardScreen = 'DashboardScreen';
} }
class AppTooltips { class AppTooltips {
@ -8,16 +7,6 @@ class AppTooltips {
static const String back = 'Back'; static const String back = 'Back';
} }
class LoginKeys {
static const String email = 'loginEmail';
static const String password = 'loginPassword';
static const String url = 'loginUrl';
static const String loginSelfHost = 'loginSelfHost';
static const String secret = 'loginSecret';
static const String oneTimePassword = 'loginOneTimePassword';
static const String loginButton = 'login';
}
class ProductKeys { class ProductKeys {
static const String screen = 'ProductScreen'; static const String screen = 'ProductScreen';
static const String drawer = 'productDrawer'; static const String drawer = 'productDrawer';
@ -32,8 +21,4 @@ class ClientKeys {
static const String screen = 'ClientScreen'; static const String screen = 'ClientScreen';
static const String fab = 'clientFab'; static const String fab = 'clientFab';
static const String drawer = 'clientDrawer'; static const String drawer = 'clientDrawer';
} }
class SettingsKeys {
static const String drawer = 'settingsDrawer';
}

View File

@ -3,5 +3,5 @@ import 'package:invoiceninja_flutter/main.dart' as app;
void main() { void main() {
enableFlutterDriverExtension(); enableFlutterDriverExtension();
app.main(); app.main(isTesting: true);
} }

View File

@ -4,5 +4,5 @@ import 'package:invoiceninja_flutter/main.dart' as app;
void main() { void main() {
// This line enables the extension // This line enables the extension
enableFlutterDriverExtension(); enableFlutterDriverExtension();
app.main(); app.main(isTesting: true);
} }

View File

@ -8,7 +8,6 @@ import 'utils/localizations.dart';
void main() { void main() {
group('LOGIN TEST', () { group('LOGIN TEST', () {
TestLocalization localization; TestLocalization localization;
FlutterDriver driver; FlutterDriver driver;
@ -26,10 +25,8 @@ void main() {
group('SELF-HOSTED', () { group('SELF-HOSTED', () {
test('No input provided by user', () async { test('No input provided by user', () async {
await login(driver, loginEmail: '', await login(driver,
loginPassword: '', loginEmail: '', loginPassword: '', loginUrl: '', loginSecret: '');
loginUrl: '',
loginSecret: '');
await driver.waitFor(find.text(localization.pleaseEnterYourEmail)); await driver.waitFor(find.text(localization.pleaseEnterYourEmail));
await driver.waitFor(find.text(localization.pleaseEnterYourPassword)); await driver.waitFor(find.text(localization.pleaseEnterYourPassword));
@ -40,7 +37,7 @@ void main() {
await login(driver, retype: true); await login(driver, retype: true);
await driver.waitFor( await driver.waitFor(
find.byType(AppKeys.dashboardScreen), find.byTooltip(AppKeys.openAppDrawer),
timeout: new Duration(seconds: 60), timeout: new Duration(seconds: 60),
); );
}); });
@ -50,4 +47,4 @@ void main() {
}); });
}); });
}); });
} }

View File

@ -4,5 +4,5 @@ import 'package:invoiceninja_flutter/main.dart' as app;
void main() { void main() {
// This line enables the extension // This line enables the extension
enableFlutterDriverExtension(); enableFlutterDriverExtension();
app.main(); app.main(isTesting: true);
} }

View File

@ -5,34 +5,36 @@ import 'package:invoiceninja_flutter/utils/keys.dart';
import 'localizations.dart'; import 'localizations.dart';
Future<void> login(FlutterDriver driver, Future<void> login(FlutterDriver driver,
{ {bool selfHosted = true,
bool selfHosted = true,
bool retype = false, bool retype = false,
String loginEmail = Config.TEST_EMAIL, String loginEmail = Config.TEST_EMAIL,
String loginPassword = Config.TEST_PASSWORD, String loginPassword = Config.TEST_PASSWORD,
String loginUrl = Config.TEST_URL, String loginUrl = Config.TEST_URL,
String loginSecret = Config.TEST_SECRET String loginSecret = Config.TEST_SECRET}) async {
}) async {
final localization = TestLocalization('en');
await fillTextFields(driver, <String, dynamic>{ await fillTextFields(driver, <String, dynamic>{
LoginKeys.email: loginEmail, localization.email: loginEmail,
LoginKeys.password: loginPassword, localization.password: loginPassword,
}); });
if (selfHosted) { if (selfHosted) {
await fillTextFields(driver, <String, dynamic>{ await fillTextFields(driver, <String, dynamic>{
LoginKeys.url: loginUrl, localization.url: loginUrl,
LoginKeys.secret: loginSecret, localization.secret: loginSecret,
}); });
} }
await driver.tap(find.text(LoginKeys.loginButton.toUpperCase())); await driver.tap(find.text(localization.login.toUpperCase()));
} }
Future<void> logout(FlutterDriver driver, TestLocalization localization) async { Future<void> logout(FlutterDriver driver, TestLocalization localization) async {
// Go to Settings Screen // Go to Settings Screen
await driver.tap(find.byTooltip(AppKeys.openAppDrawer)); await driver.tap(find.byTooltip(AppKeys.openAppDrawer));
//await driver.scrollUntilVisible(find.byType('Drawer'), find.byValueKey(SettingsKeys.drawer)); //await driver.scrollUntilVisible(find.byType('Drawer'), find.byValueKey(SettingsKeys.drawer));
await driver.tap(find.byValueKey(SettingsKeys.drawer)); //await driver.tap(find.byValueKey(SettingsKeys.drawer));
await driver.tap(find.byTooltip(localization.settings));
// Tap on Log Out // Tap on Log Out
await driver.tap(find.text(localization.logout)); await driver.tap(find.text(localization.logout));
@ -47,7 +49,7 @@ Future<void> logout(FlutterDriver driver, TestLocalization localization) async {
Future<void> loginAndOpenProducts(FlutterDriver driver) async { Future<void> loginAndOpenProducts(FlutterDriver driver) async {
login(driver); login(driver);
await driver.waitFor(find.byType(AppKeys.dashboardScreen)); await driver.waitFor(find.byTooltip(AppKeys.openAppDrawer));
await driver.tap(find.byTooltip(AppKeys.openAppDrawer)); await driver.tap(find.byTooltip(AppKeys.openAppDrawer));
await driver.tap(find.byValueKey(ProductKeys.drawer)); await driver.tap(find.byValueKey(ProductKeys.drawer));
await driver.waitFor(find.byType(ProductKeys.screen)); await driver.waitFor(find.byType(ProductKeys.screen));
@ -55,15 +57,16 @@ Future<void> loginAndOpenProducts(FlutterDriver driver) async {
Future<void> loginAndOpenClients(FlutterDriver driver) async { Future<void> loginAndOpenClients(FlutterDriver driver) async {
login(driver); login(driver);
await driver.waitFor(find.byType(AppKeys.dashboardScreen)); await driver.waitFor(find.byTooltip(AppKeys.openAppDrawer));
await driver.tap(find.byTooltip(AppKeys.openAppDrawer)); await driver.tap(find.byTooltip(AppKeys.openAppDrawer));
await driver.tap(find.byValueKey(ClientKeys.drawer)); await driver.tap(find.byValueKey(ClientKeys.drawer));
await driver.waitFor(find.byType(ClientKeys.screen)); await driver.waitFor(find.byType(ClientKeys.screen));
} }
Future<void> fillTextFields(FlutterDriver driver, Map<String, dynamic> values) async { Future<void> fillTextFields(
FlutterDriver driver, Map<String, dynamic> values) async {
for (var entry in values.entries) { for (var entry in values.entries) {
await driver.tap(find.byValueKey(entry.key)); await driver.tap(find.byValueKey(entry.key));
await driver.enterText(entry.value); await driver.enterText(entry.value);
} }
} }