diff --git a/lib/constants.dart b/lib/constants.dart index 2297f54cc..a0f7ea698 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -632,6 +632,7 @@ const kPageSizes = [ ]; const String kDrawerKey = 'drawer_key'; +const String kSelectCompanyDropdownKey = 'select_company_dropdown_key'; const String kActivityCreateClient = '1'; const String kActivityArchiveClient = '2'; diff --git a/lib/ui/app/forms/app_dropdown_button.dart b/lib/ui/app/forms/app_dropdown_button.dart index 6c70f0b3a..f5f47690b 100644 --- a/lib/ui/app/forms/app_dropdown_button.dart +++ b/lib/ui/app/forms/app_dropdown_button.dart @@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/utils/localization.dart'; class AppDropdownButton extends StatelessWidget { const AppDropdownButton({ + Key key, @required this.value, @required this.onChanged, @required this.items, @@ -13,7 +14,7 @@ class AppDropdownButton extends StatelessWidget { this.blankValue = '', this.enabled = true, this.showUseDefault = false, - }); + }) : super(key: key); final String labelText; final dynamic value; diff --git a/lib/ui/app/forms/decorated_form_field.dart b/lib/ui/app/forms/decorated_form_field.dart index 47a2524f9..b926e9a37 100644 --- a/lib/ui/app/forms/decorated_form_field.dart +++ b/lib/ui/app/forms/decorated_form_field.dart @@ -9,7 +9,7 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart class DecoratedFormField extends StatelessWidget { const DecoratedFormField({ - Key key, + this.formKey, this.controller, this.label, this.onSavePressed, @@ -36,8 +36,9 @@ class DecoratedFormField extends StatelessWidget { this.isPercent = false, this.showClear = true, this.inputFormatters, - }) : super(key: key); + }); + final Key formKey; final TextEditingController controller; final String label; final String hint; @@ -118,7 +119,7 @@ class DecoratedFormField extends StatelessWidget { } return TextFormField( - key: key ?? ValueKey(label), + key: formKey ?? ValueKey(label), focusNode: focusNode, controller: controller, autofocus: autofocus, diff --git a/lib/ui/app/forms/growable_form_field.dart b/lib/ui/app/forms/growable_form_field.dart index 64f013578..fdc5339bb 100644 --- a/lib/ui/app/forms/growable_form_field.dart +++ b/lib/ui/app/forms/growable_form_field.dart @@ -45,7 +45,7 @@ class _GrowableFormFieldState extends State { @override Widget build(BuildContext context) { return DecoratedFormField( - key: widget.key, + formKey: widget.key, focusNode: _focusNode, initialValue: widget.initialValue, onChanged: widget.onChanged, diff --git a/lib/ui/app/forms/password_field.dart b/lib/ui/app/forms/password_field.dart index 5611a5f37..1937aaf62 100644 --- a/lib/ui/app/forms/password_field.dart +++ b/lib/ui/app/forms/password_field.dart @@ -35,6 +35,7 @@ class _PasswordFormFieldState extends State { final localization = AppLocalization.of(context); return DecoratedFormField( + formKey: ValueKey(widget.labelText ?? localization.password), controller: widget.controller, onSavePressed: widget.onSavePressed, autocorrect: false, diff --git a/lib/ui/app/menu_drawer.dart b/lib/ui/app/menu_drawer.dart index 8f6e3a6fb..ad1ff392e 100644 --- a/lib/ui/app/menu_drawer.dart +++ b/lib/ui/app/menu_drawer.dart @@ -164,6 +164,7 @@ class MenuDrawer extends StatelessWidget { final _expandedCompanySelector = state.companies.isEmpty ? SizedBox() : AppDropdownButton( + key: ValueKey(kSelectCompanyDropdownKey), value: viewModel.selectedCompanyIndex, items: [ ...state.companies diff --git a/lib/ui/client/edit/client_edit_details.dart b/lib/ui/client/edit/client_edit_details.dart index 6d28eae03..b3ecd7711 100644 --- a/lib/ui/client/edit/client_edit_details.dart +++ b/lib/ui/client/edit/client_edit_details.dart @@ -131,6 +131,7 @@ class ClientEditDetailsState extends State { FormCard( children: [ DecoratedFormField( + formKey: ValueKey(localization.name), autofocus: true, controller: _nameController, validator: (String val) => !viewModel.client.hasNameSet diff --git a/lib/ui/expense/edit/expense_edit_settings.dart b/lib/ui/expense/edit/expense_edit_settings.dart index 9c06b5b4e..bac518602 100644 --- a/lib/ui/expense/edit/expense_edit_settings.dart +++ b/lib/ui/expense/edit/expense_edit_settings.dart @@ -215,7 +215,7 @@ class ExpenseEditSettingsState extends State { _setCurrency(currency), ), DecoratedFormField( - key: ValueKey('__${expense.invoiceCurrencyId}__'), + formKey: ValueKey('__${expense.invoiceCurrencyId}__'), controller: _exchangeRateController, keyboardType: TextInputType.numberWithOptions(decimal: true), diff --git a/lib/ui/invoice/edit/invoice_edit_desktop.dart b/lib/ui/invoice/edit/invoice_edit_desktop.dart index d3d465b2e..bd4615171 100644 --- a/lib/ui/invoice/edit/invoice_edit_desktop.dart +++ b/lib/ui/invoice/edit/invoice_edit_desktop.dart @@ -633,7 +633,7 @@ class InvoiceEditDesktopState extends State children: [ Expanded( child: DecoratedFormField( - key: ValueKey( + formKey: ValueKey( '__exchange_rate_${invoice.clientId}__'), label: localization.exchangeRate, initialValue: formatNumber( diff --git a/lib/ui/invoice/edit/invoice_edit_details.dart b/lib/ui/invoice/edit/invoice_edit_details.dart index 08efe4303..5e1bb76b0 100644 --- a/lib/ui/invoice/edit/invoice_edit_details.dart +++ b/lib/ui/invoice/edit/invoice_edit_details.dart @@ -389,7 +389,7 @@ class InvoiceEditDetailsState extends State { .onChanged(invoice.rebuild((b) => b..designId = value?.id)), ), DecoratedFormField( - key: ValueKey('__exchange_rate_${invoice.clientId}__'), + formKey: ValueKey('__exchange_rate_${invoice.clientId}__'), label: localization.exchangeRate, initialValue: formatNumber(invoice.exchangeRate, context, formatNumberType: FormatNumberType.inputAmount), diff --git a/lib/ui/invoice/edit/invoice_edit_items_desktop.dart b/lib/ui/invoice/edit/invoice_edit_items_desktop.dart index 396938ddc..45c27b883 100644 --- a/lib/ui/invoice/edit/invoice_edit_items_desktop.dart +++ b/lib/ui/invoice/edit/invoice_edit_items_desktop.dart @@ -517,7 +517,7 @@ class _InvoiceEditItemsDesktopState extends State { Padding( padding: const EdgeInsets.only(right: kTableColumnGap), child: DecoratedFormField( - key: ValueKey('__line_item_${index}_cost__'), + formKey: ValueKey('__line_item_${index}_cost__'), textAlign: TextAlign.right, initialValue: formatNumber( lineItems[index].cost, context, @@ -536,7 +536,7 @@ class _InvoiceEditItemsDesktopState extends State { Padding( padding: const EdgeInsets.only(right: kTableColumnGap), child: DecoratedFormField( - key: ValueKey('__line_item_${index}_quantity__'), + formKey: ValueKey('__line_item_${index}_quantity__'), textAlign: TextAlign.right, initialValue: formatNumber( lineItems[index].quantity, context, @@ -555,7 +555,7 @@ class _InvoiceEditItemsDesktopState extends State { Padding( padding: const EdgeInsets.only(right: kTableColumnGap), child: DecoratedFormField( - key: ValueKey('__line_item_${index}_discount__'), + formKey: ValueKey('__line_item_${index}_discount__'), textAlign: TextAlign.right, initialValue: formatNumber( lineItems[index].discount, context, diff --git a/lib/ui/settings/import_export.dart b/lib/ui/settings/import_export.dart index a195f8504..77353fd77 100644 --- a/lib/ui/settings/import_export.dart +++ b/lib/ui/settings/import_export.dart @@ -206,7 +206,7 @@ class _FileImportState extends State<_FileImport> { final field = DecoratedFormField( enabled: false, - key: ValueKey(uploadPart.key + + formKey: ValueKey(uploadPart.key + (multipartFile != null ? multipartFile.filename : '')), label: localization.lookup(uploadPart.value), initialValue: !_multipartFiles.containsKey(uploadPart.key) diff --git a/lib/ui/task/edit/task_edit_desktop.dart b/lib/ui/task/edit/task_edit_desktop.dart index 36c398546..04f012b3d 100644 --- a/lib/ui/task/edit/task_edit_desktop.dart +++ b/lib/ui/task/edit/task_edit_desktop.dart @@ -220,7 +220,7 @@ class _TaskEditDesktopState extends State { isMoney: false, ), DecoratedFormField( - key: ValueKey('__rate__'), + formKey: ValueKey('__rate__'), controller: _rateController, label: rateLabel, keyboardType: TextInputType.numberWithOptions( diff --git a/lib/ui/task/edit/task_edit_details.dart b/lib/ui/task/edit/task_edit_details.dart index b8cd731e6..2529ed2c1 100644 --- a/lib/ui/task/edit/task_edit_details.dart +++ b/lib/ui/task/edit/task_edit_details.dart @@ -171,7 +171,7 @@ class _TaskEditDetailsState extends State { autocorrect: false, ), DecoratedFormField( - key: ValueKey('__rate__'), + formKey: ValueKey('__rate__'), controller: _rateController, label: rateLabel, keyboardType: diff --git a/pubspec.lock b/pubspec.lock index bb337fc52..b083c5d8b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -267,6 +267,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.1" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" faker: dependency: "direct dev" description: @@ -287,7 +294,7 @@ packages: name: file url: "https://pub.dartlang.org" source: hosted - version: "5.2.1" + version: "6.0.0" file_picker: dependency: "direct main" description: @@ -377,6 +384,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.3.5" + flutter_driver: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" flutter_json_widget: dependency: "direct main" description: @@ -438,6 +450,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.5.1+1" + flutter_test: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_typeahead: dependency: "direct main" description: @@ -452,6 +469,11 @@ packages: description: flutter source: sdk version: "0.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" glob: dependency: transitive description: @@ -660,7 +682,7 @@ packages: name: node_io url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.1.1" node_preamble: dependency: transitive description: @@ -800,7 +822,7 @@ packages: name: process url: "https://pub.dartlang.org" source: hosted - version: "3.0.13" + version: "4.0.0" pub_semver: dependency: transitive description: @@ -987,7 +1009,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.0" sqflite: dependency: transitive description: @@ -1030,6 +1052,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + sync_http: + dependency: transitive + description: + name: sync_http + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" synchronized: dependency: transitive description: @@ -1162,7 +1191,7 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "6.2.0" + version: "5.5.0" watcher: dependency: transitive description: @@ -1177,6 +1206,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + webdriver: + dependency: transitive + description: + name: webdriver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" webkit_inspection_protocol: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index fd4284971..cc92b52fa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -89,8 +89,8 @@ dependency_overrides: path: packages/google_sign_in/google_sign_in_platform_interface dev_dependencies: - #flutter_driver: # TODO Re-enable - # sdk: flutter + flutter_driver: + sdk: flutter test: ^1.6.3 #flutter_test: # sdk: flutter diff --git a/test_driver/all_it.dart b/test_driver/all_it.dart index efb9df672..5f6aa8fd9 100644 --- a/test_driver/all_it.dart +++ b/test_driver/all_it.dart @@ -1,4 +1,3 @@ -/* import 'package:flutter_driver/driver_extension.dart'; import 'package:invoiceninja_flutter/main.dart' as app; @@ -6,4 +5,3 @@ void main() { enableFlutterDriverExtension(); app.main(isTesting: true); } -*/ \ No newline at end of file diff --git a/test_driver/clients_it.dart b/test_driver/clients_it.dart index 10b20ba12..35019023b 100644 --- a/test_driver/clients_it.dart +++ b/test_driver/clients_it.dart @@ -1,4 +1,3 @@ -/* import 'package:flutter_driver/driver_extension.dart'; import 'package:invoiceninja_flutter/main.dart' as app; @@ -6,5 +5,4 @@ void main() { // This line enables the extension enableFlutterDriverExtension(); app.main(isTesting: true); -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/test_driver/clients_it_test.dart b/test_driver/clients_it_test.dart index 993e5af68..88d9a9014 100644 --- a/test_driver/clients_it_test.dart +++ b/test_driver/clients_it_test.dart @@ -1,4 +1,3 @@ -/* import 'package:faker/faker.dart'; import 'package:flutter_driver/flutter_driver.dart'; import 'package:test/test.dart'; @@ -96,9 +95,10 @@ void runTestSuite({bool batchMode = false}) { }); // Archive the edited client - test('Archieve/delete client test', () async { + test('Archive/delete client test', () async { await testArchiveAndDelete( driver: driver, + name: updatedName, archivedMessage: localization.archivedClient, deletedMessage: localization.deletedClient, restoredMessage: localization.restoredClient); @@ -108,5 +108,4 @@ void runTestSuite({bool batchMode = false}) { } }); }); -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/test_driver/utils/common_actions.dart b/test_driver/utils/common_actions.dart index 6c04e51a1..ce16cf03a 100644 --- a/test_driver/utils/common_actions.dart +++ b/test_driver/utils/common_actions.dart @@ -1,9 +1,9 @@ -/* import 'dart:math'; import 'package:faker/faker.dart'; import 'package:flutter_driver/flutter_driver.dart'; import 'package:invoiceninja_flutter/.env.dart'; +import 'package:invoiceninja_flutter/constants.dart'; import 'localizations.dart'; @@ -54,10 +54,11 @@ Future login(FlutterDriver driver, if (selfHosted) { await fillTextFields(driver, { localization.url: loginUrl, - localization.secret: loginSecret, + '${localization.secret} (${localization.optional})': loginSecret, }); } + print(localization.emailSignIn); await driver.tap(find.text(localization.emailSignIn)); if (loginEmail.isNotEmpty) { @@ -75,8 +76,10 @@ Future logout(FlutterDriver driver, TestLocalization localization, } //await driver.scrollUntilVisible(find.byType('Drawer'), find.text(localization.settings)); - await driver.tap(find.text(localization.settings)); - await driver.tap(find.text(localization.deviceSettings)); + //await driver.tap(find.text(localization.settings)); + //await driver.tap(find.text(localization.deviceSettings)); + + await driver.tap(find.byValueKey(kSelectCompanyDropdownKey)); // Tap on Log Out await driver.tap(find.text(localization.logout)); @@ -129,7 +132,7 @@ Future fillAndSaveForm(FlutterDriver driver, Map values, await fillTextFields(driver, values); // Await for Debouncer - await Future.delayed(Duration(milliseconds: 400)); + await Future.delayed(Duration(milliseconds: 1000)); print('Check for updated values'); await checkTextFields(driver, values, except: skipCheckFor); @@ -145,6 +148,7 @@ Future fillAndSaveForm(FlutterDriver driver, Map values, Future testArchiveAndDelete( {FlutterDriver driver, String archivedMessage, + String name, String deletedMessage, String restoredMessage}) async { final localization = TestLocalization('en'); @@ -164,6 +168,7 @@ Future testArchiveAndDelete( //await driver.waitFor(find.text(localization.archived)); print('Restore record'); + await driver.tap(find.text(name)); await selectAction(driver, localization.restore); await driver.waitFor(find.text(restoredMessage)); await driver.waitForAbsent(find.byType('Snackbar')); @@ -174,6 +179,7 @@ Future testArchiveAndDelete( //await driver.waitFor(find.text(localization.deleted)); print('Restore record'); + await driver.tap(find.text(name)); await selectAction(driver, localization.restore); await driver.waitFor(find.text(restoredMessage)); await driver.waitForAbsent(find.byType('Snackbar')); @@ -189,4 +195,3 @@ String makeUnique(String value) => String getLineItemKey(String key, int index) => '${Keys.invoiceLineItemBaseKey}_${index}_${key}__'; -*/ \ No newline at end of file