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

[No QA] Add test for matching Translations keys #4090

Merged
merged 9 commits into from
Jul 29, 2021

Conversation

parasharrajat
Copy link
Member

@parasharrajat parasharrajat commented Jul 15, 2021

Details

Added Unit test that matches the keys from each Language file to the Main EN.js translations. If any key is missing, the test will fail. You will see a log stating the path of the key.

Fixed Issues

$ #4082

@parasharrajat parasharrajat requested a review from a team as a code owner July 15, 2021 21:22
@MelvinBot MelvinBot requested review from iwiznia and removed request for a team July 15, 2021 21:22
@parasharrajat
Copy link
Member Author

parasharrajat commented Jul 15, 2021

@parasharrajat
Copy link
Member Author

Please review the translations before merging. I don't speak Spanish but took help from google.

Copy link
Contributor

@iwiznia iwiznia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry that I did not realize about this when creating the issue, but can we also add the opposite check? Basically to ensure we don't have tons of unused keys in the non base english files, we would also alert for any key present in non base english files that are not present on the english files.

Comment on lines 82 to 83
const excludeLanguages = ['en', 'es-ES'];
const languages = _.without(_.keys(originalTranslations.default), ...excludeLanguages);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this smarter and instead of having to add es-ES here make it skip any file that has 2 components? ie: pick up es but not es-ES

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was not the original Idea. After Sometime, we can decide to add more Translations. and Two component locale would be completely valid in that case. So to skip regardless of specification will lead to code change. So I think its better, not to make it smarter. It is sufficient to fulfill its purpose.

@@ -52,3 +54,38 @@ describe('translate', () => {
expect(translate.translate('en', ['testKeyGroup', 'testFunction'], {testVariable})).toBe(expectedValue);
});
});

