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

Refactor useMediaQuery with useSyncExternalStore #48973

Merged
merged 7 commits into from
Mar 16, 2023

Conversation

Mamaduka
Copy link
Member

@Mamaduka Mamaduka commented Mar 9, 2023

What?

PR refactors useMediaQuery hook to use useSyncExternalStore instead of useEffect.

Why?

The useSyncExternalStore is better suited for similar subscriptions.

Testing Instructions

  1. Open a post.
  2. Resize the browser window, and confirm panels adjust to the width as before.
  3. Repeat the same step in the Site Editor.

Screenshots or screencast

CleanShot.2023-03-15.at.13.31.33.mp4

@github-actions
Copy link

github-actions bot commented Mar 9, 2023

Size Change: +1.05 kB (0%)

Total Size: 1.34 MB

Filename Size Change
build/block-editor/index.min.js 197 kB +132 B (0%)
build/block-editor/style-rtl.css 14.4 kB -3 B (0%)
build/block-editor/style.css 14.4 kB -3 B (0%)
build/block-library/blocks/cover/style-rtl.css 1.6 kB +25 B (+2%)
build/block-library/blocks/cover/style.css 1.59 kB +25 B (+2%)
build/block-library/index.min.js 201 kB +76 B (0%)
build/block-library/style-rtl.css 12.7 kB +26 B (0%)
build/block-library/style.css 12.7 kB +25 B (0%)
build/blocks/index.min.js 51 kB +18 B (0%)
build/components/index.min.js 208 kB -61 B (0%)
build/compose/index.min.js 12.4 kB +48 B (0%)
build/core-data/index.min.js 16.3 kB +48 B (0%)
build/edit-post/index.min.js 34.8 kB -2 B (0%)
build/edit-post/style-rtl.css 7.55 kB +18 B (0%)
build/edit-post/style.css 7.54 kB +17 B (0%)
build/edit-site/index.min.js 65 kB +192 B (0%)
build/edit-site/style-rtl.css 10.2 kB +223 B (+2%)
build/edit-site/style.css 10.2 kB +225 B (+2%)
build/edit-widgets/style-rtl.css 4.56 kB +9 B (0%)
build/edit-widgets/style.css 4.56 kB +9 B (0%)
build/editor/index.min.js 45.8 kB +2 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 483 B
build/block-directory/index.min.js 7.2 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.11 kB
build/block-editor/content.css 4.1 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 138 B
build/block-library/blocks/audio/theme.css 138 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 91 B
build/block-library/blocks/avatar/style.css 91 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 587 B
build/block-library/blocks/button/editor.css 587 B
build/block-library/blocks/button/style-rtl.css 628 B
build/block-library/blocks/button/style.css 627 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 138 B
build/block-library/blocks/embed/theme.css 138 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 265 B
build/block-library/blocks/file/style.css 265 B
build/block-library/blocks/file/view.min.js 353 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 984 B
build/block-library/blocks/gallery/editor.css 988 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 830 B
build/block-library/blocks/image/editor.css 829 B
build/block-library/blocks/image/style-rtl.css 652 B
build/block-library/blocks/image/style.css 652 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 716 B
build/block-library/blocks/navigation-link/editor.css 715 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.13 kB
build/block-library/blocks/navigation/editor.css 2.14 kB
build/block-library/blocks/navigation/style-rtl.css 2.22 kB
build/block-library/blocks/navigation/style.css 2.2 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 401 B
build/block-library/blocks/page-list/editor.css 401 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 134 B
build/block-library/blocks/post-excerpt/style.css 134 B
build/block-library/blocks/post-featured-image/editor-rtl.css 586 B
build/block-library/blocks/post-featured-image/editor.css 584 B
build/block-library/blocks/post-featured-image/style-rtl.css 322 B
build/block-library/blocks/post-featured-image/style.css 322 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 282 B
build/block-library/blocks/post-template/style.css 282 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 463 B
build/block-library/blocks/query/editor.css 463 B
build/block-library/blocks/quote/style-rtl.css 222 B
build/block-library/blocks/quote/style.css 222 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 489 B
build/block-library/blocks/site-logo/editor.css 489 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 651 B
build/block-library/blocks/table/style.css 650 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 404 B
build/block-library/blocks/template-part/editor.css 404 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 179 B
build/block-library/blocks/video/style.css 179 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.6 kB
build/block-library/editor.css 11.6 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/theme-rtl.css 698 B
build/block-library/theme.css 703 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/components/style-rtl.css 11.7 kB
build/components/style.css 11.7 kB
build/customize-widgets/index.min.js 12.2 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 8.58 kB
build/date/index.min.js 40.4 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.72 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-widgets/index.min.js 17.3 kB
build/editor/style-rtl.css 3.54 kB
build/editor/style.css 3.53 kB
build/element/index.min.js 4.95 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 7.26 kB
build/format-library/style-rtl.css 557 B
build/format-library/style.css 556 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.94 kB
build/list-reusable-blocks/index.min.js 2.14 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.99 kB
build/notices/index.min.js 977 B
build/plugins/index.min.js 1.95 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 937 B
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.26 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 11 kB
build/server-side-render/index.min.js 2.09 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.53 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.74 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.3 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@Mamaduka Mamaduka self-assigned this Mar 9, 2023
@Mamaduka Mamaduka added [Type] Enhancement A suggestion for improvement. [Package] Compose /packages/compose labels Mar 9, 2023
@Mamaduka
Copy link
Member Author

