11import "@testing-library/jest-dom" ;
22import { render } from "@testing-library/react" ;
33import userEvent , { UserEvent } from "@testing-library/user-event" ;
4- import { createElement } from "react" ;
4+ import { createElement , forwardRef } from "react" ;
55import { ModalProps } from "react-overlays/esm/Modal" ;
66import { Image , ImageProps } from "../Image/Image" ;
7- import { Lightbox } from "../Lightbox" ;
87
98jest . mock ( "../../assets/ic24-close.svg" , ( ) => "close-button-icon-svg" ) ;
109
11- jest . mock ( "react-overlays/Modal" , ( ) => ( props : ModalProps ) => {
12- const MockName = "react-overlays-modal-mock" ;
13- // The backdrop is rendered somewhere else in a portal, but for testing sake we put it here since we also mock.
14- const BackdropMockName = "react-overlays-modal-backdrop-mock" ;
15- return (
16- // @ts -expect-error lower case custom name to make clear it's a mock
17- < MockName { ...props } >
18- { props . children }
19- { /* @ts -expect-error lower case custom name to make clear it's a mock */ }
20- < BackdropMockName > { props . renderBackdrop ?.( { onClick : jest . fn ( ) , ref : jest . fn ( ) } ) } </ BackdropMockName >
21- </ MockName >
22- ) ;
23- } ) ;
10+ jest . mock ( "react-overlays/Modal" , ( ) =>
11+ forwardRef ( ( props : ModalProps , ref ) => {
12+ if ( ! props . show ) return null ;
13+ const MockName = "react-overlays-modal-mock" ;
14+ // The backdrop is rendered somewhere else in a portal, but for testing sake we put it here since we also mock.
15+ const BackdropMockName = "react-overlays-modal-backdrop-mock" ;
16+ return (
17+ // @ts -expect-error lower case custom name to make clear it's a mock
18+ < MockName { ...props } ref = { ref } >
19+ { props . children }
20+ { /* @ts -expect-error lower case custom name to make clear it's a mock */ }
21+ < BackdropMockName > { props . renderBackdrop ?.( { onClick : jest . fn ( ) , ref : jest . fn ( ) } ) } </ BackdropMockName >
22+ </ MockName >
23+ ) ;
24+ } )
25+ ) ;
2426
2527const imageProps : ImageProps = {
2628 class : "" ,
@@ -71,6 +73,12 @@ const iconProps: ImageProps = {
7173} ;
7274
7375describe ( "Image" , ( ) => {
76+ let user : UserEvent ;
77+
78+ beforeEach ( ( ) => {
79+ user = userEvent . setup ( ) ;
80+ } ) ;
81+
7482 it ( "renders the structure with an image" , ( ) => {
7583 const image = render ( < Image { ...imageProps } /> ) ;
7684 expect ( image . asFragment ( ) ) . toMatchSnapshot ( ) ;
@@ -101,185 +109,164 @@ describe("Image", () => {
101109 } ) ;
102110
103111 describe ( "when the onClickType is action" , ( ) => {
104- it ( "calls the onClick when clicking on an image" , ( ) => {
112+ it ( "calls the onClick when clicking on an image" , async ( ) => {
105113 const onClickMock = jest . fn ( ) ;
106- const imageRender = render ( < Image { ...imageProps } onClick = { onClickMock } onClickType = "action" /> ) ;
107-
108- const image = imageRender . find ( "img" ) ;
109- expect ( image ) . toHaveLength ( 1 ) ;
110-
111- image . simulate ( "click" ) ;
114+ const { getByRole } = render ( < Image { ...imageProps } onClick = { onClickMock } onClickType = "action" /> ) ;
115+ const image = getByRole ( "button" ) ;
116+ expect ( image ) . toBeInTheDocument ( ) ;
117+ await user . click ( image ) ;
112118 expect ( onClickMock ) . toHaveBeenCalled ( ) ;
113119 } ) ;
114120
115121 it ( "has tabindex if there is an action with OnClick" , ( ) => {
116122 const onClickMock = jest . fn ( ) ;
117- const imageRender = render (
123+ const { getByRole } = render (
118124 < Image { ...imageProps } onClick = { onClickMock } onClickType = "action" tabIndex = { 1 } />
119125 ) ;
120- const image = imageRender . find ( "img" ) ;
121-
122- expect ( image . prop ( "tabIndex" ) ) . toBeDefined ( ) ;
123- expect ( image . prop ( "tabIndex" ) ) . toBe ( 1 ) ;
126+ const image = getByRole ( "button" ) ;
127+ expect ( image . tabIndex ) . toBe ( 1 ) ;
124128 } ) ;
125129
126130 it ( "has no tabindex if there is no action with OnClick" , ( ) => {
127- const imageRender = render ( < Image { ...imageProps } /> ) ;
128- const image = imageRender . find ( "img" ) ;
129-
130- expect ( image . prop ( "tabIndex" ) ) . toBeUndefined ( ) ;
131+ const { getByRole } = render ( < Image { ...imageProps } /> ) ;
132+ const image = getByRole ( "img" ) ;
133+ expect ( image . tabIndex ) . toBe ( - 1 ) ;
131134 } ) ;
132135
133- it ( "calls the onClick when clicking on a glyph icon" , ( ) => {
136+ it ( "calls the onClick when clicking on a glyph icon" , async ( ) => {
134137 const onClickMock = jest . fn ( ) ;
135- const imageRender = render ( < Image { ...glyphiconProps } onClick = { onClickMock } onClickType = "action" /> ) ;
136-
137- const glyphicon = imageRender . find ( "span" ) ;
138- expect ( glyphicon ) . toHaveLength ( 1 ) ;
139-
140- glyphicon . simulate ( "click" ) ;
138+ const { getByRole } = render ( < Image { ...glyphiconProps } onClick = { onClickMock } onClickType = "action" /> ) ;
139+ const icon = getByRole ( "button" ) ;
140+ expect ( icon ) . toBeInTheDocument ( ) ;
141+ await user . click ( icon ) ;
141142 expect ( onClickMock ) . toHaveBeenCalled ( ) ;
142143 } ) ;
143144
144- it ( "calls the onClick when clicking on an icon" , ( ) => {
145+ it ( "calls the onClick when clicking on an icon" , async ( ) => {
145146 const onClickMock = jest . fn ( ) ;
146- const imageRender = render ( < Image { ...iconProps } onClick = { onClickMock } onClickType = "action" /> ) ;
147-
148- const glyphicon = imageRender . find ( "span" ) ;
149- expect ( glyphicon ) . toHaveLength ( 1 ) ;
150-
151- glyphicon . simulate ( "click" ) ;
147+ const { getByRole } = render ( < Image { ...iconProps } onClick = { onClickMock } onClickType = "action" /> ) ;
148+ const icon = getByRole ( "button" ) ;
149+ expect ( icon ) . toBeInTheDocument ( ) ;
150+ await user . click ( icon ) ;
152151 expect ( onClickMock ) . toHaveBeenCalled ( ) ;
153152 } ) ;
154153 } ) ;
155154
156155 describe ( "when the onClickType is enlarge" , ( ) => {
157- it ( "shows a lightbox when the user clicks on the image" , ( ) => {
158- const imageRender = render ( < Image { ...imageProps } onClickType = "enlarge" /> ) ;
159- expect ( imageRender . find ( Lightbox ) ) . toHaveLength ( 0 ) ;
160-
161- const image = imageRender . find ( "img" ) ;
162- expect ( image ) . toHaveLength ( 1 ) ;
163-
164- image . simulate ( "click" ) ;
165- expect ( imageRender . find ( Lightbox ) ) . toHaveLength ( 1 ) ;
156+ it ( "shows a lightbox when the user clicks on the image" , async ( ) => {
157+ const { container, getByRole } = render ( < Image { ...imageProps } onClickType = "enlarge" /> ) ;
158+ expect ( container . querySelector ( ".mx-image-viewer-lightbox" ) ) . not . toBeInTheDocument ( ) ;
159+ const image = getByRole ( "button" ) ;
160+ expect ( image ) . toBeInTheDocument ( ) ;
161+ await userEvent . click ( image ) ;
162+ const lightbox = container . querySelector ( ".mx-image-viewer-lightbox-backdrop" ) ;
163+ expect ( lightbox ) . toBeInTheDocument ( ) ;
166164 } ) ;
167165
168- it ( "closes the lightbox when the user clicks on the close button after opening it" , ( ) => {
169- const imageRender = render ( < Image { ...imageProps } onClickType = "enlarge" /> ) ;
170-
171- const image = imageRender . find ( "img" ) ;
172- expect ( image ) . toHaveLength ( 1 ) ;
173-
174- image . simulate ( "click" ) ;
175- expect ( imageRender . find ( Lightbox ) ) . toHaveLength ( 1 ) ;
176-
177- const closeButton = imageRender . find ( "button" ) ;
178- expect ( closeButton ) . toHaveLength ( 1 ) ;
179- closeButton . simulate ( "click" ) ;
180-
181- expect ( imageRender . find ( Lightbox ) ) . toHaveLength ( 0 ) ;
166+ it ( "closes the lightbox when the user clicks on the close button after opening it" , async ( ) => {
167+ const { container, getByRole } = render ( < Image { ...imageProps } onClickType = "enlarge" /> ) ;
168+ const image = getByRole ( "button" ) ;
169+ expect ( image ) . toBeInTheDocument ( ) ;
170+ await userEvent . click ( image ) ;
171+ const lightbox = container . querySelector ( ".mx-image-viewer-lightbox-backdrop" ) ;
172+ expect ( lightbox ) . toBeInTheDocument ( ) ;
173+ const closeButton = container . querySelector ( ".close-button" ) ;
174+ expect ( closeButton ) . toBeInTheDocument ( ) ;
175+ await userEvent . click ( closeButton ! ) ;
176+ expect ( lightbox ) . not . toBeInTheDocument ( ) ;
182177 } ) ;
183178 } ) ;
184179
185- it ( "does not trigger on clicks from containers if clicked on the image" , ( ) => {
180+ it ( "does not trigger on clicks from containers if clicked on the image" , async ( ) => {
186181 const onClickOuterMock = jest . fn ( ) ;
187182 const onClickImageMock = jest . fn ( ) ;
188- const imageRender = render (
183+ const { getByRole } = render (
189184 < div onClick = { onClickOuterMock } >
190185 < Image { ...imageProps } onClickType = "action" onClick = { onClickImageMock } />
191186 </ div >
192187 ) ;
193-
194- const image = imageRender . find ( "img" ) ;
195- expect ( image ) . toHaveLength ( 1 ) ;
196-
197- image . simulate ( "click" ) ;
188+ const image = getByRole ( "button" ) ;
189+ expect ( image ) . toBeInTheDocument ( ) ;
190+ await user . click ( image ) ;
198191 expect ( onClickImageMock ) . toHaveBeenCalledTimes ( 1 ) ;
199192 expect ( onClickOuterMock ) . not . toHaveBeenCalled ( ) ;
200193 } ) ;
201194
202195 describe ( "when there is an accessibility alt text" , ( ) => {
203196 it ( "is set properly on an image" , ( ) => {
204- const imageRender = render ( < Image { ...imageProps } altText = "this is an awesome image" /> ) ;
205- const image = imageRender . find ( "img" ) ;
206- expect ( image . prop ( "alt" ) ) . toBe ( "this is an awesome image" ) ;
197+ const { getByRole } = render ( < Image { ...imageProps } altText = "this is an awesome image" /> ) ;
198+ const image = getByRole ( "img" ) ;
199+ expect ( image ) . toHaveAttribute ( "alt" , "this is an awesome image" ) ;
207200 } ) ;
208201
209202 it ( "is set properly on a glyphicon" , ( ) => {
210- const imageRender = render ( < Image { ...glyphiconProps } altText = "this is an awesome glyphicon" /> ) ;
211- const image = imageRender . find ( "span ") ;
212- expect ( image . prop ( "aria-label" ) ) . toBe ( "this is an awesome glyphicon" ) ;
213- expect ( image . prop ( "role" ) ) . toBe ( "img" ) ;
203+ const { getByRole } = render ( < Image { ...glyphiconProps } altText = "this is an awesome glyphicon" /> ) ;
204+ const icon = getByRole ( "img ") ;
205+ expect ( icon ) . toHaveAttribute ( "aria-label" , "this is an awesome glyphicon" ) ;
206+ expect ( icon ) . toHaveAttribute ( "role" , "img" ) ;
214207 } ) ;
215208
216209 it ( "is set properly on an icon" , ( ) => {
217- const imageRender = render ( < Image { ...iconProps } altText = "this is an awesome icon" /> ) ;
218- const image = imageRender . find ( "span ") ;
219- expect ( image . prop ( "aria-label" ) ) . toBe ( "this is an awesome icon" ) ;
220- expect ( image . prop ( "role" ) ) . toBe ( "img" ) ;
210+ const { getByRole } = render ( < Image { ...iconProps } altText = "this is an awesome icon" /> ) ;
211+ const icon = getByRole ( "img ") ;
212+ expect ( icon ) . toHaveAttribute ( "aria-label" , "this is an awesome icon" ) ;
213+ expect ( icon ) . toHaveAttribute ( "role" , "img" ) ;
221214 } ) ;
222215 } ) ;
223216
224217 describe ( "when there is no accessibility alt text" , ( ) => {
225218 it ( "nothing is set on an image" , ( ) => {
226- const imageRender = render ( < Image { ...imageProps } /> ) ;
227- const image = imageRender . find ( "img" ) ;
228- expect ( image . prop ( "alt" ) ) . toBe ( undefined ) ;
219+ const { getByRole } = render ( < Image { ...imageProps } /> ) ;
220+ const image = getByRole ( "img" ) ;
221+ expect ( image ) . not . toHaveAttribute ( "alt" ) ;
229222 } ) ;
230223
231224 it ( "nothing is set on a glyphicon" , ( ) => {
232- const imageRender = render ( < Image { ...glyphiconProps } /> ) ;
233- const image = imageRender . find ( "span" ) ;
234- expect ( image ) . not . toHaveProperty ( "aria-label" ) ;
235- expect ( image ) . not . toHaveProperty ( "role" ) ;
225+ const { getByRole } = render ( < Image { ...glyphiconProps } /> ) ;
226+ const icon = getByRole ( "img" ) ;
227+ expect ( icon ) . not . toHaveAttribute ( "aria-label" ) ;
236228 } ) ;
237229
238230 it ( "nothing is set on an icon" , ( ) => {
239- const imageRender = render ( < Image { ...iconProps } /> ) ;
240- const image = imageRender . find ( "span" ) ;
241- expect ( image ) . not . toHaveProperty ( "aria-label" ) ;
242- expect ( image ) . not . toHaveProperty ( "role" ) ;
231+ const { getByRole } = render ( < Image { ...iconProps } /> ) ;
232+ const icon = getByRole ( "img" ) ;
233+ expect ( icon ) . not . toHaveAttribute ( "aria-label" ) ;
243234 } ) ;
244235 } ) ;
245236
246237 describe ( "when showing an image as a thumbnail" , ( ) => {
247238 it ( "includes the thumb=true URL param in the image" , ( ) => {
248- const imageRender = render ( < Image { ...imageProps } displayAs = "thumbnail" /> ) ;
249- const image = imageRender . find ( "img" ) ;
250- expect ( image . prop ( " src" ) ) . toContain ( "thumb=true" ) ;
239+ const { getByRole } = render ( < Image { ...imageProps } displayAs = "thumbnail" /> ) ;
240+ const image = getByRole ( "img" ) as HTMLImageElement ;
241+ expect ( image . src ) . toContain ( "thumb=true" ) ;
251242 } ) ;
252243
253- it ( "does not include the thumb=true URL param in the lightbox image" , ( ) => {
254- const imageRender = render ( < Image { ...imageProps } displayAs = "thumbnail" onClickType = "enlarge" /> ) ;
255-
256- const image = imageRender . find ( "img" ) ;
257- expect ( image . prop ( "src" ) ) . toContain ( "thumb=true" ) ;
258- expect ( image ) . toHaveLength ( 1 ) ;
259-
260- image . simulate ( "click" ) ;
261-
262- const allImages = imageRender . findWhere (
263- node => node . type ( ) === "img" && node . prop ( "src" ) . startsWith ( imageProps . image )
244+ it ( "does not include the thumb=true URL param in the lightbox image" , async ( ) => {
245+ const { getByRole, getAllByRole } = render (
246+ < Image { ...imageProps } displayAs = "thumbnail" onClickType = "enlarge" />
264247 ) ;
265- expect ( allImages ) . toHaveLength ( 2 ) ;
266-
267- expect ( allImages . at ( 0 ) . prop ( "src" ) ) . toContain ( "thumb=true" ) ;
268- expect ( allImages . at ( 1 ) . prop ( "src" ) ) . not . toContain ( "thumb=true" ) ;
248+ const image = getByRole ( "button" ) as HTMLImageElement ;
249+ expect ( image . src ) . toContain ( "thumb=true" ) ;
250+ await user . click ( image ) ;
251+
252+ const allImages = getAllByRole ( "img" ) as HTMLImageElement [ ] ;
253+ expect ( allImages . length ) . toBeGreaterThanOrEqual ( 2 ) ;
254+ expect ( allImages [ 0 ] . src ) . not . toContain ( "thumb=true" ) ;
255+ expect ( allImages [ 1 ] . src ) . not . toContain ( "thumb=true" ) ;
269256 } ) ;
270257 } ) ;
271258
272259 describe ( "when showing as a background image" , ( ) => {
273260 it ( "shows the content" , ( ) => {
274- const imageRender = render (
261+ const { getByText } = render (
275262 < Image { ...imageProps } renderAsBackground backgroundImageContent = { < div > Image content</ div > } />
276263 ) ;
277- expect ( imageRender . text ( ) ) . toContain ( "Image content" ) ;
264+ expect ( getByText ( "Image content" ) ) . toBeInTheDocument ( ) ;
278265 } ) ;
279266
280- it ( "properly handles on click event if configured by the user" , ( ) => {
267+ it ( "properly handles on click event if configured by the user" , async ( ) => {
281268 const onClickMock = jest . fn ( ) ;
282- const imageRender = render (
269+ const { container } = render (
283270 < Image
284271 { ...imageProps }
285272 renderAsBackground
@@ -288,10 +275,9 @@ describe("Image", () => {
288275 onClickType = "action"
289276 />
290277 ) ;
291- const backgroundImage = imageRender . find ( ".mx-image-viewer.mx-image-background" ) ;
292- expect ( backgroundImage ) . toHaveLength ( 1 ) ;
293-
294- backgroundImage . simulate ( "click" ) ;
278+ const backgroundImage = container . querySelector ( ".mx-image-viewer.mx-image-background" ) ;
279+ expect ( backgroundImage ) . toBeInTheDocument ( ) ;
280+ await user . click ( backgroundImage ! ) ;
295281 expect ( onClickMock ) . toHaveBeenCalledTimes ( 1 ) ;
296282 } ) ;
297283 } ) ;
0 commit comments