From 64c5916ee2723b1e1dda0cb134c5a2ca990d9497 Mon Sep 17 00:00:00 2001 From: Gonzalo Riestra Date: Mon, 2 Mar 2026 11:33:40 +0100 Subject: [PATCH] Remove @shopify/react-testing --- package.json | 1 - .../ui-extensions-dev-console/package.json | 3 +- .../components/Backdrop/Backdrop.test.tsx | 20 +- .../components/Tooltip/tests/Tooltip.test.tsx | 37 ++- .../sections/Extensions/Extensions.test.tsx | 27 +- .../components/AppHomeRow/AppHomeRow.test.tsx | 72 ++--- .../ExtensionRow/ExtensionRow.test.tsx | 149 +++++------ .../QRCodeModal/QRCodeModal.test.tsx | 81 +++--- .../ui-extensions-dev-console/tests/setup.ts | 2 +- .../ui-extensions-server-kit/package.json | 3 +- .../context/ExtensionServerProvider.test.tsx | 127 ++++----- .../ui-extensions-test-utils/package.json | 2 +- .../ui-extensions-test-utils/src/render.tsx | 14 +- .../src/renderHook.tsx | 51 +--- pnpm-lock.yaml | 252 ++++++++---------- 15 files changed, 385 insertions(+), 456 deletions(-) diff --git a/package.json b/package.json index ff091ef122f..eda0f5030db 100644 --- a/package.json +++ b/package.json @@ -305,7 +305,6 @@ ], "project": "**/*.{ts,tsx}!", "ignoreDependencies": [ - "@shopify/react-testing", "react-dom" ] }, diff --git a/packages/ui-extensions-dev-console/package.json b/packages/ui-extensions-dev-console/package.json index 8fe1ad363d8..6bc487b6873 100644 --- a/packages/ui-extensions-dev-console/package.json +++ b/packages/ui-extensions-dev-console/package.json @@ -23,8 +23,9 @@ "react-transition-group": "^4.4.5" }, "devDependencies": { - "@shopify/react-testing": "^5.3.0", "@shopify/ui-extensions-test-utils": "3.26.0", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", "@vitejs/plugin-react": "^5.1.4", diff --git a/packages/ui-extensions-dev-console/src/components/Modal/components/Backdrop/Backdrop.test.tsx b/packages/ui-extensions-dev-console/src/components/Modal/components/Backdrop/Backdrop.test.tsx index 021674a6a99..5e94bd6c8ac 100644 --- a/packages/ui-extensions-dev-console/src/components/Modal/components/Backdrop/Backdrop.test.tsx +++ b/packages/ui-extensions-dev-console/src/components/Modal/components/Backdrop/Backdrop.test.tsx @@ -1,6 +1,6 @@ import {Backdrop} from '.' import React from 'react' -import {render} from '@shopify/ui-extensions-test-utils' +import {render, fireEvent} from '@testing-library/react' describe('', () => { const defaultProps = { @@ -11,8 +11,8 @@ describe('', () => { describe('onClick()', () => { test('is called when the backdrop is clicked', () => { const spy = vi.fn() - const backdrop = render() - backdrop.find('div')!.trigger('onClick') + const {container} = render() + fireEvent.click(container.firstElementChild!) expect(spy).toHaveBeenCalled() }) }) @@ -20,8 +20,8 @@ describe('', () => { describe('onMouseDown', () => { test('calls setClosing()', () => { const spy = vi.fn() - const backdrop = render() - backdrop.find('div')!.trigger('onMouseDown') + const {container} = render() + fireEvent.mouseDown(container.firstElementChild!) expect(spy).toHaveBeenCalledWith(true) }) }) @@ -29,15 +29,15 @@ describe('', () => { describe('onMouseUp', () => { test('calls setClosing()', () => { const spy = vi.fn() - const backdrop = render() - backdrop.find('div')!.trigger('onMouseUp') + const {container} = render() + fireEvent.mouseUp(container.firstElementChild!) expect(spy).toHaveBeenCalledWith(false) }) - test('calls setClosing()', () => { + test('calls onClick()', () => { const spy = vi.fn() - const backdrop = render() - backdrop.find('div')!.trigger('onMouseUp') + const {container} = render() + fireEvent.mouseUp(container.firstElementChild!) expect(spy).toHaveBeenCalled() }) }) diff --git a/packages/ui-extensions-dev-console/src/components/Tooltip/tests/Tooltip.test.tsx b/packages/ui-extensions-dev-console/src/components/Tooltip/tests/Tooltip.test.tsx index d2c8b64155e..237e57f03b3 100644 --- a/packages/ui-extensions-dev-console/src/components/Tooltip/tests/Tooltip.test.tsx +++ b/packages/ui-extensions-dev-console/src/components/Tooltip/tests/Tooltip.test.tsx @@ -1,7 +1,6 @@ import {Tooltip} from '../Tooltip' import React from 'react' -import {mount} from '@shopify/react-testing' -import {vi, test} from 'vitest' +import {render, screen, fireEvent, act} from '@testing-library/react' const handleClick = vi.fn() @@ -16,33 +15,33 @@ const ComponentChildComponent = () => ( describe('', () => { test.each([ - ['onMouseEnter', 'onMouseLeave'], - ['onFocus', 'onBlur'], - ])('appears if hovered/focused/etc, hidden otherwise', (showEvent: any, hideEvent: any) => { - const wrapper = mount() + ['mouseEnter', 'mouseLeave'], + ['focus', 'blur'], + ] as const)('appears if hovered/focused/etc, hidden otherwise', (showEvent, hideEvent) => { + render() - wrapper.act(() => { - wrapper.find('div')?.trigger(showEvent) - }) + const trigger = screen.getByText('test') - let tooltip = wrapper.find('div', {role: 'tooltip'}) + act(() => { + fireEvent[showEvent](trigger) + }) - expect(tooltip).not.toBeNull() + expect(screen.queryByRole('tooltip')).toBeInTheDocument() - wrapper.act(() => { - wrapper.find('div')?.trigger(hideEvent) + act(() => { + fireEvent[hideEvent](trigger) }) - tooltip = wrapper.find('div', {role: 'tooltip'}) - - expect(tooltip).toBeNull() + expect(screen.queryByRole('tooltip')).not.toBeInTheDocument() }) test('hitting enter triggers content onClick', () => { - const wrapper = mount() + render() + + const trigger = screen.getByText('Button').closest('div[tabindex]')! - wrapper.act(() => { - wrapper.find('div')?.trigger('onKeyUp', {key: 'Enter'}) + act(() => { + fireEvent.keyUp(trigger, {key: 'Enter'}) }) expect(handleClick).toHaveBeenCalled() diff --git a/packages/ui-extensions-dev-console/src/sections/Extensions/Extensions.test.tsx b/packages/ui-extensions-dev-console/src/sections/Extensions/Extensions.test.tsx index fa60f35ef18..00fcd44e9b1 100644 --- a/packages/ui-extensions-dev-console/src/sections/Extensions/Extensions.test.tsx +++ b/packages/ui-extensions-dev-console/src/sections/Extensions/Extensions.test.tsx @@ -1,16 +1,15 @@ -import {AppHomeRow, ExtensionRow} from './components' - import {Extensions} from './Extensions.js' import {DefaultProviders} from 'tests/DefaultProviders' import React from 'react' import {ExtensionServerClient} from '@shopify/ui-extensions-server-kit' import {mockExtension} from '@shopify/ui-extensions-server-kit/testing' import {render, withProviders} from '@shopify/ui-extensions-test-utils' +import {screen} from '@testing-library/react' vi.mock('./components', () => ({ - ExtensionRow: () => null, + ExtensionRow: ({uuid}: any) =>
, PostPurchaseRow: () => null, - AppHomeRow: () => null, + AppHomeRow: () =>
, Row: () => null, })) @@ -26,21 +25,21 @@ describe('', () => { }) test('renders a blank slate if there is no data', async () => { - const container = render(, withProviders(DefaultProviders)) + render(, withProviders(DefaultProviders)) - expect(container).not.toContainReactComponent('table') - expect(container).not.toContainReactComponent(AppHomeRow) - expect(container).not.toContainReactComponent(ExtensionRow) + expect(screen.queryByRole('table')).not.toBeInTheDocument() + expect(screen.queryByTestId('app-home-row')).not.toBeInTheDocument() + expect(screen.queryByTestId(/extension-row-/)).not.toBeInTheDocument() }) test('renders ', async () => { const extensions = [mockExtension()] - const container = render(, withProviders(DefaultProviders), { + render(, withProviders(DefaultProviders), { state: {extensions, store: 'shop1.myshopify.io', app: {url: 'mock.url', title: 'Mock App Title'}}, }) - expect(container).toContainReactComponent(AppHomeRow) + expect(screen.getByTestId('app-home-row')).toBeInTheDocument() }) test('renders an for each Extension', async () => { @@ -48,12 +47,12 @@ describe('', () => { const extension2 = mockExtension() const extensions = [extension1, extension2] - const container = render(, withProviders(DefaultProviders), { + render(, withProviders(DefaultProviders), { state: {extensions, store: 'shop1.myshopify.io'}, }) - expect(container).toContainReactComponentTimes(ExtensionRow, extensions.length) - expect(container).toContainReactComponent(ExtensionRow, {uuid: extension1.uuid}) - expect(container).toContainReactComponent(ExtensionRow, {uuid: extension2.uuid}) + expect(screen.getAllByTestId(/extension-row-/)).toHaveLength(extensions.length) + expect(screen.getByTestId(`extension-row-${extension1.uuid}`)).toBeInTheDocument() + expect(screen.getByTestId(`extension-row-${extension2.uuid}`)).toBeInTheDocument() }) }) diff --git a/packages/ui-extensions-dev-console/src/sections/Extensions/components/AppHomeRow/AppHomeRow.test.tsx b/packages/ui-extensions-dev-console/src/sections/Extensions/components/AppHomeRow/AppHomeRow.test.tsx index 4ebd65c4bb6..5b748dcad2b 100644 --- a/packages/ui-extensions-dev-console/src/sections/Extensions/components/AppHomeRow/AppHomeRow.test.tsx +++ b/packages/ui-extensions-dev-console/src/sections/Extensions/components/AppHomeRow/AppHomeRow.test.tsx @@ -1,20 +1,25 @@ import {AppHomeRow} from '.' -import {PreviewLink, QRCodeModal} from '..' import {DefaultProviders} from 'tests/DefaultProviders' -import {Button} from '@/components' import React from 'react' - import {render, withProviders} from '@shopify/ui-extensions-test-utils' +import {screen, fireEvent} from '@testing-library/react' -vi.mock('..', () => ({ - NotApplicable: () => null, - PreviewLink: () => null, - QRCodeModal: () => null, - Row: (props: any) => props.children, +const {QRCodeModalMock, PreviewLinkMock} = vi.hoisted(() => ({ + QRCodeModalMock: vi.fn(), + PreviewLinkMock: vi.fn(), })) -vi.mock('@/components', () => ({ - Button: (props: any) => props.children, +vi.mock('..', () => ({ + NotApplicable: () => null, + PreviewLink: (props: any) => { + PreviewLinkMock(props) + return null + }, + QRCodeModal: (props: any) => { + QRCodeModalMock(props) + return
+ }, + Row: ({children}: any) => {children}, })) describe('', () => { @@ -22,55 +27,60 @@ describe('', () => { app: {url: 'mock.url', title: 'Mock App Title'}, } + beforeEach(() => { + QRCodeModalMock.mockClear() + PreviewLinkMock.mockClear() + }) + test('renders a , closed by default', () => { - const container = render(, withProviders(DefaultProviders), {state: defaultState}) + render(, withProviders(DefaultProviders), {state: defaultState}) - expect(container).toContainReactComponent(QRCodeModal, {code: undefined}) + expect(QRCodeModalMock).toHaveBeenLastCalledWith(expect.objectContaining({code: undefined})) }) test('Opens and closes the ', () => { - const container = render(, withProviders(DefaultProviders), {state: defaultState}) + render(, withProviders(DefaultProviders), {state: defaultState}) - container.act(() => { - container.find(Button)?.trigger('onClick') - }) + fireEvent.click(screen.getByText('View mobile')) - expect(container).toContainReactComponent(QRCodeModal, { - code: { - url: defaultState.app.url, - type: 'home', - title: defaultState.app.title, - }, - }) + expect(QRCodeModalMock).toHaveBeenLastCalledWith( + expect.objectContaining({ + code: { + url: defaultState.app.url, + type: 'home', + title: defaultState.app.title, + }, + }), + ) - container.act(() => { - container.find(QRCodeModal)?.trigger('onClose') - }) + fireEvent.click(screen.getByTestId('qr-code-modal')) - expect(container).toContainReactComponent(QRCodeModal, {code: undefined}) + expect(QRCodeModalMock).toHaveBeenLastCalledWith(expect.objectContaining({code: undefined})) }) test("renders a with the resource url set to the app's handle if the surface has been set to 'admin'", () => { const appState = { app: {url: 'mock.url', title: 'Mock App Title', handle: 'my-app-handle'}, } - const container = render(, withProviders(DefaultProviders), { + render(, withProviders(DefaultProviders), { state: appState, client: {options: {surface: 'admin'}}, }) - expect(container).toContainReactComponent(PreviewLink, {resourceUrl: '/admin/apps/my-app-handle'}) + expect(PreviewLinkMock).toHaveBeenLastCalledWith( + expect.objectContaining({resourceUrl: '/admin/apps/my-app-handle'}), + ) }) test("renders a without a resource url if the surface has not been set to 'admin'", () => { const appState = { app: {url: 'mock.url', title: 'Mock App Title', handle: 'my-app-handle'}, } - const container = render(, withProviders(DefaultProviders), { + render(, withProviders(DefaultProviders), { state: appState, client: {options: {surface: 'checkout'}}, }) - expect(container).toContainReactComponent(PreviewLink, {resourceUrl: undefined}) + expect(PreviewLinkMock).toHaveBeenLastCalledWith(expect.objectContaining({resourceUrl: undefined})) }) }) diff --git a/packages/ui-extensions-dev-console/src/sections/Extensions/components/ExtensionRow/ExtensionRow.test.tsx b/packages/ui-extensions-dev-console/src/sections/Extensions/components/ExtensionRow/ExtensionRow.test.tsx index abf19f75713..973b9ced99f 100644 --- a/packages/ui-extensions-dev-console/src/sections/Extensions/components/ExtensionRow/ExtensionRow.test.tsx +++ b/packages/ui-extensions-dev-console/src/sections/Extensions/components/ExtensionRow/ExtensionRow.test.tsx @@ -1,19 +1,24 @@ import {ExtensionRow} from '.' -import {QRCodeModal} from '..' import {DefaultProviders} from 'tests/DefaultProviders' -import {Button} from '@/components' import React from 'react' - import {render, withProviders} from '@shopify/ui-extensions-test-utils' +import {screen, fireEvent} from '@testing-library/react' import {mockExtension} from '@shopify/ui-extensions-server-kit/testing' +const {QRCodeModalMock} = vi.hoisted(() => ({ + QRCodeModalMock: vi.fn(), +})) + vi.mock('./components', () => ({ PreviewLinks: () => null, })) vi.mock('..', () => ({ - QRCodeModal: () => null, - Row: (props: any) => props.children, + QRCodeModal: (props: any) => { + QRCodeModalMock(props) + return
+ }, + Row: ({children, ...props}: any) => {children}, Status: () => null, })) @@ -53,115 +58,91 @@ describe('', () => { ], } + beforeEach(() => { + QRCodeModalMock.mockClear() + }) + test('renders a , closed by default', () => { - const container = render(, withProviders(DefaultProviders), {state: defaultState}) + render(, withProviders(DefaultProviders), {state: defaultState}) - expect(container).toContainReactComponent(QRCodeModal, {code: undefined}) + expect(QRCodeModalMock).toHaveBeenLastCalledWith(expect.objectContaining({code: undefined})) }) - test('renders a