diff --git a/.changeset/nervous-mails-peel.md b/.changeset/nervous-mails-peel.md
new file mode 100644
index 0000000000..530fa9023a
--- /dev/null
+++ b/.changeset/nervous-mails-peel.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Fix accessibility issue in ``. The component doesn't render anymore an hidden `textarea` containing the text to be copied.
diff --git a/packages/core-components/src/components/CodeSnippet/CodeSnippet.test.tsx b/packages/core-components/src/components/CodeSnippet/CodeSnippet.test.tsx
index 298a8d5780..a4ffd3462b 100644
--- a/packages/core-components/src/components/CodeSnippet/CodeSnippet.test.tsx
+++ b/packages/core-components/src/components/CodeSnippet/CodeSnippet.test.tsx
@@ -15,8 +15,6 @@
*/
import React from 'react';
-import { fireEvent } from '@testing-library/react';
-import { act } from 'react-dom/test-utils';
import { renderInTestApp } from '@backstage/test-utils';
import { CodeSnippet } from './CodeSnippet';
@@ -56,19 +54,4 @@ describe('', () => {
expect(getByText('2')).toBeInTheDocument();
expect(getByText('3')).toBeInTheDocument();
});
-
- it('copy code using button', async () => {
- jest.useFakeTimers();
- document.execCommand = jest.fn();
- const { getByTitle } = await renderInTestApp(
- ,
- );
- const button = getByTitle('Text copied to clipboard');
- fireEvent.click(button);
- act(() => {
- jest.runAllTimers();
- });
- expect(document.execCommand).toHaveBeenCalled();
- jest.useRealTimers();
- });
});
diff --git a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx
index a3badaad07..613dff80a9 100644
--- a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx
+++ b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx
@@ -42,7 +42,7 @@ export const CodeSnippet = ({
const mode = theme.palette.type === 'dark' ? dark : docco;
const highlightColor = theme.palette.type === 'dark' ? '#256bf3' : '#e6ffed';
return (
-
+
{
const PopperJS = jest.requireActual('popper.js');
@@ -51,14 +55,16 @@ const apiRegistry = ApiRegistry.from([
],
]);
+jest.mock('copy-to-clipboard', () => jest.fn());
+
describe('', () => {
it('renders without exploding', async () => {
- const { getByDisplayValue } = await renderInTestApp(
+ const { getByTestId } = await renderInTestApp(
,
);
- getByDisplayValue('mockText');
+ expect(getByTestId('copy-button')).toBeInTheDocument();
});
it('displays tooltip on click', async () => {
@@ -74,7 +80,7 @@ describe('', () => {
act(() => {
jest.runAllTimers();
});
- expect(document.execCommand).toHaveBeenCalled();
+ expect(copy).toHaveBeenCalledWith('mockText');
rendered.getByText('mockTooltip');
jest.useRealTimers();
});
diff --git a/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx b/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx
index b5bc516d1a..b7120f6ad3 100644
--- a/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx
+++ b/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx
@@ -14,11 +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, useRef, useState } from 'react';
+import React, { MouseEventHandler, useState } from 'react';
+import { useCopyToClipboard } from 'react-use';
/**
* Copy text button with visual feedback in the form of
@@ -51,31 +51,17 @@ export const CopyTextButton = (props: Props) => {
...defaultProps,
...props,
};
- const errorApi = useApi(errorApiRef);
- const inputRef = useRef(null);
const [open, setOpen] = useState(false);
+ const [, copyToClipboard] = useCopyToClipboard();
const handleCopyClick: MouseEventHandler = e => {
e.stopPropagation();
setOpen(true);
-
- try {
- if (inputRef.current) {
- inputRef.current.select();
- document.execCommand('copy');
- }
- } catch (error) {
- errorApi.post(error);
- }
+ copyToClipboard(text);
};
return (
<>
-
{
open={open}
>
-
+
>
diff --git a/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.test.tsx b/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.test.tsx
index a71cb65be0..89fbed7d79 100644
--- a/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.test.tsx
+++ b/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.test.tsx
@@ -20,9 +20,10 @@ import { PlainApiDefinitionWidget } from './PlainApiDefinitionWidget';
describe('', () => {
it('renders plain text', async () => {
- const { getByText } = await renderInTestApp(
+ const { getByTestId } = await renderInTestApp(
,
);
- expect(getByText(/Hello World/i)).toBeInTheDocument();
+
+ expect(getByTestId('code-snippet')).toMatchSnapshot();
});
});
diff --git a/plugins/api-docs/src/components/PlainApiDefinitionWidget/__snapshots__/PlainApiDefinitionWidget.test.tsx.snap b/plugins/api-docs/src/components/PlainApiDefinitionWidget/__snapshots__/PlainApiDefinitionWidget.test.tsx.snap
new file mode 100644
index 0000000000..85f93c65ae
--- /dev/null
+++ b/plugins/api-docs/src/components/PlainApiDefinitionWidget/__snapshots__/PlainApiDefinitionWidget.test.tsx.snap
@@ -0,0 +1,62 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders plain text 1`] = `
+
+
+
+
+
+ Hello
+
+
+
+
+
+ World
+
+
+
+
+
+
+`;
diff --git a/plugins/badges/src/components/EntityBadgesDialog.test.tsx b/plugins/badges/src/components/EntityBadgesDialog.test.tsx
index 7901a69cbd..1f5ee94e04 100644
--- a/plugins/badges/src/components/EntityBadgesDialog.test.tsx
+++ b/plugins/badges/src/components/EntityBadgesDialog.test.tsx
@@ -55,7 +55,7 @@ describe('EntityBadgesDialog', () => {
);
await expect(
- rendered.findByText(''),
+ rendered.findByText('test: badge'),
).resolves.toBeInTheDocument();
});
});