diff --git a/gallery/package.json b/gallery/package.json index ff5a30452f..02b6f6a96d 100644 --- a/gallery/package.json +++ b/gallery/package.json @@ -1,6 +1,6 @@ { "name": "@sonatype/react-shared-components-gallery", - "version": "12.10.3", + "version": "12.10.8", "description": "Gallery application to demonstrate usage and look of Sonatype shared UI components", "main": "src/main.ts", "scripts": { diff --git a/gallery/src/components/NxTree/NxTreeCollapsibleExample.tsx b/gallery/src/components/NxTree/NxTreeCollapsibleExample.tsx index 4ab6b323bf..c768cbfa06 100644 --- a/gallery/src/components/NxTree/NxTreeCollapsibleExample.tsx +++ b/gallery/src/components/NxTree/NxTreeCollapsibleExample.tsx @@ -63,7 +63,7 @@ export default function NxTreeCollapsibleExample() { onActivate={() => document.getElementById('images-link')?.click()}> - { alert('images'); }}> + images diff --git a/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-narrow-dropdown-1.png b/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-narrow-dropdown-1.png index 0776466114..58955d7865 100644 --- a/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-narrow-dropdown-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-narrow-dropdown-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac2b73de36fbd49f1392673ebb27999db2797558f352667de7e4c1fe551f6ca3 -size 50879 +oid sha256:6b32d3552dbda55457bf240a3b39de00aaa92d38c0f645cddcfd1a5624e16508 +size 50849 diff --git a/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-wide-dropdown-1.png b/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-wide-dropdown-1.png index 67647061b9..a175ed011b 100644 --- a/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-wide-dropdown-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-looks-right-with-a-wide-dropdown-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a30c5552ba746271482c0fe96896082a195616c82d876a2d03ee057b8ea536f3 -size 72955 +oid sha256:7bc7747615d93cb0bc0d3d4b41e52a5251717e20a16f337fd1ad15d425484a81 +size 72977 diff --git a/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-shows-overflow-tooltips-on-dropdown-links-1.png b/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-shows-overflow-tooltips-on-dropdown-links-1.png index 5f4c3a021a..5588767396 100644 --- a/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-shows-overflow-tooltips-on-dropdown-links-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-breadcrumb-js-nx-breadcrumb-shows-overflow-tooltips-on-dropdown-links-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1e2973cb05d8d2cade2ed1ff011841f9c17e30c25f24619362248c4f3cac357 -size 74590 +oid sha256:7191780111ecf0d1af831651697edc6e16a58cbbb32dacd340126a4c0b393353 +size 74576 diff --git a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-classname-disabled-nx-button-looks-disabled-when-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-classname-disabled-nx-button-looks-disabled-when-clicked-1.png index 9755e109e9..77f111613a 100644 --- a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-classname-disabled-nx-button-looks-disabled-when-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-classname-disabled-nx-button-looks-disabled-when-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87e1302fa463a7d3bab8a2942d2149ddba3ccdb15b64a41357f349d03deee34f -size 2739 +oid sha256:bffa07c1b6113cfb0d964c2d5028a3eb8db37cfbfa056bd2086670b43af911a6 +size 2716 diff --git a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-default-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-default-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png index 6a15b1c41a..cc9358435f 100644 --- a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-default-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-default-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2094ad1b59d69b974623447501836e102a66f8f9ed80256efc2d4a5fa11f104b -size 1728 +oid sha256:f6ad3ff4f2ef10252f684505d1a7fc29c0b6779503c0c085142d926302ec96ac +size 1722 diff --git a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-dark-background-when-hovered-1.png b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-dark-background-when-hovered-1.png index afebd126a4..3925c08ed4 100644 --- a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-dark-background-when-hovered-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-dark-background-when-hovered-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8301df4ac216ed122283b6942d0559bdad04d5b337acb07bcba9b0be4b11bc8d -size 2700 +oid sha256:e521f6cc34b1fc7c39d5d3e4d476205e82b17039f6dbe920f06a4d3977db9c57 +size 2754 diff --git a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-dark-blue-background-when-focused-and-hovered-1.png b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-dark-blue-background-when-focused-and-hovered-1.png index 5c12c3d261..649854b6ea 100644 --- a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-dark-blue-background-when-focused-and-hovered-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-dark-blue-background-when-focused-and-hovered-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b245652bb8ae61cdd2c2ec451acdab3ef45b8b3ac32e1791cefa0196ee006d6 -size 2870 +oid sha256:76fc2c0d3162048b4d8347239fdd2a9be8890050b123f6dc901b44f7762a6808 +size 2872 diff --git a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png index 48428cee23..21b1f85d72 100644 --- a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42269086993689597a6b1e8edd7385fa3640cd58bdf70d8c96c76e0639f2a981 -size 2556 +oid sha256:62778fbe85779ffe1350c09e80f2063d45eeef1c80fa6a315568ab5588102b50 +size 2401 diff --git a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-when-focused-1.png b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-when-focused-1.png index 5c12c3d261..649854b6ea 100644 --- a/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-when-focused-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-button-js-nx-button-primary-nx-button-has-a-light-blue-border-when-focused-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b245652bb8ae61cdd2c2ec451acdab3ef45b8b3ac32e1791cefa0196ee006d6 -size 2870 +oid sha256:76fc2c0d3162048b4d8347239fdd2a9be8890050b123f6dc901b44f7762a6808 +size 2872 diff --git a/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-does-not-close-the-collapsible-items-when-the-action-content-is-expanded-1.png b/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-does-not-close-the-collapsible-items-when-the-action-content-is-expanded-1.png index 6b764fd561..bfcd0788ac 100644 --- a/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-does-not-close-the-collapsible-items-when-the-action-content-is-expanded-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-does-not-close-the-collapsible-items-when-the-action-content-is-expanded-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad53faa78ff404a27a7f9789566749d49d38fd4f584745885ebc09ee1134036e -size 22532 +oid sha256:f2354adece6c91e7290e01e1282339d9bf284aca229f58d341cd798fe2eb0812 +size 22470 diff --git a/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-looks-right-when-the-icon-dropdown-is-expanded-and-the-collapsible-items-is-closed-1.png b/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-looks-right-when-the-icon-dropdown-is-expanded-and-the-collapsible-items-is-closed-1.png index 16215481f4..bc5ad56e6b 100644 --- a/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-looks-right-when-the-icon-dropdown-is-expanded-and-the-collapsible-items-is-closed-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-collapsible-items-js-nx-collapsible-items-nx-collapsible-items-with-action-content-looks-right-when-the-icon-dropdown-is-expanded-and-the-collapsible-items-is-closed-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26150cf8b64ae679d4573f8d6c0caddf062fe1e53a1cc0bb763b06b323f8d13a -size 14956 +oid sha256:453a489d7e13412d06f55528e7d4e4bde35d7ca03ce752b864e2508aea1f19b6 +size 14923 diff --git a/gallery/visualtests/__image_snapshots__/nx-icon-dropdown-js-nx-icon-dropdown-default-nx-icon-dropdown-when-open-has-a-dark-grey-button-border-with-expanded-menu-1.png b/gallery/visualtests/__image_snapshots__/nx-icon-dropdown-js-nx-icon-dropdown-default-nx-icon-dropdown-when-open-has-a-dark-grey-button-border-with-expanded-menu-1.png index 61a51465df..a088129d17 100644 --- a/gallery/visualtests/__image_snapshots__/nx-icon-dropdown-js-nx-icon-dropdown-default-nx-icon-dropdown-when-open-has-a-dark-grey-button-border-with-expanded-menu-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-icon-dropdown-js-nx-icon-dropdown-default-nx-icon-dropdown-when-open-has-a-dark-grey-button-border-with-expanded-menu-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19b725a595e89ac3efa98c65fb408298a6886fe290c65ea8936d0b236ace90d0 -size 17181 +oid sha256:b79bcb0116e1ea1ebe9ac803a45ac94c36667256dd8952939ad2c62b8378732b +size 17166 diff --git a/gallery/visualtests/__image_snapshots__/nx-modal-js-nx-modal-stacked-nx-modals-looks-right-1.png b/gallery/visualtests/__image_snapshots__/nx-modal-js-nx-modal-stacked-nx-modals-looks-right-1.png index ef3e0ab900..0e0f544253 100644 --- a/gallery/visualtests/__image_snapshots__/nx-modal-js-nx-modal-stacked-nx-modals-looks-right-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-modal-js-nx-modal-stacked-nx-modals-looks-right-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26379051776660bd4e4ee8d96aed0905cd3ab7f6ec48c1b128c4d40ab34ca758 -size 73050 +oid sha256:1030c4a398ed14bfeae5096d67d071d283bcac9f4192b6d595603779a0e7424e +size 73001 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-darker-blue-background-when-hovered-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-darker-blue-background-when-hovered-1.png index 5bc40f3f3d..77505d5b99 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-darker-blue-background-when-hovered-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-darker-blue-background-when-hovered-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c602cf2dbe3ba677d9f7de59a5255784fae77f6dc9d283190e2dbc7b824612c4 -size 1879 +oid sha256:e1f259732e00d6b25ad420af7cc5292607f5a1f3fa1df0823333935a00c08335 +size 1894 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-light-blue-border-when-focused-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-light-blue-border-when-focused-1.png index f66028d6b4..6e0ac95c71 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-light-blue-border-when-focused-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-light-blue-border-when-focused-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e53605031cdf9a0e1cd955ee247f619f110ddf3906096c60d9a4ce6e61ba73ce -size 1974 +oid sha256:cdca2b3c6abc22e65af7cf4d9d27b7da80964ed78279412bdf5cb893d606fa29 +size 1987 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-lighter-blue-background-when-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-lighter-blue-background-when-clicked-1.png index 90078d98a8..1560cdd571 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-lighter-blue-background-when-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-dropdown-section-has-a-lighter-blue-background-when-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b34ddacd5f53437f1f5cecd8bff00ceafd61b4852e224c9b39b57f8843f3637 -size 1973 +oid sha256:9aa13b45f02ebeeae34616c51343dacc3d38bd3213bc85058c90f8eb90e3225c +size 1878 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-darker-blue-background-when-hovered-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-darker-blue-background-when-hovered-1.png index 84a09c695d..76cfcb69a3 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-darker-blue-background-when-hovered-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-darker-blue-background-when-hovered-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a37f4da7a82f44a458a5a9c0b5c51e62acb55d34f9226549f73f1000ff7526e9 -size 1896 +oid sha256:863ce887eec2e80a96d4628d676181c98b5e8c9cb19c167151f098710dacd12f +size 1909 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-light-blue-border-when-focused-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-light-blue-border-when-focused-1.png index ea8a804891..fb69e5e322 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-light-blue-border-when-focused-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-light-blue-border-when-focused-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:593188b57bfb1d383bcce64302769e3f869b93681eaf58aacc3cef12f1294f66 -size 2018 +oid sha256:c70d11a4e64092a19e4dc6873cf6536d14106ca70e8d467d9d026ec29b67e71c +size 2016 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-lighter-blue-background-when-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-lighter-blue-background-when-clicked-1.png index d3c23b52d1..09d5e717c8 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-lighter-blue-background-when-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-primary-nx-button-primary-nx-button-main-section-has-a-lighter-blue-background-when-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e791a42a95a14fc126b0464d8883e7d86d27b70d979aa2e3ebe13d4dd4da07d8 -size 1836 +oid sha256:dc8cac9a3ccab442b1b12d530e524bda16fdfa66a0f571dc3501787d93110262 +size 1734 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-dropdown-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-dropdown-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png index a14d01508a..1423cf6802 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-dropdown-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-dropdown-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da37ce6d69ede3427a0e7fa6e27915f41e3c00754a0008a7b9ba15732c754220 -size 2052 +oid sha256:d8a8c9a50fe90f89a594c2f24ebf45eaec49a9505e779b922906e9e2f9c825a8 +size 1994 diff --git a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-main-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-main-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png index d082f4ecc2..028067e468 100644 --- a/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-main-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-segmented-button-js-nx-segmented-button-secondary-nx-button-secondary-nx-button-main-section-has-a-light-blue-border-and-light-blue-background-when-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfa2e6c19bb02b6287d5d4dd86c916469903c7bf61e29673322c73f88338965f -size 2067 +oid sha256:ff4b9d04d34f800879ce4ee060bd081437a9ec83650e4a60fa242a6c8744624a +size 2001 diff --git a/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-doesnt-render-a-move-icon-when-on-item-change-is-not-provided-1.png b/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-doesnt-render-a-move-icon-when-on-item-change-is-not-provided-1.png new file mode 100644 index 0000000000..25d5a81794 --- /dev/null +++ b/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-doesnt-render-a-move-icon-when-on-item-change-is-not-provided-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:530665184e428f440236232d1e76c97bb43194e6e63e75e22feb7dc8155c0b3c +size 1301 diff --git a/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-renders-a-plus-icon-when-on-item-change-is-provided-but-is-selected-is-false-1.png b/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-renders-a-plus-icon-when-on-item-change-is-provided-but-is-selected-is-false-1.png new file mode 100644 index 0000000000..768e745ed2 --- /dev/null +++ b/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-renders-a-plus-icon-when-on-item-change-is-provided-but-is-selected-is-false-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3436457d1be4b16fe141df97e8ddd6acb2969048acc4ddb7f23bd615e5329842 +size 1506 diff --git a/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-renders-an-x-icon-when-on-item-change-is-provided-and-is-selected-is-true-1.png b/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-renders-an-x-icon-when-on-item-change-is-provided-and-is-selected-is-true-1.png new file mode 100644 index 0000000000..c9edec589e --- /dev/null +++ b/gallery/visualtests/__image_snapshots__/nx-transfer-list-half-js-nx-transfer-list-half-move-icons-renders-an-x-icon-when-on-item-change-is-provided-and-is-selected-is-true-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e295e771b4c6b4cb03aecb3d368658a8a57e1055e19be5125e0a8adf1018ec0b +size 1697 diff --git a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-a-collapse-control-is-clicked-1.png b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-a-collapse-control-is-clicked-1.png index 5ac543cb43..99caf84fb8 100644 --- a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-a-collapse-control-is-clicked-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-a-collapse-control-is-clicked-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63b8660461cedfcea092173daf396a3a68b2f0465525459a38e26b70d25f4c30 -size 27948 +oid sha256:20a8e4266a110d8a7604398386c697abd4ca478054994570c1a5d42b1787a224 +size 27974 diff --git a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-an-item-is-focused-1.png b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-an-item-is-focused-1.png index aa899ae2ca..259d15f8d9 100644 --- a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-an-item-is-focused-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-when-an-item-is-focused-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e17034b8793ec20303a9e9c5ea28fa7004b6730913c42e6bac87c0b9cb5de78f -size 36662 +oid sha256:e6d4a1767f07cc6fdd2dc91e7231bf16d0119115451f84b26a01c07bea96d06b +size 36689 diff --git a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-a-single-top-entry-and-collapsing-1.png b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-a-single-top-entry-and-collapsing-1.png index fd97dc5169..500b126de6 100644 --- a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-a-single-top-entry-and-collapsing-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-a-single-top-entry-and-collapsing-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59530a215573be625c2b6d4a4d858ce704c98d15c45df89c663c6bbc60c31caa -size 35414 +oid sha256:e86b00716e798b29414995fead4fbdac06e64995a50a250ff5e55e7af47217f2 +size 35440 diff --git a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-some-collapsible-elements-collapsed-1.png b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-some-collapsible-elements-collapsed-1.png index 08dda9e3db..f6d718c34e 100644 --- a/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-some-collapsible-elements-collapsed-1.png +++ b/gallery/visualtests/__image_snapshots__/nx-tree-js-nx-tree-looks-right-with-some-collapsible-elements-collapsed-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:982e1af4048f6a3ae00cf7a42cde76a27ce1cb6f16e7aafdd307e5e1ef3af614 -size 20053 +oid sha256:eb0a2391f9b18b49aa3fd4dea3c3e0fc879c8d44d16ee2bedd4f34199d1eb00f +size 20083 diff --git a/gallery/visualtests/nxTransferListHalf.js b/gallery/visualtests/nxTransferListHalf.js index d96e029803..984ac4909f 100644 --- a/gallery/visualtests/nxTransferListHalf.js +++ b/gallery/visualtests/nxTransferListHalf.js @@ -38,6 +38,8 @@ describe('NxTransferListHalf', function() { secondItemSelector = `${itemsSelector}:nth-child(2) .nx-transfer-list__select`, transferAllSelector = `${complexListSelector} .nx-transfer-list__move-all`, complexFirstItemSelector = `${complexListSelector} .nx-transfer-list__item:first-child`, + complexSecondItemSelector + = `${complexListSelector} .nx-transfer-list__item:nth-child(2) .nx-transfer-list__select`, moveUpSelector = `${complexFirstItemSelector} .nx-transfer-list__button-bar > :first-child`, moveDownSelector = `${complexFirstItemSelector} .nx-transfer-list__button-bar > :last-child`, filterBoxSelector = `${complexListSelector} .nx-text-input__input`, @@ -133,4 +135,11 @@ describe('NxTransferListHalf', function() { await wait(500); await a11yTest()(); }); + + describe('move icons', function() { + it('renders an x icon when onItemChange is provided and isSelected is true', simpleTest(secondItemSelector)); + it('renders a plus icon when onItemChange is provided but isSelected is false', + simpleTest(complexSecondItemSelector)); + it('doesn\'t render a move icon when onItemChange is not provided', simpleTest(secondDisableTransferItemSelector)); + }); }); diff --git a/gallery/visualtests/nxTree.js b/gallery/visualtests/nxTree.js index 584dd1705e..7e0fb56a84 100644 --- a/gallery/visualtests/nxTree.js +++ b/gallery/visualtests/nxTree.js @@ -14,6 +14,7 @@ describe('NxTree', function() { waitAndGetElements, getPage, isFocused, + scrollPage, a11yTest } = setupBrowser('#/pages/Tree'); @@ -80,6 +81,23 @@ describe('NxTree', function() { await simpleTest(collapsibleExampleSelector)(); }); + // Check for RSC-1342 + it('does not scroll when a partially out-of-view tree\'s label is clicked', async function() { + const [tree] = await waitAndGetElements(collapsibleExampleSelector), + images = await itemWithText(tree, 'images'); + + await scrollPage(0); + + const imagesLowerBound = await images.evaluate(e => e.getBoundingClientRect().bottom), + viewportHeight = await getPage().evaluate(() => window.innerHeight), + desiredScroll = imagesLowerBound - viewportHeight - 50; + + await scrollPage(desiredScroll); + await (await clickTarget(images)).click(); + + expect(await getPage().evaluate(() => window.scrollY)).toBe(desiredScroll); + }); + describe('keyboard navigation', function() { it('initially focuses the first item in the tree when reached via tab', async function() { const [previousFocusableElement, tree] = await waitAndGetElements( @@ -637,14 +655,14 @@ describe('NxTree', function() { expect(await hasClass(images, 'open')).toBe(true); await imagesClick.click(); - const sawAlert = new Promise(resolve => { - page.once('dialog', dialog => { - dialog.dismiss().then(resolve); + const sawSecondPopup = new Promise(resolve => { + page.once('popup', newTab => { + newTab.close().then(resolve); }); }); await page.keyboard.press('Enter'); - await sawAlert; + await sawSecondPopup; expect(await hasClass(images, 'open')).toBe(true); }); diff --git a/gallery/visualtests/testUtils.js b/gallery/visualtests/testUtils.js index 43ee4b72c6..5a042b75e0 100644 --- a/gallery/visualtests/testUtils.js +++ b/gallery/visualtests/testUtils.js @@ -178,6 +178,10 @@ module.exports = { await el.evaluate(e => e.scrollIntoView({ block: 'center' })); } + async function scrollPage(y) { + await page.evaluate((y) => window.scrollTo(0, y), y); + } + async function moveMouseAway() { await page.mouse.move(0, 0); } @@ -260,6 +264,7 @@ module.exports = { disableLoadingSpinnerAnimation, setupUploadableFiles, scrollIntoView, + scrollPage, waitForSelectors, getElements, diff --git a/lib/.eslintrc b/lib/.eslintrc index 0c578c633a..636e3a7c2d 100644 --- a/lib/.eslintrc +++ b/lib/.eslintrc @@ -159,7 +159,7 @@ "overrides": [ { "files": ["*.tsx", "*.js", "*.ts"], - "excludedFiles": ["*.test.tsx"], + "excludedFiles": ["*.test.tsx", "src/__testutils__/*", "src/setupTests.ts"], "extends": ["plugin:jsx-a11y/recommended"], "plugins": ["jsx-a11y"], "rules": { @@ -169,7 +169,7 @@ } }, { - "files": ["*.test.tsx", "*.test.ts"], + "files": ["*.test.tsx", "*.test.ts", "src/__testutils__/*", "src/setupTests.ts"], "globals": { "jest": true, "it": true, diff --git a/lib/package.json b/lib/package.json index 970296c5e9..db69aea4d5 100644 --- a/lib/package.json +++ b/lib/package.json @@ -1,6 +1,6 @@ { "name": "@sonatype/react-shared-components", - "version": "12.10.3", + "version": "12.10.8", "description": "Sonatype shared UI components and utilities written in React", "main": "index.js", "repository": { diff --git a/lib/src/__testutils__/rtlUtils.tsx b/lib/src/__testutils__/rtlUtils.tsx index d50e616a05..5cb1d3116a 100644 --- a/lib/src/__testutils__/rtlUtils.tsx +++ b/lib/src/__testutils__/rtlUtils.tsx @@ -5,11 +5,13 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import React, { ComponentType } from 'react'; -import { render, RenderResult } from '@testing-library/react'; +import { act, render, RenderResult } from '@testing-library/react'; import '@testing-library/jest-dom'; +import realUserEvent from '@testing-library/user-event'; import { path, pipe } from 'ramda'; import { within } from '@testing-library/dom'; +import { Options } from '@testing-library/user-event/dist/types/options'; export function rtlRender

(Component: ComponentType

, minimalProps: P) { return function renderWrapper(additionalProps?: Partial

): RenderResult { @@ -27,3 +29,18 @@ type RenderElementRetval

= (additionalProps?: Partial

) => HTMLElement | un export function rtlRenderElement

(Component: ComponentType

, minimalProps: P): RenderElementRetval

{ return pipe(rtlRender(Component, minimalProps), path(['container', 'firstElementChild'])); } + +export async function runTimers() { + await act(async () => { await jest.runAllTimers(); }); +} + +export async function advanceTimers(time: number) { + await act(async () => { await jest.advanceTimersByTime(time); }); +} + +export const userEvent = { + ...realUserEvent, + setup(options?: Options) { + return realUserEvent.setup({ advanceTimers, ...options }); + } +}; diff --git a/lib/src/base-styles/_nx-btn.scss b/lib/src/base-styles/_nx-btn.scss index ef985d2fad..0ae4df911e 100644 --- a/lib/src/base-styles/_nx-btn.scss +++ b/lib/src/base-styles/_nx-btn.scss @@ -28,8 +28,8 @@ background-color: var(--nx-swatch-blue-90); } - &:focus { - border: 1px solid var(--nx-color-interactive-border-focus); + &:focus:not(:active) { + border-color: var(--nx-color-interactive-border-focus); box-shadow: var(--nx-box-shadow-focus); outline: 0; } @@ -55,7 +55,7 @@ color: var(--nx-swatch-white); &:hover, &:focus { - background-color: var(--nx-swatch-blue-20); + background-color: var(--nx-swatch-blue-30); } &:active { diff --git a/lib/src/components/AbstractNxPageHeader/__tests__/AbstractNxPageHeader.test.tsx b/lib/src/components/AbstractNxPageHeader/__tests__/AbstractNxPageHeader.test.tsx index 4e4827e2f9..f5b3cbc037 100644 --- a/lib/src/components/AbstractNxPageHeader/__tests__/AbstractNxPageHeader.test.tsx +++ b/lib/src/components/AbstractNxPageHeader/__tests__/AbstractNxPageHeader.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import AbstractNxPageHeader, { Props, HeaderLink, HeaderLinkProps } from '../AbstractNxPageHeader'; describe('AbstractNxPageHeader', function() { diff --git a/lib/src/components/Counter/__tests__/Counter.test.tsx b/lib/src/components/Counter/__tests__/Counter.test.tsx index 8d9365002f..a235387612 100644 --- a/lib/src/components/Counter/__tests__/Counter.test.tsx +++ b/lib/src/components/Counter/__tests__/Counter.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import {getShallowComponent} from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import Counter, {Props} from '../Counter'; describe('Counter', function() { diff --git a/lib/src/components/Counter/__tests__/MultiSelectCounter.test.tsx b/lib/src/components/Counter/__tests__/MultiSelectCounter.test.tsx index 3be3260bf0..96629f0791 100644 --- a/lib/src/components/Counter/__tests__/MultiSelectCounter.test.tsx +++ b/lib/src/components/Counter/__tests__/MultiSelectCounter.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import {getShallowComponent} from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import MultiSelectCounter, {Props} from '../MultiSelectCounter'; import Counter from '../Counter'; diff --git a/lib/src/components/NxAccordion/__tests__/NxAccordion.test.tsx b/lib/src/components/NxAccordion/__tests__/NxAccordion.test.tsx index 7b4bc14f9d..6968f70d30 100644 --- a/lib/src/components/NxAccordion/__tests__/NxAccordion.test.tsx +++ b/lib/src/components/NxAccordion/__tests__/NxAccordion.test.tsx @@ -5,7 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import React from 'react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxAccordion/stateful/NxStatefulAccordion.tsx b/lib/src/components/NxAccordion/stateful/NxStatefulAccordion.tsx index 702dd27197..4483dc4a46 100644 --- a/lib/src/components/NxAccordion/stateful/NxStatefulAccordion.tsx +++ b/lib/src/components/NxAccordion/stateful/NxStatefulAccordion.tsx @@ -12,10 +12,18 @@ import { Props, propTypes } from './types'; import useToggle from '../../../util/useToggle'; export { Props }; -export default function NxStatefulAccordion({ defaultOpen, ...otherProps }: Props) { +export default function NxStatefulAccordion({defaultOpen, onToggle, ...otherProps }: Props) { const [open, toggleOpen] = useToggle(defaultOpen || false); - return ; + function openHandler() { + const newStatus = toggleOpen(); + + if (onToggle) { + onToggle(newStatus); + } + } + + return ; } NxStatefulAccordion.propTypes = propTypes; diff --git a/lib/src/components/NxAccordion/stateful/__tests__/NxStatefulAccordion.test.tsx b/lib/src/components/NxAccordion/stateful/__tests__/NxStatefulAccordion.test.tsx index 071de918f6..d1d68e258f 100644 --- a/lib/src/components/NxAccordion/stateful/__tests__/NxStatefulAccordion.test.tsx +++ b/lib/src/components/NxAccordion/stateful/__tests__/NxStatefulAccordion.test.tsx @@ -4,46 +4,233 @@ * the terms of the Eclipse Public License 2.0 which accompanies this * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ -import { act } from 'react-dom/test-utils'; +import React from 'react'; -import NxStatefulAccordion, { Props } from '../NxStatefulAccordion'; +import NxStatefulAccordion from '../NxStatefulAccordion'; import NxAccordion from '../../NxAccordion'; -import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; +import { rtlRender, rtlRenderElement, userEvent } from '../../../../__testutils__/rtlUtils'; +import { render } from '@testing-library/react'; +import NxButton from '../../../NxButton/NxButton'; describe('NxStatefulAccordion', function() { - const getShallowComponent = enzymeUtils.getShallowComponent(NxStatefulAccordion, {}); - it('renders an NxAccordion with the specified props', function() { + const quickRender = rtlRender(NxStatefulAccordion, {}); + const renderEl = rtlRenderElement(NxStatefulAccordion, {}); + + it('renders a

with the specified props', function() { const onToggle = jest.fn(), - component = getShallowComponent({ onToggle, className: 'foo', id: 'bar' }); + component = renderEl({ onToggle, id: 'bar' }); + + expect(component!.tagName).toBe('DETAILS'); + expect(component).toHaveAttribute('id', 'bar'); + }); - expect(component).toMatchSelector(NxAccordion); - expect(component).toHaveProp('onToggle', onToggle); - expect(component).toHaveProp('className', 'foo'); - expect(component).toHaveProp('id', 'bar'); + it('sets the provided className', function() { + const el = renderEl()!; + const customEl = renderEl({ className: 'foo' })!; + + expect(customEl).toHaveClass('foo'); + + for (const cls of Array.from(el.classList)) { + expect(customEl).toHaveClass(cls); + } }); it('sets the NxAccordion open prop to the defaultOpen prop initially', function() { - expect(getShallowComponent()).toHaveProp('open', false); - expect(getShallowComponent({ defaultOpen: false })).toHaveProp('open', false); - expect(getShallowComponent({ defaultOpen: true })).toHaveProp('open', true); + expect(renderEl()).not.toHaveAttribute('open'); + expect(renderEl({ defaultOpen: false })).not.toHaveAttribute('open'); + expect(renderEl({ defaultOpen: true })).toHaveAttribute('open'); }); - it('toggles the NxAccordion open prop when the NxAccordion onToggle callback is called', function() { - const component = getShallowComponent(); + it('renders non-header children in content wrapper', function() { + const { container } = render( + + + Foo + + Bar + + ); + + expect(container.querySelector('summary .bar')).not.toBeInTheDocument(); + expect(container.querySelector('.bar')).toBeInTheDocument(); + }); + + describe('Header', function() { + it('sets aria-controls to the accordion id when id is not specified', function() { + const { container } = quickRender({ + children: ( + + ) + }); + const id = container.querySelector('DETAILS')?.getAttribute('id'); + expect(container.querySelector('SUMMARY')).toHaveAttribute('aria-controls', id); + }); + + it('sets aria-controls to the specified accordion id', function() { + const { container } = quickRender({ + id: 'foo', + children: ( + + Foo + + ) + }); + + expect(container.querySelector('SUMMARY')).toHaveAttribute('aria-controls', 'foo'); + }); + }); + + describe('accordion header click', function() { + describe('when the accordion is currently closed', function() { + it('calls onToggle', async function() { + const user = userEvent.setup(), + onToggle = jest.fn(), + el = quickRender({ + onToggle, + children: ( + + Foo + + )}); + const header = el.getByRole('button')!; + expect(onToggle).not.toHaveBeenCalled(); + + await user.click(header); + + expect(onToggle).toHaveBeenCalled(); + }); + + it('toggles the accordion open prop', async function() { + const user = userEvent.setup(), + onToggle = jest.fn(), + el = quickRender({ + onToggle, + children: ( + + Foo + + )}); + const header = el.getByRole('button')!; + expect(el.getByRole('group')).not.toHaveAttribute('open'); + + await user.click(header); + + expect(el.getByRole('group')).toHaveAttribute('open'); + }); + }); + + describe('when the accordion is currently open', function() { + it('calls onToggle', async function() { + const user = userEvent.setup(); + const onToggle = jest.fn(); - expect(component).toHaveProp('open', false); + const { container } = quickRender({ + onToggle, + defaultOpen: true, + children: ( + + Foo + + )}); - act(function() { - component.simulate('toggle'); + const header = container.querySelector('summary')!; + + expect(onToggle).not.toHaveBeenCalled(); + + await user.click(header); + + expect(onToggle).toHaveBeenCalledTimes(1); + + await user.click(container); + + expect(onToggle).toHaveBeenCalledTimes(1); + }); + + it('toggles the accordion open prop', async function() { + const user = userEvent.setup(); + const onToggle = jest.fn(); + + const el = quickRender({ + onToggle, + defaultOpen: true, + children: ( + + Foo + + )}); + + const header = el.getByRole('button')!; + + expect(el.getByRole('group')).toHaveAttribute('open'); + + await user.click(header); + + expect(el.getByRole('group')).not.toHaveAttribute('open'); + }); }); - expect(component).toHaveProp('open', true); + describe('when a non-button element in the header with its own onClick handler is clicked', function() { + it('changes the open state and fires onToggle', async function() { + const user = userEvent.setup(); + const titleOnClick = jest.fn(), + onToggle = jest.fn(); - act(function() { - component.simulate('toggle'); + const component = render( + + + Foo + + , + ); + const title = component.getByTestId('foo'); + + expect(onToggle).not.toHaveBeenCalled(); + expect(titleOnClick).not.toHaveBeenCalled(); + expect(component.getByRole('group')).not.toHaveAttribute('open'); + + await user.click(title); + + expect(onToggle).toHaveBeenCalledTimes(1); + expect(titleOnClick).toHaveBeenCalledTimes(1); + expect(component.getByRole('group')).toHaveAttribute('open'); + }); }); - expect(component).toHaveProp('open', false); + describe('when a button element in the header is clicked', function() { + it('does not change the open state or fire onToggle', async function() { + const user = userEvent.setup(); + const btnOnClick = jest.fn(), + onToggle = jest.fn(); + + const component = render( + + + Foo +
+ + +
+
+
, + ); + const btn1 = component.getByTestId('btn1'), + btn2 = component.getByTestId('btn2'); + + expect(component.getByRole('group')).not.toHaveAttribute('open'); + await user.click(btn1); + + expect(onToggle).not.toHaveBeenCalled(); + expect(btnOnClick).not.toHaveBeenCalled(); + expect(component.getByRole('group')).not.toHaveAttribute('open'); + + await user.click(btn2); + + expect(onToggle).not.toHaveBeenCalled(); + expect(btnOnClick).toHaveBeenCalled(); + expect(component.getByRole('group')).not.toHaveAttribute('open'); + }); + }); }); + }); diff --git a/lib/src/components/NxAlert/__tests__/NxAlert.test.tsx b/lib/src/components/NxAlert/__tests__/NxAlert.test.tsx index ef7b0b83a5..18f2380983 100644 --- a/lib/src/components/NxAlert/__tests__/NxAlert.test.tsx +++ b/lib/src/components/NxAlert/__tests__/NxAlert.test.tsx @@ -7,7 +7,7 @@ import React, { ComponentType } from 'react'; import { faBiohazard } from '@fortawesome/free-solid-svg-icons'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; import NxAlert, { Props, NxErrorAlert, NxWarningAlert, NxInfoAlert, NxSuccessAlert } from '../NxAlert'; diff --git a/lib/src/components/NxAlert/stateful/__tests__/NxStatefulAlert.test.tsx b/lib/src/components/NxAlert/stateful/__tests__/NxStatefulAlert.test.tsx index abaf30ec50..e65bcd414c 100644 --- a/lib/src/components/NxAlert/stateful/__tests__/NxStatefulAlert.test.tsx +++ b/lib/src/components/NxAlert/stateful/__tests__/NxStatefulAlert.test.tsx @@ -7,6 +7,7 @@ import { faCheckCircle } from '@fortawesome/free-solid-svg-icons'; import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxStatefulAlert, { NxStatefulInfoAlert, NxStatefulErrorAlert, diff --git a/lib/src/components/NxBackButton/__tests__/NxBackButton.test.tsx b/lib/src/components/NxBackButton/__tests__/NxBackButton.test.tsx index 3104158efc..769a989212 100644 --- a/lib/src/components/NxBackButton/__tests__/NxBackButton.test.tsx +++ b/lib/src/components/NxBackButton/__tests__/NxBackButton.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxBackButton, { Props } from '../NxBackButton'; describe('NxBackButton', function() { diff --git a/lib/src/components/NxBinaryDonutChart/__tests__/NxDonutChart.test.tsx b/lib/src/components/NxBinaryDonutChart/__tests__/NxDonutChart.test.tsx index 908bb72605..4e828e58ba 100644 --- a/lib/src/components/NxBinaryDonutChart/__tests__/NxDonutChart.test.tsx +++ b/lib/src/components/NxBinaryDonutChart/__tests__/NxDonutChart.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxBinaryDonutChart, {Props} from '../NxBinaryDonutChart'; describe('NxBinaryDonutChart', function() { diff --git a/lib/src/components/NxBreadcrumb/__tests__/NxBreadcrumb.test.tsx b/lib/src/components/NxBreadcrumb/__tests__/NxBreadcrumb.test.tsx index e2ce15d52a..1f63a55942 100644 --- a/lib/src/components/NxBreadcrumb/__tests__/NxBreadcrumb.test.tsx +++ b/lib/src/components/NxBreadcrumb/__tests__/NxBreadcrumb.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { render, waitFor, within } from '@testing-library/react'; -import userEvents from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; import NxBreadcrumb, { Props } from '../NxBreadcrumb'; @@ -20,18 +20,6 @@ describe('NxBreadcrumb', function() { quickRender = rtlRender(NxBreadcrumb, minimalProps), renderEl = rtlRenderElement(NxBreadcrumb, minimalProps); - beforeEach(function() { - // JSDOM is missing this function. https://github.com/jsdom/jsdom/issues/3002 - Range.prototype.getBoundingClientRect = jest.fn().mockReturnValue({ - bottom: 0, - height: 0, - left: 0, - right: 0, - top: 0, - width: 0 - } as DOMRect); - }); - it('renders an element with a navigation role and an accessible name of "breadcrumbs"', function() { const view = quickRender(), nav = view.getByRole('navigation'); @@ -246,7 +234,7 @@ describe('NxBreadcrumb', function() { }); it('calls onToggleDropdown when the dropdown button is clicked', async function() { - const user = userEvents.setup(), + const user = userEvent.setup(), onToggleDropdown = jest.fn(), view = quickRender({ crumbs: [ diff --git a/lib/src/components/NxBreadcrumb/stateful/__tests__/NxStatefulBreadcrumb.test.tsx b/lib/src/components/NxBreadcrumb/stateful/__tests__/NxStatefulBreadcrumb.test.tsx index 542080f945..49e518f7d9 100644 --- a/lib/src/components/NxBreadcrumb/stateful/__tests__/NxStatefulBreadcrumb.test.tsx +++ b/lib/src/components/NxBreadcrumb/stateful/__tests__/NxStatefulBreadcrumb.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { act, render, waitFor, within } from '@testing-library/react'; -import userEvents from '@testing-library/user-event'; +import { userEvent } from '../../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../../__testutils__/rtlUtils'; import NxStatefulBreadcrumb, { Props } from '../NxStatefulBreadcrumb'; @@ -18,18 +18,6 @@ describe('NxStatefulBreadcrumb', function() { quickRender = rtlRender(NxStatefulBreadcrumb, minimalProps), renderEl = rtlRenderElement(NxStatefulBreadcrumb, minimalProps); - beforeEach(function() { - // JSDOM is missing this function. https://github.com/jsdom/jsdom/issues/3002 - Range.prototype.getBoundingClientRect = jest.fn().mockReturnValue({ - bottom: 0, - height: 0, - left: 0, - right: 0, - top: 0, - width: 0 - } as DOMRect); - }); - it('renders an element with a navigation role and an accessible name of "breadcrumbs"', function() { const view = quickRender(), nav = view.getByRole('navigation'); @@ -145,7 +133,7 @@ describe('NxStatefulBreadcrumb', function() { describe('five or more crumbs', function() { it('initially renders the dropdown closed, and toggles it when its button is clicked', async function() { - const user = userEvents.setup(), + const user = userEvent.setup(), view = quickRender({ crumbs: [ { name: 'A', href: 'a' }, @@ -173,7 +161,7 @@ describe('NxStatefulBreadcrumb', function() { it('renders the first and last two crumbs in the list and the rest in a dropdown placed after the first crumb', async function() { - const user = userEvents.setup(), + const user = userEvent.setup(), view = quickRender({ crumbs: [ { name: 'A', href: 'a' }, diff --git a/lib/src/components/NxCheckbox/__tests__/NxCheckbox.test.tsx b/lib/src/components/NxCheckbox/__tests__/NxCheckbox.test.tsx index c136729809..be7d3e7af2 100644 --- a/lib/src/components/NxCheckbox/__tests__/NxCheckbox.test.tsx +++ b/lib/src/components/NxCheckbox/__tests__/NxCheckbox.test.tsx @@ -7,7 +7,7 @@ import React, { RefAttributes } from 'react'; import { within } from '@testing-library/react'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import NxCheckbox, { Props } from '../NxCheckbox'; diff --git a/lib/src/components/NxCheckbox/stateful/__tests__/NxStatefulCheckbox.test.tsx b/lib/src/components/NxCheckbox/stateful/__tests__/NxStatefulCheckbox.test.tsx index 973fd6f840..8e9a7a5bfd 100644 --- a/lib/src/components/NxCheckbox/stateful/__tests__/NxStatefulCheckbox.test.tsx +++ b/lib/src/components/NxCheckbox/stateful/__tests__/NxStatefulCheckbox.test.tsx @@ -7,7 +7,7 @@ import React, { RefAttributes } from 'react'; import { within } from '@testing-library/react'; import { rtlRender, rtlRenderElement } from '../../../../__testutils__/rtlUtils'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../../__testutils__/rtlUtils'; import NxStatefulCheckbox, { Props } from '../NxStatefulCheckbox'; diff --git a/lib/src/components/NxCloseButton/__tests__/NxCloseButton.test.tsx b/lib/src/components/NxCloseButton/__tests__/NxCloseButton.test.tsx index d4e9eedf31..3bff2d5332 100644 --- a/lib/src/components/NxCloseButton/__tests__/NxCloseButton.test.tsx +++ b/lib/src/components/NxCloseButton/__tests__/NxCloseButton.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; import NxCloseButton from '../NxCloseButton'; diff --git a/lib/src/components/NxCollapsibleItems/__tests__/NxCollapsibleItems.test.tsx b/lib/src/components/NxCollapsibleItems/__tests__/NxCollapsibleItems.test.tsx index e9773f40f3..9f7851f68e 100644 --- a/lib/src/components/NxCollapsibleItems/__tests__/NxCollapsibleItems.test.tsx +++ b/lib/src/components/NxCollapsibleItems/__tests__/NxCollapsibleItems.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxCollapsibleItems, { Props } from '../NxCollapsibleItems'; import { NxTreeView, NxTreeViewChild } from '../../../index'; diff --git a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/__tests__/NxCollapsibleMultiSelect.test.tsx b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/__tests__/NxCollapsibleMultiSelect.test.tsx index 7e448cd07d..4af6a9ee0c 100644 --- a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/__tests__/NxCollapsibleMultiSelect.test.tsx +++ b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/__tests__/NxCollapsibleMultiSelect.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import {getShallowComponent} from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxCollapsibleMultiSelect, {Props, Option} from '../NxCollapsibleMultiSelect'; import { NxTreeViewMultiSelect } from '../../../../index'; diff --git a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/stateful/__tests__/NxStatefulCollapsibleMultiSelect.test.tsx b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/stateful/__tests__/NxStatefulCollapsibleMultiSelect.test.tsx index c3ca0a1c7e..5656b9c790 100644 --- a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/stateful/__tests__/NxStatefulCollapsibleMultiSelect.test.tsx +++ b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleMultiSelect/stateful/__tests__/NxStatefulCollapsibleMultiSelect.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import {getShallowComponent} from '../../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxStatefulCollapsibleMultiSelect, {Props, Option} from '../NxStatefulCollapsibleMultiSelect'; import { NxStatefulTreeViewMultiSelect } from '../../../../../index'; diff --git a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/__tests__/NxCollapsibleRadioSelect.test.tsx b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/__tests__/NxCollapsibleRadioSelect.test.tsx index 941c3e76ea..6ea019e597 100644 --- a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/__tests__/NxCollapsibleRadioSelect.test.tsx +++ b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/__tests__/NxCollapsibleRadioSelect.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import {getShallowComponent} from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxCollapsibleRadioSelect, {Option, Props} from '../NxCollapsibleRadioSelect'; import Counter from '../../../Counter/Counter'; diff --git a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/stateful/__tests__/NxStatefulCollapsibleRadioSelect.test.tsx b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/stateful/__tests__/NxStatefulCollapsibleRadioSelect.test.tsx index 55d7f4210b..83c6e5477d 100644 --- a/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/stateful/__tests__/NxStatefulCollapsibleRadioSelect.test.tsx +++ b/lib/src/components/NxCollapsibleItemsSelect/NxCollapsibleRadioSelect/stateful/__tests__/NxStatefulCollapsibleRadioSelect.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import {getShallowComponent} from '../../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxStatefulCollapsibleRadioSelect, {Props, Option} from '../NxStatefulCollapsibleRadioSelect'; import { NxStatefulTreeViewRadioSelect } from '../../../../../index'; diff --git a/lib/src/components/NxCollapsibleItemsSelect/__tests__/AbstractCollapsibleItemsSelect.test.tsx b/lib/src/components/NxCollapsibleItemsSelect/__tests__/AbstractCollapsibleItemsSelect.test.tsx index dd6b719111..66a9a5b50f 100644 --- a/lib/src/components/NxCollapsibleItemsSelect/__tests__/AbstractCollapsibleItemsSelect.test.tsx +++ b/lib/src/components/NxCollapsibleItemsSelect/__tests__/AbstractCollapsibleItemsSelect.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import {times} from 'ramda'; import {getShallowComponent} from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import AbstractCollapsibleItemsSelect, {Props} from '../AbstractCollapsibleItemsSelect'; import {Option} from '../commonTypes'; import NxCollapsibleItems, { PrivateNxCollapsibleItems } from '../../NxCollapsibleItems/NxCollapsibleItems'; diff --git a/lib/src/components/NxColorPicker/__tests__/NxColorPicker.test.tsx b/lib/src/components/NxColorPicker/__tests__/NxColorPicker.test.tsx index 64d460a260..3316565568 100644 --- a/lib/src/components/NxColorPicker/__tests__/NxColorPicker.test.tsx +++ b/lib/src/components/NxColorPicker/__tests__/NxColorPicker.test.tsx @@ -5,7 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import React from 'react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { render, within } from '@testing-library/react'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxCombobox/NxCombobox.tsx b/lib/src/components/NxCombobox/NxCombobox.tsx index d261c00233..017ea855cf 100644 --- a/lib/src/components/NxCombobox/NxCombobox.tsx +++ b/lib/src/components/NxCombobox/NxCombobox.tsx @@ -346,7 +346,8 @@ function NxComboboxRender { await jest.runAllTimers(); }); - } - - async function advanceTimers(time: number) { - await act(async () => { await jest.advanceTimersByTime(time); }); - } - describe('when false, null, or undefined', function() { it('does not render a clear button', async function() { const unsetNoValue = quickRender(), @@ -1224,7 +1207,7 @@ describe('NxCombobox', function() { // tested here it('renders a clear button with "Clear filter" as the tooltip and a11y name', async function() { - const user = userEvent.setup({ advanceTimers }), + const user = userEvent.setup(), view = quickRender({ value: 'a' }); await runTimers(); @@ -1240,7 +1223,7 @@ describe('NxCombobox', function() { }); it('still clears the input and triggers a search on the empty string when Escape key is pressed', async () => { - const user = userEvent.setup({ advanceTimers }), + const user = userEvent.setup(), onChange = jest.fn(), onSearch = jest.fn(), { getByRole } = quickRender({ @@ -1263,7 +1246,7 @@ describe('NxCombobox', function() { }); it('clears the input when the clear button is clicked', async function() { - const user = userEvent.setup({ advanceTimers }), + const user = userEvent.setup(), onChange = jest.fn(), onSearch = jest.fn(), view = quickRender({ @@ -1312,7 +1295,7 @@ describe('NxCombobox', function() { const quickRender = rtlRender(NxCombobox, { ...minimalProps, filterInput: 'search' }); it('renders a clear button with "Clear search" as the tooltip and a11y name', async function() { - const user = userEvent.setup({ advanceTimers }), + const user = userEvent.setup(), view = quickRender({ value: 'a' }); await runTimers(); @@ -1328,7 +1311,7 @@ describe('NxCombobox', function() { }); it('still clears the input and triggers a search on the empty string when Escape key is pressed', async () => { - const user = userEvent.setup({ advanceTimers }), + const user = userEvent.setup(), onChange = jest.fn(), onSearch = jest.fn(), { getByRole } = quickRender({ @@ -1351,7 +1334,7 @@ describe('NxCombobox', function() { }); it('clears the input when the clear button is clicked', async function() { - const user = userEvent.setup({ advanceTimers }), + const user = userEvent.setup(), onChange = jest.fn(), onSearch = jest.fn(), view = quickRender({ diff --git a/lib/src/components/NxCopyToClipboard/__tests__/NxCopyToClipboard.test.tsx b/lib/src/components/NxCopyToClipboard/__tests__/NxCopyToClipboard.test.tsx index 4dd423fb1e..2d08e2bda6 100644 --- a/lib/src/components/NxCopyToClipboard/__tests__/NxCopyToClipboard.test.tsx +++ b/lib/src/components/NxCopyToClipboard/__tests__/NxCopyToClipboard.test.tsx @@ -6,11 +6,13 @@ */ import { getShallowComponent, getMountedComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { default as NxCopyToClipboard, Props } from '../NxCopyToClipboard'; import NxButton from '../../NxButton/NxButton'; import NxFormGroup from '../../NxFormGroup/NxFormGroup'; import NxTextInput from '../../NxTextInput/NxTextInput'; import { NxCodeSnippet } from '../../../index'; +import { runTimers } from '../../../__testutils__/rtlUtils'; describe('NxCopyToClipboard', function() { const minimalProps: Props = { @@ -129,7 +131,7 @@ describe('NxCopyToClipboard', function() { expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith('Lorem Ipsum'); }); - it('calls onCopyUsingBtn after writing the text to the clipboard', function(done) { + it('calls onCopyUsingBtn after writing the text to the clipboard', async function() { const onCopyUsingBtn = jest.fn(), component = getMounted({ onCopyUsingBtn }, { attachTo: container }); @@ -141,31 +143,29 @@ describe('NxCopyToClipboard', function() { // the promise then() is called asynchronously so we must do our expectation of its result asynchronously // as well - setTimeout(function() { - expect(onCopyUsingBtn).toHaveBeenCalled(); - done(); - }, 0); + await runTimers(); + expect(onCopyUsingBtn).toHaveBeenCalled(); }); - it('sets the text selection to the textarea\'s contents after writing the text to the clipboard', function(done) { - const component = getMounted({}, { attachTo: container }), - textarea = component.find('textarea').getDOMNode() as HTMLTextAreaElement; + it('sets the text selection to the textarea\'s contents after writing the text to the clipboard', + async function() { + const component = getMounted({}, { attachTo: container }), + textarea = component.find('textarea').getDOMNode() as HTMLTextAreaElement; - expect(getElementSelection(textarea)).toBe(''); + expect(getElementSelection(textarea)).toBe(''); - component.find(NxButton).simulate('click'); + component.find(NxButton).simulate('click'); - expect(getElementSelection(textarea)).toBe(''); + expect(getElementSelection(textarea)).toBe(''); - resolveClipboardPromise!(); + resolveClipboardPromise!(); - setTimeout(function() { - expect(getElementSelection(textarea)).toBe('Lorem Ipsum'); - done(); - }, 0); - }); + await runTimers(); + expect(getElementSelection(textarea)).toBe('Lorem Ipsum'); + } + ); - it('does not call onCopyUsingBtn or set the text selection if the copy fails', function(done) { + it('does not call onCopyUsingBtn or set the text selection if the copy fails', async function() { const onCopyUsingBtn = jest.fn(), component = getMounted({ onCopyUsingBtn }, { attachTo: container }), textarea = component.find('textarea').getDOMNode() as HTMLTextAreaElement; @@ -174,12 +174,9 @@ describe('NxCopyToClipboard', function() { rejectClipboardPromise!('This is expected to be logged'); - setTimeout(function() { - expect(getElementSelection(textarea)).toBe(''); - - expect(onCopyUsingBtn).not.toHaveBeenCalled(); - done(); - }, 0); + await runTimers(); + expect(getElementSelection(textarea)).toBe(''); + expect(onCopyUsingBtn).not.toHaveBeenCalled(); }); }); diff --git a/lib/src/components/NxDateInput/__tests__/NxDateInput.test.tsx b/lib/src/components/NxDateInput/__tests__/NxDateInput.test.tsx index 17d55548cb..3a0b30ffc0 100644 --- a/lib/src/components/NxDateInput/__tests__/NxDateInput.test.tsx +++ b/lib/src/components/NxDateInput/__tests__/NxDateInput.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; diff --git a/lib/src/components/NxDateInput/stateful/__tests__/NxStatefulDateInput.test.tsx b/lib/src/components/NxDateInput/stateful/__tests__/NxStatefulDateInput.test.tsx index ff6ff7a9bb..960bbf7a9a 100644 --- a/lib/src/components/NxDateInput/stateful/__tests__/NxStatefulDateInput.test.tsx +++ b/lib/src/components/NxDateInput/stateful/__tests__/NxStatefulDateInput.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; import { PrivateNxStatefulTextInput } from '../../../NxTextInput/stateful/NxStatefulTextInput'; diff --git a/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListButtonItem.test.tsx b/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListButtonItem.test.tsx index d94f805210..922ca9ec4c 100644 --- a/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListButtonItem.test.tsx +++ b/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListButtonItem.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { zip } from 'ramda'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { render, within } from '@testing-library/react'; import { rtlRenderElement, rtlRender } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListLinkItem.test.tsx b/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListLinkItem.test.tsx index 526381985a..13cc0a4f5f 100644 --- a/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListLinkItem.test.tsx +++ b/lib/src/components/NxDescriptionList/__tests__/NxDescriptionListLinkItem.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { zip } from 'ramda'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { fireEvent, render, within } from '@testing-library/react'; import { rtlRenderElement, rtlRender } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxDrawer/__tests__/NxDrawer.test.tsx b/lib/src/components/NxDrawer/__tests__/NxDrawer.test.tsx index 810668e188..5a78ae70f9 100644 --- a/lib/src/components/NxDrawer/__tests__/NxDrawer.test.tsx +++ b/lib/src/components/NxDrawer/__tests__/NxDrawer.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { render, fireEvent, within, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxDropdown/AbstractDropdown.tsx b/lib/src/components/NxDropdown/AbstractDropdown.tsx index 6a4feb1f83..f75288c024 100644 --- a/lib/src/components/NxDropdown/AbstractDropdown.tsx +++ b/lib/src/components/NxDropdown/AbstractDropdown.tsx @@ -146,7 +146,8 @@ const AbstractDropdown = forwardRef((prop toggleElementRef={toggleRef} isOpen={isOpen} onToggleCollapse={onToggleCollapseProp ?? undefined} - id={menuId ?? undefined}> + id={menuId ?? undefined} + useActiveDescendant={true}> { children } diff --git a/lib/src/components/NxDropdown/__tests__/NxDropdown.test.tsx b/lib/src/components/NxDropdown/__tests__/NxDropdown.test.tsx index f0aa64cbe5..21f55208a6 100644 --- a/lib/src/components/NxDropdown/__tests__/NxDropdown.test.tsx +++ b/lib/src/components/NxDropdown/__tests__/NxDropdown.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { faCaretDown, faTrash } from '@fortawesome/free-solid-svg-icons'; import NxDropdown, { Props } from '../NxDropdown'; diff --git a/lib/src/components/NxDropdown/stateful/__tests__/NxStatefulDropdown.test.tsx b/lib/src/components/NxDropdown/stateful/__tests__/NxStatefulDropdown.test.tsx index 4064f00304..13602a7566 100644 --- a/lib/src/components/NxDropdown/stateful/__tests__/NxStatefulDropdown.test.tsx +++ b/lib/src/components/NxDropdown/stateful/__tests__/NxStatefulDropdown.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { mount, ReactWrapper } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; import NxButton from '../../../NxButton/NxButton'; diff --git a/lib/src/components/NxDropdownMenu/NxDropdownMenu.backup.md b/lib/src/components/NxDropdownMenu/NxDropdownMenu.backup.md new file mode 100644 index 0000000000..2daeab4ec4 --- /dev/null +++ b/lib/src/components/NxDropdownMenu/NxDropdownMenu.backup.md @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2019-present Sonatype, Inc. + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. + */ +import React, { + useLayoutEffect, + forwardRef, + useState, + useEffect, + useRef, + KeyboardEventHandler +} from 'react'; +import classnames from 'classnames'; +import useMergedRef from '@react-hook/merged-ref'; +import { always, dec, inc, move, reduce } from 'ramda'; + +import { Props, propTypes } from './types'; + +import './NxDropdownMenu.scss'; + +export { Props }; + +const FOCUSABLE_ELEMENTS = ['a', 'button', 'input']; +const FOCUSABLE_MENU_ITEMS_SELECTOR = FOCUSABLE_ELEMENTS.join(', '); +const ACTIVE_FOCUSABLE_MENU_ITEMS_SELECTOR = FOCUSABLE_ELEMENTS.join(':not([disabled], .disabled), '); + +/** + * This component is not currently intended for public export. It is a helper for NxDropdown and NxSegmentedButton + * so they can reset focus when they close + */ +/* eslint-disable-next-line react/prop-types */ +const NxDropdownMenu = forwardRef(function NxDropdownMenu(props, ref) { + const { + className: classNameProp, + children, + disableMenuKeyNav, + toggleElementRef, + isOpen, + onToggleCollapse, + onClosing, + onKeyDown: onKeyDownProp, + onMenuItemFocus, + useActiveDescendant, + ...attrs + } = props; + + const menuRef = useRef(null); + const mergedRef = useMergedRef(menuRef, ref); + + const [focusedMenuItemIndex, setFocusedMenuItemIndex] = useState(0); + + // Move this to NxDropdown... + const getFocusableMenuItems = (selector: string) => { + if (menuRef.current) { + const focusableElements = Array.from(menuRef.current.querySelectorAll(selector)); + const isRightButton = (element: Element) => element.classList.contains('nx-dropdown-right-button'); + const indicesToSwap = focusableElements.reduce((acc, element, i) => + isRightButton(element) ? [...acc, i] : acc, []); + return reduce((els, i) => move(i, i + 1, els), focusableElements, indicesToSwap); + } + return []; + }; + + const setMenuItemFocus = (adjust: (i: number) => number) => () => { + if (menuRef.current) { + const focusableElements = getFocusableMenuItems(ACTIVE_FOCUSABLE_MENU_ITEMS_SELECTOR); + const adjustedMenuItemIndex = adjust(focusedMenuItemIndex ?? 0); + + let newMenuItemIndex = adjustedMenuItemIndex; + + if (adjustedMenuItemIndex < 0) { + newMenuItemIndex = focusableElements.length - 1; + } + else if (adjustedMenuItemIndex >= focusableElements.length) { + newMenuItemIndex = 0; + } + + const elementToFocus = focusableElements[newMenuItemIndex]; + if (elementToFocus) { + if (onMenuItemFocus) { + onMenuItemFocus(newMenuItemIndex, focusableElements); + } + + if (useActiveDescendant) { + focusableElements.forEach(el => el.classList.remove('selected')); + elementToFocus.classList.add('selected'); + } + else { + elementToFocus.focus(); + } + + setFocusedMenuItemIndex(newMenuItemIndex); + elementToFocus.scrollIntoView({ block: 'nearest' }); + } + } + }; + const focusNext = setMenuItemFocus(inc); + const focusPrev = setMenuItemFocus(dec); + const focusFirst = setMenuItemFocus(always(0)); + const focusLast = setMenuItemFocus(always(-1)); + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + const toggleOpen = () => { + if (!isOpen && onToggleCollapse) { + onToggleCollapse(); + } + }; + + switch (event.key) { + case 'ArrowUp': + event.preventDefault(); + toggleOpen(); + focusLast(); + break; + case 'ArrowDown': + event.preventDefault(); + toggleOpen(); + focusFirst(); + console.log('help'); + break; + } + }; + + if (!disableMenuKeyNav && toggleElementRef && toggleElementRef.current) { + toggleElementRef.current.removeEventListener('keydown', handleKeyDown); + toggleElementRef.current.addEventListener('keydown', handleKeyDown); + } + + return () => { + if (!disableMenuKeyNav && toggleElementRef && toggleElementRef.current) { + toggleElementRef.current.removeEventListener('keydown', handleKeyDown); + } + }; + }, [toggleElementRef, disableMenuKeyNav]); + + useEffect(() => { + // Trigger onToggleCollapse when focus goes outside the menu and toggle element. + const handleFocusIn = () => { + const currentlyFocusedElement = document.activeElement as HTMLElement; + if ( + toggleElementRef + && menuRef + && menuRef.current + && toggleElementRef.current !== currentlyFocusedElement + && !menuRef.current.contains(document.activeElement) + && isOpen + && onToggleCollapse + ) { + onToggleCollapse(); + } + }; + + document.addEventListener('focusin', handleFocusIn); + return () => document.removeEventListener('focusin', handleFocusIn); + }, [toggleElementRef, menuRef, isOpen, onToggleCollapse]); + + // onClosing must execute when this element is being removed but BEFORE it actually gets removed from the DOM + useLayoutEffect(() => onClosing, []); + + useEffect(() => { + if (menuRef.current) { + const focusableElements = getFocusableMenuItems(FOCUSABLE_MENU_ITEMS_SELECTOR); + focusableElements.forEach(menuItem => menuItem.tabIndex = -1); + } + }, [menuRef, children]); + + function activateMenuItem(event: React.KeyboardEvent) { + if (menuRef.current) { + const focusableEls = menuRef.current.querySelectorAll(ACTIVE_FOCUSABLE_MENU_ITEMS_SELECTOR); + const currentFocusedEl = focusableEls[focusedMenuItemIndex]; + if (currentFocusedEl.matches('a, button')) { + event.preventDefault(); + currentFocusedEl.click(); + } + } + } + + const handleMenuKeyDown: KeyboardEventHandler = (event) => { + if (!disableMenuKeyNav) { + switch (event.key) { + case 'Home': + focusFirst(); + event.preventDefault(); + break; + case 'End': + focusLast(); + event.preventDefault(); + break; + case 'ArrowUp': + focusPrev(); + event.preventDefault(); + break; + case 'ArrowDown': + focusNext(); + event.preventDefault(); + break; + case ' ': case 'Enter': + activateMenuItem(event); + break; + case 'Escape': + event.preventDefault(); + if (onToggleCollapse) { + onToggleCollapse(); + } + if (toggleElementRef && toggleElementRef.current) { + toggleElementRef.current.focus(); + } + break; + } + } + + if (onKeyDownProp) { + onKeyDownProp(event); + } + }; + + const className = classnames('nx-dropdown-menu', classNameProp); + + return isOpen ? ( + // eslint-disable-next-line jsx-a11y/interactive-supports-focus +
+ { children } +
+ ) : null; +}); + +NxDropdownMenu.propTypes = propTypes; + +export default NxDropdownMenu; diff --git a/lib/src/components/NxDropdownMenu/NxDropdownMenu.scss b/lib/src/components/NxDropdownMenu/NxDropdownMenu.scss index 609f173687..eeabd8d4d7 100644 --- a/lib/src/components/NxDropdownMenu/NxDropdownMenu.scss +++ b/lib/src/components/NxDropdownMenu/NxDropdownMenu.scss @@ -47,7 +47,7 @@ text-decoration: none; width: 100%; - &:focus { + &:focus, &.selected { background-color: transparent; border-radius: 0; box-shadow: var(--nx-box-shadow-focus); diff --git a/lib/src/components/NxDropdownMenu/NxDropdownMenu.tsx b/lib/src/components/NxDropdownMenu/NxDropdownMenu.tsx index 239a6efb0f..7c41890103 100644 --- a/lib/src/components/NxDropdownMenu/NxDropdownMenu.tsx +++ b/lib/src/components/NxDropdownMenu/NxDropdownMenu.tsx @@ -42,6 +42,7 @@ const NxDropdownMenu = forwardRef(function NxDropdownMenu onClosing, onKeyDown: onKeyDownProp, onMenuItemFocus, + useActiveDescendant, ...attrs } = props; @@ -77,11 +78,26 @@ const NxDropdownMenu = forwardRef(function NxDropdownMenu } const elementToFocus = focusableElements[newMenuItemIndex]; + if (elementToFocus) { if (onMenuItemFocus) { onMenuItemFocus(newMenuItemIndex, focusableElements); } - elementToFocus.focus(); + + console.log(useActiveDescendant); + if (useActiveDescendant) { + focusableElements.forEach(el => el.classList.remove('selected')); + focusableElements.forEach(el => { + el.getAttribute('id'); + el.removeAttribute('id'); + }); + elementToFocus.classList.add('selected'); + elementToFocus.setAttribute('id', 'dropdownmenu-selected'); + } + else { + elementToFocus.focus(); + } + setFocusedMenuItemIndex(newMenuItemIndex); elementToFocus.scrollIntoView({ block: 'nearest' }); } @@ -116,15 +132,23 @@ const NxDropdownMenu = forwardRef(function NxDropdownMenu if (!disableMenuKeyNav && toggleElementRef && toggleElementRef.current) { toggleElementRef.current.removeEventListener('keydown', handleKeyDown); - toggleElementRef.current.addEventListener('keydown', handleKeyDown); + toggleElementRef.current.removeEventListener('keydown', handleToggleKeyDown); + + if (useActiveDescendant && isOpen) { + toggleElementRef.current.addEventListener('keydown', handleToggleKeyDown); + } + else { + toggleElementRef.current.addEventListener('keydown', handleKeyDown); + } } return () => { - if (!disableMenuKeyNav && toggleElementRef && toggleElementRef.current) { + if (toggleElementRef && toggleElementRef.current) { toggleElementRef.current.removeEventListener('keydown', handleKeyDown); + toggleElementRef.current.removeEventListener('keydown', handleToggleKeyDown); } }; - }, [toggleElementRef, disableMenuKeyNav]); + }, [isOpen, toggleElementRef, disableMenuKeyNav, useActiveDescendant, focusedMenuItemIndex]); useEffect(() => { // Trigger onToggleCollapse when focus goes outside the menu and toggle element. @@ -157,7 +181,7 @@ const NxDropdownMenu = forwardRef(function NxDropdownMenu } }, [menuRef, children]); - function activateMenuItem(event: React.KeyboardEvent) { + function activateMenuItem(event: React.KeyboardEvent | KeyboardEvent) { if (menuRef.current) { const focusableEls = menuRef.current.querySelectorAll(ACTIVE_FOCUSABLE_MENU_ITEMS_SELECTOR); const currentFocusedEl = focusableEls[focusedMenuItemIndex]; @@ -168,8 +192,43 @@ const NxDropdownMenu = forwardRef(function NxDropdownMenu } } - const handleMenuKeyDown: KeyboardEventHandler = (event) => { + function handleToggleKeyDown(event: KeyboardEvent) { if (!disableMenuKeyNav) { + switch (event.key) { + case 'Home': + focusFirst(); + event.preventDefault(); + break; + case 'End': + focusLast(); + event.preventDefault(); + break; + case 'ArrowUp': + focusPrev(); + event.preventDefault(); + break; + case 'ArrowDown': + focusNext(); + event.preventDefault(); + break; + case ' ': case 'Enter': + activateMenuItem(event); + break; + case 'Escape': + event.preventDefault(); + if (onToggleCollapse) { + onToggleCollapse(); + } + // if (toggleElementRef && toggleElementRef.current) { + // toggleElementRef.current.focus(); + // } + break; + } + } + } + + const handleMenuKeyDown: KeyboardEventHandler = (event) => { + if (!disableMenuKeyNav && !useActiveDescendant) { switch (event.key) { case 'Home': focusFirst(); diff --git a/lib/src/components/NxDropdownMenu/types.tsx b/lib/src/components/NxDropdownMenu/types.tsx index d050b74888..a4ee3734e5 100644 --- a/lib/src/components/NxDropdownMenu/types.tsx +++ b/lib/src/components/NxDropdownMenu/types.tsx @@ -14,10 +14,12 @@ export interface Props extends HTMLAttributes { onMenuItemFocus?: (index: number, focusableElements: HTMLElement[]) => void | null; isOpen?: boolean; onToggleCollapse?: () => void | null; + useActiveDescendant?: boolean | null; } export const propTypes: PropTypes.ValidationMap = { onClosing: PropTypes.func.isRequired, children: PropTypes.node, - disableMenuKeyNav: PropTypes.bool + disableMenuKeyNav: PropTypes.bool, + useActiveDescendant: PropTypes.bool }; diff --git a/lib/src/components/NxFieldset/__tests__/stateHelpers.test.tsx b/lib/src/components/NxFieldset/__tests__/stateHelpers.test.tsx index ea792addf3..ca83e127d7 100644 --- a/lib/src/components/NxFieldset/__tests__/stateHelpers.test.tsx +++ b/lib/src/components/NxFieldset/__tests__/stateHelpers.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxFilterDropdown/__tests__/NxFilterDropdown.test.tsx b/lib/src/components/NxFilterDropdown/__tests__/NxFilterDropdown.test.tsx index 77513a37e0..bd34a14346 100644 --- a/lib/src/components/NxFilterDropdown/__tests__/NxFilterDropdown.test.tsx +++ b/lib/src/components/NxFilterDropdown/__tests__/NxFilterDropdown.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import { faFilter } from '@fortawesome/free-solid-svg-icons'; import NxFilterDropdown, { Props } from '../NxFilterDropdown'; diff --git a/lib/src/components/NxFilterDropdown/stateful/__tests__/NxStatefulFilterDropdown.test.tsx b/lib/src/components/NxFilterDropdown/stateful/__tests__/NxStatefulFilterDropdown.test.tsx index 1c8336eae7..9c60e156a6 100644 --- a/lib/src/components/NxFilterDropdown/stateful/__tests__/NxStatefulFilterDropdown.test.tsx +++ b/lib/src/components/NxFilterDropdown/stateful/__tests__/NxStatefulFilterDropdown.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import { getShallowComponent } from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxFilterDropdown from '../../NxFilterDropdown'; import NxStatefulFilterDropdown, { Props } from '../NxStatefulFilterDropdown'; diff --git a/lib/src/components/NxFilterInput/__tests__/NxFilterInput.test.tsx b/lib/src/components/NxFilterInput/__tests__/NxFilterInput.test.tsx index 6e830f06ea..8096ad3bff 100644 --- a/lib/src/components/NxFilterInput/__tests__/NxFilterInput.test.tsx +++ b/lib/src/components/NxFilterInput/__tests__/NxFilterInput.test.tsx @@ -7,7 +7,7 @@ import React, { RefAttributes } from 'react'; import { createEvent, fireEvent, waitFor } from '@testing-library/react'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import NxFilterInput, { Props } from '../NxFilterInput'; diff --git a/lib/src/components/NxFontAwesomeIcon/__tests__/NxFontAwesomeIcon.test.tsx b/lib/src/components/NxFontAwesomeIcon/__tests__/NxFontAwesomeIcon.test.tsx index 86baf8dc3f..8cb82b023d 100644 --- a/lib/src/components/NxFontAwesomeIcon/__tests__/NxFontAwesomeIcon.test.tsx +++ b/lib/src/components/NxFontAwesomeIcon/__tests__/NxFontAwesomeIcon.test.tsx @@ -8,6 +8,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCheck } from '@fortawesome/free-solid-svg-icons'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxFontAwesomeIcon from '../NxFontAwesomeIcon'; diff --git a/lib/src/components/NxForm/__tests__/NxForm.test.tsx b/lib/src/components/NxForm/__tests__/NxForm.test.tsx index dd83c45ae7..8086f1b0ba 100644 --- a/lib/src/components/NxForm/__tests__/NxForm.test.tsx +++ b/lib/src/components/NxForm/__tests__/NxForm.test.tsx @@ -6,7 +6,7 @@ */ import React, { useContext } from 'react'; import { within, fireEvent } from '@testing-library/dom'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; import NxForm from '../NxForm'; diff --git a/lib/src/components/NxForm/stateful/__tests__/NxStatefulForm.test.tsx b/lib/src/components/NxForm/stateful/__tests__/NxStatefulForm.test.tsx index 45ca187db9..8ddfe10e78 100644 --- a/lib/src/components/NxForm/stateful/__tests__/NxStatefulForm.test.tsx +++ b/lib/src/components/NxForm/stateful/__tests__/NxStatefulForm.test.tsx @@ -6,7 +6,7 @@ */ import React, { useContext } from 'react'; import { within, fireEvent, screen } from '@testing-library/dom'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../../__testutils__/rtlUtils'; import NxStatefulForm from '../NxStatefulForm'; diff --git a/lib/src/components/NxFormGroup/__tests__/NxFormGroup.test.tsx b/lib/src/components/NxFormGroup/__tests__/NxFormGroup.test.tsx index 9b680accb8..3a25f273a5 100644 --- a/lib/src/components/NxFormGroup/__tests__/NxFormGroup.test.tsx +++ b/lib/src/components/NxFormGroup/__tests__/NxFormGroup.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxFormGroup, { Props } from '../NxFormGroup'; import NxStatefulTextInput from '../../NxTextInput/stateful/NxStatefulTextInput'; diff --git a/lib/src/components/NxFormSelect/__tests__/NxFormSelect.test.tsx b/lib/src/components/NxFormSelect/__tests__/NxFormSelect.test.tsx index 6ac3ab4f6b..bef36d361c 100644 --- a/lib/src/components/NxFormSelect/__tests__/NxFormSelect.test.tsx +++ b/lib/src/components/NxFormSelect/__tests__/NxFormSelect.test.tsx @@ -5,7 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import React from 'react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxFormSelect/__tests__/stateHelpers.test.tsx b/lib/src/components/NxFormSelect/__tests__/stateHelpers.test.tsx index 9eba1d69ab..3c9a25491c 100644 --- a/lib/src/components/NxFormSelect/__tests__/stateHelpers.test.tsx +++ b/lib/src/components/NxFormSelect/__tests__/stateHelpers.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { render, within } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebar.test.tsx b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebar.test.tsx index 245a23daa9..1d5fe46fcd 100644 --- a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebar.test.tsx +++ b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebar.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { ShallowWrapper } from 'enzyme'; +import 'jest-enzyme'; import { faCrow, faBiohazard } from '@fortawesome/free-solid-svg-icons'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; diff --git a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarFooter.test.tsx b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarFooter.test.tsx index b83d65f0e1..6ef6297f8b 100644 --- a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarFooter.test.tsx +++ b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarFooter.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxGlobalSidebarFooter, { NxGlobalSidebarFooterProps as Props } from '../NxGlobalSidebarFooter'; diff --git a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigation.test.tsx b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigation.test.tsx index 7792d41a90..cfd29c0b08 100644 --- a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigation.test.tsx +++ b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigation.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxGlobalSidebarNavigation, { NxGlobalSidebarNavigationProps as Props } from '../NxGlobalSidebarNavigation'; describe('NxGlobalSidebarNavigation', function() { diff --git a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigationLink.test.tsx b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigationLink.test.tsx index 66b06d4a18..5faba97af3 100644 --- a/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigationLink.test.tsx +++ b/lib/src/components/NxGlobalSidebar/__tests__/NxGlobalSidebarNavigationLink.test.tsx @@ -8,6 +8,7 @@ import { faCrow, faBiohazard } from '@fortawesome/free-solid-svg-icons'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxFontAwesomeIcon from '../../NxFontAwesomeIcon/NxFontAwesomeIcon'; import NxOverflowTooltip from '../../NxTooltip/NxOverflowTooltip'; import NxGlobalSidebarNavigationLink, { NxGlobalSidebarNavigationLinkProps as Props } diff --git a/lib/src/components/NxGlobalSidebar/stateful/__tests__/NxStatefulGlobalSidebar.test.tsx b/lib/src/components/NxGlobalSidebar/stateful/__tests__/NxStatefulGlobalSidebar.test.tsx index 542aa7c673..d974f2ea48 100644 --- a/lib/src/components/NxGlobalSidebar/stateful/__tests__/NxStatefulGlobalSidebar.test.tsx +++ b/lib/src/components/NxGlobalSidebar/stateful/__tests__/NxStatefulGlobalSidebar.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { faCrow, faBiohazard } from '@fortawesome/free-solid-svg-icons'; import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxStatefulGlobalSidebar, { Props } from '../NxStatefulGlobalSidebar'; import NxGlobalSidebar from '../../NxGlobalSidebar'; diff --git a/lib/src/components/NxIconDropdown/__tests__/NxIconDropdown.test.tsx b/lib/src/components/NxIconDropdown/__tests__/NxIconDropdown.test.tsx index eb394f4bd0..f189da5d77 100644 --- a/lib/src/components/NxIconDropdown/__tests__/NxIconDropdown.test.tsx +++ b/lib/src/components/NxIconDropdown/__tests__/NxIconDropdown.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { faCog, faEllipsisV } from '@fortawesome/free-solid-svg-icons'; import NxIconDropdown, { Props } from '../NxIconDropdown'; diff --git a/lib/src/components/NxIconDropdown/stateful/__tests__/NxStatefulIconDropdown.test.tsx b/lib/src/components/NxIconDropdown/stateful/__tests__/NxStatefulIconDropdown.test.tsx index 52f5758a20..724b7c16e6 100644 --- a/lib/src/components/NxIconDropdown/stateful/__tests__/NxStatefulIconDropdown.test.tsx +++ b/lib/src/components/NxIconDropdown/stateful/__tests__/NxStatefulIconDropdown.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { mount, ReactWrapper } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; import NxButton from '../../../NxButton/NxButton'; diff --git a/lib/src/components/NxIndeterminatePagination/__tests__/NxIndeterminatePagination.test.tsx b/lib/src/components/NxIndeterminatePagination/__tests__/NxIndeterminatePagination.test.tsx index 89d38343b4..2d65323fac 100644 --- a/lib/src/components/NxIndeterminatePagination/__tests__/NxIndeterminatePagination.test.tsx +++ b/lib/src/components/NxIndeterminatePagination/__tests__/NxIndeterminatePagination.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons'; diff --git a/lib/src/components/NxList/__tests__/NxList.test.tsx b/lib/src/components/NxList/__tests__/NxList.test.tsx index 7c9668261c..0c7a2dd381 100644 --- a/lib/src/components/NxList/__tests__/NxList.test.tsx +++ b/lib/src/components/NxList/__tests__/NxList.test.tsx @@ -9,6 +9,7 @@ import { NxLoadError, NxLoadingSpinner } from '../../..'; import NxList from '../NxList'; import { NxListProps } from '../types'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { act } from 'react-dom/test-utils'; import { mount, ReactWrapper } from 'enzyme'; import NxListButtonItem from '../NxListButtonItem'; diff --git a/lib/src/components/NxList/__tests__/NxListActions.test.tsx b/lib/src/components/NxList/__tests__/NxListActions.test.tsx index 5909f2d52c..d85fbc1a88 100644 --- a/lib/src/components/NxList/__tests__/NxListActions.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListActions.test.tsx @@ -6,6 +6,7 @@ */ import NxList from '../NxList'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListActions', function() { diff --git a/lib/src/components/NxList/__tests__/NxListButtonItem.test.tsx b/lib/src/components/NxList/__tests__/NxListButtonItem.test.tsx index 5640f0e4c0..ff3a74a26c 100644 --- a/lib/src/components/NxList/__tests__/NxListButtonItem.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListButtonItem.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { NxListButtonItemProps } from '../types'; import NxList from '../NxList'; import { getMountedComponent, getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListButtonItem', function() { diff --git a/lib/src/components/NxList/__tests__/NxListDescription.test.tsx b/lib/src/components/NxList/__tests__/NxListDescription.test.tsx index 00d093903c..c89b578f49 100644 --- a/lib/src/components/NxList/__tests__/NxListDescription.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListDescription.test.tsx @@ -6,6 +6,7 @@ */ import NxList from '../NxList'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListDescription', function() { diff --git a/lib/src/components/NxList/__tests__/NxListDescriptionTerm.test.tsx b/lib/src/components/NxList/__tests__/NxListDescriptionTerm.test.tsx index 44815db1ac..562c0d46db 100644 --- a/lib/src/components/NxList/__tests__/NxListDescriptionTerm.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListDescriptionTerm.test.tsx @@ -6,6 +6,7 @@ */ import NxList from '../NxList'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListDescriptionTerm', function() { diff --git a/lib/src/components/NxList/__tests__/NxListItem.test.tsx b/lib/src/components/NxList/__tests__/NxListItem.test.tsx index 8567ce2aa0..0f2c20eb4c 100644 --- a/lib/src/components/NxList/__tests__/NxListItem.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListItem.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import NxList from '../NxList'; import { getMountedComponent, getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListItem', function() { diff --git a/lib/src/components/NxList/__tests__/NxListLinkItem.test.tsx b/lib/src/components/NxList/__tests__/NxListLinkItem.test.tsx index 10e3813f18..03f20c760b 100644 --- a/lib/src/components/NxList/__tests__/NxListLinkItem.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListLinkItem.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import NxList from '../NxList'; import { NxListLinkItemProps } from '../types'; import { getMountedComponent, getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListLinkItem', function() { diff --git a/lib/src/components/NxList/__tests__/NxListSubtext.test.tsx b/lib/src/components/NxList/__tests__/NxListSubtext.test.tsx index 99e04d86d5..995c7b9806 100644 --- a/lib/src/components/NxList/__tests__/NxListSubtext.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListSubtext.test.tsx @@ -6,6 +6,7 @@ */ import NxList from '../NxList'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListSubtext', function() { diff --git a/lib/src/components/NxList/__tests__/NxListText.test.tsx b/lib/src/components/NxList/__tests__/NxListText.test.tsx index b957782d61..6a4f130288 100644 --- a/lib/src/components/NxList/__tests__/NxListText.test.tsx +++ b/lib/src/components/NxList/__tests__/NxListText.test.tsx @@ -6,6 +6,7 @@ */ import NxList from '../NxList'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxListText', function() { diff --git a/lib/src/components/NxLoadError/__tests__/NxLoadError.test.tsx b/lib/src/components/NxLoadError/__tests__/NxLoadError.test.tsx index 1adc1a2fa4..9707cd4963 100644 --- a/lib/src/components/NxLoadError/__tests__/NxLoadError.test.tsx +++ b/lib/src/components/NxLoadError/__tests__/NxLoadError.test.tsx @@ -5,8 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import { screen } from '@testing-library/react'; -import { rtlRenderElement, rtlRender } from '../../../__testutils__/rtlUtils'; -import userEvent from '@testing-library/user-event'; +import { userEvent, rtlRenderElement, rtlRender } from '../../../__testutils__/rtlUtils'; import NxLoadError from '../NxLoadError'; describe('NxLoadError', function() { diff --git a/lib/src/components/NxLoadWrapper/__tests__/NxLoadWrapper.test.tsx b/lib/src/components/NxLoadWrapper/__tests__/NxLoadWrapper.test.tsx index 0134fe23c4..1717d066cd 100644 --- a/lib/src/components/NxLoadWrapper/__tests__/NxLoadWrapper.test.tsx +++ b/lib/src/components/NxLoadWrapper/__tests__/NxLoadWrapper.test.tsx @@ -4,48 +4,83 @@ * the terms of the Eclipse Public License 2.0 which accompanies this * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ +import { screen } from '@testing-library/react'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import React from 'react'; -import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; -import NxLoadWrapper, { Props } from '../NxLoadWrapper'; -import NxLoadError from '../../NxLoadError/NxLoadError'; -import NxLoadingSpinner from '../../NxLoadingSpinner/NxLoadingSpinner'; +import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; + +import NxLoadWrapper from '../NxLoadWrapper'; describe('NxLoadError', function() { - const children =
, - retryHandler = jest.fn(), - getShallowComponent = enzymeUtils.getShallowComponent(NxLoadWrapper, { children, retryHandler }); + const children =
Foo
; + const minimalProps = { + children, + retryHandler: () => {} + }; + const renderEl = rtlRenderElement(NxLoadWrapper, minimalProps); + const quickRender = rtlRender(NxLoadWrapper, minimalProps); - it('renders a NxLoadError if there is an error', function() { - const ErrorFixture = () => ; + describe('when there is an error', ()=> { + it('an alert is rendered', ()=> { + const componentWithError = renderEl({error: 'Error!'}); + expect(componentWithError).toBeInTheDocument(); + expect(componentWithError).toHaveAttribute('role', 'alert'); + expect(componentWithError?.textContent).toContain('Error!'); + }); - expect(getShallowComponent({ error: 'foo' })).toMatchElement(); - expect(getShallowComponent({ error: 'foo', loading: true })).toMatchElement(); - }); + it('Retry button is rendered within the alert', ()=> { + expect(renderEl()?.textContent).not.toContain('Retry'); + expect(quickRender({ error: 'Error' }).getByRole('button', { name: 'Retry' })) + .toBeInTheDocument(); + }); - it('passes the retryHandler to NxLoadError', function () { - expect(getShallowComponent({ error: 'foo' }).find(NxLoadError)).toHaveProp('retryHandler', retryHandler); - }); + it('retryHandler is called when that Retry button is clicked', async ()=> { + const user = userEvent.setup(); + const retryHandler = jest.fn(); + expect(renderEl()?.textContent).not.toContain('Retry'); + expect(quickRender({ error: 'Error', retryHandler }).getByRole('button', { name: 'Retry' })) + .toBeInTheDocument(); + const retryButton = screen.getByRole('button', { name: 'Retry' }); + expect(retryHandler).not.toHaveBeenCalled(); + await user.click(retryButton); + expect(retryHandler).toHaveBeenCalled(); + }); + + it('children content and loading spinner are not rendered when error is present', ()=> { + const toCheck = ['Loading…', 'Foo']; + toCheck.forEach(nameToCheck => { + expect(renderEl({error: 'Error'})?.textContent).not.toContain(nameToCheck); + }); - it('renders a loading spinner if error is not set and loading is true', function() { - const SpinnerFixture = () => ; + }); - expect(getShallowComponent({ loading: true })).toMatchElement(); - expect(getShallowComponent({ error: 'foo', loading: true })).not.toMatchElement(); }); - it('renders provided children if loading is false and error is unset', function() { - expect(getShallowComponent()).toContainReact(children); - expect(getShallowComponent({ loading: false })).toContainReact(children); - expect(getShallowComponent({ error: 'foo' })).not.toContainReact(children); - expect(getShallowComponent({ loading: true })).not.toContainReact(children); + it('when it is loading', ()=> { + expect(renderEl()?.textContent).not.toContain('Loading…'); + expect(quickRender({ loading: true }).container.textContent).toContain('Loading…'); + expect(quickRender({ loading: true }).container.textContent).not.toContain('Foo'); + expect(quickRender({ loading: true }).container).not.toHaveAttribute('role', 'alert'); }); - it('renders children provided by a function if loading is false and error is unset', function() { - const childrenFn = () => children; + describe('renders provided children', ()=> { + it('renders provided children if loading is false and error is unset', ()=> { + const { container: withChildren } = quickRender(); + expect(withChildren.textContent).toContain('Foo'); + expect(withChildren.textContent).not.toContain('Loading…'); + expect(withChildren).not.toHaveAttribute('role', 'alert'); + }); - expect(getShallowComponent({ children: childrenFn })).toContainReact(children); - expect(getShallowComponent({ children: childrenFn, loading: false })).toContainReact(children); - expect(getShallowComponent({ children: childrenFn, error: 'foo' })).not.toContainReact(children); - expect(getShallowComponent({ children: childrenFn, loading: true })).not.toContainReact(children); + it('renders children provided by a function if loading is false and error is unset', ()=> { + const childrenFn = () => children; + const { container: withFuncChild } = quickRender({ + children: childrenFn, + loading: false, + error: '' + }); + expect(withFuncChild.textContent).toContain('Foo'); + expect(withFuncChild.textContent).not.toContain('Loading…'); + expect(withFuncChild).not.toHaveAttribute('role', 'alert'); + }); }); }); diff --git a/lib/src/components/NxModal/__tests__/NxModal.test.tsx b/lib/src/components/NxModal/__tests__/NxModal.test.tsx index f8234dec99..fce53c2620 100644 --- a/lib/src/components/NxModal/__tests__/NxModal.test.tsx +++ b/lib/src/components/NxModal/__tests__/NxModal.test.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; import {mount, shallow} from 'enzyme'; +import 'jest-enzyme'; import { getMountedComponent } from '../../../__testutils__/enzymeUtils'; import NxModal, { Props } from '../NxModal'; import NxTooltip from '../../NxTooltip/NxTooltip'; import NxButton from '../../NxButton/NxButton'; import { Tooltip } from '@material-ui/core'; +import { runTimers } from '../../../__testutils__/rtlUtils'; describe('NxModal', function() { const dummyCloseHandler = jest.fn(); @@ -176,7 +178,7 @@ describe('NxModal', function() { expect(tooltip.prop('PopperProps')!.container).toBe(nxModal.getDOMNode()); }); - it('moves focus back to the previously focused element when closed', function(done) { + it('moves focus back to the previously focused element when closed', async function() { function Fixture({ modalOpen }: { modalOpen: boolean }) { return ( <> @@ -204,10 +206,9 @@ describe('NxModal', function() { expect(component).not.toContainMatchingElement(NxModal); // The focus is moved asynchronously - setTimeout(() => { - expect(document.activeElement === externalBtn).toBe(true); - done(); - }, 100); + await runTimers(); + + expect(document.activeElement === externalBtn).toBe(true); }); }); diff --git a/lib/src/components/NxPageHeader/__tests__/NxPageHeader.test.tsx b/lib/src/components/NxPageHeader/__tests__/NxPageHeader.test.tsx index aa82c9e7e0..8b2feee667 100644 --- a/lib/src/components/NxPageHeader/__tests__/NxPageHeader.test.tsx +++ b/lib/src/components/NxPageHeader/__tests__/NxPageHeader.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; import NxPageHeader from '../NxPageHeader'; diff --git a/lib/src/components/NxPagination/__tests__/NxPagination.test.tsx b/lib/src/components/NxPagination/__tests__/NxPagination.test.tsx index 67a50a4375..31b333c26e 100644 --- a/lib/src/components/NxPagination/__tests__/NxPagination.test.tsx +++ b/lib/src/components/NxPagination/__tests__/NxPagination.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons'; diff --git a/lib/src/components/NxPolicyThreatSlider/__tests__/NxPolicyThreatSlider.test.tsx b/lib/src/components/NxPolicyThreatSlider/__tests__/NxPolicyThreatSlider.test.tsx index f73918c7ad..1cb792297f 100644 --- a/lib/src/components/NxPolicyThreatSlider/__tests__/NxPolicyThreatSlider.test.tsx +++ b/lib/src/components/NxPolicyThreatSlider/__tests__/NxPolicyThreatSlider.test.tsx @@ -8,6 +8,7 @@ import React, { FunctionComponent } from 'react'; import { Slider } from '@material-ui/core'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxPolicyThreatSlider, { Props } from '../NxPolicyThreatSlider'; import { LabelDisplayProps } from '../types'; diff --git a/lib/src/components/NxPolicyViolationIndicator/__tests__/NxPolicyViolationIndicator.test.tsx b/lib/src/components/NxPolicyViolationIndicator/__tests__/NxPolicyViolationIndicator.test.tsx index 563ea711eb..d08bdcb5de 100644 --- a/lib/src/components/NxPolicyViolationIndicator/__tests__/NxPolicyViolationIndicator.test.tsx +++ b/lib/src/components/NxPolicyViolationIndicator/__tests__/NxPolicyViolationIndicator.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxPolicyViolationIndicator, { Props } from '../NxPolicyViolationIndicator'; import NxFontAwesomeIcon from '../../NxFontAwesomeIcon/NxFontAwesomeIcon'; diff --git a/lib/src/components/NxProgressBar/__tests__/NxProgressBar.test.tsx b/lib/src/components/NxProgressBar/__tests__/NxProgressBar.test.tsx index 0483a92afa..0f9ac01d9a 100644 --- a/lib/src/components/NxProgressBar/__tests__/NxProgressBar.test.tsx +++ b/lib/src/components/NxProgressBar/__tests__/NxProgressBar.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxProgressBar from '../NxProgressBar'; diff --git a/lib/src/components/NxRadio/__tests__/NxRadio.test.tsx b/lib/src/components/NxRadio/__tests__/NxRadio.test.tsx index c8e32d7102..598a25e013 100644 --- a/lib/src/components/NxRadio/__tests__/NxRadio.test.tsx +++ b/lib/src/components/NxRadio/__tests__/NxRadio.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { screen, within } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxSearchDropdown/NxSearchDropdown.tsx b/lib/src/components/NxSearchDropdown/NxSearchDropdown.tsx index 3bfe932b9c..cca95bb4c0 100644 --- a/lib/src/components/NxSearchDropdown/NxSearchDropdown.tsx +++ b/lib/src/components/NxSearchDropdown/NxSearchDropdown.tsx @@ -153,6 +153,7 @@ function NxSearchDropdownRender( onKeyDown={handleButtonKeyDown} isOpen={true} toggleElementRef={filterRef} + useActiveDescendant={true} aria-busy={!!loading} aria-live="polite" aria-hidden={!showDropdown} diff --git a/lib/src/components/NxSearchDropdown/__tests__/NxSearchDropdown.test.tsx b/lib/src/components/NxSearchDropdown/__tests__/NxSearchDropdown.test.tsx index f9476872af..95dec3e613 100644 --- a/lib/src/components/NxSearchDropdown/__tests__/NxSearchDropdown.test.tsx +++ b/lib/src/components/NxSearchDropdown/__tests__/NxSearchDropdown.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import { getShallowComponent, getMountedComponent } from '../../../__testutils__/enzymeUtils'; import NxFilterInput from '../../NxFilterInput/NxFilterInput'; diff --git a/lib/src/components/NxSearchDropdown/stateful/__tests__/NxStatefulSearchDropdown.test.tsx b/lib/src/components/NxSearchDropdown/stateful/__tests__/NxStatefulSearchDropdown.test.tsx index 484a300054..37d6758404 100644 --- a/lib/src/components/NxSearchDropdown/stateful/__tests__/NxStatefulSearchDropdown.test.tsx +++ b/lib/src/components/NxSearchDropdown/stateful/__tests__/NxStatefulSearchDropdown.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import { omit } from 'ramda'; import { getShallowComponent } from '../../../../__testutils__/enzymeUtils'; import NxSearchDropdown from '../../NxSearchDropdown'; diff --git a/lib/src/components/NxSearchTransferList/__tests__/NxSearchTransferList.test.tsx b/lib/src/components/NxSearchTransferList/__tests__/NxSearchTransferList.test.tsx index c586c8d38d..35f2132b11 100644 --- a/lib/src/components/NxSearchTransferList/__tests__/NxSearchTransferList.test.tsx +++ b/lib/src/components/NxSearchTransferList/__tests__/NxSearchTransferList.test.tsx @@ -7,6 +7,7 @@ import DataItem from '../../../util/DataItem'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxSearchDropdown from '../../NxSearchDropdown/NxSearchDropdown'; import NxTransferListHalf from '../../NxTransferListHalf/NxTransferListHalf'; import NxSearchTransferList, { Props } from '../NxSearchTransferList'; diff --git a/lib/src/components/NxSearchTransferList/stateful/__tests__/NxStatefulSearchTransferList.test.tsx b/lib/src/components/NxSearchTransferList/stateful/__tests__/NxStatefulSearchTransferList.test.tsx index 453732d7b4..2ad65e5933 100644 --- a/lib/src/components/NxSearchTransferList/stateful/__tests__/NxStatefulSearchTransferList.test.tsx +++ b/lib/src/components/NxSearchTransferList/stateful/__tests__/NxStatefulSearchTransferList.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import { getShallowComponent } from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxStatefulSearchTranferList, { Props } from '../NxStatefulSearchTransferList'; describe('NxStatefulSearchTranferList', function() { diff --git a/lib/src/components/NxSegmentedButton/__tests__/NxSegmentedButton.test.tsx b/lib/src/components/NxSegmentedButton/__tests__/NxSegmentedButton.test.tsx index cde5517d37..bbc40f783a 100644 --- a/lib/src/components/NxSegmentedButton/__tests__/NxSegmentedButton.test.tsx +++ b/lib/src/components/NxSegmentedButton/__tests__/NxSegmentedButton.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import { act } from 'react-dom/test-utils'; import { getMountedComponent, getShallowComponent } from '../../../__testutils__/enzymeUtils'; diff --git a/lib/src/components/NxSegmentedButton/stateful/__tests__/NxStatefulSegmentedButton.test.tsx b/lib/src/components/NxSegmentedButton/stateful/__tests__/NxStatefulSegmentedButton.test.tsx index 6187ae1e7c..e3fe47a8f4 100644 --- a/lib/src/components/NxSegmentedButton/stateful/__tests__/NxStatefulSegmentedButton.test.tsx +++ b/lib/src/components/NxSegmentedButton/stateful/__tests__/NxStatefulSegmentedButton.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { mount, ReactWrapper } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; import NxSegmentedButton from '../../NxSegmentedButton'; diff --git a/lib/src/components/NxSmallThreatCounter/__tests__/NxSmallThreatCounter.test.tsx b/lib/src/components/NxSmallThreatCounter/__tests__/NxSmallThreatCounter.test.tsx index 54b6ab7d76..7cb9585f26 100644 --- a/lib/src/components/NxSmallThreatCounter/__tests__/NxSmallThreatCounter.test.tsx +++ b/lib/src/components/NxSmallThreatCounter/__tests__/NxSmallThreatCounter.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxTooltip from '../../NxTooltip/NxTooltip'; import NxSmallThreatCounter, { Props } from '../NxSmallThreatCounter'; diff --git a/lib/src/components/NxStatusIndicator/__tests__/NxStatusIndicator.test.tsx b/lib/src/components/NxStatusIndicator/__tests__/NxStatusIndicator.test.tsx index 1cb546d6cf..6e3c3b971a 100644 --- a/lib/src/components/NxStatusIndicator/__tests__/NxStatusIndicator.test.tsx +++ b/lib/src/components/NxStatusIndicator/__tests__/NxStatusIndicator.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import { NxErrorStatusIndicator, NxIntermediateStatusIndicator, NxNegativeStatusIndicator, NxPositiveStatusIndicator } from '../NxStatusIndicator'; diff --git a/lib/src/components/NxSubmitMask/stateful/__tests__/NxStatefulSubmitMask.test.tsx b/lib/src/components/NxSubmitMask/stateful/__tests__/NxStatefulSubmitMask.test.tsx index 3bad7daa14..08db068825 100644 --- a/lib/src/components/NxSubmitMask/stateful/__tests__/NxStatefulSubmitMask.test.tsx +++ b/lib/src/components/NxSubmitMask/stateful/__tests__/NxStatefulSubmitMask.test.tsx @@ -6,6 +6,7 @@ */ import { act } from 'react-dom/test-utils'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../../__testutils__/enzymeUtils'; import NxStatefulSubmitMask from '../NxStatefulSubmitMask'; diff --git a/lib/src/components/NxSystemNotice/__tests__/NxSystemNotice.test.tsx b/lib/src/components/NxSystemNotice/__tests__/NxSystemNotice.test.tsx index 91d976f0c4..71cac7d7c9 100644 --- a/lib/src/components/NxSystemNotice/__tests__/NxSystemNotice.test.tsx +++ b/lib/src/components/NxSystemNotice/__tests__/NxSystemNotice.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import NxSystemNotice from '../NxSystemNotice'; describe('NxSystemNotice', function() { diff --git a/lib/src/components/NxTable/__tests__/NxTable.test.tsx b/lib/src/components/NxTable/__tests__/NxTable.test.tsx index 20afe84e57..ed48d52239 100644 --- a/lib/src/components/NxTable/__tests__/NxTable.test.tsx +++ b/lib/src/components/NxTable/__tests__/NxTable.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow, mount, ReactWrapper } from 'enzyme'; +import 'jest-enzyme'; import NxTable from '../NxTable'; import NxTableHead from '../NxTableHead'; import NxTableRow from '../NxTableRow'; diff --git a/lib/src/components/NxTable/__tests__/NxTableBody.test.tsx b/lib/src/components/NxTable/__tests__/NxTableBody.test.tsx index fbe3d5511e..3a17ad9bbd 100644 --- a/lib/src/components/NxTable/__tests__/NxTableBody.test.tsx +++ b/lib/src/components/NxTable/__tests__/NxTableBody.test.tsx @@ -6,6 +6,7 @@ */ import React, { ReactElement } from 'react'; import { shallow, mount, ReactWrapper } from 'enzyme'; +import 'jest-enzyme'; import { act } from 'react-dom/test-utils'; import NxTableBody from '../NxTableBody'; import NxTableCell from '../NxTableCell'; diff --git a/lib/src/components/NxTable/__tests__/NxTableCell.test.tsx b/lib/src/components/NxTable/__tests__/NxTableCell.test.tsx index cd91839b71..d54104f681 100644 --- a/lib/src/components/NxTable/__tests__/NxTableCell.test.tsx +++ b/lib/src/components/NxTable/__tests__/NxTableCell.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { faSort, faSortDown, faSortUp, faChevronRight, faEdit } from '@fortawesome/free-solid-svg-icons'; import NxFontAwesomeIcon from '../../NxFontAwesomeIcon/NxFontAwesomeIcon'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; import NxTableCell from '../NxTableCell'; diff --git a/lib/src/components/NxTable/__tests__/NxTableHead.test.tsx b/lib/src/components/NxTable/__tests__/NxTableHead.test.tsx index fe457bb385..d8bd6ab316 100644 --- a/lib/src/components/NxTable/__tests__/NxTableHead.test.tsx +++ b/lib/src/components/NxTable/__tests__/NxTableHead.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import NxTableHead from '../NxTableHead'; describe('NxTableHead', function () { diff --git a/lib/src/components/NxTable/__tests__/NxTableRow.test.tsx b/lib/src/components/NxTable/__tests__/NxTableRow.test.tsx index ae18a99039..7744e79201 100644 --- a/lib/src/components/NxTable/__tests__/NxTableRow.test.tsx +++ b/lib/src/components/NxTable/__tests__/NxTableRow.test.tsx @@ -6,6 +6,7 @@ */ import React, { useContext } from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; import NxTableRow from '../NxTableRow'; diff --git a/lib/src/components/NxTabs/__tests__/NxStatefulTabs.test.tsx b/lib/src/components/NxTabs/__tests__/NxStatefulTabs.test.tsx index 31657fcdb2..c42f450cdb 100644 --- a/lib/src/components/NxTabs/__tests__/NxStatefulTabs.test.tsx +++ b/lib/src/components/NxTabs/__tests__/NxStatefulTabs.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import NxStatefulTabs from '../stateful/NxStatefulTabs'; import NxTabList from '../NxTabList'; import NxTab from '../NxTab'; diff --git a/lib/src/components/NxTabs/__tests__/NxTab.test.tsx b/lib/src/components/NxTabs/__tests__/NxTab.test.tsx index 304cefd8b0..c4de6d9626 100644 --- a/lib/src/components/NxTabs/__tests__/NxTab.test.tsx +++ b/lib/src/components/NxTabs/__tests__/NxTab.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import NxOverflowTooltip from '../../NxTooltip/NxOverflowTooltip'; import NxTab from '../NxTab'; diff --git a/lib/src/components/NxTabs/__tests__/NxTabList.test.tsx b/lib/src/components/NxTabs/__tests__/NxTabList.test.tsx index 105044136d..d324ff030a 100644 --- a/lib/src/components/NxTabs/__tests__/NxTabList.test.tsx +++ b/lib/src/components/NxTabs/__tests__/NxTabList.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import NxTabList from '../NxTabList'; describe('NxTabList', function () { diff --git a/lib/src/components/NxTabs/__tests__/NxTabPanel.test.tsx b/lib/src/components/NxTabs/__tests__/NxTabPanel.test.tsx index 7ae8b3e276..da1741faa8 100644 --- a/lib/src/components/NxTabs/__tests__/NxTabPanel.test.tsx +++ b/lib/src/components/NxTabs/__tests__/NxTabPanel.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import NxTabPanel from '../NxTabPanel'; import TabContext from '../TabContext'; diff --git a/lib/src/components/NxTabs/__tests__/NxTabs.test.tsx b/lib/src/components/NxTabs/__tests__/NxTabs.test.tsx index de894ad192..4d3e603ded 100644 --- a/lib/src/components/NxTabs/__tests__/NxTabs.test.tsx +++ b/lib/src/components/NxTabs/__tests__/NxTabs.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount, shallow } from 'enzyme'; +import 'jest-enzyme'; import NxTabs from '../NxTabs'; import NxTabList from '../NxTabList'; import NxTab from '../NxTab'; diff --git a/lib/src/components/NxTag/__tests__/NxTag.test.tsx b/lib/src/components/NxTag/__tests__/NxTag.test.tsx index 0706700941..0048a5eae9 100644 --- a/lib/src/components/NxTag/__tests__/NxTag.test.tsx +++ b/lib/src/components/NxTag/__tests__/NxTag.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { shallow, mount } from 'enzyme'; import { faPlusCircle, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; diff --git a/lib/src/components/NxTextInput/__tests__/NxTextInput.test.tsx b/lib/src/components/NxTextInput/__tests__/NxTextInput.test.tsx index a357e0b141..ca584b1eea 100644 --- a/lib/src/components/NxTextInput/__tests__/NxTextInput.test.tsx +++ b/lib/src/components/NxTextInput/__tests__/NxTextInput.test.tsx @@ -7,7 +7,7 @@ import React, { RefAttributes } from 'react'; import { render, within } from '@testing-library/react'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import NxTextInput, { PublicProps } from '../NxTextInput'; import NxForm from '../../NxForm/NxForm'; diff --git a/lib/src/components/NxTextInput/stateful/__tests__/NxStatefulTextInput.test.tsx b/lib/src/components/NxTextInput/stateful/__tests__/NxStatefulTextInput.test.tsx index dbaa5f3198..27ea764f94 100644 --- a/lib/src/components/NxTextInput/stateful/__tests__/NxStatefulTextInput.test.tsx +++ b/lib/src/components/NxTextInput/stateful/__tests__/NxStatefulTextInput.test.tsx @@ -7,7 +7,7 @@ import React, { RefAttributes } from 'react'; import { fireEvent, render, within } from '@testing-library/react'; import { rtlRender, rtlRenderElement } from '../../../../__testutils__/rtlUtils'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../../__testutils__/rtlUtils'; import NxStatefulTextInput, { PublicProps } from '../NxStatefulTextInput'; import NxForm from '../../../NxForm/NxForm'; diff --git a/lib/src/components/NxThreatCounter/__tests__/NxThreatCounter.test.tsx b/lib/src/components/NxThreatCounter/__tests__/NxThreatCounter.test.tsx index 67b0994b6d..f974786d80 100644 --- a/lib/src/components/NxThreatCounter/__tests__/NxThreatCounter.test.tsx +++ b/lib/src/components/NxThreatCounter/__tests__/NxThreatCounter.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxThreatCounter, { Props } from '../NxThreatCounter'; diff --git a/lib/src/components/NxThreatIndicator/__tests__/NxThreatIndicator.test.tsx b/lib/src/components/NxThreatIndicator/__tests__/NxThreatIndicator.test.tsx index 207534665f..1ac4bccb62 100644 --- a/lib/src/components/NxThreatIndicator/__tests__/NxThreatIndicator.test.tsx +++ b/lib/src/components/NxThreatIndicator/__tests__/NxThreatIndicator.test.tsx @@ -7,6 +7,7 @@ import { faCircle } from '@fortawesome/free-solid-svg-icons'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxThreatIndicator from '../NxThreatIndicator'; import NxFontAwesomeIcon from '../../NxFontAwesomeIcon/NxFontAwesomeIcon'; diff --git a/lib/src/components/NxThreatIndicatorLegend/__tests__/NxThreatIndicatorLegend.test.tsx b/lib/src/components/NxThreatIndicatorLegend/__tests__/NxThreatIndicatorLegend.test.tsx index 90245d4070..0c28b77026 100644 --- a/lib/src/components/NxThreatIndicatorLegend/__tests__/NxThreatIndicatorLegend.test.tsx +++ b/lib/src/components/NxThreatIndicatorLegend/__tests__/NxThreatIndicatorLegend.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { faCircle } from '@fortawesome/free-solid-svg-icons'; import * as enzymeUtils from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import { mount } from 'enzyme'; import NxThreatIndicatorLegend from '../NxThreatIndicatorLegend'; diff --git a/lib/src/components/NxTile/__tests__/NxTile.test.tsx b/lib/src/components/NxTile/__tests__/NxTile.test.tsx index 02ee6f3965..27fe38ea7d 100644 --- a/lib/src/components/NxTile/__tests__/NxTile.test.tsx +++ b/lib/src/components/NxTile/__tests__/NxTile.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import NxTile from '../NxTile'; diff --git a/lib/src/components/NxToast/__tests__/NxToast.test.tsx b/lib/src/components/NxToast/__tests__/NxToast.test.tsx index 4d240c9c12..472012cdc0 100644 --- a/lib/src/components/NxToast/__tests__/NxToast.test.tsx +++ b/lib/src/components/NxToast/__tests__/NxToast.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { rtlRender, rtlRenderElement } from '../../../__testutils__/rtlUtils'; import { fireEvent, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import NxToast from '../NxToast'; import { NxToastProps } from '../types'; diff --git a/lib/src/components/NxToast/__tests__/NxToastContainer.test.tsx b/lib/src/components/NxToast/__tests__/NxToastContainer.test.tsx index 6dc9918431..9e8cfe1a70 100644 --- a/lib/src/components/NxToast/__tests__/NxToastContainer.test.tsx +++ b/lib/src/components/NxToast/__tests__/NxToastContainer.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { rtlRenderElement, rtlRender } from '../../../__testutils__/rtlUtils'; import { screen, render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import NxToastContainer from '../NxToastContainer'; import { NxToastContainerProps } from '../types'; @@ -69,6 +69,7 @@ describe('NxToastContainer', function() { it('sets focus to previous focused element when the last remaining toast is closed', async function() { + const user = userEvent.setup(); render( <> @@ -86,7 +87,7 @@ describe('NxToastContainer', function() { prevFocusBtn.focus(); closeBtn.focus(); - await userEvent.click(closeBtn); + await user.click(closeBtn); expect(prevFocusBtn).toHaveFocus(); }); @@ -94,6 +95,7 @@ describe('NxToastContainer', function() { it('sets focus to previous focused element (before any toasts rendered) when the last remaining toast is closed', async function() { + const user = userEvent.setup(); const { rerender } = render( <> @@ -120,7 +122,7 @@ describe('NxToastContainer', function() { const closeBtn = screen.getByRole('button', {name: 'Close'}); closeBtn.focus(); - await userEvent.click(closeBtn); + await user.click(closeBtn); expect(prevFocusBtn).toHaveFocus(); }); diff --git a/lib/src/components/NxToggle/__tests__/NxToggle.test.tsx b/lib/src/components/NxToggle/__tests__/NxToggle.test.tsx index c0b8a3434a..544207f4c7 100644 --- a/lib/src/components/NxToggle/__tests__/NxToggle.test.tsx +++ b/lib/src/components/NxToggle/__tests__/NxToggle.test.tsx @@ -8,7 +8,7 @@ import * as rtlUtils from '../../../__testutils__/rtlUtils'; import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import NxToggle, { Props } from '../NxToggle'; diff --git a/lib/src/components/NxToggle/stateful/__tests__/NxStatefulToggle.test.tsx b/lib/src/components/NxToggle/stateful/__tests__/NxStatefulToggle.test.tsx index 63f5e5633b..587125daf3 100644 --- a/lib/src/components/NxToggle/stateful/__tests__/NxStatefulToggle.test.tsx +++ b/lib/src/components/NxToggle/stateful/__tests__/NxStatefulToggle.test.tsx @@ -7,6 +7,7 @@ import NxToggle from '../../NxToggle'; import NxStatefulToggle, { Props } from '../NxStatefulToggle'; import {getShallowComponent} from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; describe('NxStatefulToggle', function() { const simpleProps: Props = { diff --git a/lib/src/components/NxTooltip/__tests__/NxOverflowTooltip.test.tsx b/lib/src/components/NxTooltip/__tests__/NxOverflowTooltip.test.tsx index efa9b89117..ebc69489ba 100644 --- a/lib/src/components/NxTooltip/__tests__/NxOverflowTooltip.test.tsx +++ b/lib/src/components/NxTooltip/__tests__/NxOverflowTooltip.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxOverflowTooltip, { OverflowTooltipProps as Props } from '../NxOverflowTooltip'; diff --git a/lib/src/components/NxTooltip/__tests__/NxTooltip.test.tsx b/lib/src/components/NxTooltip/__tests__/NxTooltip.test.tsx index 2eb93acc76..5d1437e07b 100644 --- a/lib/src/components/NxTooltip/__tests__/NxTooltip.test.tsx +++ b/lib/src/components/NxTooltip/__tests__/NxTooltip.test.tsx @@ -5,7 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import { within, screen, act } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { userEvent } from '../../../__testutils__/rtlUtils'; import React from 'react'; import { rtlRender } from '../../../__testutils__/rtlUtils'; diff --git a/lib/src/components/NxTransferList/__tests__/NxTransferList.test.tsx b/lib/src/components/NxTransferList/__tests__/NxTransferList.test.tsx index 17f8981837..66863864c7 100644 --- a/lib/src/components/NxTransferList/__tests__/NxTransferList.test.tsx +++ b/lib/src/components/NxTransferList/__tests__/NxTransferList.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import { ShallowWrapper } from 'enzyme'; +import 'jest-enzyme'; import { always } from 'ramda'; import { getShallowComponent } from '../../../__testutils__/enzymeUtils'; diff --git a/lib/src/components/NxTransferListHalf/__tests__/NxTransferListHalf.test.tsx b/lib/src/components/NxTransferListHalf/__tests__/NxTransferListHalf.test.tsx index becba056bc..0b7550bfff 100644 --- a/lib/src/components/NxTransferListHalf/__tests__/NxTransferListHalf.test.tsx +++ b/lib/src/components/NxTransferListHalf/__tests__/NxTransferListHalf.test.tsx @@ -4,495 +4,509 @@ * the terms of the Eclipse Public License 2.0 which accompanies this * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ -import { faArrowDown, faArrowUp, faEdit, faPlusCircle, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; + import { includes } from 'ramda'; +import { faEdit } from '@fortawesome/free-solid-svg-icons'; import React from 'react'; +import { rtlRenderElement, rtlRender, runTimers, userEvent } from '../../../__testutils__/rtlUtils'; +import { within, render, screen } from '@testing-library/react'; -import { getShallowComponent, getMountedComponent } from '../../../__testutils__/enzymeUtils'; -import NxTooltip from '../../NxTooltip/NxTooltip'; -import NxFieldset from '../../NxFieldset/NxFieldset'; -import NxFilterInput from '../../NxFilterInput/NxFilterInput'; import NxFontAwesomeIcon from '../../NxFontAwesomeIcon/NxFontAwesomeIcon'; - -import NxTransferListHalf from '../NxTransferListHalf'; -import { Props } from '../types'; +import NxTransferListHalf, { Props } from '../NxTransferListHalf'; describe('NxTransferListHalf', function() { - const minimalProps = { + const minimalProps: Props = { label: 'Foo', filterValue: '', onFilterChange: () => {}, items: [], footerContent:
}, - getShallow = getShallowComponent>(NxTransferListHalf, minimalProps), - getMounted = getMountedComponent>(NxTransferListHalf, minimalProps); + quickRender = rtlRender(NxTransferListHalf, minimalProps), + renderEl = rtlRenderElement(NxTransferListHalf, minimalProps); - it('renders an NxFieldset with the nx-transfer-list__half class', function() { - expect(getShallow()).toMatchSelector(NxFieldset); - expect(getShallow()).toHaveClassName('nx-transfer-list__half'); + it('renders a fieldset as top-level element', function() { + const el = renderEl()!; + expect(el.tagName).toBe('FIELDSET'); }); it('passes the label to the NxFieldset', function() { - expect(getShallow()).toHaveProp('label', 'Foo'); - }); - - it('renders a div with class nx-transfer-list__control-box within the fieldset', function() { - expect(getShallow().children()).toMatchSelector('div.nx-transfer-list__control-box'); + const el = renderEl()!; + expect(el).toHaveAccessibleName('Foo'); + expect(el).toHaveTextContent('Foo'); }); - it('renders an NxFilterInput with class nx-transfer-list__filter within the control-box', function() { - expect(getShallow().find('.nx-transfer-list__control-box > .nx-transfer-list__filter')) - .toMatchSelector(NxFilterInput); - }); + it('renders an input with type="text" within NxTransferListHalf', function() { + const el = renderEl()!, + input = within(el).getByRole('textbox'); - it('Sets the filter inputs placeholder to "filter"', function() { - expect(getShallow().find(NxFilterInput)).toHaveProp('placeholder', 'Filter'); + expect(input).toBeInTheDocument(); + expect(input).toHaveAttribute('type', 'text'); }); - it('sets the filterValue as the value of the NxFilterInput', function() { - expect(getShallow({ filterValue: 'foo' }).find(NxFilterInput)).toHaveProp('value', 'foo'); + it('sets the filter inputs placeholder to "Filter"', function() { + expect(quickRender().getByRole('textbox')).toHaveAttribute('placeholder', 'Filter'); }); - it('sets the onFilterChange handler as the filter input onChange', function() { - const onFilterChange = jest.fn(), - component = getShallow({ onFilterChange }).find(NxFilterInput); - - expect(component).toHaveProp('onChange', onFilterChange); + it('sets the filterValue as the value of the filter input', function() { + expect(quickRender({ filterValue: 'foo' }).getByRole('textbox')).toHaveValue('foo'); }); - it('renders an .nx-transfer-list__move-all button only if showMoveAll is true', function() { - expect(getShallow().find('.nx-transfer-list__move-all')).not.toExist(); - expect(getShallow({ showMoveAll: true }).find('button.nx-transfer-list__move-all')).toExist(); - }); + it('calls onFilterChange when the filterValue is updated', async function() { + const user = userEvent.setup(), + onFilterChange = jest.fn().mockImplementation((_, evt) => { evt.persist(); }), + input = quickRender({ onFilterChange }).getByRole('textbox'); - it('fires onMoveAll when the .nx-transfer-list__move-all button is clicked', function() { - const onMoveAll = jest.fn(), - component = getShallow({ onMoveAll, showMoveAll: true }); + expect(onFilterChange).not.toHaveBeenCalled(); - expect(onMoveAll).not.toHaveBeenCalled(); + await user.type(input, 'a'); - component.find('.nx-transfer-list__move-all').simulate('click'); - - expect(onMoveAll).toHaveBeenCalledTimes(1); + expect(onFilterChange).toHaveBeenCalledWith('a', expect.objectContaining({ target: input })); }); - it('passes onMoveAll an array containing every id if no filterValue is set', function() { - const items = [{ - id: 1, - displayName: 'foo' - }, { - id: 2, - displayName: 'Foo' - }, { - id: 3, - displayName: 'bar' - }, { - id: 4, - displayName: 'foo' - }, { - id: 5, - displayName: 'Foo' - }, { - id: 6, - displayName: 'bar' - }], - onMoveAll = jest.fn(), - component = getShallow({ items, onMoveAll, showMoveAll: true }); - - component.find('.nx-transfer-list__move-all').simulate('click'); - - expect(onMoveAll).toHaveBeenCalledWith([1, 2, 3, 4, 5, 6]); + it('only renders a "Remove All"/ "Transfer All" button when showMoveAll is true', function() { + expect(quickRender({ showMoveAll: undefined }).queryByRole('button', { name: /all/i })).not.toBeInTheDocument(); + expect(quickRender({ showMoveAll: null }).queryByRole('button', { name: /all/i })).not.toBeInTheDocument(); + expect(quickRender({ showMoveAll: false }).queryByRole('button', { name: /all/i })).not.toBeInTheDocument(); + expect(quickRender({ showMoveAll: true }).queryByRole('button', { name: /all/i })).toBeInTheDocument(); }); - it('sets the .nx-transfer-list__move-all icon to an x in a circle if isSelected, otherwise a plus in a circle', + it('sets the button text to "Transfer All" when isSelected is false, otherwise "Remove All"', function() { - const withSelected = getShallow({ showMoveAll: true }) - .find('.nx-transfer-list__move-all').find(NxFontAwesomeIcon), - withSelectedNull = getShallow({ showMoveAll: true, isSelected: null }) - .find('.nx-transfer-list__move-all').find(NxFontAwesomeIcon), - withSelectedFalse = getShallow({ showMoveAll: true, isSelected: false }) - .find('.nx-transfer-list__move-all').find(NxFontAwesomeIcon); - - expect(withSelected).toHaveProp('icon', faTimesCircle); - expect(withSelectedNull).toHaveProp('icon', faTimesCircle); - expect(withSelectedFalse).toHaveProp('icon', faPlusCircle); - } - ); - - it('sets the .nx-transfer-list__move-all text to "Remove All" when isSelected, otherwise "Transfer All"', function() { - const withSelected = getShallow({ showMoveAll: true }) - .find('.nx-transfer-list__move-all'), - withSelectedNull = getShallow({ showMoveAll: true, isSelected: null }) - .find('.nx-transfer-list__move-all'), - withSelectedFalse = getShallow({ showMoveAll: true, isSelected: false }) - .find('.nx-transfer-list__move-all'); - - expect(withSelected).toIncludeText('Remove All'); - expect(withSelectedNull).toIncludeText('Remove All'); - expect(withSelectedFalse).toIncludeText('Transfer All'); - }); - - it('contains an .nx-transfer-list__item-list', function() { - expect(getShallow().find('.nx-transfer-list__control-box .nx-transfer-list__item-list')).toExist(); - }); - - it('renders items into the .nx-transfer-list__item-list', function() { - const items = [{ - id: 1, - displayName: 'foo' - }, { - id: 3, - displayName: 'baz' - }], - onItemChange = jest.fn(), - component = getMounted({ items, onItemChange }), - list = component.find('.nx-transfer-list__item-list'); - - expect(list.children().length).toBe(2); - - const item = list.find('.nx-transfer-list__item').at(0), - select = item.find('.nx-transfer-list__select').at(0), - icon = select.find(NxFontAwesomeIcon), - checkbox = select.find('input.nx-transfer-list__checkbox'); + expect(quickRender({ showMoveAll: true, isSelected: true }) + .queryAllByRole('button')[1]).toHaveTextContent('Remove All'); + expect(quickRender({ showMoveAll: true, isSelected: undefined }) + .queryAllByRole('button')[1]).toHaveTextContent('Remove All'); + expect(quickRender({ showMoveAll: true, isSelected: null }) + .queryAllByRole('button')[1]).toHaveTextContent('Remove All'); + expect(quickRender({ showMoveAll: true, isSelected: false }) + .queryAllByRole('button')[1]).toHaveTextContent('Transfer All'); + }); - expect(item).toExist(); - expect(item).toMatchSelector('div'); + it('fires onMoveAll when the "Remove All"/ "Transfer All" button is clicked', async function() { + const user = userEvent.setup(), + onMoveAll = jest.fn(), + moveBtn = quickRender({ onMoveAll, showMoveAll: true }).getByRole('button', { name: /remove all/i }); - expect(select).toExist(); - expect(select).toMatchSelector('label'); - expect(select).toHaveText('foo'); + expect(onMoveAll).not.toHaveBeenCalled(); + await user.click(moveBtn); + expect(onMoveAll).toHaveBeenCalled(); + }); - expect(icon).toExist(); - expect(icon).toHaveProp('icon', faTimesCircle); + it('passes onMoveAll an array containing every id if no filterValue is set', async function() { + const dataItems = [{ + id: '1', + displayName: 'foo' + }, { + id: '2', + displayName: 'Foo' + }, { + id: '3', + displayName: 'bar' + }, { + id: '4', + displayName: 'foo' + }, { + id: '5', + displayName: 'Foo' + }, { + id: '6', + displayName: 'bar' + }]; - expect(checkbox).toExist(); - expect(checkbox).toHaveProp('type', 'checkbox'); + const user = userEvent.setup(), + onMoveAll = jest.fn(), + moveBtn = quickRender({ items: dataItems, onMoveAll, showMoveAll: true }) + .getByRole('button', { name: /remove all/i }); - const otherItem = list.find('.nx-transfer-list__item').at(1); + expect(onMoveAll).not.toHaveBeenCalled(); + await user.click(moveBtn); - expect(otherItem).toHaveText('baz'); + expect(onMoveAll).toHaveBeenCalledWith(['1', '2', '3', '4', '5', '6']); }); - it('does not render move icon and checkbox input when onItemChange is not provided', function() { - const items = [{ - id: 1, - displayName: 'foo' - }], - componentDisableItemMove = getMounted({ items }), - select = componentDisableItemMove - .find('.nx-transfer-list__item-list .nx-transfer-list__item .nx-transfer-list__select'); + it('renders items into the .nx-transfer-list__item-list', function() { + const dataItems = [{ + id: '1', + displayName: 'foo' + }, { + id: '2', + displayName: 'baz' + }]; - expect(select.find(NxFontAwesomeIcon)).not.toExist(); - expect(select.find('input.nx-transfer-list__checkbox')).not.toExist(); + // At this time, there are ARIA roles assigned to either .nx-transfer-list__item-list or .nx-transfer-list__item. + // Revisit and improve these tests in RSC-998 (Improve Transfer List Keyboard Navigation) + const { container } = quickRender({ items: dataItems }), + itemList = container.querySelector('.nx-transfer-list__item-list') as HTMLElement, + items = itemList.querySelectorAll('.nx-transfer-list__item'); + + expect(items.length).toBe(2); + expect(items[0]).toHaveTextContent('foo'); + expect(items[1]).toHaveTextContent('baz'); }); - it('sets the item checked prop to isSelected', function() { + it('renders a checkbox input only when onItemChange is provided', function() { const onItemChange = jest.fn(), - withSelected = getMounted({ items: [{ id: 1, displayName: 'foo' }], onItemChange }), - withSelectedNull = getMounted({ items: [{ id: 1, displayName: 'foo' }], isSelected: null, onItemChange }), - withSelectedFalse = getMounted({ items: [{ id: 1, displayName: 'foo' }], isSelected: false, onItemChange }); + { container, rerender } = quickRender({ items: [{id: '1', displayName: 'foo'}], onItemChange }), + item = container.querySelector('.nx-transfer-list__item') as HTMLElement, + checkbox = within(item).getByRole('checkbox'); - expect(withSelected.find('input.nx-transfer-list__checkbox')).toHaveProp('checked', true); - expect(withSelectedNull.find('input.nx-transfer-list__checkbox')).toHaveProp('checked', true); - expect(withSelectedFalse.find('input.nx-transfer-list__checkbox')).toHaveProp('checked', false); - }); + expect(item).toBeInTheDocument(); + expect(checkbox).toBeInTheDocument(); - it('contains an .nx-transfer-list__footer with the specified footerContent', function() { - const component = getShallow({ footerContent:
}), - footer = component.find('.nx-transfer-list__footer'); - - expect(footer).toExist(); - expect(footer.children()).toMatchSelector('div#foo'); + rerender( + + ); + expect(checkbox).not.toBeInTheDocument(); }); - it('calls onItemChange when an item checkbox is toggled, passing the new boolean state and the item id', function() { - const selectedContainer = document.createElement('div'), - unselectedContainer = document.createElement('div'); - - document.body.appendChild(selectedContainer); - document.body.appendChild(unselectedContainer); + it('sets the input to checked if isSelected is not false', function() { + const onItemChange = jest.fn(), + withSelected = quickRender({ items: [{ id: '1', displayName: 'foo' }], isSelected: true, onItemChange }), + withSelectedNull = quickRender({ items: [{ id: '1', displayName: 'foo' }], isSelected: null, onItemChange }), + withSelectedUndefined = quickRender({ + items: [{ id: '1', displayName: 'foo' }], + isSelected: undefined, + onItemChange + }), + withSelectedFalse = quickRender({ items: [{ id: '1', displayName: 'foo' }], isSelected: false, onItemChange }); + + expect(withSelected.getByRole('checkbox')).toBeChecked(); + expect(withSelectedNull.getByRole('checkbox')).toBeChecked(); + expect(withSelectedUndefined.getByRole('checkbox')).toBeChecked(); + expect(withSelectedFalse.getByRole('checkbox')).not.toBeChecked(); + }); - const items = [{ - id: 1, + it('calls onItemChange when an item checkbox is toggled, passing the new boolean state and the item id', + async function() { + const dataItems = [{ + id: '1', displayName: 'foo' }, { - id: 3, + id: '2', displayName: 'baz' - }], - onItemChangeSelected = jest.fn(), - onItemChangeUnselected = jest.fn(), - selectedComponent = getMounted({ items, onItemChange: onItemChangeSelected }, - { attachTo: selectedContainer }), - unselectedComponent = getMounted({ items, onItemChange: onItemChangeUnselected, isSelected: false }, - { attachTo: unselectedContainer }), - selectedList = selectedComponent.find('.nx-transfer-list__item-list'), - unselectedList = unselectedComponent.find('.nx-transfer-list__item-list'); + }]; + + const user = userEvent.setup(), + onItemChange = jest.fn(), + { rerender, getAllByRole } = render( +
+ +
+ ), + selectedItem = getAllByRole('checkbox'); + + expect(onItemChange).not.toHaveBeenCalled(); - expect(onItemChangeSelected).not.toHaveBeenCalled(); - expect(onItemChangeUnselected).not.toHaveBeenCalled(); + await user.click(selectedItem[0]); + expect(onItemChange).toHaveBeenCalledWith(false, '1'); - (selectedList.find('.nx-transfer-list__checkbox').at(0).getDOMNode() as HTMLElement).click(); + rerender( +
+ +
+ ); - expect(onItemChangeSelected).toHaveBeenCalledWith(false, 1); + await user.click(selectedItem[1]); + expect(onItemChange).toHaveBeenCalledWith(true, '2'); + }); - (unselectedList.find('.nx-transfer-list__checkbox').at(1).getDOMNode() as HTMLElement).click(); - expect(onItemChangeUnselected).toHaveBeenCalledWith(true, 3); + it('contains a footer with the specified footerContent', function() { + const component = quickRender({ footerContent:
content
}), + footerContent = component.queryByTestId('foo'); - selectedContainer.remove(); - unselectedContainer.remove(); + expect(footerContent).toBeInTheDocument(); + expect(footerContent).toHaveTextContent('content'); }); describe('filtering', function() { - const items = [{ - id: 1, + const dataItems = [{ + id: '1', displayName: 'foo' }, { - id: 2, + id: '2', displayName: 'Foo' }, { - id: 3, + id: '3', displayName: 'bar' }, { - id: 4, + id: '4', displayName: <>foo }, { - id: 5, + id: '5', displayName: <>Foo }, { - id: 6, + id: '6', displayName: <>bar }]; - const getComponent = (moreProps: Partial>) => getMounted({ items, ...moreProps }); + const getComponent = (moreProps: Partial>) => renderEl({items: dataItems, ...moreProps})!; it('renders only items which contain the filterValue case-insensitively', function() { - const component = getComponent({ filterValue: 'fo' }); - - expect(component.find('.nx-transfer-list__item').length).toBe(4); - - expect(component.find('.nx-transfer-list__item').at(0)).toHaveText('foo'); - expect(component.find('.nx-transfer-list__item').at(1)).toHaveText('Foo'); - expect(component.find('.nx-transfer-list__item').at(2)).toHaveText('foo'); - expect(component.find('.nx-transfer-list__item').at(3)).toHaveText('Foo'); + const component = getComponent({ filterValue: 'fo' }), + items = component.querySelectorAll('.nx-transfer-list__item'); + + expect(items.length).toBe(4); + expect(items[0]).toHaveTextContent('foo'); + expect(items[1]).toHaveTextContent('Foo'); + expect(items[2]).toHaveTextContent('foo'); + expect(items[3]).toHaveTextContent('Foo'); }); it('renders only items that match the filterValue according to the filterFn when specified', function() { const component = getComponent({ - filterValue: 'fo', - filterFn: includes // case sensitive inclusion - }); - - expect(component.find('.nx-transfer-list__item').length).toBe(2); - - expect(component.find('.nx-transfer-list__item').at(0)).toHaveText('foo'); - expect(component.find('.nx-transfer-list__item').at(1)).toHaveText('foo'); + filterValue: 'fo', + filterFn: includes // case sensitive inclusion + }), + items = component.querySelectorAll('.nx-transfer-list__item'); + + expect(items.length).toBe(2); + expect(items[0]).toHaveTextContent('foo'); + expect(items[1]).toHaveTextContent('foo'); }); - it('passes onMoveAll a set containing ids of visible items if filterValue is set', function() { - const onMoveAll = jest.fn(), - component = getComponent({ filterValue: 'fo', onMoveAll, showMoveAll: true }); + it('passes onMoveAll a set containing ids of visible items if filterValue is set', async function() { + const user = userEvent.setup(), + onMoveAll = jest.fn(), + { getByRole } = quickRender({ items: dataItems, filterValue: 'fo', onMoveAll, showMoveAll: true }); expect(onMoveAll).not.toHaveBeenCalled(); - component.find('.nx-transfer-list__move-all').simulate('click'); + const button = getByRole('button', { name: /remove all/i }); + await user.click(button); - expect(onMoveAll).toHaveBeenCalledWith([1, 2, 4, 5]); + expect(onMoveAll).toHaveBeenCalledWith(['1', '2', '4', '5']); }); }); describe('reordering', function() { - it('renders move up and down buttons inside .nx-transfer-list__item in the correct state', function() { - const items = [{ - id: 1, - displayName: 'top' + it('renders move up and down buttons inside .nx-transfer-list__item when allowReordering is true', + async function() { + const dataItems = [{ + id: '1', + displayName: 'foo' }, { - id: 3, - displayName: 'middle' + id: '2', + displayName: 'bar' }, { - id: 4, - displayName: 'bottom' - }], - component = getMounted({ allowReordering: true, items }), - list = component.find('.nx-transfer-list__item-list'); - - const firstItem = list.find('.nx-transfer-list__item').at(0), - secondItem = list.find('.nx-transfer-list__item').at(1), - thirdItem = list.find('.nx-transfer-list__item').at(2), - firstItemMoveUpButton = firstItem.find('.nx-btn').at(0), - firstItemMoveDownButton = firstItem.find('.nx-btn').at(1), - secondItemMoveUpButton = secondItem.find('.nx-btn').at(0), - secondItemMoveDownButton = secondItem.find('.nx-btn').at(1), - thirdItemMoveUpButton = thirdItem.find('.nx-btn').at(0), - thirdItemMoveDownButton = thirdItem.find('.nx-btn').at(1); - - expect(firstItem).toExist(); - expect(firstItemMoveUpButton).toExist(); - expect(firstItemMoveDownButton).toExist(); - expect(firstItemMoveUpButton).toHaveClassName('disabled'); - expect(firstItemMoveDownButton).not.toHaveClassName('disabled'); - - expect(secondItem).toExist(); - expect(secondItemMoveUpButton).toExist(); - expect(secondItemMoveDownButton).toExist(); - expect(secondItemMoveUpButton).not.toHaveClassName('disabled'); - expect(secondItemMoveDownButton).not.toHaveClassName('disabled'); - - expect(thirdItem).toExist(); - expect(thirdItemMoveUpButton).toExist(); - expect(thirdItemMoveDownButton).toExist(); - expect(thirdItemMoveUpButton).not.toHaveClassName('disabled'); - expect(thirdItemMoveDownButton).toHaveClassName('disabled'); + id: '3', + displayName: 'foobar' + }]; + + const { container, rerender } = quickRender({ allowReordering: true, items: dataItems}), + middleItem = container.querySelectorAll('.nx-transfer-list__item')[1], + buttons = within(middleItem).getAllByRole('button', { hidden: true }); + + await runTimers(); + + // assert both a move up and move down button are present + expect(buttons.length).toBe(2); + expect(buttons[0]).toHaveAccessibleName('Move Up'); + expect(buttons[1]).toHaveAccessibleName('Move Down'); + + rerender(); + expect(buttons[0]).not.toBeInTheDocument(); + expect(buttons[1]).not.toBeInTheDocument(); + + rerender(); + expect(buttons[0]).not.toBeInTheDocument(); + expect(buttons[1]).not.toBeInTheDocument(); + + rerender( + + ); + expect(buttons[0]).not.toBeInTheDocument(); + expect(buttons[1]).not.toBeInTheDocument(); + }); + + it('sets aria-disabled to true on the top item\'s move up button, and the bottom item\'s move down button', + function() { + const dataItems = [{ + id: '1', + displayName: 'foo' + }, { + id: '2', + displayName: 'bar' + }]; + + const component = renderEl({ allowReordering: true, items: dataItems })!; + + const topItem = component.querySelectorAll('.nx-transfer-list__item')[0], + topButtons = within(topItem).getAllByRole('button', { hidden: true }), + bottomItem = component.querySelectorAll('.nx-transfer-list__item')[1], + bottomButtons = within(bottomItem).getAllByRole('button', { hidden: true }); + + // assert there are two buttons present in each item + expect(topButtons.length).toBe(2); + expect(bottomButtons.length).toBe(2); + + // assert the topmost item's moveUp button and bottommost item's moveDown button are disabled + expect(topButtons[0]).toHaveAttribute('aria-disabled', 'true'); + expect(topButtons[1]).not.toHaveAttribute('aria-disabled', 'true'); + expect(bottomButtons[0]).not.toHaveAttribute('aria-disabled', 'true'); + expect(bottomButtons[1]).toHaveAttribute('aria-disabled', 'true'); + }); + + it('sets the correct title on tooltip based on button\'s location and direction', async function() { + const dataItems = [{ + id: '1', + displayName: 'foo' + }, { + id: '2', + displayName: 'bar' + }, { + id: '3', + displayName: 'foobar' + }]; + + const user = userEvent.setup(), + onReorderItem = jest.fn(), + component = renderEl({items: dataItems, allowReordering: true, onReorderItem})!, + items = component.querySelectorAll('.nx-transfer-list__item'), + firstItemBtns = within(items[0]).getAllByRole('button', { hidden: true }), + lastItemBtns = within(items[2]).getAllByRole('button', { hidden: true }); + + // first item move up button + await user.hover(firstItemBtns[0]); + await runTimers(); + let tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toBeInTheDocument(); + expect(tooltip).toHaveTextContent('Move Up (disabled)'); + + // first item move down button + await user.hover(firstItemBtns[1]); + await runTimers(); + tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveTextContent('Move Down'); + + // last item move up button + await user.hover(lastItemBtns[0]); + await runTimers(); + tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveTextContent('Move Up'); + + // last item move down button + await user.hover(lastItemBtns[1]); + await runTimers(); + tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveTextContent('Move Down (disabled)'); }); - }); - it('passes onReorderItem with id and direction when move up or down button is clicked', function() { - const items = [{ - id: 1, - displayName: 'a' - }, { - id: 2, - displayName: 'b' - }, { - id: 3, - displayName: 'c' - }]; - - const onReorderItem = jest.fn(), - component = getMounted({ allowReordering: true, items, onReorderItem }), - list = component.find('.nx-transfer-list__item-list'); - - expect(onReorderItem).not.toHaveBeenCalled(); - - const firstItem = list.find('.nx-transfer-list__item').at(0), - secondItem = list.find('.nx-transfer-list__item').at(1); - const moveDownButton = firstItem.find('.nx-btn').at(1); - const moveUpButton = secondItem.find('.nx-btn').at(0); - - expect(moveDownButton).toExist(); - expect(moveUpButton).toExist(); - - moveDownButton.simulate('click'); - - expect(onReorderItem).toHaveBeenCalledWith(1, 1); - - moveUpButton.simulate('click'); - - expect(onReorderItem).toHaveBeenCalledWith(2, -1); - }); + it('passes onReorderItem the item id and direction when move up or down button is clicked', async function() { + const dataItems = [{ + id: '1', + displayName: 'foo' + }, { + id: '2', + displayName: 'bar' + }, { + id: '3', + displayName: 'foobar' + }]; + + const user = userEvent.setup(), + onReorderItem = jest.fn(), + component = renderEl({ allowReordering: true, items: dataItems, onReorderItem })!; + + const topItem = component.querySelectorAll('.nx-transfer-list__item')[0] as HTMLElement, + bottomItem = component.querySelectorAll('.nx-transfer-list__item')[2] as HTMLElement, + moveDownButton = within(topItem).getAllByRole('button', { hidden: true })[1], + moveUpButton = within(bottomItem).getAllByRole('button', { hidden: true })[0]; + + expect(onReorderItem).not.toHaveBeenCalled(); + + await user.click(moveDownButton); + expect(onReorderItem).toHaveBeenCalledWith('1', 1); + + await user.click(moveUpButton); + expect(onReorderItem).toHaveBeenCalledWith('3', -1); + }); - it('set the move up and down icon button with faArrowUp and faArrowDown respectively', - function() { - const items = [{ - id: 1, - displayName: 'a' + describe('when filtered', function() { + it('disables move up and down buttons', async function() { + const dataItems = [{ + id: '1', + displayName: 'foo' }, { - id: 2, - displayName: 'b' + id: '2', + displayName: 'bar' }, { - id: 3, - displayName: 'c' + id: '3', + displayName: 'foobar' }]; - const component = getMounted({ allowReordering: true, items }), - listItem = component.find('.nx-transfer-list__item').at(0); - - const buttons = listItem.find('.nx-transfer-list__button-bar .nx-btn'); - const moveUpButton = buttons.at(0).find(NxFontAwesomeIcon); - const moveDownButton = buttons.at(1).find(NxFontAwesomeIcon); + const user = userEvent.setup(), + onReorderItem = jest.fn(), + component = renderEl({ items: dataItems, filterValue: 'fo', allowReordering: true, onReorderItem })!, + items = component.querySelectorAll('.nx-transfer-list__item'); - expect(moveUpButton).toHaveProp('icon', faArrowUp); - expect(moveDownButton).toHaveProp('icon', faArrowDown); - } - ); + // confirm filtering + expect(items.length).toBe(2); + expect(items[0]).toHaveTextContent('foo'); + expect(items[1]).toHaveTextContent('foobar'); - it('sets move up and down buttons to disabled state when items are filtered', function() { - const items = [{ - id: 1, - displayName: 'a1' - }, { - id: 2, - displayName: 'b1' - }, { - id: 3, - displayName: 'c1' - }, - { - id: 4, - displayName: 'd' - }]; - - const onReorderItem = jest.fn(), - component = getMounted({ filterValue: '1', allowReordering: true, items, onReorderItem }), - list = component.find('.nx-transfer-list__item-list'); - - expect(onReorderItem).not.toHaveBeenCalled(); - - const firstItem = list.find('.nx-transfer-list__item').at(0); - const secondItem = list.find('.nx-transfer-list__item').at(1); - const lastItem = list.find('.nx-transfer-list__item').at(2); - - const firstMoveUpButton = firstItem.find('.nx-btn').at(0); - const lastMoveDownButton = lastItem.find('.nx-btn').at(1); - - const middleMoveUpButton = secondItem.find('.nx-btn').at(0); - const middleMoveDownButton = secondItem.find('.nx-btn').at(1); + const topItem = items[0], + bottomItem = items[1], + topItemButtons = within(topItem).getAllByRole('button', { hidden: true }), + bottomItemButtons = within(bottomItem).getAllByRole('button', { hidden: true }); - expect(firstMoveUpButton).toHaveClassName('disabled'); - expect(lastMoveDownButton).toHaveClassName('disabled'); - expect(middleMoveUpButton).toHaveClassName('disabled'); - expect(middleMoveDownButton).toHaveClassName('disabled'); + expect(onReorderItem).not.toHaveBeenCalled(); + expect(topItemButtons[0]).toHaveAttribute('aria-disabled', 'true'); + expect(topItemButtons[1]).toHaveAttribute('aria-disabled', 'true'); + expect(bottomItemButtons[0]).toHaveAttribute('aria-disabled', 'true'); + expect(bottomItemButtons[1]).toHaveAttribute('aria-disabled', 'true'); - firstMoveUpButton.simulate('click'); - lastMoveDownButton.simulate('click'); + await user.click(topItemButtons[1]); + expect(onReorderItem).not.toHaveBeenCalled(); - middleMoveUpButton.simulate('click'); - middleMoveDownButton.simulate('click'); - - expect(onReorderItem).not.toHaveBeenCalled(); - }); - - it('sets the correct button title based on location, direction, and when filtered', function() { - const items = [{ - id: 1, - displayName: 'a1' - }, { - id: 2, - displayName: 'b1' - }, { - id: 3, - displayName: 'c1' - }, { - id: 4, - displayName: 'c' - }]; - - const onReorderItem = jest.fn(), - filteredComponent = getMounted({ filterValue: '1', allowReordering: true, items, onReorderItem }), - component = getMounted({ allowReordering: true, items, onReorderItem }), - filteredList = filteredComponent.find('.nx-transfer-list__item-list'), - list = component.find('.nx-transfer-list__item-list'); - - const secondItem = list.find('.nx-transfer-list__item').at(1); - const filteredSecondItem = filteredList.find('.nx-transfer-list__item').at(1); - - const moveUpButtonTooltip = secondItem.find('.nx-transfer-list__button-bar').find(NxTooltip).at(0); - const moveDownButtonTooltip = secondItem.find('.nx-transfer-list__button-bar').find(NxTooltip).at(1); - - const filteredMoveUpButtonTooltip = filteredSecondItem.find('.nx-transfer-list__button-bar').find(NxTooltip).at(0); - const filteredMoveDownButtonTooltip = - filteredSecondItem.find('.nx-transfer-list__button-bar').find(NxTooltip).at(1); - - const itemTooltip = secondItem.find(NxTooltip).at(1); - const filteredItemTooltip = filteredSecondItem.find(NxTooltip).at(1); - - expect(moveUpButtonTooltip).toHaveProp('title', 'Move Up'); - expect(moveDownButtonTooltip).toHaveProp('title', 'Move Down'); + await user.click(topItemButtons[0]); + expect(onReorderItem).not.toHaveBeenCalled(); + }); - expect(filteredMoveUpButtonTooltip).toHaveProp('title', ''); - expect(filteredMoveDownButtonTooltip).toHaveProp('title', ''); + it('sets the correct title on tooltip', async function() { + const dataItems = [{ + id: '1', + displayName: 'foo' + }, { + id: '2', + displayName: 'bar' + }, { + id: '3', + displayName: 'foobar' + }]; - expect(filteredItemTooltip).toHaveProp('title', 'Reordering is disabled when filtered'); - expect(itemTooltip).toHaveProp('title', ''); + const user = userEvent.setup(), + onReorderItem = jest.fn(), + component = renderEl({items: dataItems, filterValue: 'fo', allowReordering: true, onReorderItem})!, + items = component.querySelectorAll('.nx-transfer-list__item'), + firstItemBtns = within(items[0]).getAllByRole('button', { hidden: true }), + lastItemBtns = within(items[1]).getAllByRole('button', { hidden: true }); + + // first item move up button + await user.hover(firstItemBtns[0]); + await runTimers(); + let tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toBeInTheDocument(); + expect(tooltip).toHaveTextContent('Reordering is disabled when filtered'); + + // first item move down button + await user.hover(firstItemBtns[1]); + await runTimers(); + tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveTextContent('Reordering is disabled when filtered'); + + // last item move up button + await user.hover(lastItemBtns[0]); + await runTimers(); + tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveTextContent('Reordering is disabled when filtered'); + + // last item move down button + await user.hover(lastItemBtns[1]); + await runTimers(); + tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveTextContent('Reordering is disabled when filtered'); + }); + }); }); }); diff --git a/lib/src/components/NxTree/NxTreeItem.tsx b/lib/src/components/NxTree/NxTreeItem.tsx index 997caf8031..edc777fdea 100644 --- a/lib/src/components/NxTree/NxTreeItem.tsx +++ b/lib/src/components/NxTree/NxTreeItem.tsx @@ -66,6 +66,10 @@ export default function NxTreeItem(props: ItemProps) { focusedChild: (focusState === 'children') && ref.current?.querySelector('.nx-tree') || null }; + function getLabelElement() { + return ref.current?.querySelector(':scope > .nx-tree__item-label'); + } + function focusSelf() { setFocusState('self'); @@ -73,7 +77,8 @@ export default function NxTreeItem(props: ItemProps) { // leave actual focus alone and just make this item the part of the tree that is _focusable_ const treeRoot = parentKeyNavContext?.getTreeRoot(); if (treeRoot?.contains(document.activeElement)) { - ref.current?.focus(); + ref.current?.focus({ preventScroll: true }); + getLabelElement()?.scrollIntoView({ block: 'nearest', inline: 'nearest' }); } } @@ -125,7 +130,7 @@ export default function NxTreeItem(props: ItemProps) { // Establish a11y label for this item useEffect(function() { - setLabelId(ref.current?.querySelector(':scope > .nx-tree__item-label')?.id || null); + setLabelId(getLabelElement()?.id || null); }, []); function onKeyDown(evt: KeyboardEvent) { diff --git a/lib/src/components/NxTree/__tests__/NxTree.test.tsx b/lib/src/components/NxTree/__tests__/NxTree.test.tsx index 42b51951e4..916aafa848 100644 --- a/lib/src/components/NxTree/__tests__/NxTree.test.tsx +++ b/lib/src/components/NxTree/__tests__/NxTree.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow, mount } from 'enzyme'; +import 'jest-enzyme'; import NxTree from '../NxTree'; import NxTreeItem from '../NxTreeItem'; diff --git a/lib/src/components/NxTree/__tests__/NxTreeItem.test.tsx b/lib/src/components/NxTree/__tests__/NxTreeItem.test.tsx index 575ef6363d..2722188712 100644 --- a/lib/src/components/NxTree/__tests__/NxTreeItem.test.tsx +++ b/lib/src/components/NxTree/__tests__/NxTreeItem.test.tsx @@ -7,6 +7,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import { faMinusSquare, faPlusSquare } from '@fortawesome/free-regular-svg-icons'; import NxFontAwesomeIcon from '../../NxFontAwesomeIcon/NxFontAwesomeIcon'; diff --git a/lib/src/components/NxTree/__tests__/NxTreeItemLabel.test.tsx b/lib/src/components/NxTree/__tests__/NxTreeItemLabel.test.tsx index 4a89d17c74..dcdf4e74e1 100644 --- a/lib/src/components/NxTree/__tests__/NxTreeItemLabel.test.tsx +++ b/lib/src/components/NxTree/__tests__/NxTreeItemLabel.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount } from 'enzyme'; +import 'jest-enzyme'; import TreeKeyNavContext from '../TreeKeyNavContext'; import NxTreeItemLabel from '../NxTreeItemLabel'; diff --git a/lib/src/components/NxTree/stateful/__tests__/NxTreeStatefulItem.test.tsx b/lib/src/components/NxTree/stateful/__tests__/NxTreeStatefulItem.test.tsx index 68802de125..5377f2a137 100644 --- a/lib/src/components/NxTree/stateful/__tests__/NxTreeStatefulItem.test.tsx +++ b/lib/src/components/NxTree/stateful/__tests__/NxTreeStatefulItem.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import { getShallowComponent } from '../../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxTreeItem from '../../NxTreeItem'; import NxTreeStatefulItem from '../NxTreeStatefulItem'; diff --git a/lib/src/components/NxVulnerabilityDetails/__tests__/NxVulnerabilityDetails.test.tsx b/lib/src/components/NxVulnerabilityDetails/__tests__/NxVulnerabilityDetails.test.tsx index 02a8bf8837..c4b69b5c7d 100644 --- a/lib/src/components/NxVulnerabilityDetails/__tests__/NxVulnerabilityDetails.test.tsx +++ b/lib/src/components/NxVulnerabilityDetails/__tests__/NxVulnerabilityDetails.test.tsx @@ -7,6 +7,7 @@ import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; import { getMountedComponent, getShallowComponent } from '../../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import NxFontAwesomeIcon from '../../NxFontAwesomeIcon/NxFontAwesomeIcon'; import NxVulnerabilityDetails from '../NxVulnerabilityDetails'; import { ReferenceLink, SeverityScore, VulnerabilityDetails } from '../types'; diff --git a/lib/src/components/NxVulnerabilityDetails/__tests__/RenderMarkdown.test.tsx b/lib/src/components/NxVulnerabilityDetails/__tests__/RenderMarkdown.test.tsx index 4675d381f1..da9ae7f350 100644 --- a/lib/src/components/NxVulnerabilityDetails/__tests__/RenderMarkdown.test.tsx +++ b/lib/src/components/NxVulnerabilityDetails/__tests__/RenderMarkdown.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { render, shallow, mount } from 'enzyme'; +import 'jest-enzyme'; import RenderMarkdown from '../details/RenderMarkdown'; diff --git a/lib/src/components/__tests__/SimpleComponents.test.tsx b/lib/src/components/__tests__/SimpleComponents.test.tsx index d259d912a8..2c602e8a9c 100644 --- a/lib/src/components/__tests__/SimpleComponents.test.tsx +++ b/lib/src/components/__tests__/SimpleComponents.test.tsx @@ -5,6 +5,7 @@ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/. */ import { shallow } from 'enzyme'; +import 'jest-enzyme'; import React from 'react'; import { diff --git a/lib/src/setupTests.ts b/lib/src/setupTests.ts index 71262ae823..d0bf42dbe5 100644 --- a/lib/src/setupTests.ts +++ b/lib/src/setupTests.ts @@ -6,9 +6,26 @@ */ /// -import 'jest-enzyme'; - import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; +import { runTimers } from './__testutils__/rtlUtils'; Enzyme.configure({ adapter: new Adapter() }); + +beforeEach(function() { + // because so many of our components rely on NxTooltip which initializes asynchronously. If some tests + // use fake timers and some don't it can cause weird inter-test timing bugs + jest.useFakeTimers(); + + // JSDOM is missing this function. https://github.com/jsdom/jsdom/issues/3002 + Range.prototype.getBoundingClientRect = jest.fn().mockReturnValue({ + bottom: 0, + height: 0, + left: 0, + right: 0, + top: 0, + width: 0 + } as DOMRect); +}); + +afterEach(runTimers); diff --git a/lib/src/util/__tests__/idUtil.test.tsx b/lib/src/util/__tests__/idUtil.test.tsx index f54db45fa2..c33804f1a2 100644 --- a/lib/src/util/__tests__/idUtil.test.tsx +++ b/lib/src/util/__tests__/idUtil.test.tsx @@ -10,6 +10,7 @@ import ReactDOMServer from 'react-dom/server'; import { getUniqueId, useUniqueId } from '../idUtil'; import { times } from 'ramda'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import NxStableUniqueIdContext from '../../components/NxStableUniqueIdContext/NxStableUniqueIdContext'; describe('idUtil', function() { diff --git a/lib/src/util/__tests__/reactUtil.test.tsx b/lib/src/util/__tests__/reactUtil.test.tsx index cadf3187ac..77b8ff8dd1 100644 --- a/lib/src/util/__tests__/reactUtil.test.tsx +++ b/lib/src/util/__tests__/reactUtil.test.tsx @@ -6,6 +6,7 @@ */ import React, { ReactElement, ReactNode } from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import { ensureElement, ensureStartEndElements } from '../reactUtil'; diff --git a/lib/src/util/__tests__/useFuzzyFilter.test.tsx b/lib/src/util/__tests__/useFuzzyFilter.test.tsx index b091864e5b..f26ece816b 100644 --- a/lib/src/util/__tests__/useFuzzyFilter.test.tsx +++ b/lib/src/util/__tests__/useFuzzyFilter.test.tsx @@ -9,6 +9,7 @@ import React, {FunctionComponent} from 'react'; import Fuse from 'fuse.js'; import {getShallowComponent} from '../../__testutils__/enzymeUtils'; +import 'jest-enzyme'; import useFuzzyFilter from '../useFuzzyFilter'; interface Entry { diff --git a/lib/src/util/__tests__/useToggle.test.tsx b/lib/src/util/__tests__/useToggle.test.tsx index 65ccdeeb4b..2fb8792e58 100644 --- a/lib/src/util/__tests__/useToggle.test.tsx +++ b/lib/src/util/__tests__/useToggle.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { shallow } from 'enzyme'; +import 'jest-enzyme'; import useToggle from '../useToggle'; diff --git a/lib/src/util/__tests__/withClass.test.tsx b/lib/src/util/__tests__/withClass.test.tsx index 828ff345b4..48cacdb262 100644 --- a/lib/src/util/__tests__/withClass.test.tsx +++ b/lib/src/util/__tests__/withClass.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { mount, shallow } from 'enzyme'; +import 'jest-enzyme'; import withClass from '../withClass'; import { getShallowComponent } from '../../__testutils__/enzymeUtils'; import NxOverflowTooltip from '../../components/NxTooltip/NxOverflowTooltip';