How to deal with i18n in integration tests?


#1

Let’s say I have a component that displays the next localized text:

Your score is 6

Using ember-i18n and ember-test-selectors it looks like this:

<div data-test-score>
  {{i18n 'yourScoreIs' score=6}}
</div>

In the integration test I’d like to make sure the score is displayed correctly, but of the different assertions I can make none of them feels right.

assert.dom('[data-test-score]').hasText('Your score is 6');
// Breaks as soon as the translation changes.
// Also depends heavily on the chosen language.

assert.dom('[data-test-score]').includesText('6');
// Assumes the given value is not part if the translation.
// For example, breaks if translation is changed to "Out of 6 attempts, your best score is...".

assert.dom('[data-test-score]').hasAnyText();
// Doesn't really test if the score is displayed.

One solution could be to mock the i18n service to always return the same value.

const i18n = Service.extend({
  t(key, data = {}) {
    let output = 'tStub ' +  Object.entries(data)
      .map(entry => `${entry[0]}=${entry[1]}`)
      .join(' ');

    return output.trim(); 
  }
});

this.inject.service('i18n', { as: 'i18n' });

Then an assertion can be made to simply check if some translation is displayed and the right value is passed in.

assert.dom('[data-test-score]').hasText('tStub score=6');

What do you think of this solution? Do you might have an alternative strategy?


#2

Another option would be to import i18n’s test helper

import { t } from 'ember-i18n/test-support';

Then in the test

 assert.dom('[data-test-score]').hasText(t('yourScoreIs', { score: 6 }));

That way the tests should pass up until you make larger changes to the text like adding more variables.