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

CI: Run package/date unit tests in different timezones #27552

Merged
merged 7 commits into from
Dec 8, 2020

Conversation

ockham
Copy link
Contributor

@ockham ockham commented Dec 7, 2020

Fixes #27500. See #27550 (comment) for more context.

Description

Run unit tests for the @wordpress/date package in different timezones, and with different locales. This will be important to guard against regressions once we re-attempt migrating away from moment.js to another date/time package (such as date-fns).

How has this been tested?

Verify that the Unit Tests GH action goes green.

Types of changes

Increase test coverage.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@ockham ockham added [Status] In Progress Tracking issues with work in progress [Type] Automated Testing Testing infrastructure changes impacting the execution of end-to-end (E2E) and/or unit tests. [Package] Date /packages/date labels Dec 7, 2020
@ockham ockham self-assigned this Dec 7, 2020
@github-actions
Copy link

github-actions bot commented Dec 7, 2020

Size Change: -278 B (0%)

Total Size: 1.21 MB

Filename Size Change
build/annotations/index.js 3.8 kB +1 B
build/autop/index.js 2.83 kB -1 B
build/block-editor/index.js 128 kB -4 B (0%)
build/block-library/editor-rtl.css 9.07 kB +3 B (0%)
build/block-library/editor.css 9.07 kB +3 B (0%)
build/block-library/index.js 149 kB -32 B (0%)
build/block-library/style-rtl.css 8.34 kB +7 B (0%)
build/block-library/style.css 8.34 kB +7 B (0%)
build/blocks/index.js 48.1 kB -4 B (0%)
build/components/index.js 172 kB -242 B (0%)
build/compose/index.js 10.1 kB +166 B (1%)
build/dom/index.js 4.95 kB -1 B
build/edit-navigation/index.js 11.1 kB -3 B (0%)
build/edit-post/index.js 306 kB +3 B (0%)
build/edit-site/index.js 24.7 kB -2 B (0%)
build/editor/index.js 43.4 kB -165 B (0%)
build/element/index.js 4.62 kB -3 B (0%)
build/format-library/index.js 6.74 kB +1 B
build/hooks/index.js 2.27 kB -1 B
build/keyboard-shortcuts/index.js 2.54 kB -1 B
build/keycodes/index.js 1.93 kB -1 B
build/media-utils/index.js 5.31 kB -3 B (0%)
build/nux/index.js 3.42 kB -1 B
build/rich-text/index.js 13.4 kB -2 B (0%)
build/url/index.js 2.84 kB -1 B
build/viewport/index.js 1.86 kB -2 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/api-fetch/index.js 3.42 kB 0 B
build/blob/index.js 665 B 0 B
build/block-directory/index.js 8.72 kB 0 B
build/block-directory/style-rtl.css 943 B 0 B
build/block-directory/style.css 942 B 0 B
build/block-editor/style-rtl.css 11.2 kB 0 B
build/block-editor/style.css 11.2 kB 0 B
build/block-library/theme-rtl.css 789 B 0 B
build/block-library/theme.css 790 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/components/style-rtl.css 15.3 kB 0 B
build/components/style.css 15.3 kB 0 B
build/core-data/index.js 15.3 kB 0 B
build/data-controls/index.js 827 B 0 B
build/data/index.js 8.97 kB 0 B
build/date/index.js 31.8 kB 0 B
build/deprecated/index.js 769 B 0 B
build/dom-ready/index.js 571 B 0 B
build/edit-navigation/style-rtl.css 881 B 0 B
build/edit-navigation/style.css 885 B 0 B
build/edit-post/style-rtl.css 6.49 kB 0 B
build/edit-post/style.css 6.47 kB 0 B
build/edit-site/style-rtl.css 3.93 kB 0 B
build/edit-site/style.css 3.93 kB 0 B
build/edit-widgets/index.js 26.3 kB 0 B
build/edit-widgets/style-rtl.css 3.13 kB 0 B
build/edit-widgets/style.css 3.13 kB 0 B
build/editor/editor-styles-rtl.css 476 B 0 B
build/editor/editor-styles.css 478 B 0 B
build/editor/style-rtl.css 3.85 kB 0 B
build/editor/style.css 3.84 kB 0 B
build/escape-html/index.js 735 B 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.57 kB 0 B
build/is-shallow-equal/index.js 698 B 0 B
build/list-reusable-blocks/index.js 3.1 kB 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/notices/index.js 1.82 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/plugins/index.js 2.56 kB 0 B
build/primitives/index.js 1.43 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.84 kB 0 B
build/reusable-blocks/index.js 2.92 kB 0 B
build/server-side-render/index.js 2.77 kB 0 B
build/shortcode/index.js 1.69 kB 0 B
build/token-list/index.js 1.27 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.22 kB 0 B