describe('Translation Keys', () => {
let activeLanguage;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this "global"? Can't we pass it as a regular argument to matchKeys?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is convenient.

path += key ? `${key}.` : '';
const pathLevel = path;
if (key && !_.has(target, key)) {
console.debug(`🏹 ${path.slice(0, -1)} is missing from ${activeLanguage}.js`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a debug log line, can we make it so that the test itself fails? Ideally it would show one failed test per missing key if that's possible, but if that's hard we can have one test fail that prints all missing keys.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test will fail, if key don't match. This log is just to show what is missing.

Ideally it would show one failed test per missing key if that's possible,

I don't think its a good idea to create multiple tests that basically test the same thing.

if that's hard we can have one test fail that prints all missing keys.

This can be done. We can log all the missing keys.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok cool, my main point is that it's better to have the test failure show what keys failed instead of having to look at the logs.

Copy link
Member Author

@parasharrajat parasharrajat Jul 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to find way to add the missing key as failure message itself but I don't think its possible AFAIK. So we have to stick with logs. Could you please give me a hint about how to do that if possible?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmmm, I think that if you change the expect from toBeTruthy to something like arrayContaining would make jest to print the diff of the arrays and thus the missing keys?

@parasharrajat
Copy link
Member Author

Basically to ensure we don't have tons of unused keys in the non base english files, we would also alert for any key present in non base english files that are not present on the english files.

Hmm, let me think about it.

@iwiznia
Copy link
Contributor

iwiznia commented Jul 26, 2021

Any update here @parasharrajat? I see we are missing translations in several places and this would prevent all those errors.

@parasharrajat
Copy link
Member Author

@iwiznia I am thinking to rewrite the tests with a simpler and robust implementation. I will post multiple test clauses for each language file...etc. Maybe I'll finish it today.

@parasharrajat
Copy link
Member Author

@iwiznia It's ready. Expect.arrayContaining is not useful as it does not give the required output and does not tell us which keys are missing. WRT, it outputs huge string on the logs which basically make it non-readable. So I have created our on Logs using console.log.

Copy link
Contributor

@iwiznia iwiznia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, but you got conflicts. Can you:

  1. Resolve the conflicts
  2. Make some tests fail in one of your commits, so I can look at the output of the failing tests in the GH actions
    Please?

tests/unit/TranslateTest.js Outdated Show resolved Hide resolved
tests/unit/TranslateTest.js Outdated Show resolved Hide resolved
@parasharrajat
Copy link
Member Author

@iwiznia I have made few changes to es.js which will result in a test failure. Please check https://github.com/Expensify/App/pull/4090/checks?check_run_id=3192256522#step:6:595.

@iwiznia
Copy link
Contributor

iwiznia commented Jul 29, 2021

Ah damn, that's not that great as the exact failures are mixed in with other non useful logs. Making some suggestions in the PR to see if we can make it better.

if (hasAllKeys.length) {
console.debug(`🏹 [ ${hasAllKeys.join(', ')} ] are missing from ${ln}.js`);
}
expect(hasAllKeys.length).toBe(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I was thinking, maybe we could do this and get a better error message?

Suggested change
expect(hasAllKeys.length).toBe(0);
expect(hasAllKeys).toBeEqual([]);

I think this will show in the test result exactly which keys are missing, no?
(same applies to the one below)

Copy link
Member Author

@parasharrajat parasharrajat Jul 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not show the keys that are not correct. It just shows Expected and produced output. So all the correct and wrong keys would be shown as a big string which is like 50 lines long.

 Expected: 0 <-- would be all the keys on main language in green color.
 Received: 2 <-- would be all the keys on matching language in red color.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested with expect.objectContaining and expect.arrayContaining.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmmm, can we change the code to do _.without(mainLagunageKeys, ...languageKeys)? That would return only the missing keys, right?

Copy link
Member Author

@parasharrajat parasharrajat Jul 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It currently only gives the missing keys. Again _.without(mainLagunageKeys, ...languageKeys) will go in console.log. @iwiznia

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The console log is not good enough as it is super hard to find the right message. In any case I don't think you understood what I meant, because I just tried and it works. Here's the test code:

        it(`Does ${ln} locale has all the keys`, () => {
            const hasAllKeys = _.without(mainLanguageKeys, ...languageKeys);
            expect(hasAllKeys).toEqual([]);
        });

        it(`Does ${ln} locale has unused keys`, () => {
            const hasAllKeys = _.without(languageKeys, ...mainLanguageKeys);
            expect(hasAllKeys).toEqual([]);
        });

And this is the output:

 ● Translation Keys › Does es locale has all the keys

    expect(received).toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 4

    - Array []
    + Array [
    +   "preferencesPage.mostRecent",
    +   "passwordForm.error.incorrectLoginOrPassword",
    + ]

      79 |         it(`Does ${ln} locale has all the keys`, () => {
      80 |             const hasAllKeys = _.without(mainLanguageKeys, ...languageKeys);
    > 81 |             expect(hasAllKeys).toEqual([]);
         |                                ^
      82 |         });
      83 |
      84 |         it(`Does ${ln} locale has unused keys`, () => {

      at Object.<anonymous> (tests/unit/TranslateTest.js:81:32)

  ● Translation Keys › Does es locale has unused keys

    expect(received).toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 4

    - Array []
    + Array [
    +   "initialSettingsPage.appDownloadLinks.window.label",
    +   "initialSettingsPage.appDownloadLinks.Rajat.label",
    + ]

      84 |         it(`Does ${ln} locale has unused keys`, () => {
      85 |             const hasAllKeys = _.without(languageKeys, ...mainLanguageKeys);
    > 86 |             expect(hasAllKeys).toEqual([]);
         |                                ^
      87 |         });
      88 |     });
      89 | });

      at Object.<anonymous> (tests/unit/TranslateTest.js:86:32)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh Yeah. This way I got it now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@parasharrajat
Copy link
Member Author

parasharrajat commented Jul 29, 2021

@iwiznia Thanks for the hint. I have updated the PR with the following changes:

  1. Your suggestion of toBeEqual([]).
  2. Added Annotations to quickly see what is the cause of failure.

image

  1. Separate tests (Missing key and unused key) for each translation file.
  2. Fixed all the translations and Finalized the PR.

It's now ready to be merged.

Copy link
Contributor

@iwiznia iwiznia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah lovely!

@iwiznia iwiznia merged commit 039ec01 into Expensify:main Jul 29, 2021
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

🚀 Deployed to staging in version: 1.0.81-5🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 failure ❌
🕸 web 🕸 success ✅

@OSBotify
Copy link
Contributor

OSBotify commented Aug 6, 2021

🚀 Deployed to production in version: 1.0.82-7🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@parasharrajat parasharrajat deleted the tests branch November 20, 2023 13:07
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

Successfully merging this pull request may close these issues.

3 participants