mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-25 08:33:00 +08:00
a03e2024d4
* refactor(qr-code): improve a11y attributes handling in QRCode component * test: update snapshot * feat(qr-code): improve a11y attributes handling in QRCode component * chore: remove useless code * test: add test case * chore: remove data attr and update test cases * chore: omit a11yProps from props
193 lines
7.0 KiB
TypeScript
193 lines
7.0 KiB
TypeScript
import React, { useState } from 'react';
|
|
|
|
import QRCode from '..';
|
|
import mountTest from '../../../tests/shared/mountTest';
|
|
import rtlTest from '../../../tests/shared/rtlTest';
|
|
import { fireEvent, render } from '../../../tests/utils';
|
|
import type { QRCodeProps } from '../interface';
|
|
|
|
describe('QRCode test', () => {
|
|
mountTest(() => <QRCode value="" />);
|
|
rtlTest(() => <QRCode value="" />);
|
|
|
|
it('should correct render', () => {
|
|
const { container } = render(<QRCode value="test" />);
|
|
expect(container?.querySelector<HTMLCanvasElement>('.ant-qrcode canvas')).toBeTruthy();
|
|
expect(container).toMatchSnapshot();
|
|
});
|
|
|
|
it('should render `null` and console Error when value not exist', () => {
|
|
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
const { container } = render(<QRCode value={undefined as unknown as string} />);
|
|
expect(container.firstChild).toBe(null);
|
|
expect(container.firstChild).toMatchSnapshot();
|
|
expect(errSpy).toHaveBeenCalledWith('Warning: [antd: QRCode] need to receive `value` props');
|
|
errSpy.mockRestore();
|
|
});
|
|
|
|
it('support custom icon', () => {
|
|
const { container } = render(<QRCode value="test" icon="test" />);
|
|
expect(container?.querySelector<HTMLImageElement>('.ant-qrcode img')).toBeTruthy();
|
|
});
|
|
|
|
it('support custom size', () => {
|
|
const { container } = render(<QRCode value="test" size={100} />);
|
|
const canvas = container.querySelector<HTMLCanvasElement>('.ant-qrcode > canvas')!;
|
|
expect(canvas.width).toBe(100);
|
|
expect(canvas.height).toBe(100);
|
|
});
|
|
|
|
it('support refresh', () => {
|
|
const refresh = jest.fn();
|
|
const { container } = render(<QRCode value="test" status="expired" onRefresh={refresh} />);
|
|
fireEvent.click(
|
|
container?.querySelector<HTMLButtonElement>('.ant-qrcode button.ant-btn-link')!,
|
|
);
|
|
expect(refresh).toHaveBeenCalled();
|
|
});
|
|
|
|
it('support click', () => {
|
|
const handleClick = jest.fn();
|
|
const { container } = render(<QRCode value="test" onClick={handleClick} />);
|
|
fireEvent.click(container?.querySelector<HTMLDivElement>('.ant-qrcode')!);
|
|
expect(handleClick).toHaveBeenCalled();
|
|
});
|
|
|
|
it('support loading', () => {
|
|
const Demo: React.FC = () => {
|
|
const [status, setStatus] = useState<QRCodeProps['status']>('active');
|
|
return (
|
|
<>
|
|
<QRCode value="test" status={status} />
|
|
<button type="button" onClick={() => setStatus('loading')}>
|
|
set loading
|
|
</button>
|
|
</>
|
|
);
|
|
};
|
|
const { container } = render(<Demo />);
|
|
expect(container.querySelector<HTMLDivElement>('.ant-spin-spinning')).toBeFalsy();
|
|
fireEvent.click(container?.querySelector<HTMLButtonElement>('button')!);
|
|
expect(container.querySelector<HTMLDivElement>('.ant-spin-spinning')).toBeTruthy();
|
|
});
|
|
|
|
it('support bordered', () => {
|
|
const { container } = render(<QRCode value="test" bordered={false} />);
|
|
expect(container?.querySelector<HTMLDivElement>('.ant-qrcode')).toHaveClass(
|
|
'ant-qrcode-borderless',
|
|
);
|
|
});
|
|
|
|
it('should console Error when icon exist && errorLevel is `L`', () => {
|
|
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
render(<QRCode value="test" icon="test" errorLevel="L" />);
|
|
expect(errSpy).toHaveBeenCalledWith(
|
|
'Warning: [antd: QRCode] ErrorLevel `L` is not recommended to be used with `icon`, for scanning result would be affected by low level.',
|
|
);
|
|
errSpy.mockRestore();
|
|
});
|
|
|
|
it('correct style for wrapper & canvas', () => {
|
|
const { container } = render(
|
|
<QRCode value="test" size={60} style={{ width: '100%', height: '80%' }} />,
|
|
);
|
|
expect(container.querySelector<HTMLElement>('.ant-qrcode')).toHaveStyle(
|
|
'width: 100%; height: 80%;',
|
|
);
|
|
expect(container.querySelector<HTMLElement>('.ant-qrcode canvas')).toHaveStyle(
|
|
'width: 100%; height: 80%;',
|
|
);
|
|
});
|
|
it('custom status render', () => {
|
|
const refreshCb = jest.fn();
|
|
const customStatusRender: QRCodeProps['statusRender'] = (info) => {
|
|
switch (info.status) {
|
|
case 'expired':
|
|
return (
|
|
<div className="custom-expired">
|
|
<span>{info.locale?.expired}</span>
|
|
<button id="refresh" onClick={info.onRefresh} type="button">
|
|
refresh
|
|
</button>
|
|
</div>
|
|
);
|
|
case 'loading':
|
|
return <div className="custom-loading">Loading</div>;
|
|
case 'scanned':
|
|
return <div className="custom-scanned">{info.locale?.scanned}</div>;
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
const { container } = render(
|
|
<>
|
|
<QRCode
|
|
className="qrcode-expired"
|
|
value="test"
|
|
status="expired"
|
|
statusRender={customStatusRender}
|
|
onRefresh={refreshCb}
|
|
/>
|
|
<QRCode
|
|
className="qrcode-loading"
|
|
value="test"
|
|
status="loading"
|
|
statusRender={customStatusRender}
|
|
/>
|
|
<QRCode
|
|
className="qrcode-scanned"
|
|
value="test"
|
|
status="scanned"
|
|
statusRender={customStatusRender}
|
|
/>
|
|
</>,
|
|
);
|
|
expect(
|
|
container.querySelector<HTMLDivElement>('.qrcode-expired .custom-expired>span')?.textContent,
|
|
).toBe('QR code expired');
|
|
fireEvent.click(container?.querySelector<HTMLButtonElement>('#refresh')!);
|
|
expect(refreshCb).toHaveBeenCalled();
|
|
expect(
|
|
container.querySelector<HTMLDivElement>('.qrcode-loading .custom-loading')?.textContent,
|
|
).toBe('Loading');
|
|
expect(
|
|
container.querySelector<HTMLDivElement>('.qrcode-scanned .custom-scanned')?.textContent,
|
|
).toBe('Scanned');
|
|
expect(container).toMatchSnapshot();
|
|
});
|
|
|
|
it('should pass aria and data props to qrcode element', () => {
|
|
const { container } = render(<QRCode value="test" aria-label="Test QR Code" />);
|
|
const qrcodeElement = container.querySelector('.ant-qrcode canvas');
|
|
expect(qrcodeElement).toHaveAttribute('aria-label', 'Test QR Code');
|
|
});
|
|
|
|
it('should not pass other props to qrcode element', () => {
|
|
const { container } = render(
|
|
<QRCode
|
|
value="test"
|
|
aria-label="Test QR Code"
|
|
title="qr-title" // This prop should not be passed to canvas
|
|
/>,
|
|
);
|
|
|
|
const qrcodeElement = container.querySelector('.ant-qrcode canvas');
|
|
expect(qrcodeElement).toHaveAttribute('aria-label', 'Test QR Code');
|
|
expect(qrcodeElement).not.toHaveAttribute('title', 'qr-title');
|
|
});
|
|
|
|
it('should work with both canvas and svg type', () => {
|
|
const ariaLabel = 'Test QR Code';
|
|
// test canvas type
|
|
const { container: canvasContainer } = render(
|
|
<QRCode value="test" type="canvas" aria-label={ariaLabel} />,
|
|
);
|
|
expect(canvasContainer.querySelector('canvas')).toHaveAttribute('aria-label', ariaLabel);
|
|
// test svg type
|
|
const { container: svgContainer } = render(
|
|
<QRCode value="test" type="svg" aria-label={ariaLabel} />,
|
|
);
|
|
expect(svgContainer.querySelector('svg')).toHaveAttribute('aria-label', ariaLabel);
|
|
});
|
|
});
|