compressed-size-action

@ockham ockham force-pushed the add/timezones-matrix-for-date-functions-unit-test-ci branch from d271c13 to 18fef83 Compare December 7, 2020 14:52
@ockham
Copy link
Contributor Author

ockham commented Dec 7, 2020

Rebased, and pushed a few more commits.
Tests are passing without the commit that adds languages (f56f865). If they start failing with that commit, we can consider reverting it, merging the PR without, and addressing different languages in a separate PR.

@ockham ockham marked this pull request as ready for review December 7, 2020 15:10
@ockham ockham requested a review from vcanales December 7, 2020 15:10
Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

Have you considered updating the test suite for dates package to run with different time zones instead?

There is https://jestjs.io/docs/en/api#describeeachtablename-fn-timeout that could help here.

@david-szabo97
Copy link
Member

@gziolo It's not possible to change timezone and locale during runtime in Node.js. One option would be to use process package to create separate processes/forks but that's a lot more complicated and fragile compared to GH actions.

@gziolo
Copy link
Member

gziolo commented Dec 7, 2020

It's not possible to change timezone and locale during runtime in Node.js.

Have you tried mocking date-fns package with:
https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename

You can also reset the state with:
https://jestjs.io/docs/en/jest-object#jestresetmodules

It should be possible to load the same package several times and initialize it differently.

One option would be to use process package to create separate processes/forks but that's a lot more complicated and fragile compared to GH actions.

The changes proposed to CI are complicated as well. Another downside is that contributors won't be able to run the same tests locally.

@ockham
Copy link
Contributor Author

ockham commented Dec 7, 2020

@gziolo As @david-szabo97 said, our first choice would've been to change the timezone (and locale) through Jest so it'd be easier to run the tests locally (as part of a normal test run). However, this turned out to be very complicated, as there doesn't seem to be a lot of dedicated utilities to that end, so we chose the CI-based approach, as it's much more straight-forward, reasonably elegant, and provides a solid baseline of unit tests against regressions.

Have you tried mocking date-fns package with:
https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename

I haven't, but TBH, I don't think that is what we should be testing for, since it'd test at implementation level. The context for this PR is that the moment -> date-fns migration was broken in a number of ways, so we decided to revert it -- which means that @wordpress/date is no longer date-fns based, and we'd currently have to mock moment instead when testing.

But the whole point of this PR is to guard against regressions when working on the implementation of @wordpress/date -- which by definition shouldn't mock whatever npm module is used to implement it, but agnostically test that it doesn't break any contracts at API level. In case of date-fns, the original migration PR was green in CI because it was only tested in GMT; testing in other timezones revealed issues that also had user-visible impact in Gutenberg (#27514, #27251).

To be clear, I'm not opposed to a Jest-level solution (as long as it's implementation-agnostic), but I think it'll require much more work, and I'd like us to start with at least some coverage. I think we can come back to this later to figure out something at Jest level.

Doing this at CI level provides a solid backstop for now; if something is broken for these timezones, CI will turn red and prevent a merge, prompting developers to investigate. If they look into the broken action, they should see fairly quickly that their code fails for a given timezone or locale, and be able to simulate that test locally (basically by prepending TZ="My/timezone" or LANG="wh_at-Ever" to npm run test-unit).

@ockham
Copy link
Contributor Author

ockham commented Dec 8, 2020

With 4 timezones and 4 locales, we now have 16 new entries in our CI. That seems a bit excessive. Considering cutting back a bit -- e.g. I don't think we need to test that many locales -- en_US and ja_JP is probably enough.

Copy link
Member

@david-szabo97 david-szabo97 left a comment

Choose a reason for hiding this comment

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

LGTM! ✅ Thank you so much for working on this!

With 4 timezones and 4 locales, we now have 16 new entries in our CI. That seems a bit excessive. Considering cutting back a bit -- e.g. I don't think we need to test that many locales -- en_US and ja_JP is probably enough.

Isn't there a way to merge them into a single entry? 🤔

@gziolo
Copy link
Member

gziolo commented Dec 8, 2020

