copy-text-button: refactoring tests and error handling
Signed-off-by: Vincenzo Scamporlino <me@vinzscam.dev>
This commit is contained in:
@@ -19,12 +19,9 @@ import { fireEvent } from '@testing-library/react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { CopyTextButton } from './CopyTextButton';
|
||||
import { ApiRegistry, ApiProvider } from '@backstage/core-app-api';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
import { errorApiRef, ErrorApi } from '@backstage/core-plugin-api';
|
||||
// should we add this to dev dependencies?
|
||||
// (already a dependency of react-use)
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
|
||||
jest.mock('popper.js', () => {
|
||||
const PopperJS = jest.requireActual('popper.js');
|
||||
@@ -37,6 +34,17 @@ jest.mock('popper.js', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('react-use', () => {
|
||||
const original = jest.requireActual('react-use');
|
||||
|
||||
return {
|
||||
...original,
|
||||
useCopyToClipboard: jest
|
||||
.fn()
|
||||
.mockImplementation(original.useCopyToClipboard),
|
||||
};
|
||||
});
|
||||
|
||||
const props = {
|
||||
text: 'mockText',
|
||||
tooltipDelay: 2,
|
||||
@@ -47,29 +55,30 @@ const apiRegistry = ApiRegistry.from([
|
||||
[
|
||||
errorApiRef,
|
||||
{
|
||||
post(error) {
|
||||
throw error;
|
||||
},
|
||||
post: jest.fn(),
|
||||
error$: jest.fn(),
|
||||
} as ErrorApi,
|
||||
],
|
||||
]);
|
||||
|
||||
jest.mock('copy-to-clipboard', () => jest.fn());
|
||||
|
||||
describe('<CopyTextButton />', () => {
|
||||
it('renders without exploding', async () => {
|
||||
const { getByTestId } = await renderInTestApp(
|
||||
const { getByTitle, queryByText } = await renderInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<CopyTextButton {...props} />
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(getByTestId('copy-button')).toBeInTheDocument();
|
||||
expect(getByTitle('mockTooltip')).toBeInTheDocument();
|
||||
expect(queryByText('mockTooltip')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('displays tooltip on click', async () => {
|
||||
it('displays tooltip and copy the text on click', async () => {
|
||||
jest.useFakeTimers();
|
||||
document.execCommand = jest.fn();
|
||||
|
||||
const spy = useCopyToClipboard as jest.Mock;
|
||||
const copy = jest.fn();
|
||||
spy.mockReturnValue([{}, copy]);
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<CopyTextButton {...props} />
|
||||
@@ -84,4 +93,18 @@ describe('<CopyTextButton />', () => {
|
||||
rendered.getByText('mockTooltip');
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('reports copy errors', async () => {
|
||||
const spy = useCopyToClipboard as jest.Mock;
|
||||
|
||||
const error = new Error('just an error');
|
||||
spy.mockReturnValue([{ error }, jest.fn()]);
|
||||
|
||||
await renderInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<CopyTextButton {...props} />
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(apiRegistry.get(errorApiRef)?.post).toHaveBeenCalledWith(error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,10 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { errorApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
import { IconButton, Tooltip } from '@material-ui/core';
|
||||
import CopyIcon from '@material-ui/icons/FileCopy';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { MouseEventHandler, useState } from 'react';
|
||||
import React, { MouseEventHandler, useEffect, useState } from 'react';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
|
||||
/**
|
||||
@@ -51,8 +52,15 @@ export const CopyTextButton = (props: Props) => {
|
||||
...defaultProps,
|
||||
...props,
|
||||
};
|
||||
const errorApi = useApi(errorApiRef);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [, copyToClipboard] = useCopyToClipboard();
|
||||
const [{ error }, copyToClipboard] = useCopyToClipboard();
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
errorApi.post(error);
|
||||
}
|
||||
}, [error, errorApi]);
|
||||
|
||||
const handleCopyClick: MouseEventHandler = e => {
|
||||
e.stopPropagation();
|
||||
@@ -71,7 +79,7 @@ export const CopyTextButton = (props: Props) => {
|
||||
open={open}
|
||||
>
|
||||
<IconButton onClick={handleCopyClick}>
|
||||
<CopyIcon data-testid="copy-button" />
|
||||
<CopyIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user