svi3c
svi3c

Reputation: 575

How to test localized widgets in flutter?

I added l10n to my flutter app as suggested in the flutter docs, it is suggested to get the localizations with a static method like this:

static DemoLocalizations of(BuildContext context) {
  return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}

This works fine when running the app, but when I try to test my widgets, the returned value is always null.

Is there any easy way to provide the localizations within the tests?

For now I'm passing through the localizations via DI, but it is quite an overhead.

Upvotes: 25

Views: 15818

Answers (7)

Timo
Timo

Reputation: 921

For just accessing localised text in a widget test, the translation for a specific locale can be accessed in a static way. By Fixing the widget under test to a known language, the actual text for that language can be used to e.g. find a Text widget:

import 'package:flutter_gen/gen_l10n/app_localizations_en.dart';
// etc...

void main() {
  // Concrete instance of English translations
  final localized = AppLocalizationsEn();

  testWidgets('finds localized text', (tester) async {
    await tester.pumpMyView();

    expect(find.text(localized.myLocalizedText), findsOneWidget);
  });
}

/// Adds the view under test to [WidgetTester]
extension on WidgetTester {
  Future<void> pumpMyView() async {
    await pumpWidget(
      MaterialApp(
        localizationsDelegates: const [
          GlobalCupertinoLocalizations.delegate,
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          AppLocalizations.delegate,
        ],
        supportedLocales: AppLocalizations.supportedLocales,
        locale: const Locale('en'), // Fixed to ENGLISH
        home: Scaffold(
          body: Builder(
            builder: (context) {
              return Text(AppLocalizations.of(context).myLocalizedText);
            },
          ),
        ),
      ),
    );
  }
}

Note that you can extract the common application setup part to a common extension on WidgetTester that can be used across many widget tests.

Upvotes: 0

ziqq
ziqq

Reputation: 971

It's modifiable of How to test localized widgets in flutter?

U need to add after return await t.pumpAndSettle();

Full code:

  Future<AppLocalizations> getLocalizationsUnderTests(
    WidgetTester t,
  ) async {
    late AppLocalizations result;
    await t.pumpWidget(
      MaterialApp(
        localizationsDelegates: const <LocalizationsDelegate>[
          GlobalCupertinoLocalizations.delegate,
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          AppLocalizations.delegate,
        ],
        supportedLocales: AppLocalizations.supportedLocales,
        locale: const Locale('en'),
        home: Material(
          child: Builder(
            builder: (BuildContext context) {
              result = AppLocalizations.of(context);
              debugPrint('[DEBUG]: locale: $result');

              // The builder function must return a widget.
              return const Placeholder();
            },
          ),
        ),
      ),
    );
    await t.pumpAndSettle();
    return result;
  }

Upvotes: 0

Felix Mittermeier
Felix Mittermeier

Reputation: 228

I wrote an universal utility function to make the usage of localization easier inside widget testing:

// Don't forget the import
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

...

Future<AppLocalizations> getLocalizations(WidgetTester t) async {
  late AppLocalizations result;
  await t.pumpWidget(
    MaterialApp(
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,
      home: Material(
        child: Builder(
          builder: (BuildContext context) {
            result = AppLocalizations.of(context)!;
            return Container();
          },
        ),
      ),
    ),
  );
  return result;
}

In order to grab a localized text in one line you just have to call

 await getLocalizations(t).then((l) => l.YOUR_KEY_HERE)

then. Maybe it's also useful for someone :)

Upvotes: 4

User Rebo
User Rebo

Reputation: 4580

If you want test existing widgets with in a specific language, you can get the localization by:

import 'package:flutter_localizations/flutter_localizations.dart';
...
(await GlobalMaterialLocalizations.delegate.load(Locale('en'))).okButtonLabel

or

import 'package:flutter_gen/gen_l10n/app_localizations.dart';
...
(await GlobalMaterialLocalizations.delegate.load(Locale('en'))).myCustomLabel

Upvotes: 3

Quyen Anh Nguyen
Quyen Anh Nguyen

Reputation: 1730

I think you should read this issues. In case file json over 10kb, it cannot load assets. We should keep following and wait Flutter team fix it or real solution https://github.com/flutter/flutter/issues/22193

Upvotes: 2

Hyo
Hyo

Reputation: 21

The above answer didn't help because I was calling strings from json file. The medium blog actually handled my problem in solving the issue.

Upvotes: 5

R&#233;mi Rousselet
R&#233;mi Rousselet

Reputation: 276947

You can wrap the widget you want to tests into a Localizations

Localizations(
  delegates: [
    yourDelegate
  ],
  locale: Locale('en'),
  child: YourWidget(),
);

Upvotes: 36

Related Questions