I haven't, but TBH, I don't think that is what we should be testing for, since it'd test at implementation level. The context for this PR is that the moment -> date-fns migration was broken in a number of ways, so we decided to revert it -- which means that @wordpress/date is no longer date-fns based, and we'd currently have to mock moment instead when testing.

Now that the PR was reverted and we have the old implementation that uses moment. Is this PR still necessary? At least in the case of unit tests there is setSettings method that is used to enforce a given configuration for the library, example:

// Simulate different timezone
setSettings( {
...settings,
timezone: { offset: -4, string: 'America/New_York' },
} );

@david-szabo97
Copy link
Member

setSettings simulates the timezone of the WP site, not the system.

@ockham
Copy link
Contributor Author

ockham commented Dec 8, 2020

LGTM! ✅ Thank you so much for working on this!

Thank you for reviewing/testing/approving!

With 4 timezones and 4 locales, we now have 16 new entries in our CI. That seems a bit excessive. Considering cutting back a bit -- e.g. I don't think we need to test that many locales -- en_US and ja_JP is probably enough.

Isn't there a way to merge them into a single entry? 🤔

There is a way to couple them, yes. But I prefer to keep those as independent 'factors' -- since there's a chance we might miss bugs if we limit ourselves to certain scenarios (e.g. only testing UTC with en_US and CET with en_GB might miss a localization issue in UTC-positive timezones). I think an actual matrix gives us more combinations that can potentially reveal bugs in some scenarios.

@ockham
Copy link
Contributor Author

ockham commented Dec 8, 2020

I haven't, but TBH, I don't think that is what we should be testing for, since it'd test at implementation level. The context for this PR is that the moment -> date-fns migration was broken in a number of ways, so we decided to revert it -- which means that @wordpress/date is no longer date-fns based, and we'd currently have to mock moment instead when testing.

Now that the PR was reverted and we have the old implementation that uses moment. Is this PR still necessary?

It guards us against regressions if we ever try to change the implementation of @wordpress/date again (which I think is likely, since moment.js is notoriously big, and people have expressed interest to move away from it) -- or modify smaller bits of it. This kind of strategy helps us avoid making the same mistake twice, doesn't it?

@ockham
Copy link
Contributor Author

ockham commented Dec 8, 2020

I'll go ahead and merge this per the rationale above, since I'd like some closure on the date-fns aftermath (see this list -- great job @vcanales and @david-szabo97! 🎉 )

If this needs more discussion, we can do that here or in a follow-up issue or PR 🙂

@ockham ockham merged commit a2366e8 into master Dec 8, 2020
@ockham ockham deleted the add/timezones-matrix-for-date-functions-unit-test-ci branch December 8, 2020 16:12
@github-actions github-actions bot added this to the Gutenberg 9.6 milestone Dec 8, 2020
@gziolo gziolo removed the [Status] In Progress Tracking issues with work in progress label Dec 8, 2020
- name: Running the tests
env:
TZ: ${{ matrix.timezone }}
LANG: ${{ matrix.locale }}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to achieve the same thing without creating a big number of jobs? Maybe by hooking into jsdom or something? We have limited resources on the WP org github running and this is going to hurt :(

Copy link
Contributor

Choose a reason for hiding this comment

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

The other "easy" alternative is to just do the same thing that is done here but using a loop after the end of the unit-test job (without creating new jobs).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One more (easy) alternative that comes to mind: We could limit these tests to be only run if files in packages/date/ are touched 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

We'd miss package upgrades and things like that and if we do include package-lock.json they'd be triggering very often.

Copy link
Member

Choose a reason for hiding this comment

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

How about a bash file or npm script which these tests?

#!/bin/bash

timezones=(EST GMT CET)
locales=(en_US ja_JP)

for timezone in "${timezones[@]}"; do
    for locale in "${locales[@]}"; do
        ( TZ=$timezone LANG=$locale npm run test-unit -- packages/date )
    done
done

npm script would become horribly long:

"unit-test:date": "TZ=EST LANG=en_US npm run test-unit -- packages/date && TZ=CET LANG=en_US npm run test-unit -- packages/date ......." 

Copy link
Member

Choose a reason for hiding this comment

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

Draft here: #27600

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Date /packages/date [Type] Automated Testing Testing infrastructure changes impacting the execution of end-to-end (E2E) and/or unit tests.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Date: Tests are false-positive, assumes it is ran in GMT timezone and en_US locale
5 participants