Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not sure how to widget test #116

Open
2cData opened this issue Nov 3, 2019 · 3 comments
Open

Not sure how to widget test #116

2cData opened this issue Nov 3, 2019 · 3 comments

Comments

@2cData
Copy link

2cData commented Nov 3, 2019

I had originally used the basic Flutter internationalization strategy and even managed to widget test it using @remonh87 workaround (https://medium.com/flutterpub/testing-localized-widget-in-flutter-3bfa5492bc84)

But, like most people, this was just too much boilerplate and this plugin makes life much better. However, now my widget tests don't work and I am not sure how to implement a solution like @remonh87, since the underlying class is now autogenerated (which is why this is such a great tool to begin with!)

I was wondering if anyone else has been able to get widget testing using the localized strings working before I looked into doing a PR.

@remonh87
Copy link

remonh87 commented Nov 4, 2019

@2cData I think you can still use this plugin and have proper widget tests. If you do not care about testing the localized strings you can simply inject a stubtestdelegate in your widget test and test the screen. If you do care about strings according to the flutter team you can solve it by tester.runAsync according to issue flutter/flutter#22193 . Never test this myself though

@ViniciusSossela
Copy link

ViniciusSossela commented Nov 19, 2019

flutter/flutter#22193 (comment)
@chunhtai actually it doesn't work.

In our case, we are using .json files to do translations. So we have like these:

  • assets/lang/en.json
  • assets/lang/pt.json
  • assets/lang/es.json

.....

The way we load and use these json files are through LocalizationsDelegate extension like this:

class AppLocalizations {
  final Locale locale;

  AppLocalizations(this.locale);

  static AppLocalizations of(BuildContext context) =>
      Localizations.of<AppLocalizations>(context, AppLocalizations);

  static const LocalizationsDelegate<AppLocalizations> delegate =
      _AppLocalizationsDelegate();

  Map<String, String> _localizedStrings;

  Future<bool> load() async {
    try {
      String jsonString = await rootBundle.loadString('assets/lang/${locale.languageCode}.json'); **here is the problem**
      Map<String, dynamic> jsonMap = json.decode(jsonString);

      _localizedStrings = jsonMap.map((key, value) => MapEntry(key, value));
      return true;
    } catch (e) {
      return false;
    }
  }

  String translate(String key) => _localizedStrings[key];
}

class _AppLocalizationsDelegate
    extends LocalizationsDelegate<AppLocalizations> {
  const _AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) {
    return ['en', 'pt', 'es'].contains(locale.languageCode);
  }

  @override
  Future<AppLocalizations> load(Locale locale) async {
    AppLocalizations localizations = AppLocalizations(locale);
    await localizations.load();
    return localizations;
  }

  @override
  bool shouldReload(LocalizationsDelegate<AppLocalizations> old) => false;
}
class MyTranslatedWidget extends StatefulWidget {
  @override
  _MyTranslatedWidgetState createState() => _MyTranslatedWidgetState();
}

class _MyTranslatedWidget extends State<MyTranslatedWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text(
        AppLocalizations.of(context).translate('hello_key'),
      ),
    );
  }
}

and then in our widget test, we have something like this:

 testWidgets(
    'my test description',
    (WidgetTester tester) async {
      await tester.runAsync(() async {

        await tester.pumpWidget(MaterialApp(
          locale: Locale('en'),
          localizationsDelegates: [
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            AppLocalizations.delegate   **here is the problem**
          ],
          home: MyTranslatedWidget(),
        ));

        final titleFinder = find.text('hello');
        expect(titleFinder, findsOneWidget);
      });
    },
  );

After running this test we got the following problem:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown while running async test code:
  Expected: exactly one matching node in the widget tree
  Actual: ?:<zero widgets with text "hello" (ignoring offstage widgets)>
   Which: means none were found but one was expected

This happens because,AppLocalizations.delegate that is called on localizationsDelegates from MaterialApp is not able to load the .json file that have all the text translations.

Something happens here: String jsonString = await rootBundle.loadString('assets/lang/${locale.languageCode}.json');

it seems like the rootBundle can't find or load the json assets...

@2cData
Copy link
Author

2cData commented Nov 22, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants