Skip to content

Commit c7e4aef

Browse files
authored
revert: Remove One Theme motion for Tabs active indicator and CopyToClipboard glyph swap (#5252)
1 parent 1a6b6c2 commit c7e4aef

12 files changed

Lines changed: 44 additions & 860 deletions

File tree

‎pages/copy-to-clipboard/motion.page.tsx‎

Lines changed: 0 additions & 70 deletions
This file was deleted.

‎src/copy-to-clipboard/__tests__/copy-to-clipboard-motion.test.ts‎

Lines changed: 0 additions & 79 deletions
This file was deleted.

‎src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx‎

Lines changed: 0 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,11 @@
33
import React from 'react';
44
import { act, render, waitFor } from '@testing-library/react';
55

6-
import { isThemeActive } from '@cloudscape-design/component-toolkit/internal';
7-
86
import CopyToClipboard from '../../../lib/components/copy-to-clipboard';
97
import InternalCopyToClipboard from '../../../lib/components/copy-to-clipboard/internal';
108
import createWrapper from '../../../lib/components/test-utils/dom';
11-
import { KeyCode } from '../../internal/keycode';
129

1310
import styles from '../../../lib/components/copy-to-clipboard/styles.css.js';
14-
import iconStyles from '../../../lib/components/icon/styles.css.js';
15-
16-
jest.mock('@cloudscape-design/component-toolkit/internal', () => ({
17-
...jest.requireActual('@cloudscape-design/component-toolkit/internal'),
18-
isThemeActive: jest.fn().mockReturnValue(false),
19-
}));
2011

2112
const defaultProps = {
2213
copyTarget: 'Test content',
@@ -31,7 +22,6 @@ describe('CopyToClipboard', () => {
3122
const originalNavigatorPermissions = global.navigator.permissions;
3223

3324
beforeEach(() => {
34-
(isThemeActive as jest.Mock).mockReturnValue(false);
3525
Object.assign(global.navigator, {
3626
clipboard: {
3727
writeText: (text: string) =>
@@ -144,20 +134,6 @@ describe('CopyToClipboard', () => {
144134
expect(mockedWriteText).toHaveBeenCalledWith('Text to copy');
145135
});
146136

147-
test('does not schedule the One Theme status icon timer outside One Theme', async () => {
148-
jest.useFakeTimers();
149-
const { container } = render(<CopyToClipboard {...defaultProps} />);
150-
const wrapper = createWrapper(container).findCopyToClipboard()!;
151-
152-
await act(async () => {
153-
wrapper.findCopyButton().click();
154-
await Promise.resolve();
155-
});
156-
157-
expect(jest.getTimerCount()).toBe(0);
158-
jest.useRealTimers();
159-
});
160-
161137
describe.each([false, true])('popoverRenderWithPortal set to %s', (popoverRenderWithPortal: boolean) => {
162138
test('copies to clipboard and shows success message', async () => {
163139
const { container } = render(
@@ -554,168 +530,4 @@ describe('CopyToClipboard', () => {
554530
const { container } = render(<InternalCopyToClipboard {...defaultProps} variant="inline" wrapText={false} />);
555531
expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).not.toBeNull();
556532
});
557-
558-
describe('One Theme glyph-swap behavior', () => {
559-
beforeEach(() => {
560-
(isThemeActive as jest.Mock).mockReturnValue(true);
561-
jest.useFakeTimers();
562-
});
563-
564-
afterEach(() => {
565-
jest.useRealTimers();
566-
});
567-
568-
function renderCopyToClipboard(props: Partial<React.ComponentProps<typeof CopyToClipboard>> = {}) {
569-
const { container, unmount } = render(<CopyToClipboard {...defaultProps} {...props} />);
570-
const wrapper = createWrapper(container).findCopyToClipboard()!;
571-
const hasClass = (className: string) => container.querySelector(`.${className}`) !== null;
572-
const copy = () =>
573-
act(async () => {
574-
wrapper.findCopyButton().click();
575-
await Promise.resolve();
576-
});
577-
return { container, unmount, wrapper, hasClass, copy };
578-
}
579-
580-
test('swaps the copy glyph for the success glyph and shows the message as plain text', async () => {
581-
const { wrapper, hasClass, copy } = renderCopyToClipboard();
582-
// Both glyphs are mounted up front so the swap can transition; the result is hidden until a copy.
583-
expect(hasClass(styles['icon-swap'])).toBe(true);
584-
expect(hasClass(styles['icon-swap-copied'])).toBe(false);
585-
586-
await copy();
587-
588-
expect(wrapper.findStatusText()!.getElement().textContent).toBe('Copied to clipboard');
589-
expect(wrapper.findStatusText()!.findByClassName(styles['popover-message'])).not.toBeNull();
590-
expect(hasClass(iconStyles['variant-success'])).toBe(true);
591-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
592-
});
593-
594-
test('swaps the copy glyph for the error glyph when the copy fails', async () => {
595-
const { wrapper, hasClass, copy } = renderCopyToClipboard({ textToCopy: 'Text to copy with error' });
596-
597-
await copy();
598-
599-
expect(wrapper.findStatusText()!.getElement().textContent).toBe('Failed to copy to clipboard');
600-
expect(hasClass(iconStyles['variant-error'])).toBe(true);
601-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
602-
});
603-
604-
test('hands back to the copy glyph after the status icon duration and keeps the popover open', async () => {
605-
const { wrapper, hasClass, copy } = renderCopyToClipboard();
606-
await copy();
607-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
608-
expect(wrapper.findStatusText()).not.toBeNull();
609-
610-
act(() => jest.advanceTimersByTime(1499));
611-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
612-
613-
act(() => jest.advanceTimersByTime(1));
614-
expect(hasClass(styles['icon-swap-copied'])).toBe(false);
615-
expect(wrapper.findStatusText()).not.toBeNull();
616-
});
617-
618-
test('restarts the status icon timer without replaying the swap on rapid re-click', async () => {
619-
const { hasClass, copy } = renderCopyToClipboard();
620-
await copy();
621-
act(() => jest.advanceTimersByTime(1000));
622-
await copy();
623-
624-
act(() => jest.advanceTimersByTime(1000));
625-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
626-
627-
act(() => jest.advanceTimersByTime(500));
628-
expect(hasClass(styles['icon-swap-copied'])).toBe(false);
629-
});
630-
631-
test('does not render the stacked glyphs outside One Theme', () => {
632-
(isThemeActive as jest.Mock).mockReturnValue(false);
633-
const { wrapper, hasClass } = renderCopyToClipboard();
634-
expect(hasClass(styles['icon-swap'])).toBe(false);
635-
expect(wrapper.findCopyButton().getElement().querySelector('svg')).not.toBeNull();
636-
});
637-
638-
test.each(['button', 'icon', 'inline'] as const)('swaps the glyph for variant="%s"', async variant => {
639-
const { hasClass, copy } = renderCopyToClipboard({ variant });
640-
expect(hasClass(styles['icon-swap'])).toBe(true);
641-
await copy();
642-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
643-
});
644-
645-
test('does not swap the glyph or show a popover when disabled', async () => {
646-
const { container, hasClass, copy } = renderCopyToClipboard({ disabled: true });
647-
await copy();
648-
expect(hasClass(styles['icon-swap-copied'])).toBe(false);
649-
expect(createWrapper(container).findPopover()).toBeNull();
650-
});
651-
652-
test('keeps the copy glyph when permission is denied on mount and recovers on a successful copy', async () => {
653-
// The permission query resolves through a promise chain; real timers let `waitFor` observe it.
654-
jest.useRealTimers();
655-
Object.assign(global.navigator, {
656-
permissions: { query: jest.fn().mockResolvedValue({ state: 'denied' }) },
657-
});
658-
const { hasClass, copy } = renderCopyToClipboard();
659-
660-
// The denial only seeds the status; the trigger does not announce anything before a click.
661-
await waitFor(() => expect(hasClass(iconStyles['variant-error'])).toBe(true));
662-
expect(hasClass(styles['icon-swap-copied'])).toBe(false);
663-
664-
await copy();
665-
666-
await waitFor(() => expect(hasClass(styles['icon-swap-copied'])).toBe(true));
667-
expect(hasClass(iconStyles['variant-success'])).toBe(true);
668-
expect(hasClass(iconStyles['variant-error'])).toBe(false);
669-
});
670-
671-
test('swaps to the error glyph when the clipboard API is unavailable', async () => {
672-
Object.assign(global.navigator, { clipboard: undefined });
673-
const onCopyFailure = jest.fn();
674-
const { wrapper, hasClass, copy } = renderCopyToClipboard({ onCopyFailure });
675-
await copy();
676-
677-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
678-
expect(hasClass(iconStyles['variant-error'])).toBe(true);
679-
expect(wrapper.findStatusText()!.getElement().textContent).toBe('Failed to copy to clipboard');
680-
expect(onCopyFailure).toHaveBeenCalledWith(expect.objectContaining({ detail: { text: 'Text to copy' } }));
681-
});
682-
683-
test('keeps the button accessible name and hides the glyphs from assistive technology', async () => {
684-
const { wrapper, copy } = renderCopyToClipboard({ copyButtonAriaLabel: 'Copy ARN' });
685-
const button = wrapper.findCopyButton().getElement();
686-
expect(button).toHaveAccessibleName('Copy ARN');
687-
688-
await copy();
689-
690-
expect(button).toHaveAccessibleName('Copy ARN');
691-
expect(button).not.toHaveAttribute('aria-pressed');
692-
const stack = button.querySelector(`.${styles['icon-swap']}`)!;
693-
expect(stack.closest('[aria-hidden="true"]')).not.toBeNull();
694-
});
695-
696-
test('cancels the status icon timer on unmount', async () => {
697-
const { unmount, copy } = renderCopyToClipboard();
698-
await copy();
699-
const pendingTimersWhileShown = jest.getTimerCount();
700-
701-
unmount();
702-
703-
expect(jest.getTimerCount()).toBeLessThan(pendingTimersWhileShown);
704-
expect(() => act(() => jest.advanceTimersByTime(1500))).not.toThrow();
705-
});
706-
707-
test('closes the popover with Escape while the status icon finishes its own hold', async () => {
708-
const { wrapper, hasClass, copy } = renderCopyToClipboard();
709-
await copy();
710-
expect(wrapper.findStatusText()).not.toBeNull();
711-
712-
act(() => wrapper.findCopyButton().keydown(KeyCode.escape));
713-
expect(wrapper.findStatusText()).toBeNull();
714-
expect(hasClass(styles['icon-swap-copied'])).toBe(true);
715-
716-
act(() => jest.advanceTimersByTime(1500));
717-
expect(hasClass(styles['icon-swap-copied'])).toBe(false);
718-
expect(wrapper.findStatusText()).toBeNull();
719-
});
720-
});
721533
});

0 commit comments

Comments
 (0)