i18n test utils

This Kernel helps you to test the translations on your component by replacing i18nHelper with a different implementation. It allows you to check on your tests if the component is getting and rendering the translated text correclty.

Usage
Copy
import { i18nTestUtilsKernel } from '@orion/i18n/test-utils';

useKernels(i18nTestUtilsKernel);

You only have to import the i18nTestUtilsKernel into your test file in order to use it on the test cases, this Kernel will take care of the component you initialize and will check if it is returning the translation as expected.

How it works

You need to define keys in a translations file, because the library will look for them,

Copy
// File: translations/en.json

{
  "key1": "Hello"
}

Once you have defined your key translations on this file, i18nHelper brings you several options to get the translation related to the key you are requesting:

  1. t() method.

  2. withTranslation() method.

  3. <I18nComponent> component.

Copy
// File: translationsPlugin.js

// Defining the element using t() wait until translations are loaded
const makeTranslatedHello = async ({ i18nHelper }) => await i18nHelper.t('key1', { wait: true });

Finally, the test file will use the i18n-test-utils kernel and it will look for the key and the translation related that you defined,

Copy
// File: translationPlugin.spec.js

test('Text is translated!', () => {
  useKernels(uiKernel, i18nTestUtilsKernel);

  addPlugin(pkg, TranslationsPlugin);
  renderPOSComponent('Hello');

  const translatedText = screen.getByText('T_key1');

  expect(translatedText).toBeInTheDocument();
});

Important: When the key matches the one initialized on the translations file, the library adds the prefix T_ to the key, returning T_key1 for the showing example.

To assert on interpolation parameters, we need to call the configuration function setDisableInterpolationAssertion with a false value. This will change the behaviour of the translation t to append the interpolation object as __arguments:${JSON(parameters)}. The serialized object will have its keys ordered.

Copy
test('will return the translations key and the interpolation params serialized if configured', async () => {
  configure(({ i18nTestUtilsConfigurationProvider }) => {
    i18nTestUtilsConfigurationProvider.setDisableInterpolationAssertion(false);
  });

  let translatedText;
  class TranslationsPlugin {
    constructor({ i18nHelper }) {
      this._i18nHelper = i18nHelper;
    }

    async onInit() {
      translatedText = await this._i18nHelper.t(
        'key5 {{param2}} {{param1}}',
        { wait: true, param2: 'PARAM_2', param1: 'PARAM_1' },
        'another-translations-plugin',
      );
    }
  }

  addPlugin(TranslationsPluginPkg, TranslationsPlugin);
  await waitFor(() =>
    expect(translatedText).toBe(
      'T_key5 {{param2}} {{param1}}__arguments:{"param1":"PARAM_1","param2":"PARAM_2"}',
    ),
  );
});

Important: Interpolation parameters are not appended by default. However, the test utils will raise a deprecation warning when it detects interpolation parameters but setDisableInterpolationAssertion was not called with a false values.

In futures releases, appending the parameters will be the default behaviour. We recommend to update your tests before that breaking change is released.

Must know

On the other hand, there are some mandatory concepts that you need to know in order to get the translations correctly, otherwise the tests will fail.

  1. The most obvious one is that the key must exist on the translations file.

    Copy
    test('t() tries to translate a key that does not exist', async () => {
      class TranslationsPlugin {
        constructor({ i18nHelper }) {
          this._i18nHelper = i18nHelper;
        }
        async testTranslation() {
          await this._i18nHelper.t('notDefined', { wait: true });
        }
      }
      const translationsPlugin = addPlugin({ name: 'translations-plugin' }, TranslationsPlugin);
      await expect(translationsPlugin.testTranslation()).rejects.toThrow(
        /The key "notDefined" doesn't exist/,
      );
    });
  2. You need to initialize wait attribute to true when calling t() method.

    Copy
    test('t() tries to translate a key without waiting', async () => {
      class TranslationsPlugin {
        constructor({ i18nHelper }) {
          this._i18nHelper = i18nHelper;
        }
        async testTranslation() {
          await this._i18nHelper.t('key1', { wait: false });
        }
      }
      const translationsPlugin = addPlugin({ name: 'translations-plugin' }, TranslationsPlugin);
      await expect(translationsPlugin.testTranslation()).rejects.toThrow(
        /trying to translate "key1" without waiting/,
      );
    });

More information

If you want to see live examples and/or need more info about translations, you can check these links out: