From 6a72e535551282ee926af41200fe95f97b5fa441 Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Wed, 6 Sep 2023 14:47:55 -0400
Subject: [PATCH 1/9] chore(ClipboardCopy): updated tests

---
 .../ClipboardCopy/ClipboardCopyButton.tsx     |   2 +
 .../__tests__/ClipboardCopyAction.test.tsx    |  37 +++++
 .../__tests__/ClipboardCopyButton.test.tsx    | 136 +++++++++++++++---
 .../__tests__/ClipboardCopyExpanded.test.tsx  |  23 ---
 .../__tests__/ClipboardCopyToggle.test.tsx    |  48 -------
 .../ClipboardCopyAction.test.tsx.snap         |  11 ++
 .../ClipboardCopyButton.test.tsx.snap         |  81 +++++++----
 7 files changed, 223 insertions(+), 115 deletions(-)
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx
 delete mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
 delete mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyAction.test.tsx.snap

diff --git a/packages/react-core/src/components/ClipboardCopy/ClipboardCopyButton.tsx b/packages/react-core/src/components/ClipboardCopy/ClipboardCopyButton.tsx
index e0add211d15..ad55776ca61 100644
--- a/packages/react-core/src/components/ClipboardCopy/ClipboardCopyButton.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/ClipboardCopyButton.tsx
@@ -57,6 +57,7 @@ export const ClipboardCopyButton: React.FunctionComponent<ClipboardCopyButtonPro
   children,
   variant = 'control',
   onTooltipHidden = () => {},
+  className,
   ...props
 }: ClipboardCopyButtonProps) => {
   const triggerRef = React.createRef<HTMLButtonElement>();
@@ -79,6 +80,7 @@ export const ClipboardCopyButton: React.FunctionComponent<ClipboardCopyButtonPro
         variant={variant}
         onClick={onClick}
         aria-label={ariaLabel}
+        className={className}
         id={id}
         aria-labelledby={`${id} ${textId}`}
         {...props}
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx
new file mode 100644
index 00000000000..98015f64dc9
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { screen, render } from '@testing-library/react';
+import { ClipboardCopyAction } from '../ClipboardCopyAction';
+import styles from '@patternfly/react-styles/css/components/ClipboardCopy/clipboard-copy';
+
+test('Renders without children', () => {
+  render(
+    <div data-testid="container">
+      <ClipboardCopyAction />
+    </div>
+  );
+
+  expect(screen.getByTestId('container').firstChild).toBeVisible();
+});
+
+test(`Renders with class ${styles.clipboardCopyActionsItem} by default`, () => {
+  render(<ClipboardCopyAction>Action text</ClipboardCopyAction>);
+
+  expect(screen.getByText('Action text')).toHaveClass(styles.clipboardCopyActionsItem);
+});
+
+test(`Renders with custom class when className is passed`, () => {
+  render(<ClipboardCopyAction className="custom-class">Action text</ClipboardCopyAction>);
+
+  expect(screen.getByText('Action text')).toHaveClass('custom-class');
+});
+
+test(`Spreads additional props`, () => {
+  render(<ClipboardCopyAction id="test-id">Action text</ClipboardCopyAction>);
+
+  expect(screen.getByText('Action text')).toHaveAttribute('id', 'test-id');
+});
+
+test('Matches snapshot', () => {
+  const { asFragment } = render(<ClipboardCopyAction>Action text</ClipboardCopyAction>);
+  expect(asFragment()).toMatchSnapshot();
+});
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
index c87ccb90f51..64193765b82 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
@@ -2,36 +2,132 @@ import React from 'react';
 
 import { render, screen } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
-
 import { ClipboardCopyButton } from '../ClipboardCopyButton';
+import buttonStyles from '@patternfly/react-styles/css/components/Button/button';
+
+jest.mock('../../Tooltip', () => ({
+  Tooltip: ({ content, children, exitDelay, entryDelay, maxWidth, position, onTooltipHidden, ...props }) => (
+    <div data-testid="tooltip-mock" {...props}>
+      <div data-testid="tooltip-mock-content">{content}</div>
+      <p>{`exitDelay: ${exitDelay}`}</p>
+      <p>{`entryDelay: ${entryDelay}`}</p>
+      <p>{`maxWidth: ${maxWidth}`}</p>
+      <p>{`position: ${position}`}</p>
+      <p>{`onTooltipHidden: ${onTooltipHidden}`}</p>
+      {children}
+    </div>
+  )
+}));
 
-const props = {
-  id: 'my-id',
-  textId: 'my-text-id',
-  className: 'fancy-copy-button',
+const requiredProps = {
   onClick: jest.fn(),
-  exitDelay: 1000,
-  entryDelay: 2000,
-  maxWidth: '500px',
-  position: 'right' as 'right',
-  'aria-label': 'click this button to copy text'
+  children: 'Button content',
+  id: 'button-id',
+  textId: 'text-id'
 };
 
-test('copy button render', () => {
-  const { asFragment } = render(<ClipboardCopyButton {...props}>Copy Me</ClipboardCopyButton>);
-  expect(asFragment()).toMatchSnapshot();
+test('Renders with passed id prop', () => {
+  render(<ClipboardCopyButton {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveAttribute('id', 'button-id');
 });
 
-test('copy button onClick', async () => {
-  const onclick = jest.fn();
-  const user = userEvent.setup();
+test('Renders with aria-labelledby with passed id and textId prop values', () => {
+  render(
+    <>
+      <div id="text-id">Copyable text</div>
+      <ClipboardCopyButton {...requiredProps} />
+    </>
+  );
+
+  expect(screen.getByRole('button')).toHaveAttribute('aria-labelledby', 'button-id text-id');
+});
+
+test('Renders with concatenated aria-label by default', () => {
+  render(
+    <>
+      <div id="text-id">Copyable text</div>
+      <ClipboardCopyButton {...requiredProps} />
+    </>
+  );
 
+  expect(screen.getByRole('button')).toHaveAccessibleName('Copyable input Copyable text');
+});
+
+test('Renders with concatenated aria-label when custom aria-label is passed', () => {
   render(
-    <ClipboardCopyButton {...props} onClick={onclick}>
-      Copy to Clipboard
-    </ClipboardCopyButton>
+    <>
+      <div id="text-id">Copyable text</div>
+      <ClipboardCopyButton aria-label="Custom label" {...requiredProps} />
+    </>
   );
 
+  expect(screen.getByRole('button')).toHaveAccessibleName('Custom label Copyable text');
+});
+
+test('Passes className to Button', () => {
+  render(<ClipboardCopyButton className="test-class" {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveClass('test-class');
+});
+
+test('Passes variant to Button by default', () => {
+  render(<ClipboardCopyButton {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveClass(buttonStyles.modifiers.control);
+});
+
+test('Passes variant to Button when variant is passed', () => {
+  render(<ClipboardCopyButton variant="plain" {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveClass(buttonStyles.modifiers.plain);
+});
+
+test('Calls onClick when passed', async () => {
+  const user = userEvent.setup();
+
+  render(<ClipboardCopyButton {...requiredProps} />);
+
   await user.click(screen.getByRole('button'));
-  expect(onclick).toHaveBeenCalled();
+  expect(requiredProps.onClick).toHaveBeenCalledTimes(1);
+});
+
+test('Passes children to Tooltip content', () => {
+  render(<ClipboardCopyButton {...requiredProps} />);
+
+  expect(screen.getByText('Button content')).toBeVisible();
+});
+
+test('Passes exitDelay to Tooltip', () => {
+  render(<ClipboardCopyButton exitDelay={200} {...requiredProps} />);
+
+  expect(screen.getByText('exitDelay: 200')).toBeVisible();
+});
+
+test('Passes entryDelay to Tooltip', () => {
+  render(<ClipboardCopyButton entryDelay={200} {...requiredProps} />);
+
+  expect(screen.getByText('entryDelay: 200')).toBeVisible();
+});
+
+test('Passes maxWidth to Tooltip', () => {
+  render(<ClipboardCopyButton maxWidth="200px" {...requiredProps} />);
+
+  expect(screen.getByText('maxWidth: 200px')).toBeVisible();
+});
+
+test('Passes position to Tooltip', () => {
+  render(<ClipboardCopyButton position="bottom" {...requiredProps} />);
+
+  expect(screen.getByText('position: bottom')).toBeVisible();
+});
+test('Passes onTooltipHidden to Tooltip', () => {
+  render(<ClipboardCopyButton onTooltipHidden={() => {}} {...requiredProps} />);
+
+  expect(screen.getByText('onTooltipHidden: () => {}')).toBeVisible();
+});
+
+test('Matches snapshot', () => {
+  const { asFragment } = render(<ClipboardCopyButton {...requiredProps} />);
+  expect(asFragment()).toMatchSnapshot();
 });
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
deleted file mode 100644
index 0a9c8b32174..00000000000
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import { ClipboardCopyExpanded } from '../ClipboardCopyExpanded';
-
-const props = {
-  className: 'class-1',
-  id: 'id-1'
-};
-
-test('expanded content render', () => {
-  const { asFragment } = render(<ClipboardCopyExpanded {...props}>This is my text</ClipboardCopyExpanded>);
-  expect(asFragment()).toMatchSnapshot();
-});
-
-test('expanded code content render', () => {
-  const { asFragment } = render(
-    <ClipboardCopyExpanded isCode {...props}>{`{
-    "name": "@patternfly/react-core",
-    "version": "1.33.2"
-  }`}</ClipboardCopyExpanded>
-  );
-  expect(asFragment()).toMatchSnapshot();
-});
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
deleted file mode 100644
index b3885e985ab..00000000000
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import React from 'react';
-
-import { render, screen } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-
-import { ClipboardCopyToggle, ClipboardCopyToggleProps } from '../ClipboardCopyToggle';
-
-const props: ClipboardCopyToggleProps = {
-  id: 'my-id',
-  textId: 'my-text-id',
-  contentId: 'my-content-id',
-  isExpanded: false,
-  className: 'myclassName',
-  onClick: jest.fn()
-};
-
-describe('ClipboardCopyToggle', () => {
-  test('toggle button render', () => {
-    const desc = 'toggle content';
-    const { asFragment } = render(<ClipboardCopyToggle {...props} aria-label={desc} />);
-
-    expect(asFragment()).toMatchSnapshot();
-  });
-
-  test('toggle button onClick', async () => {
-    const onclick = jest.fn();
-    const user = userEvent.setup();
-
-    render(<ClipboardCopyToggle {...props} onClick={onclick} />);
-
-    await user.click(screen.getByRole('button'));
-    expect(onclick).toHaveBeenCalled();
-  });
-
-  test('has aria-expanded set to true when isExpanded is true', () => {
-    render(<ClipboardCopyToggle {...props} isExpanded />);
-
-    const toggleButton = screen.getByRole('button');
-    expect(toggleButton).toHaveAttribute('aria-expanded', 'true');
-  });
-
-  test('has aria-expanded set to false when isExpanded is false', () => {
-    render(<ClipboardCopyToggle {...props} />);
-
-    const toggleButton = screen.getByRole('button');
-    expect(toggleButton).toHaveAttribute('aria-expanded', 'false');
-  });
-});
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyAction.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyAction.test.tsx.snap
new file mode 100644
index 00000000000..0b7ff942012
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyAction.test.tsx.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Matches snapshot 1`] = `
+<DocumentFragment>
+  <span
+    class="pf-v5-c-clipboard-copy__actions-item"
+  >
+    Action text
+  </span>
+</DocumentFragment>
+`;
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
index 8ba62b22f84..4311fe4d86e 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
@@ -1,31 +1,64 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`copy button render 1`] = `
+exports[`Matches snapshot 1`] = `
 <DocumentFragment>
-  <button
-    aria-disabled="false"
-    aria-label="click this button to copy text"
-    aria-labelledby="my-id my-text-id"
-    class="pf-v5-c-button pf-m-control fancy-copy-button"
-    data-ouia-component-id="OUIA-Generated-Button-control-1"
-    data-ouia-component-type="PF5/Button"
-    data-ouia-safe="true"
-    id="my-id"
-    type="button"
+  <div
+    aria="none"
+    aria-live="polite"
+    data-testid="tooltip-mock"
+    trigger="mouseenter focus click"
+    triggerref="[object Object]"
   >
-    <svg
-      aria-hidden="true"
-      class="pf-v5-svg"
-      fill="currentColor"
-      height="1em"
-      role="img"
-      viewBox="0 0 448 512"
-      width="1em"
+    <div
+      data-testid="tooltip-mock-content"
     >
-      <path
-        d="M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"
-      />
-    </svg>
-  </button>
+      <div>
+        Button content
+      </div>
+    </div>
+    <p>
+      exitDelay: 0
+    </p>
+    <p>
+      entryDelay: 300
+    </p>
+    <p>
+      maxWidth: 100px
+    </p>
+    <p>
+      position: top
+    </p>
+    <p>
+      onTooltipHidden: () =&gt; {
+        /* istanbul ignore next */
+        cov_274vctcufi().f[1]++;
+      }
+    </p>
+    <button
+      aria-disabled="false"
+      aria-label="Copyable input"
+      aria-labelledby="button-id text-id"
+      class="pf-v5-c-button pf-m-control"
+      data-ouia-component-id="OUIA-Generated-Button-control-14"
+      data-ouia-component-type="PF5/Button"
+      data-ouia-safe="true"
+      id="button-id"
+      type="button"
+    >
+      <svg
+        aria-hidden="true"
+        class="pf-v5-svg"
+        fill="currentColor"
+        height="1em"
+        role="img"
+        viewBox="0 0 448 512"
+        width="1em"
+      >
+        <path
+          d="M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"
+        />
+      </svg>
+    </button>
+  </div>
 </DocumentFragment>
 `;

From ede1c6123a78d6612d81ccb17f9fbc1cb302ff03 Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Thu, 7 Sep 2023 10:07:50 -0400
Subject: [PATCH 2/9] Added tests for ClipboardCopy

---
 .../ClipboardCopy/ClipboardCopy.tsx           |   2 +-
 .../__tests__/ClipboardCopy.test.tsx          | 275 ++++++++++++++++++
 .../cypress/integration/clipboardcopy.spec.ts |   9 +
 .../ClipboardCopyDemo/ClipboardCopyDemo.tsx   |  11 +
 4 files changed, 296 insertions(+), 1 deletion(-)
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx

diff --git a/packages/react-core/src/components/ClipboardCopy/ClipboardCopy.tsx b/packages/react-core/src/components/ClipboardCopy/ClipboardCopy.tsx
index bb70d7af704..b4338b36ce7 100644
--- a/packages/react-core/src/components/ClipboardCopy/ClipboardCopy.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/ClipboardCopy.tsx
@@ -75,7 +75,7 @@ export interface ClipboardCopyProps extends Omit<React.HTMLProps<HTMLDivElement>
   onChange?: (event: React.FormEvent, text?: string | number) => void;
   /** The text which is copied. */
   children: React.ReactNode;
-  /** Additional actions for inline clipboard copy. Should be wrapped with ClipboardCopyAction. */
+  /** Additional actions for inline-compact clipboard copy. Should be wrapped with ClipboardCopyAction. */
   additionalActions?: React.ReactNode;
   /** Value to overwrite the randomly generated data-ouia-component-id.*/
   ouiaId?: number | string;
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
new file mode 100644
index 00000000000..b71b7bfa92c
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
@@ -0,0 +1,275 @@
+import React from 'react';
+import { screen, render } from '@testing-library/react';
+import { ClipboardCopy } from '../ClipboardCopy';
+import styles from '@patternfly/react-styles/css/components/ClipboardCopy/clipboard-copy';
+import userEvent from '@testing-library/user-event';
+
+jest.mock('../ClipboardCopyButton', () => ({
+  ClipboardCopyButton: ({ 'aria-label': ariaLabel, children, entryDelay, exitDelay, maxWidth, position }) => (
+    <div data-testid="clipboardCopyButton-mock">
+      <p>{`exitDelay: ${exitDelay}`}</p>
+      <p>{`entryDelay: ${entryDelay}`}</p>
+      <p>{`maxWidth: ${maxWidth}`}</p>
+      <p>{`position: ${position}`}</p>
+      <p>{`button-ariaLabel: ${ariaLabel}`}</p>
+      <div>{`children: ${children}`}</div>
+    </div>
+  )
+}));
+
+jest.mock('../ClipboardCopyToggle', () => ({
+  ClipboardCopyToggle: ({ 'aria-label': ariaLabel }) => (
+    <div data-testid="clipboardCopyToggle-mock">
+      <p>{`toggle-ariaLabel: ${ariaLabel}`}</p>
+    </div>
+  )
+}));
+
+const children = 'Copyable text';
+const testId = 'clipboard-copy';
+
+test(`Renders with class ${styles.clipboardCopy} by default`, () => {
+  render(<ClipboardCopy data-testid={testId}>{children}</ClipboardCopy>);
+
+  expect(screen.getByTestId(testId)).toHaveClass(styles.clipboardCopy);
+});
+
+test(`Renders with custom class when className is passed`, () => {
+  render(
+    <ClipboardCopy className="test-class" data-testid={testId}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByTestId(testId)).toHaveClass('test-class');
+});
+
+test(`Does not render with class ${styles.modifiers.inline} by default`, () => {
+  render(<ClipboardCopy data-testid={testId}>{children}</ClipboardCopy>);
+
+  expect(screen.getByTestId(testId)).not.toHaveClass(styles.modifiers.inline);
+});
+
+test(`Does not render with class ${styles.modifiers.inline} if variant is not inline-compact`, () => {
+  render(
+    <ClipboardCopy variant="expansion" data-testid={testId}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByTestId(testId)).not.toHaveClass(styles.modifiers.inline);
+});
+
+test(`Renders with class ${styles.modifiers.inline} when variant is inline-compact`, () => {
+  render(
+    <ClipboardCopy variant="inline-compact" data-testid={testId}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByTestId(testId)).toHaveClass(styles.modifiers.inline);
+});
+
+test(`Does not render with class ${styles.modifiers.expanded} by default`, () => {
+  render(<ClipboardCopy data-testid={testId}>{children}</ClipboardCopy>);
+
+  expect(screen.getByTestId(testId)).not.toHaveClass(styles.modifiers.expanded);
+});
+
+test(`Renders with class ${styles.modifiers.expanded} when isExpanded is passed`, () => {
+  render(
+    <ClipboardCopy isExpanded data-testid={testId}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByTestId(testId)).toHaveClass(styles.modifiers.expanded);
+});
+
+test(`Does not render with class ${styles.modifiers.block} by default`, () => {
+  render(<ClipboardCopy data-testid={testId}>{children}</ClipboardCopy>);
+
+  expect(screen.getByTestId(testId)).not.toHaveClass(styles.modifiers.block);
+});
+
+test(`Renders with class ${styles.modifiers.block} when isBlock is passed`, () => {
+  render(
+    <ClipboardCopy isBlock data-testid={testId}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByTestId(testId)).toHaveClass(styles.modifiers.block);
+});
+
+test('Spreads additional props to container div', () => {
+  render(
+    <ClipboardCopy data-testid={testId} role="group">
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByTestId(testId)).toHaveAttribute('role', 'group');
+});
+
+test(`Renders children without class ${styles.modifiers.code} when variant is inline-compact and isCode is not passed`, () => {
+  render(
+    <ClipboardCopy variant="inline-compact" data-testid={testId}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText(children)).not.toHaveClass(styles.modifiers.code);
+});
+
+test(`Renders children with class ${styles.modifiers.code} when variant is inline-compact and isCode is passed`, () => {
+  render(
+    <ClipboardCopy isCode variant="inline-compact" data-testid={testId}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText(children)).toHaveClass(styles.modifiers.code);
+});
+
+test('Does not render content passed to additionalActions by default', () => {
+  render(<ClipboardCopy additionalActions="Additional action">{children}</ClipboardCopy>);
+
+  expect(screen.queryByText('Additional action')).toBeNull();
+});
+
+test('Does not render content passed to additionalActions when variant is not inline-compact', () => {
+  render(
+    <ClipboardCopy variant="expansion" additionalActions="Additional action">
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.queryByText('Additional action')).toBeNull();
+});
+
+test('Renders content passed to additionalActions when variant is inline-compact', () => {
+  render(
+    <ClipboardCopy variant="inline-compact" additionalActions="Additional action">
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText('Additional action')).toBeVisible();
+});
+
+test('Passes hoverTip to ClipboardCopyButton by default', () => {
+  render(<ClipboardCopy hoverTip="hover tip">{children}</ClipboardCopy>);
+
+  expect(screen.getByText('button-ariaLabel: hover tip')).toBeVisible();
+  expect(screen.getByText('children: hover tip')).toBeVisible();
+});
+
+test('Passes hoverTip to ClipboardCopyButton when variant is inline-compact', () => {
+  render(
+    <ClipboardCopy variant="inline-compact" hoverTip="hover tip">
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText('button-ariaLabel: hover tip')).toBeVisible();
+  expect(screen.getByText('children: hover tip')).toBeVisible();
+});
+
+test('Passes entryDelay to ClipboardCopyButton by default', () => {
+  render(<ClipboardCopy entryDelay={100}>{children}</ClipboardCopy>);
+
+  expect(screen.getByText('entryDelay: 100')).toBeVisible();
+});
+
+test('Passes entryDelay to ClipboardCopyButton when variant is inline-compact', () => {
+  render(
+    <ClipboardCopy variant="inline-compact" entryDelay={100}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText('entryDelay: 100')).toBeVisible();
+});
+
+test('Passes exitDelay to ClipboardCopyButton by default', () => {
+  render(<ClipboardCopy exitDelay={100}>{children}</ClipboardCopy>);
+
+  expect(screen.getByText('exitDelay: 100')).toBeVisible();
+});
+
+test('Passes exitDelay to ClipboardCopyButton when variant is inline-compact', () => {
+  render(
+    <ClipboardCopy variant="inline-compact" exitDelay={100}>
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText('exitDelay: 100')).toBeVisible();
+});
+
+test('Passes maxWidth to ClipboardCopyButton by default', () => {
+  render(<ClipboardCopy maxWidth="100">{children}</ClipboardCopy>);
+
+  expect(screen.getByText('maxWidth: 100')).toBeVisible();
+});
+
+test('Passes maxWidth to ClipboardCopyButton when variant is inline-compact', () => {
+  render(
+    <ClipboardCopy variant="inline-compact" maxWidth="100">
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText('maxWidth: 100')).toBeVisible();
+});
+
+test('Passes position to ClipboardCopyButton by default', () => {
+  render(<ClipboardCopy position="bottom">{children}</ClipboardCopy>);
+
+  expect(screen.getByText('position: bottom')).toBeVisible();
+});
+
+test('Passes position to ClipboardCopyButton when variant is inline-compact', () => {
+  render(
+    <ClipboardCopy variant="inline-compact" position="bottom">
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText('position: bottom')).toBeVisible();
+});
+
+test('Passes toggleAriaLabel to ClipboardCopyToggle when variant is expansion', () => {
+  render(
+    <ClipboardCopy variant="expansion" toggleAriaLabel="toggle label">
+      {children}
+    </ClipboardCopy>
+  );
+
+  expect(screen.getByText('toggle-ariaLabel: toggle label')).toBeVisible();
+});
+
+test('Passes isReadOnly to TextInput', () => {
+  render(<ClipboardCopy isReadOnly>{children}</ClipboardCopy>);
+
+  expect(screen.getByRole('textbox')).toHaveAttribute('readonly');
+});
+
+test('Passes textAriaLabel to TextInput', () => {
+  render(<ClipboardCopy textAriaLabel="text label">{children}</ClipboardCopy>);
+
+  expect(screen.getByRole('textbox')).toHaveAccessibleName('text label');
+});
+
+test('Calls onChange', async () => {
+  const onChangeMock = jest.fn();
+  const user = userEvent.setup();
+  const typedText = 'stuff';
+
+  render(<ClipboardCopy onChange={onChangeMock}>{children}</ClipboardCopy>);
+
+  await user.type(screen.getByRole('textbox'), typedText);
+
+  expect(onChangeMock).toHaveBeenCalledTimes(typedText.length);
+});
diff --git a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
index fbed3c30aec..8a19d362223 100644
--- a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
+++ b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
@@ -16,4 +16,13 @@ describe('Clipboard Copy Demo Test', () => {
     cy.get('#inline-copy').should('have.class', 'pf-m-inline');
     cy.get('#inline-copy').should('have.class', 'pf-m-block');
   });
+
+  it('Verify clickTip renders', () => {
+    cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').focus();
+    // Wait for default entryDelay of 300ms
+    cy.wait(500);
+    cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button not clicked');
+    cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').click();
+    cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button clicked');
+  });
 });
diff --git a/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx
index b75562c9e36..3b380df3129 100644
--- a/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx
+++ b/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import { ClipboardCopy, ClipboardCopyVariant, ClipboardCopyAction, Button } from '@patternfly/react-core';
 import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon';
 
+// eslint-disable-next-line patternfly-react/no-anonymous-functions
 export class ClipboardCopyDemo extends React.Component {
   static displayName = 'ClipboardCopyDemo';
   render() {
@@ -32,6 +33,16 @@ export class ClipboardCopyDemo extends React.Component {
           </ClipboardCopy>
           is inline in a sentence.
         </div>
+        <br />
+        <br />
+        <ClipboardCopy
+          onCopy={() => {}}
+          id="tooltip-test"
+          hoverTip="Copy button not clicked"
+          clickTip="Copy button clicked"
+        >
+          Some random text.
+        </ClipboardCopy>
       </React.Fragment>
     );
   }

From aed53f0c362702729852b94699a4d663fc392fce Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Thu, 7 Sep 2023 10:15:12 -0400
Subject: [PATCH 3/9] Removed generated tests, added snapshot

---
 .../__tests__/ClipboardCopy.test.tsx          |  5 ++
 .../Generated/ClipboardCopy.test.tsx          | 40 --------------
 .../__snapshots__/ClipboardCopy.test.tsx.snap | 55 -------------------
 .../__snapshots__/ClipboardCopy.test.tsx.snap | 52 ++++++++++++++++++
 4 files changed, 57 insertions(+), 95 deletions(-)
 delete mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/Generated/ClipboardCopy.test.tsx
 delete mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/Generated/__snapshots__/ClipboardCopy.test.tsx.snap
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap

diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
index b71b7bfa92c..448e42dffa1 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
@@ -273,3 +273,8 @@ test('Calls onChange', async () => {
 
   expect(onChangeMock).toHaveBeenCalledTimes(typedText.length);
 });
+
+test('Matches snapshot', () => {
+  const { asFragment } = render(<ClipboardCopy>{children}</ClipboardCopy>);
+  expect(asFragment()).toMatchSnapshot();
+});
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/Generated/ClipboardCopy.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/Generated/ClipboardCopy.test.tsx
deleted file mode 100644
index 612abfd0e14..00000000000
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/Generated/ClipboardCopy.test.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * This test was generated
- */
-import * as React from 'react';
-import { render } from '@testing-library/react';
-import { ClipboardCopy } from '../../ClipboardCopy';
-// any missing imports can usually be resolved by adding them here
-import {} from '../..';
-
-it('ClipboardCopy should match snapshot (auto-generated)', () => {
-  const { asFragment } = render(
-    <ClipboardCopy
-      className={'string'}
-      hoverTip={"'Copy to clipboard'"}
-      clickTip={"'Successfully copied to clipboard!'"}
-      textAriaLabel={"'Copyable input'"}
-      toggleAriaLabel={"'Show content'"}
-      isReadOnly={false}
-      isExpanded={false}
-      isCode={false}
-      variant={'inline'}
-      position={'auto'}
-      maxWidth={"'150px'"}
-      exitDelay={1600}
-      entryDelay={100}
-      onCopy={(event: React.ClipboardEvent<HTMLDivElement>, text?: React.ReactNode) => {
-        const clipboard = event.currentTarget.parentElement;
-        const el = document.createElement('input');
-        el.value = text.toString();
-        clipboard.appendChild(el);
-        el.select();
-        document.execCommand('copy');
-        clipboard.removeChild(el);
-      }}
-      onChange={(): any => undefined}
-      children={<div>ReactNode</div>}
-    />
-  );
-  expect(asFragment()).toMatchSnapshot();
-});
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/Generated/__snapshots__/ClipboardCopy.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/Generated/__snapshots__/ClipboardCopy.test.tsx.snap
deleted file mode 100644
index 9b881779f24..00000000000
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/Generated/__snapshots__/ClipboardCopy.test.tsx.snap
+++ /dev/null
@@ -1,55 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ClipboardCopy should match snapshot (auto-generated) 1`] = `
-<DocumentFragment>
-  <div
-    class="pf-v5-c-clipboard-copy string"
-    data-ouia-component-type="PF5/ClipboardCopy"
-    data-ouia-safe="true"
-  >
-    <div
-      class="pf-v5-c-clipboard-copy__group"
-    >
-      <span
-        class="pf-v5-c-form-control"
-      >
-        <input
-          aria-invalid="false"
-          aria-label="'Copyable input'"
-          data-ouia-component-id="OUIA-Generated-TextInputBase-1"
-          data-ouia-component-type="PF5/TextInput"
-          data-ouia-safe="true"
-          id="text-input-0"
-          type="text"
-          value="[object Object]"
-        />
-      </span>
-      <button
-        aria-disabled="false"
-        aria-label="'Copy to clipboard'"
-        aria-labelledby="copy-button-0 text-input-0"
-        class="pf-v5-c-button pf-m-control"
-        data-ouia-component-id="OUIA-Generated-Button-control-1"
-        data-ouia-component-type="PF5/Button"
-        data-ouia-safe="true"
-        id="copy-button-0"
-        type="button"
-      >
-        <svg
-          aria-hidden="true"
-          class="pf-v5-svg"
-          fill="currentColor"
-          height="1em"
-          role="img"
-          viewBox="0 0 448 512"
-          width="1em"
-        >
-          <path
-            d="M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"
-          />
-        </svg>
-      </button>
-    </div>
-  </div>
-</DocumentFragment>
-`;
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap
new file mode 100644
index 00000000000..fa7540bf2e4
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap
@@ -0,0 +1,52 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Matches snapshot 1`] = `
+<DocumentFragment>
+  <div
+    class="pf-v5-c-clipboard-copy"
+    data-ouia-component-type="PF5/ClipboardCopy"
+    data-ouia-safe="true"
+  >
+    <div
+      class="pf-v5-c-clipboard-copy__group"
+    >
+      <span
+        class="pf-v5-c-form-control"
+      >
+        <input
+          aria-invalid="false"
+          aria-label="Copyable input"
+          data-ouia-component-id="OUIA-Generated-TextInputBase-21"
+          data-ouia-component-type="PF5/TextInput"
+          data-ouia-safe="true"
+          id="text-input-29"
+          type="text"
+          value="Copyable text"
+        />
+      </span>
+      <div
+        data-testid="clipboardCopyButton-mock"
+      >
+        <p>
+          exitDelay: 1500
+        </p>
+        <p>
+          entryDelay: 300
+        </p>
+        <p>
+          maxWidth: 150px
+        </p>
+        <p>
+          position: top
+        </p>
+        <p>
+          button-ariaLabel: Copy to clipboard
+        </p>
+        <div>
+          children: Copy to clipboard
+        </div>
+      </div>
+    </div>
+  </div>
+</DocumentFragment>
+`;

From b756909794ba05b290ad5dca0dbfbab3a59f80f8 Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Thu, 7 Sep 2023 13:14:32 -0400
Subject: [PATCH 4/9] Updated onTooltipHidden test to integration

---
 .../__tests__/ClipboardCopyButton.test.tsx           | 10 ++--------
 .../__snapshots__/ClipboardCopyButton.test.tsx.snap  | 12 +-----------
 .../cypress/integration/clipboardcopy.spec.ts        | 10 +++++++++-
 3 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
index 64193765b82..00b705e020c 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
@@ -6,14 +6,13 @@ import { ClipboardCopyButton } from '../ClipboardCopyButton';
 import buttonStyles from '@patternfly/react-styles/css/components/Button/button';
 
 jest.mock('../../Tooltip', () => ({
-  Tooltip: ({ content, children, exitDelay, entryDelay, maxWidth, position, onTooltipHidden, ...props }) => (
-    <div data-testid="tooltip-mock" {...props}>
+  Tooltip: ({ content, children, exitDelay, entryDelay, maxWidth, position }) => (
+    <div data-testid="tooltip-mock">
       <div data-testid="tooltip-mock-content">{content}</div>
       <p>{`exitDelay: ${exitDelay}`}</p>
       <p>{`entryDelay: ${entryDelay}`}</p>
       <p>{`maxWidth: ${maxWidth}`}</p>
       <p>{`position: ${position}`}</p>
-      <p>{`onTooltipHidden: ${onTooltipHidden}`}</p>
       {children}
     </div>
   )
@@ -121,11 +120,6 @@ test('Passes position to Tooltip', () => {
 
   expect(screen.getByText('position: bottom')).toBeVisible();
 });
-test('Passes onTooltipHidden to Tooltip', () => {
-  render(<ClipboardCopyButton onTooltipHidden={() => {}} {...requiredProps} />);
-
-  expect(screen.getByText('onTooltipHidden: () => {}')).toBeVisible();
-});
 
 test('Matches snapshot', () => {
   const { asFragment } = render(<ClipboardCopyButton {...requiredProps} />);
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
index 4311fe4d86e..37358735497 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
@@ -3,11 +3,7 @@
 exports[`Matches snapshot 1`] = `
 <DocumentFragment>
   <div
-    aria="none"
-    aria-live="polite"
     data-testid="tooltip-mock"
-    trigger="mouseenter focus click"
-    triggerref="[object Object]"
   >
     <div
       data-testid="tooltip-mock-content"
@@ -28,18 +24,12 @@ exports[`Matches snapshot 1`] = `
     <p>
       position: top
     </p>
-    <p>
-      onTooltipHidden: () =&gt; {
-        /* istanbul ignore next */
-        cov_274vctcufi().f[1]++;
-      }
-    </p>
     <button
       aria-disabled="false"
       aria-label="Copyable input"
       aria-labelledby="button-id text-id"
       class="pf-v5-c-button pf-m-control"
-      data-ouia-component-id="OUIA-Generated-Button-control-14"
+      data-ouia-component-id="OUIA-Generated-Button-control-13"
       data-ouia-component-type="PF5/Button"
       data-ouia-safe="true"
       id="button-id"
diff --git a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
index 8a19d362223..ea5f9cd51c4 100644
--- a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
+++ b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
@@ -17,12 +17,20 @@ describe('Clipboard Copy Demo Test', () => {
     cy.get('#inline-copy').should('have.class', 'pf-m-block');
   });
 
-  it('Verify clickTip renders', () => {
+  it('Verify hoverTip and clickTip render and onTooltipHidden called', () => {
     cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').focus();
     // Wait for default entryDelay of 300ms
     cy.wait(500);
     cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button not clicked');
     cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').click();
     cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button clicked');
+    cy.get('#tooltip-test input').focus();
+
+    // By default onTooltipHidden is called to set internal copied state to false, which
+    // would reset the tooltip content to the hoverTip prop value
+    cy.wait(500);
+    cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').focus();
+    cy.wait(500);
+    cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button not clicked');
   });
 });

From facced169b34eab92bd910fbe965af87956ae7d3 Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Fri, 8 Sep 2023 09:10:48 -0400
Subject: [PATCH 5/9] Separated tooltip and callback tests

---
 .../cypress/integration/clipboardcopy.spec.ts | 25 +++++++++++--------
 .../ClipboardCopyDemo/ClipboardCopyDemo.tsx   | 12 +++++++++
 2 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
index ea5f9cd51c4..a679f57c04c 100644
--- a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
+++ b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
@@ -17,20 +17,25 @@ describe('Clipboard Copy Demo Test', () => {
     cy.get('#inline-copy').should('have.class', 'pf-m-block');
   });
 
-  it('Verify hoverTip and clickTip render and onTooltipHidden called', () => {
+  it('Verify hoverTip and clickTip render', () => {
     cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').focus();
-    // Wait for default entryDelay of 300ms
-    cy.wait(500);
     cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button not clicked');
+    // Wait for defaulty entryDelay
+    cy.wait(500);
     cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').click();
     cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button clicked');
-    cy.get('#tooltip-test input').focus();
+  });
 
-    // By default onTooltipHidden is called to set internal copied state to false, which
-    // would reset the tooltip content to the hoverTip prop value
-    cy.wait(500);
-    cy.get('#tooltip-test .pf-v5-c-button.pf-m-control').focus();
-    cy.wait(500);
-    cy.get('.pf-v5-c-tooltip').should('have.text', 'Copy button not clicked');
+  it('Verify onTooltipHidden callback is called', () => {
+    cy.get('#onTooltipHidden-test .pf-v5-c-button.pf-m-control').focus();
+    cy.get('.pf-v5-c-tooltip').should('have.text', 'onTooltipHidden not clicked');
+    cy.get('#onTooltipHidden-test .pf-v5-c-button.pf-m-control').click();
+    cy.get('.pf-v5-c-tooltip').should('have.text', 'onTooltipHidden clicked');
+    cy.get('#onTooltipHidden-test input').focus();
+    cy.wait(50);
+    cy.get('#onTooltipHidden-test .pf-v5-c-button.pf-m-control').focus();
+    // By default onTooltipHidden is called within ClipboardCopy to set internal copied state,
+    // which will reset the tooltip content to the hoverTip prop value
+    cy.get('.pf-v5-c-tooltip').should('have.text', 'onTooltipHidden not clicked');
   });
 });
diff --git a/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx
index 3b380df3129..cd4f0b3f555 100644
--- a/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx
+++ b/packages/react-integration/demo-app-ts/src/components/demos/ClipboardCopyDemo/ClipboardCopyDemo.tsx
@@ -43,6 +43,18 @@ export class ClipboardCopyDemo extends React.Component {
         >
           Some random text.
         </ClipboardCopy>
+        <br />
+        <br />
+        <ClipboardCopy
+          exitDelay={0}
+          entryDelay={0}
+          onCopy={() => {}}
+          id="onTooltipHidden-test"
+          hoverTip="onTooltipHidden not clicked"
+          clickTip="onTooltipHidden clicked"
+        >
+          Some random text.
+        </ClipboardCopy>
       </React.Fragment>
     );
   }

From e0c45bf7bb751691970e00079815dca70e41deef Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Fri, 8 Sep 2023 09:56:16 -0400
Subject: [PATCH 6/9] Adjusted wait time in cypress

---
 .../react-integration/cypress/integration/clipboardcopy.spec.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
index a679f57c04c..48b2860351c 100644
--- a/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
+++ b/packages/react-integration/cypress/integration/clipboardcopy.spec.ts
@@ -32,7 +32,7 @@ describe('Clipboard Copy Demo Test', () => {
     cy.get('#onTooltipHidden-test .pf-v5-c-button.pf-m-control').click();
     cy.get('.pf-v5-c-tooltip').should('have.text', 'onTooltipHidden clicked');
     cy.get('#onTooltipHidden-test input').focus();
-    cy.wait(50);
+    cy.wait(500);
     cy.get('#onTooltipHidden-test .pf-v5-c-button.pf-m-control').focus();
     // By default onTooltipHidden is called within ClipboardCopy to set internal copied state,
     // which will reset the tooltip content to the hoverTip prop value

From c4277f5b592560617f47592d54eea20a12a1bf3d Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Mon, 9 Oct 2023 13:16:22 -0400
Subject: [PATCH 7/9] Updated snapshots after rebase

---
 .../ClipboardCopyExpanded.test.tsx.snap       | 32 ----------------
 .../ClipboardCopyToggle.test.tsx.snap         | 37 -------------------
 2 files changed, 69 deletions(-)
 delete mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap
 delete mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap

diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap
deleted file mode 100644
index 01bc2ca3bce..00000000000
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap
+++ /dev/null
@@ -1,32 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`expanded code content render 1`] = `
-<DocumentFragment>
-  <div
-    class="pf-v5-c-clipboard-copy__expandable-content class-1"
-    contenteditable="true"
-    id="id-1"
-  >
-    <pre
-      dir="ltr"
-    >
-      {
-    "name": "@patternfly/react-core",
-    "version": "1.33.2"
-  }
-    </pre>
-  </div>
-</DocumentFragment>
-`;
-
-exports[`expanded content render 1`] = `
-<DocumentFragment>
-  <div
-    class="pf-v5-c-clipboard-copy__expandable-content class-1"
-    contenteditable="true"
-    id="id-1"
-  >
-    This is my text
-  </div>
-</DocumentFragment>
-`;
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap
deleted file mode 100644
index ea395c521de..00000000000
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap
+++ /dev/null
@@ -1,37 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ClipboardCopyToggle toggle button render 1`] = `
-<DocumentFragment>
-  <button
-    aria-controls="my-id my-content-id"
-    aria-disabled="false"
-    aria-expanded="false"
-    aria-label="toggle content"
-    aria-labelledby="my-id my-text-id"
-    class="pf-v5-c-button pf-m-control myclassName"
-    data-ouia-component-id="OUIA-Generated-Button-control-1"
-    data-ouia-component-type="PF5/Button"
-    data-ouia-safe="true"
-    id="my-id"
-    type="button"
-  >
-    <div
-      class="pf-v5-c-clipboard-copy__toggle-icon"
-    >
-      <svg
-        aria-hidden="true"
-        class="pf-v5-svg"
-        fill="currentColor"
-        height="1em"
-        role="img"
-        viewBox="0 0 256 512"
-        width="1em"
-      >
-        <path
-          d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"
-        />
-      </svg>
-    </div>
-  </button>
-</DocumentFragment>
-`;

From 8d4c53587823c8f88e5db2fffa0e806e4c83a69f Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Mon, 16 Oct 2023 11:30:42 -0400
Subject: [PATCH 8/9] Added tests for non-exported components

---
 .../ClipboardCopy/ClipboardCopyToggle.tsx     |  2 +-
 .../__tests__/ClipboardCopy.test.tsx          |  2 +-
 .../__tests__/ClipboardCopyAction.test.tsx    |  2 +-
 .../__tests__/ClipboardCopyExpanded.test.tsx  | 80 ++++++++++++++++
 .../__tests__/ClipboardCopyToggle.test.tsx    | 92 +++++++++++++++++++
 .../ClipboardCopyExpanded.test.tsx.snap       | 12 +++
 .../ClipboardCopyToggle.test.tsx.snap         | 36 ++++++++
 7 files changed, 223 insertions(+), 3 deletions(-)
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap
 create mode 100644 packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap

diff --git a/packages/react-core/src/components/ClipboardCopy/ClipboardCopyToggle.tsx b/packages/react-core/src/components/ClipboardCopy/ClipboardCopyToggle.tsx
index 1146d326d06..c26bdbbc2e9 100644
--- a/packages/react-core/src/components/ClipboardCopy/ClipboardCopyToggle.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/ClipboardCopyToggle.tsx
@@ -28,7 +28,7 @@ export const ClipboardCopyToggle: React.FunctionComponent<ClipboardCopyTogglePro
     onClick={onClick}
     id={id}
     aria-labelledby={`${id} ${textId}`}
-    aria-controls={`${id} ${contentId}`}
+    aria-controls={contentId}
     aria-expanded={isExpanded}
     {...props}
   >
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
index 448e42dffa1..108f7ca5539 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
@@ -31,7 +31,7 @@ const testId = 'clipboard-copy';
 test(`Renders with class ${styles.clipboardCopy} by default`, () => {
   render(<ClipboardCopy data-testid={testId}>{children}</ClipboardCopy>);
 
-  expect(screen.getByTestId(testId)).toHaveClass(styles.clipboardCopy);
+  expect(screen.getByTestId(testId)).toHaveClass(styles.clipboardCopy, { exact: true });
 });
 
 test(`Renders with custom class when className is passed`, () => {
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx
index 98015f64dc9..0419477b26b 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyAction.test.tsx
@@ -16,7 +16,7 @@ test('Renders without children', () => {
 test(`Renders with class ${styles.clipboardCopyActionsItem} by default`, () => {
   render(<ClipboardCopyAction>Action text</ClipboardCopyAction>);
 
-  expect(screen.getByText('Action text')).toHaveClass(styles.clipboardCopyActionsItem);
+  expect(screen.getByText('Action text')).toHaveClass(styles.clipboardCopyActionsItem, { exact: true });
 });
 
 test(`Renders with custom class when className is passed`, () => {
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
new file mode 100644
index 00000000000..bbc2f1c24fe
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
@@ -0,0 +1,80 @@
+import React from 'react';
+import { screen, render } from '@testing-library/react';
+import { ClipboardCopyExpanded } from '../ClipboardCopyExpanded';
+import styles from '@patternfly/react-styles/css/components/ClipboardCopy/clipboard-copy';
+import userEvent from '@testing-library/user-event';
+
+test(`Renders with classname ${styles.clipboardCopyExpandableContent} by default`, () => {
+  render(<ClipboardCopyExpanded>Expanded content</ClipboardCopyExpanded>);
+
+  expect(screen.getByText('Expanded content')).toHaveClass(styles.clipboardCopyExpandableContent, { exact: true });
+});
+
+test(`Renders with custom class when className is passed`, () => {
+  render(<ClipboardCopyExpanded className="test-class">Expanded content</ClipboardCopyExpanded>);
+
+  expect(screen.getByText('Expanded content')).toHaveClass('test-class');
+});
+
+test('Does not render with <pre> tag by default', () => {
+  render(<ClipboardCopyExpanded>Expanded content</ClipboardCopyExpanded>);
+
+  expect(screen.getByText('Expanded content').tagName).not.toBe('PRE');
+});
+
+test('Renders with <pre> tag when isCode is true', () => {
+  render(<ClipboardCopyExpanded isCode>Expanded content</ClipboardCopyExpanded>);
+
+  expect(screen.getByText('Expanded content').tagName).toBe('PRE');
+});
+
+test('Renders with contenteditable attribute of true by default', () => {
+  render(<ClipboardCopyExpanded>Expanded content</ClipboardCopyExpanded>);
+
+  expect(screen.getByText('Expanded content')).toHaveAttribute('contenteditable', 'true');
+});
+
+test('Renders with contenteditable attribute of false when isReadOnly is passed', () => {
+  render(<ClipboardCopyExpanded isReadOnly>Expanded content</ClipboardCopyExpanded>);
+
+  expect(screen.getByText('Expanded content')).toHaveAttribute('contenteditable', 'false');
+});
+
+test('Calls onChange when expanded content is typed in', async () => {
+  const user = userEvent.setup();
+  const onChangeMock = jest.fn();
+
+  render(<ClipboardCopyExpanded onChange={onChangeMock}>Expanded content</ClipboardCopyExpanded>);
+
+  await user.type(screen.getByText('Expanded content'), 's');
+
+  expect(onChangeMock).toHaveBeenCalled();
+});
+
+test('Does not call onChange when expanded content is not typed in', async () => {
+  const user = userEvent.setup();
+  const onChangeMock = jest.fn();
+
+  render(
+    <>
+      <ClipboardCopyExpanded onChange={onChangeMock}>Expanded content</ClipboardCopyExpanded>
+      <input />
+    </>
+  );
+
+  await user.type(screen.getByRole('textbox'), 'A');
+
+  expect(onChangeMock).not.toHaveBeenCalled();
+});
+
+test('Spreads additional props to container', () => {
+  render(<ClipboardCopyExpanded data-prop="test">Expanded content</ClipboardCopyExpanded>);
+
+  expect(screen.getByText('Expanded content')).toHaveAttribute('data-prop', 'test');
+});
+
+test('Matches snapshot', () => {
+  const { asFragment } = render(<ClipboardCopyExpanded>Expanded content</ClipboardCopyExpanded>);
+
+  expect(asFragment()).toMatchSnapshot();
+});
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
new file mode 100644
index 00000000000..1c98cd4e53c
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import { screen, render } from '@testing-library/react';
+import { ClipboardCopyToggle } from '../ClipboardCopyToggle';
+import styles from '@patternfly/react-styles/css/components/ClipboardCopy/clipboard-copy';
+import userEvent from '@testing-library/user-event';
+
+const onClickMock = jest.fn();
+const requiredProps = {
+  id: 'main-id',
+  textId: 'text-id',
+  contentId: 'content-id',
+  onClick: onClickMock
+};
+
+// Must be kept as first test to avoid Button's ouiaId updating in snapshots
+test('Matches snapshot', () => {
+  const { asFragment } = render(<ClipboardCopyToggle {...requiredProps} />);
+
+  expect(asFragment()).toMatchSnapshot();
+});
+
+test('Renders without children', () => {
+  render(
+    <div data-testid="container">
+      <ClipboardCopyToggle {...requiredProps} />
+    </div>
+  );
+
+  expect(screen.getByTestId('container').firstChild).toBeVisible();
+});
+
+test('Renders with id prop', () => {
+  render(<ClipboardCopyToggle {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveAttribute('id', requiredProps.id);
+});
+
+test('Renders with aria-labelledby concatenated from id and textId props', () => {
+  render(
+    <>
+      <ClipboardCopyToggle aria-label="Toggle content" {...requiredProps} />
+      <span id={requiredProps.textId}>Test content</span>
+    </>
+  );
+
+  expect(screen.getByRole('button')).toHaveAccessibleName('Toggle content Test content');
+});
+
+test('Renders with aria-controls with passed in contentId prop', () => {
+  render(<ClipboardCopyToggle {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveAttribute('aria-controls', requiredProps.contentId);
+});
+
+test('Renders with aria-expanded of false by default', () => {
+  render(<ClipboardCopyToggle {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'false');
+});
+
+test('Renders with aria-expanded based on isExpanded prop', () => {
+  render(<ClipboardCopyToggle isExpanded={true} {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'true');
+});
+
+test('Calls onClick when clipboard toggle is clicked', async () => {
+  const user = userEvent.setup();
+  render(<ClipboardCopyToggle {...requiredProps} />);
+
+  await user.click(screen.getByRole('button'));
+  expect(onClickMock).toHaveBeenCalled();
+});
+
+test('Does not call onClick when clipboard toggle is not clicked', async () => {
+  const user = userEvent.setup();
+  render(
+    <>
+      <ClipboardCopyToggle {...requiredProps} />
+      <button>Test clicker</button>
+    </>
+  );
+
+  await user.click(screen.getByRole('button', { name: 'Test clicker' }));
+  expect(onClickMock).not.toHaveBeenCalled();
+});
+
+test('Spreads additional props to container', () => {
+  render(<ClipboardCopyToggle data-prop="test" {...requiredProps} />);
+
+  expect(screen.getByRole('button')).toHaveAttribute('data-prop', 'test');
+});
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap
new file mode 100644
index 00000000000..3204f2ba149
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap
@@ -0,0 +1,12 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Matches snapshot 1`] = `
+<DocumentFragment>
+  <div
+    class="pf-v5-c-clipboard-copy__expandable-content"
+    contenteditable="true"
+  >
+    Expanded content
+  </div>
+</DocumentFragment>
+`;
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap
new file mode 100644
index 00000000000..cd43bec9fc7
--- /dev/null
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap
@@ -0,0 +1,36 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Matches snapshot 1`] = `
+<DocumentFragment>
+  <button
+    aria-controls="content-id"
+    aria-disabled="false"
+    aria-expanded="false"
+    aria-labelledby="main-id text-id"
+    class="pf-v5-c-button pf-m-control"
+    data-ouia-component-id="OUIA-Generated-Button-control-1"
+    data-ouia-component-type="PF5/Button"
+    data-ouia-safe="true"
+    id="main-id"
+    type="button"
+  >
+    <div
+      class="pf-v5-c-clipboard-copy__toggle-icon"
+    >
+      <svg
+        aria-hidden="true"
+        class="pf-v5-svg"
+        fill="currentColor"
+        height="1em"
+        role="img"
+        viewBox="0 0 256 512"
+        width="1em"
+      >
+        <path
+          d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"
+        />
+      </svg>
+    </div>
+  </button>
+</DocumentFragment>
+`;

From 68d6f8f91a429bb591f551ae211e422254c27deb Mon Sep 17 00:00:00 2001
From: Eric Olkowski <thatblindgeye@gmail.com>
Date: Thu, 19 Oct 2023 08:25:01 -0400
Subject: [PATCH 9/9] Updated per Austin comments

---
 .../__tests__/ClipboardCopy.test.tsx          | 70 ++++++++++++++++++-
 .../__tests__/ClipboardCopyButton.test.tsx    | 39 +++++++++--
 .../__tests__/ClipboardCopyExpanded.test.tsx  |  2 +-
 .../__tests__/ClipboardCopyToggle.test.tsx    |  2 +-
 .../__snapshots__/ClipboardCopy.test.tsx.snap |  9 ++-
 .../ClipboardCopyButton.test.tsx.snap         |  5 +-
 6 files changed, 113 insertions(+), 14 deletions(-)

diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
index 108f7ca5539..4d2b38cb5a6 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx
@@ -5,7 +5,7 @@ import styles from '@patternfly/react-styles/css/components/ClipboardCopy/clipbo
 import userEvent from '@testing-library/user-event';
 
 jest.mock('../ClipboardCopyButton', () => ({
-  ClipboardCopyButton: ({ 'aria-label': ariaLabel, children, entryDelay, exitDelay, maxWidth, position }) => (
+  ClipboardCopyButton: ({ 'aria-label': ariaLabel, children, entryDelay, exitDelay, maxWidth, position, onClick }) => (
     <div data-testid="clipboardCopyButton-mock">
       <p>{`exitDelay: ${exitDelay}`}</p>
       <p>{`entryDelay: ${entryDelay}`}</p>
@@ -13,6 +13,7 @@ jest.mock('../ClipboardCopyButton', () => ({
       <p>{`position: ${position}`}</p>
       <p>{`button-ariaLabel: ${ariaLabel}`}</p>
       <div>{`children: ${children}`}</div>
+      <button onClick={onClick}>Test CCB clicker</button>
     </div>
   )
 }));
@@ -176,6 +177,15 @@ test('Passes hoverTip to ClipboardCopyButton when variant is inline-compact', ()
   expect(screen.getByText('children: hover tip')).toBeVisible();
 });
 
+test('Passes clickTip when ClipboardCopyButton clicked', async () => {
+  const user = userEvent.setup();
+  render(<ClipboardCopy clickTip="click tip">{children}</ClipboardCopy>);
+
+  await user.click(screen.getByRole('button', { name: 'Test CCB clicker' }));
+
+  expect(screen.getByText('children: click tip')).toBeVisible();
+});
+
 test('Passes entryDelay to ClipboardCopyButton by default', () => {
   render(<ClipboardCopy entryDelay={100}>{children}</ClipboardCopy>);
 
@@ -250,6 +260,12 @@ test('Passes toggleAriaLabel to ClipboardCopyToggle when variant is expansion',
   expect(screen.getByText('toggle-ariaLabel: toggle label')).toBeVisible();
 });
 
+test('Does not set textinput to readonly when isReadOnly is not passed', () => {
+  render(<ClipboardCopy>{children}</ClipboardCopy>);
+
+  expect(screen.getByRole('textbox')).not.toHaveAttribute('readonly');
+});
+
 test('Passes isReadOnly to TextInput', () => {
   render(<ClipboardCopy isReadOnly>{children}</ClipboardCopy>);
 
@@ -262,7 +278,7 @@ test('Passes textAriaLabel to TextInput', () => {
   expect(screen.getByRole('textbox')).toHaveAccessibleName('text label');
 });
 
-test('Calls onChange', async () => {
+test('Calls onChange when ClipboardCopy textinput is typed in', async () => {
   const onChangeMock = jest.fn();
   const user = userEvent.setup();
   const typedText = 'stuff';
@@ -274,7 +290,55 @@ test('Calls onChange', async () => {
   expect(onChangeMock).toHaveBeenCalledTimes(typedText.length);
 });
 
+test('Does not call onChange when ClipboardCopy textinput is not typed in', async () => {
+  const onChangeMock = jest.fn();
+  const user = userEvent.setup();
+  const typedText = 'stuff';
+
+  render(
+    <>
+      <ClipboardCopy onChange={onChangeMock}>{children}</ClipboardCopy>
+      <input aria-label="native input" />
+    </>
+  );
+
+  await user.type(screen.getByRole('textbox', { name: 'native input' }), typedText);
+
+  expect(onChangeMock).not.toHaveBeenCalled();
+});
+
+test('Calls onCopy when ClipboardCopyButton is clicked', async () => {
+  const onCopyMock = jest.fn();
+  const user = userEvent.setup();
+
+  render(<ClipboardCopy onCopy={onCopyMock}>{children}</ClipboardCopy>);
+
+  await user.click(screen.getByRole('button', { name: 'Test CCB clicker' }));
+
+  expect(onCopyMock).toHaveBeenCalledTimes(1);
+});
+
+test('Does not call onCopy when ClipboardCopyButton is not clicked', async () => {
+  const onCopyMock = jest.fn();
+  const user = userEvent.setup();
+
+  render(
+    <>
+      <ClipboardCopy onCopy={onCopyMock}>{children}</ClipboardCopy>
+      <button>Test native clicker</button>
+    </>
+  );
+
+  await user.click(screen.getByRole('button', { name: 'Test native clicker' }));
+
+  expect(onCopyMock).not.toHaveBeenCalled();
+});
+
 test('Matches snapshot', () => {
-  const { asFragment } = render(<ClipboardCopy>{children}</ClipboardCopy>);
+  const { asFragment } = render(
+    <ClipboardCopy id="snapshot" ouiaId="snapshot">
+      {children}
+    </ClipboardCopy>
+  );
   expect(asFragment()).toMatchSnapshot();
 });
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
index 00b705e020c..34f027dd1c8 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyButton.test.tsx
@@ -6,13 +6,14 @@ import { ClipboardCopyButton } from '../ClipboardCopyButton';
 import buttonStyles from '@patternfly/react-styles/css/components/Button/button';
 
 jest.mock('../../Tooltip', () => ({
-  Tooltip: ({ content, children, exitDelay, entryDelay, maxWidth, position }) => (
+  Tooltip: ({ content, children, exitDelay, entryDelay, maxWidth, position, onTooltipHidden }) => (
     <div data-testid="tooltip-mock">
       <div data-testid="tooltip-mock-content">{content}</div>
       <p>{`exitDelay: ${exitDelay}`}</p>
       <p>{`entryDelay: ${entryDelay}`}</p>
       <p>{`maxWidth: ${maxWidth}`}</p>
       <p>{`position: ${position}`}</p>
+      <a onClick={onTooltipHidden}>onTooltipHidden clicker</a>
       {children}
     </div>
   )
@@ -25,6 +26,12 @@ const requiredProps = {
   textId: 'text-id'
 };
 
+// Must be kept as first test to avoid Button's ouiaId updating in snapshots
+test('Matches snapshot', () => {
+  const { asFragment } = render(<ClipboardCopyButton {...requiredProps} />);
+  expect(asFragment()).toMatchSnapshot();
+});
+
 test('Renders with passed id prop', () => {
   render(<ClipboardCopyButton {...requiredProps} />);
 
@@ -39,7 +46,7 @@ test('Renders with aria-labelledby with passed id and textId prop values', () =>
     </>
   );
 
-  expect(screen.getByRole('button')).toHaveAttribute('aria-labelledby', 'button-id text-id');
+  expect(screen.getByRole('button')).toHaveAccessibleName('Copyable input Copyable text');
 });
 
 test('Renders with concatenated aria-label by default', () => {
@@ -82,7 +89,7 @@ test('Passes variant to Button when variant is passed', () => {
   expect(screen.getByRole('button')).toHaveClass(buttonStyles.modifiers.plain);
 });
 
-test('Calls onClick when passed', async () => {
+test('Calls onClick when ClipboardCopyButton is clicked', async () => {
   const user = userEvent.setup();
 
   render(<ClipboardCopyButton {...requiredProps} />);
@@ -91,6 +98,20 @@ test('Calls onClick when passed', async () => {
   expect(requiredProps.onClick).toHaveBeenCalledTimes(1);
 });
 
+test('Does not call onClick when ClipboardCopyButton is not clicked', async () => {
+  const user = userEvent.setup();
+
+  render(
+    <>
+      <ClipboardCopyButton {...requiredProps} />
+      <button>Test clicker</button>
+    </>
+  );
+
+  await user.click(screen.getByRole('button', { name: 'Test clicker' }));
+  expect(requiredProps.onClick).not.toHaveBeenCalled();
+});
+
 test('Passes children to Tooltip content', () => {
   render(<ClipboardCopyButton {...requiredProps} />);
 
@@ -121,7 +142,13 @@ test('Passes position to Tooltip', () => {
   expect(screen.getByText('position: bottom')).toBeVisible();
 });
 
-test('Matches snapshot', () => {
-  const { asFragment } = render(<ClipboardCopyButton {...requiredProps} />);
-  expect(asFragment()).toMatchSnapshot();
+test('Passes onTooltipHidden to Tooltip', async () => {
+  const user = userEvent.setup();
+  const onTooltipHiddenMock = jest.fn();
+
+  render(<ClipboardCopyButton onTooltipHidden={onTooltipHiddenMock} {...requiredProps} />);
+
+  await user.click(screen.getByText('onTooltipHidden clicker'));
+
+  expect(onTooltipHiddenMock).toHaveBeenCalled();
 });
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
index bbc2f1c24fe..d91426d6e17 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyExpanded.test.tsx
@@ -48,7 +48,7 @@ test('Calls onChange when expanded content is typed in', async () => {
 
   await user.type(screen.getByText('Expanded content'), 's');
 
-  expect(onChangeMock).toHaveBeenCalled();
+  expect(onChangeMock).toHaveBeenCalledTimes(1);
 });
 
 test('Does not call onChange when expanded content is not typed in', async () => {
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
index 1c98cd4e53c..bb6a297c470 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyToggle.test.tsx
@@ -69,7 +69,7 @@ test('Calls onClick when clipboard toggle is clicked', async () => {
   render(<ClipboardCopyToggle {...requiredProps} />);
 
   await user.click(screen.getByRole('button'));
-  expect(onClickMock).toHaveBeenCalled();
+  expect(onClickMock).toHaveBeenCalledTimes(1);
 });
 
 test('Does not call onClick when clipboard toggle is not clicked', async () => {
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap
index fa7540bf2e4..832f82d2ba4 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap
@@ -4,8 +4,10 @@ exports[`Matches snapshot 1`] = `
 <DocumentFragment>
   <div
     class="pf-v5-c-clipboard-copy"
+    data-ouia-component-id="snapshot"
     data-ouia-component-type="PF5/ClipboardCopy"
     data-ouia-safe="true"
+    id="snapshot"
   >
     <div
       class="pf-v5-c-clipboard-copy__group"
@@ -16,10 +18,10 @@ exports[`Matches snapshot 1`] = `
         <input
           aria-invalid="false"
           aria-label="Copyable input"
-          data-ouia-component-id="OUIA-Generated-TextInputBase-21"
+          data-ouia-component-id="OUIA-Generated-TextInputBase-26"
           data-ouia-component-type="PF5/TextInput"
           data-ouia-safe="true"
-          id="text-input-29"
+          id="text-input-34"
           type="text"
           value="Copyable text"
         />
@@ -45,6 +47,9 @@ exports[`Matches snapshot 1`] = `
         <div>
           children: Copy to clipboard
         </div>
+        <button>
+          Test CCB clicker
+        </button>
       </div>
     </div>
   </div>
diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
index 37358735497..0ca5758ef2c 100644
--- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
+++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyButton.test.tsx.snap
@@ -24,12 +24,15 @@ exports[`Matches snapshot 1`] = `
     <p>
       position: top
     </p>
+    <a>
+      onTooltipHidden clicker
+    </a>
     <button
       aria-disabled="false"
       aria-label="Copyable input"
       aria-labelledby="button-id text-id"
       class="pf-v5-c-button pf-m-control"
-      data-ouia-component-id="OUIA-Generated-Button-control-13"
+      data-ouia-component-id="OUIA-Generated-Button-control-1"
       data-ouia-component-type="PF5/Button"
       data-ouia-safe="true"
       id="button-id"