Mamaduka commented Mar 9, 2023

I'm unsure how to emulate/mock the event-driven behavior for window.matchMedia. It's needed for the should correctly update the value when the query evaluation matches test.

Maybe tests like these are better suited for the E2E/Playwright. Refactoring becomes more challenging if I mock stub/everything and we end up testing implementation details.

@jsnajdr, @tyxla, @kevin940726, any suggestion on how I can improve tests for this hook?

@kevin940726
Copy link
Member

IMO, if the test is just testing implementation details then it's not providing much value. I'd vote for removing it if it's too much trouble to fix.

@Mamaduka
Copy link
Member Author

IMO, if the test is just testing implementation details then it's not providing much value.

The whole test suite for this hook is like that. We're mocking the return values of window.matchMedia and then asserting against those values.

@Mamaduka Mamaduka marked this pull request as ready for review March 10, 2023 09:29
@Mamaduka Mamaduka requested a review from ajitbohra as a code owner March 10, 2023 09:29
@Mamaduka Mamaduka changed the title WIP: Refactor useMediaQuery with useSyncExternalStore Refactor useMediaQuery with useSyncExternalStore Mar 10, 2023
@jsnajdr
Copy link
Member

jsnajdr commented Mar 10, 2023

I'm unsure how to emulate/mock the event-driven behavior for window.matchMedia.

The jest-matchmedia-mock package should be able to test this, like:

const { container } = render( <TestComponent query="(min-width: 782px)" /> );

// the query doesn't match yet
expect( container ).toHaveTextContent( 'useMediaQuery: false' );

// make the query match
act( () => {
  window.matchMedia.useMediaQuery( '(min-width: 782px)' );
} );

// test that it has rerendered
expect( container ).toHaveTextContent( 'useMediaQuery: true' );

With jest-matchmedia-mock you only won't be able to test that the useMediaQuery hook unsubscribes on unmount. For that, you'd have to spy on the removeEventListener method and verify that it has been called.

@Mamaduka
Copy link
Member Author

@jsnajdr, for some reason, that also fails.

I'm using this logic to test if listeners are removed.

unmount();
expect( matchMedia.getListeners( '(min-width: 782px)' ).length ).toBe(
0
);

@jsnajdr
Copy link
Member

jsnajdr commented Mar 10, 2023

for some reason, that also fails.

What exactly fails? Looking at the jest-matchmedia-mock source, it seems to me it's not implemented very well. Here the .matches field is initialized to a constant at the time when I call window.matchMedia( query ):

https://github.com/dyakovk/jest-matchmedia-mock/blob/master/src/matchmedia-mock.ts#L31

After useMediaQuery, this .matches value doesn't change, although it should. Only an event with a matches: newValue property is fired, but that's not enough.

So, yes, in the test I suggested above, after the act( () => useMediaQuery( ... ) ) call, the component won't be rerendered with useMediaQuery: true, because the .matches field our hook is reading remains false.

Another thing that looks bad is that the mock doesn't fire an event with matches: false when I call useMediaQuery to switch away from the currently active query. It only fires a matches: true event when activating a query.

