|
1 |
| -import { render } from '../../__tests__/utils'; |
| 1 | +import type { DSize } from '../../utils/types'; |
| 2 | +import type { DButtonProps } from './Button'; |
| 3 | + |
| 4 | +import { render, fireEvent } from '../../__tests__/utils'; |
| 5 | +import { DCompose } from '../compose'; |
2 | 6 | import { DButton } from './index';
|
3 | 7 |
|
| 8 | +const dPrefix = 'rd-'; |
| 9 | + |
| 10 | +const getTypeClass = (dType: DButtonProps['dType'], prefix = dPrefix) => { |
| 11 | + return `${prefix}button--${dType || 'primary'}`; |
| 12 | +}; |
| 13 | +const getThemeClass = (dTheme: DButtonProps['dTheme'], prefix = 't') => { |
| 14 | + return `${prefix}-${dTheme || 'primary'}`; |
| 15 | +}; |
| 16 | +const getOtherClass = (ots?: 'icon' | DSize | 'block' | DButtonProps['dVariant'] | 'icon-right', separator = '--', prefix = dPrefix) => { |
| 17 | + return !ots ? `${prefix}button` : `${prefix}button${separator}${ots || ''}`; |
| 18 | +}; |
| 19 | + |
| 20 | +const sleep = (time: number) => |
| 21 | + new Promise((resolve) => |
| 22 | + setTimeout(() => { |
| 23 | + resolve(''); |
| 24 | + }, time) |
| 25 | + ); |
| 26 | + |
4 | 27 | describe('DButton', () => {
|
5 | 28 | const text = 'This is DButton';
|
6 | 29 |
|
7 | 30 | it('should `children` work', () => {
|
8 | 31 | const { getByText } = render(<DButton children={text} />);
|
9 | 32 | expect(getByText(text)).toBeInTheDocument();
|
10 | 33 | });
|
| 34 | + |
| 35 | + describe('the type property of DButton', () => { |
| 36 | + it('should render with the root, text, and primary classes but no others', () => { |
| 37 | + const buttonText = 'Hello World'; |
| 38 | + const { getByRole, getByText } = render( |
| 39 | + <DButton className="cust-btn" type="submit"> |
| 40 | + {buttonText} |
| 41 | + </DButton> |
| 42 | + ); |
| 43 | + const button = getByRole('button'); |
| 44 | + expect(getByText(buttonText)).toBeInTheDocument(); |
| 45 | + expect(button.classList.contains(`cust-btn`)).toBe(true); |
| 46 | + expect(button.classList.contains(getOtherClass())).toBe(true); |
| 47 | + expect(button.classList.contains(getTypeClass('primary'))).toBe(true); |
| 48 | + expect(button.classList.contains(getThemeClass('primary'))).toBe(true); |
| 49 | + |
| 50 | + expect(button.classList.contains(getOtherClass('icon'))).not.toBe(true); |
| 51 | + expect(button.classList.contains(getOtherClass('block'))).not.toBe(true); |
| 52 | + expect(button.classList.contains(getOtherClass('smaller'))).not.toBe(true); |
| 53 | + expect(button.classList.contains(getOtherClass('larger'))).not.toBe(true); |
| 54 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 55 | + expect(button.getAttribute('type')).toBe('submit'); |
| 56 | + }); |
| 57 | + |
| 58 | + it('should render a text secondary button', () => { |
| 59 | + const buttonText = 'Hello World'; |
| 60 | + const { getByRole } = render(<DButton dType="secondary">{buttonText}</DButton>); |
| 61 | + const button = getByRole('button'); |
| 62 | + |
| 63 | + expect(button.classList.contains(getTypeClass('secondary'))).toBe(true); |
| 64 | + expect(button.classList.contains(getOtherClass())).toBe(true); |
| 65 | + expect(button.classList.contains(getThemeClass('primary'))).toBe(true); |
| 66 | + |
| 67 | + expect(button.classList.contains(getOtherClass('icon'))).not.toBe(true); |
| 68 | + expect(button.classList.contains(getOtherClass('block'))).not.toBe(true); |
| 69 | + expect(button.classList.contains(getOtherClass('smaller'))).not.toBe(true); |
| 70 | + expect(button.classList.contains(getOtherClass('larger'))).not.toBe(true); |
| 71 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 72 | + }); |
| 73 | + |
| 74 | + it('should render a text outline button', () => { |
| 75 | + const buttonText = 'Hello World'; |
| 76 | + const { getByRole } = render(<DButton dType="outline">{buttonText}</DButton>); |
| 77 | + const button = getByRole('button'); |
| 78 | + |
| 79 | + expect(button.classList.contains(getTypeClass('outline'))).toBe(true); |
| 80 | + expect(button.classList.contains(getOtherClass())).toBe(true); |
| 81 | + expect(button.classList.contains(getThemeClass('primary'))).toBe(true); |
| 82 | + |
| 83 | + expect(button.classList.contains(getOtherClass('icon'))).not.toBe(true); |
| 84 | + expect(button.classList.contains(getOtherClass('block'))).not.toBe(true); |
| 85 | + expect(button.classList.contains(getOtherClass('smaller'))).not.toBe(true); |
| 86 | + expect(button.classList.contains(getOtherClass('larger'))).not.toBe(true); |
| 87 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 88 | + }); |
| 89 | + |
| 90 | + it('should render a text dashed button', () => { |
| 91 | + const buttonText = 'Hello World'; |
| 92 | + const { getByRole } = render(<DButton dType="dashed">{buttonText}</DButton>); |
| 93 | + const button = getByRole('button'); |
| 94 | + |
| 95 | + expect(button.classList.contains(getTypeClass('dashed'))).toBe(true); |
| 96 | + expect(button.classList.contains(getOtherClass())).toBe(true); |
| 97 | + expect(button.classList.contains(getThemeClass('primary'))).toBe(true); |
| 98 | + |
| 99 | + expect(button.classList.contains(getOtherClass('icon'))).not.toBe(true); |
| 100 | + expect(button.classList.contains(getOtherClass('block'))).not.toBe(true); |
| 101 | + expect(button.classList.contains(getOtherClass('smaller'))).not.toBe(true); |
| 102 | + expect(button.classList.contains(getOtherClass('larger'))).not.toBe(true); |
| 103 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 104 | + }); |
| 105 | + |
| 106 | + it('should render a text text button', () => { |
| 107 | + const buttonText = 'Hello World'; |
| 108 | + const { getByRole } = render(<DButton dType="text">{buttonText}</DButton>); |
| 109 | + const button = getByRole('button'); |
| 110 | + |
| 111 | + expect(button.classList.contains(getTypeClass('text'))).toBe(true); |
| 112 | + expect(button.classList.contains(getOtherClass())).toBe(true); |
| 113 | + expect(button.classList.contains(getThemeClass('primary'))).toBe(true); |
| 114 | + |
| 115 | + expect(button.classList.contains(getOtherClass('icon'))).not.toBe(true); |
| 116 | + expect(button.classList.contains(getOtherClass('block'))).not.toBe(true); |
| 117 | + expect(button.classList.contains(getOtherClass('smaller'))).not.toBe(true); |
| 118 | + expect(button.classList.contains(getOtherClass('larger'))).not.toBe(true); |
| 119 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 120 | + }); |
| 121 | + |
| 122 | + it('should render a text link button', () => { |
| 123 | + const buttonText = 'Hello World'; |
| 124 | + const { getByRole } = render(<DButton dType="link">{buttonText}</DButton>); |
| 125 | + const button = getByRole('button'); |
| 126 | + |
| 127 | + expect(button.classList.contains(getTypeClass('link'))).toBe(true); |
| 128 | + expect(button.classList.contains(getOtherClass())).toBe(true); |
| 129 | + expect(button.classList.contains(getThemeClass('primary'))).toBe(true); |
| 130 | + |
| 131 | + expect(button.classList.contains(getOtherClass('icon'))).not.toBe(true); |
| 132 | + expect(button.classList.contains(getOtherClass('block'))).not.toBe(true); |
| 133 | + expect(button.classList.contains(getOtherClass('smaller'))).not.toBe(true); |
| 134 | + expect(button.classList.contains(getOtherClass('larger'))).not.toBe(true); |
| 135 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 136 | + }); |
| 137 | + }); |
| 138 | + |
| 139 | + describe('the theme property of DButton', () => { |
| 140 | + it('should render a primary button', () => { |
| 141 | + const buttonText = 'Hello World'; |
| 142 | + const { getByRole } = render(<DButton dTheme="primary">{buttonText}</DButton>); |
| 143 | + const button = getByRole('button'); |
| 144 | + |
| 145 | + expect(button.classList.contains(getThemeClass('primary'))).toBe(true); |
| 146 | + }); |
| 147 | + |
| 148 | + it('should render a success button', () => { |
| 149 | + const buttonText = 'Hello World'; |
| 150 | + const { getByRole } = render(<DButton dTheme="success">{buttonText}</DButton>); |
| 151 | + const button = getByRole('button'); |
| 152 | + |
| 153 | + expect(button.classList.contains(getThemeClass('success'))).toBe(true); |
| 154 | + }); |
| 155 | + |
| 156 | + it('should render a warning button', () => { |
| 157 | + const buttonText = 'Hello World'; |
| 158 | + const { getByRole } = render(<DButton dTheme="warning">{buttonText}</DButton>); |
| 159 | + const button = getByRole('button'); |
| 160 | + |
| 161 | + expect(button.classList.contains(getThemeClass('warning'))).toBe(true); |
| 162 | + }); |
| 163 | + |
| 164 | + it('should render a danger button', () => { |
| 165 | + const buttonText = 'Hello World'; |
| 166 | + const { getByRole } = render(<DButton dTheme="danger">{buttonText}</DButton>); |
| 167 | + const button = getByRole('button'); |
| 168 | + |
| 169 | + expect(button.classList.contains(getThemeClass('danger'))).toBe(true); |
| 170 | + }); |
| 171 | + }); |
| 172 | + |
| 173 | + describe('the icon property of DButton', () => { |
| 174 | + it('should render a button with icon', () => { |
| 175 | + const buttonText = 'Hello World'; |
| 176 | + const mockIcon = <div>icon</div>; |
| 177 | + const { getByRole, getByText } = render(<DButton dIcon={mockIcon}>{buttonText}</DButton>); |
| 178 | + const button = getByRole('button'); |
| 179 | + const icon = getByText('icon'); |
| 180 | + |
| 181 | + expect(icon).toBeInTheDocument(); |
| 182 | + expect(button.contains(icon)).toBe(true); |
| 183 | + expect(button.getElementsByClassName(getOtherClass('icon', '__'))).toBeTruthy(); |
| 184 | + }); |
| 185 | + |
| 186 | + it('should render a icon on the right', () => { |
| 187 | + const mockIcon = <div>icon</div>; |
| 188 | + const { getByRole } = render( |
| 189 | + <DButton dIcon={mockIcon} dIconRight> |
| 190 | + Hello World |
| 191 | + </DButton> |
| 192 | + ); |
| 193 | + const button = getByRole('button'); |
| 194 | + expect(button.className.includes(getOtherClass('icon-right'))).toBe(true); |
| 195 | + }); |
| 196 | + }); |
| 197 | + |
| 198 | + describe('the disabled property of DButton', () => { |
| 199 | + it('should render a clickable button', () => { |
| 200 | + const buttonText = 'Hello World'; |
| 201 | + const cb = jest.fn(); |
| 202 | + const { getByRole } = render(<DButton onClick={cb}>{buttonText}</DButton>); |
| 203 | + const button = getByRole('button'); |
| 204 | + expect(cb).not.toBeCalled(); |
| 205 | + |
| 206 | + fireEvent.click(button); |
| 207 | + expect(cb.mock.calls.length).toBe(1); |
| 208 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 209 | + }); |
| 210 | + |
| 211 | + it('should render a disabled button', () => { |
| 212 | + const buttonText = 'Hello World'; |
| 213 | + const cb = jest.fn(); |
| 214 | + const { getByRole } = render(<DButton disabled>{buttonText}</DButton>); |
| 215 | + const button = getByRole('button'); |
| 216 | + |
| 217 | + expect(cb).not.toBeCalled(); |
| 218 | + expect(button['disabled']).toBe(true); |
| 219 | + fireEvent.click(button); |
| 220 | + expect(cb).not.toBeCalled(); |
| 221 | + expect(button.classList.contains('is-loading')).not.toBe(true); |
| 222 | + }); |
| 223 | + }); |
| 224 | + |
| 225 | + describe('the loading property of DButton', () => { |
| 226 | + it('should render a loading-button', () => { |
| 227 | + const buttonText = 'Hello World'; |
| 228 | + const cb = jest.fn(); |
| 229 | + const { getByRole } = render( |
| 230 | + <DButton dLoading={true} onClick={cb}> |
| 231 | + {buttonText} |
| 232 | + </DButton> |
| 233 | + ); |
| 234 | + const button = getByRole('button'); |
| 235 | + expect(button.className.includes('is-loading')).toBe(true); |
| 236 | + expect(button.querySelector(`.${dPrefix}button__icon`)).toBeInTheDocument(); |
| 237 | + fireEvent.click(button); |
| 238 | + expect(cb).not.toBeCalled(); |
| 239 | + }); |
| 240 | + |
| 241 | + it('should render a loading-button without icon', () => { |
| 242 | + const buttonText = 'Hello World'; |
| 243 | + const cb = jest.fn(); |
| 244 | + const mockIcon = <div>icon</div>; |
| 245 | + const { getByRole, queryByText } = render( |
| 246 | + <DButton dIcon={mockIcon} dLoading onClick={cb}> |
| 247 | + {buttonText} |
| 248 | + </DButton> |
| 249 | + ); |
| 250 | + const button = getByRole('button'); |
| 251 | + const icon = queryByText('icon'); |
| 252 | + |
| 253 | + expect(icon).toBeNull(); |
| 254 | + expect(button.className.includes('is-loading')).toBe(true); |
| 255 | + expect(button.getElementsByClassName(getOtherClass('icon', '__'))).toBeTruthy(); |
| 256 | + fireEvent.click(button); |
| 257 | + expect(cb.mock.calls.length).toBe(0); |
| 258 | + }); |
| 259 | + }); |
| 260 | + |
| 261 | + describe('the block property of DButton', () => { |
| 262 | + it('should render a button that suitable for its parent width', () => { |
| 263 | + const buttonText = 'Hello World'; |
| 264 | + const { getByRole } = render(<DButton dBlock>{buttonText}</DButton>); |
| 265 | + const button = getByRole('button'); |
| 266 | + expect(button.className.includes(getOtherClass('block'))).toBe(true); |
| 267 | + }); |
| 268 | + }); |
| 269 | + |
| 270 | + describe('the size property of DButton', () => { |
| 271 | + it('should render a small button', () => { |
| 272 | + const buttonText = 'Hello World'; |
| 273 | + const { getByRole } = render(<DButton dSize="smaller">{buttonText}</DButton>); |
| 274 | + const button = getByRole('button'); |
| 275 | + |
| 276 | + expect(button.className.includes(getOtherClass('smaller'))).toBe(true); |
| 277 | + }); |
| 278 | + |
| 279 | + it('should render a large button', () => { |
| 280 | + const buttonText = 'Hello World'; |
| 281 | + const { getByRole } = render(<DButton dSize="larger">{buttonText}</DButton>); |
| 282 | + const button = getByRole('button'); |
| 283 | + |
| 284 | + expect(button.className.includes(getOtherClass('larger'))).toBe(true); |
| 285 | + }); |
| 286 | + }); |
| 287 | + |
| 288 | + describe('the variant property of DButton', () => { |
| 289 | + it('should render a circle button', () => { |
| 290 | + const buttonText = 'Hello World'; |
| 291 | + const { getByRole } = render( |
| 292 | + <DButton dSize="larger" dVariant="circle"> |
| 293 | + {buttonText} |
| 294 | + </DButton> |
| 295 | + ); |
| 296 | + const button = getByRole('button'); |
| 297 | + expect(button.className.includes(getOtherClass('circle'))).toBe(true); |
| 298 | + }); |
| 299 | + |
| 300 | + it('should render a round button', () => { |
| 301 | + const buttonText = 'Hello World'; |
| 302 | + const { getByRole } = render( |
| 303 | + <DButton dSize="larger" dVariant="round"> |
| 304 | + {buttonText} |
| 305 | + </DButton> |
| 306 | + ); |
| 307 | + const button = getByRole('button'); |
| 308 | + expect(button.className.includes(getOtherClass('round'))).toBe(true); |
| 309 | + }); |
| 310 | + }); |
| 311 | + |
| 312 | + describe('Emotion compatibility', () => { |
| 313 | + it('should have a wave by default', async () => { |
| 314 | + const { getByRole } = render( |
| 315 | + <DButton dSize="larger" dVariant="round"> |
| 316 | + Hello World |
| 317 | + </DButton> |
| 318 | + ); |
| 319 | + const button = getByRole('button'); |
| 320 | + |
| 321 | + expect(button.querySelector('.rd-wave')).toBeNull(); |
| 322 | + fireEvent.click(button); |
| 323 | + expect(button.querySelector('.rd-wave')).toBeTruthy(); |
| 324 | + // animation-duration |
| 325 | + await sleep(4 * 1000); |
| 326 | + |
| 327 | + expect(button.querySelector('rd-wave')).toBeNull(); |
| 328 | + }); |
| 329 | + |
| 330 | + it('the properties of size and disabled should be inherited from DCmpose', () => { |
| 331 | + const { container, getAllByRole } = render( |
| 332 | + <DCompose dSize="larger" dDisabled={true}> |
| 333 | + <DButton id="middle-btn1">middle-btn1</DButton> |
| 334 | + <DButton id="middle-btn2">middle-btn2</DButton> |
| 335 | + <DButton id="middle-btn3">middle-btn3</DButton> |
| 336 | + <DButton id="small-btn" dSize="smaller"> |
| 337 | + small-btn |
| 338 | + </DButton> |
| 339 | + </DCompose> |
| 340 | + ); |
| 341 | + const buttons = getAllByRole('button'); |
| 342 | + expect(buttons.length).toBe(4); |
| 343 | + for (let idx = 0; idx < buttons.length; idx++) { |
| 344 | + expect(buttons[idx]['disabled']).toBe(true); |
| 345 | + } |
| 346 | + expect(container.querySelector('#middle-btn1')?.className.includes(getOtherClass('larger'))).toBe(true); |
| 347 | + expect(container.querySelector('#small-btn')?.className.includes(getOtherClass('smaller'))).toBe(true); |
| 348 | + }); |
| 349 | + }); |
11 | 350 | });
|
0 commit comments