I think we'd be better off writing our own simple mock.

package.json Outdated
@@ -197,6 +197,7 @@
"jest": "29.5.0",
"jest-jasmine2": "29.5.0",
"jest-junit": "13.0.0",
"jest-matchmedia-mock": "1.1.0",
Copy link
Member

Choose a reason for hiding this comment

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

Should it be a dev dependency of the compose package though? Is there a good reason why it's required by the entire project?

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably, but the sub-packages don't have devDependencies specified, so I put it here. In any case, we'll go with custom mocking for the tests - #48973 (comment).

Copy link
Member

Choose a reason for hiding this comment

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

I agree with Jarda on using custom mockups for it 👍 Seems like a sensible and flexible enough solution for the time being.

Copy link
Member

Choose a reason for hiding this comment

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

Should it be a dev dependency of the compose package though?

I think that a few years ago, we had serious issues with devDependencies being declared on individual packages. Something with Lerna, or hoisting, or was it NPM unable to find a binary for such a package, in the top-level or package-specific node_modules/.bin directory? I don't remember, maybe @blowery or @sirreal does.

In any case, Gutenberg seems to follow a convention where all devDependencies are declared at the top. While Calypso prefers that individual packages have their own devDependencies. Many of the were added during the Yarn migration though.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I don't remember the details about these conventions.

@Mamaduka
Copy link
Member Author

Thanks again, @jsnajdr! I'll try to come up with a simple mock for these tests later today or early next week.

P.S. Here's the current test's failure.

CleanShot 2023-03-10 at 15 29 01

@tyxla
Copy link
Member

tyxla commented Mar 10, 2023

@Mamaduka in case that's helpful, in Automattic/wp-calypso#73890 I recently mocked matchMedia to address some test failures too. Here's the mock I used:

beforeAll( () => {
	window.matchMedia = jest.fn().mockImplementation( ( query ) => {
		return {
			matches: true,
			media: query,
			onchange: null,
			addListener: jest.fn(),
			removeListener: jest.fn(),
		};
	} );
} );

Perhaps you could reuse it with some adaptation to suit your needs?

@jsnajdr
Copy link
Member

jsnajdr commented Mar 10, 2023

Here's the current test's failure.

It's like if someone already called useMediaQuery before the initial render. Maybe the mock state leaks from the previous test?

@Mamaduka
Copy link
Member Author

I've found a different library (mock-match-media) that also emulates the events. The only problem is that I can't test listener removal on umount as previous tests did.

P.S. I tried writing a "simple mock", but emulating events was more challenging than I expected.

@Mamaduka
Copy link
Member Author

The PR is ready for testing 🙇

Copy link
Member

@jsnajdr jsnajdr left a comment

Choose a reason for hiding this comment

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

Looks good 👍

addListener = jest.fn();
removeListener = jest.fn();
window.matchMedia = matchMedia;
window.MediaQueryListEvent = MediaQueryListEvent;
Copy link
Member

Choose a reason for hiding this comment

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

Do you need to set the MediaQueryListEvent global? That seems useful only if you wanted to manually create and dispatch these events.

Copy link
Member Author

@Mamaduka Mamaduka Mar 15, 2023

Choose a reason for hiding this comment

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

I need to check and confirm, but this is based on the library's Jest setup polyfill - https://github.com/Ayc0/mock-match-media/blob/master/polyfill.js.

I'll remove it if it's not required to trigger changes.

Update: You were right; setting the MediaQueryListEvent isn't needed.

@jsnajdr
Copy link
Member

jsnajdr commented Mar 15, 2023

The only problem is that I can't test listener removal on umount as previous tests did.

That's probably OK, because big part of the work is done by useSyncExternalStore hook today. You'd be basically testing if the subscribe function really returns a correct removeEventListener callback.

@github-actions
Copy link

Flaky tests detected in a0b0cb9.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4428026786
📝 Reported issues:

@Mamaduka Mamaduka merged commit 8ac3b00 into trunk Mar 16, 2023
@Mamaduka Mamaduka deleted the refactor/use-media-query branch March 16, 2023 07:13
@github-actions github-actions bot added this to the Gutenberg 15.5 milestone Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Compose /packages/compose [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants