diff --git a/packages/hydrogen/src/components/ExternalVideo/tests/ExternalVideo.test.tsx b/packages/hydrogen/src/components/ExternalVideo/tests/ExternalVideo.test.tsx
deleted file mode 100644
index fcd7e600dc..0000000000
--- a/packages/hydrogen/src/components/ExternalVideo/tests/ExternalVideo.test.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-import React from 'react';
-import {mount} from '@shopify/react-testing';
-import {ExternalVideo} from '../index.js';
-import {getExternalVideoData} from '../../../utilities/tests/media.js';
-
-describe('', () => {
- it('renders an iframe element with sensible defaults', () => {
- const video = getExternalVideoData();
- const component = mount();
-
- expect(component).toContainReactComponent('iframe', {
- src: video.embedUrl,
- id: video.id,
- allow:
- 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture',
- allowFullScreen: true,
- frameBorder: '0',
- });
- });
-
- it('allows defaults to be overridden', () => {
- const component = mount(
-
- );
-
- expect(component).toContainReactComponent('iframe', {
- id: 'hello',
- allow: 'autoplay',
- allowFullScreen: false,
- frameBorder: '1',
- });
- });
-
- it('includes options in the iframe src when the `options` prop is provided', () => {
- const options = {
- color: 'red',
- autoplay: true,
- };
- const component = mount(
-
- );
-
- expect(component).toContainReactComponent('iframe', {
- src: 'https://www.youtube.com/embed/a2YSgfwXc9c?&color=red&autoplay=true',
- });
- });
-
- it('allows passthrough props', () => {
- const component = mount(
-
- );
-
- expect(component).toContainReactComponent('iframe', {
- className: 'fancy',
- });
- });
-
- describe(`throws when necessary props aren't passed`, () => {
- it(`data.embedUrl`, () => {
- // to silence the test runner's console.error from being called
- const consoleSpy = jest
- .spyOn(console, 'error')
- .mockImplementation(() => {});
- expect(() => mount()).toThrow();
- expect(console.error).toHaveBeenCalled();
- consoleSpy.mockRestore();
- });
- });
-});
diff --git a/packages/hydrogen/src/components/ExternalVideo/tests/ExternalVideo.vitest.tsx b/packages/hydrogen/src/components/ExternalVideo/tests/ExternalVideo.vitest.tsx
index 7a8fd24d53..354df4a4a5 100644
--- a/packages/hydrogen/src/components/ExternalVideo/tests/ExternalVideo.vitest.tsx
+++ b/packages/hydrogen/src/components/ExternalVideo/tests/ExternalVideo.vitest.tsx
@@ -84,9 +84,8 @@ describe('', () => {
it(`throws when 'data.embedUrl' isn't passed`, () => {
// to silence the test runner's console.error from being called
- const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
+ vi.spyOn(console, 'error').mockImplementation(() => {});
expect(() => render()).toThrow();
expect(console.error).toHaveBeenCalled();
- consoleSpy.mockRestore();
});
});
diff --git a/packages/hydrogen/src/components/Image/tests/Image.test.tsx b/packages/hydrogen/src/components/Image/tests/Image.vitest.tsx
similarity index 57%
rename from packages/hydrogen/src/components/Image/tests/Image.test.tsx
rename to packages/hydrogen/src/components/Image/tests/Image.vitest.tsx
index 4a70efe0d8..d8d8d44eb3 100644
--- a/packages/hydrogen/src/components/Image/tests/Image.test.tsx
+++ b/packages/hydrogen/src/components/Image/tests/Image.vitest.tsx
@@ -1,59 +1,56 @@
import React from 'react';
+import {vi} from 'vitest';
+import {render, screen} from '@testing-library/react';
import {Image} from '../index.js';
-import {mount} from '@shopify/react-testing';
import {getPreviewImage} from '../../../utilities/tests/media.js';
import * as utilities from '../../../utilities/index.js';
describe('', () => {
- let consoleWarnSpy: jest.SpyInstance;
- beforeEach(() => {
- consoleWarnSpy = jest.spyOn(console, 'warn');
- consoleWarnSpy.mockImplementation(() => {});
- });
- afterEach(() => {
- consoleWarnSpy.mockRestore();
+ beforeAll(() => {
+ vi.spyOn(console, 'error').mockImplementation(() => {});
});
+
describe('Shopify image data', () => {
it('renders an `img` element', () => {
- const image = getPreviewImage();
- const {url: src, altText, id, width, height} = image;
-
- const component = mount();
-
- expect(component).toContainReactComponent('img', {
- src,
- alt: altText,
- id,
- width,
- height,
- loading: 'lazy',
- });
+ const previewImage = getPreviewImage();
+ const {url: src, altText, id, width, height} = previewImage;
+ render();
+
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('src', src);
+ expect(image).toHaveAttribute('id', id);
+ expect(image).toHaveAttribute('alt', altText);
+ expect(image).toHaveAttribute('width', `${width}`);
+ expect(image).toHaveAttribute('height', `${height}`);
+ expect(image).toHaveAttribute('loading', 'lazy');
});
it('renders an `img` element with provided `id`', () => {
- const image = getPreviewImage();
+ const previewImage = getPreviewImage();
const id = 'catImage';
+ render();
- const component = mount();
+ const image = screen.getByRole('img');
- expect(component).toContainReactComponent('img', {
- id,
- });
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('id', id);
});
it('renders an `img` element with provided `loading` value', () => {
- const image = getPreviewImage();
+ const previewImage = getPreviewImage();
const loading = 'eager';
+ render();
- const component = mount();
+ const image = screen.getByRole('img');
- expect(component).toContainReactComponent('img', {
- loading,
- });
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('loading', loading);
});
it('renders an `img` with `width` and `height` values', () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
});
const options = {scale: 2 as const};
@@ -61,23 +58,22 @@ describe('', () => {
width: 200,
height: 100,
};
- jest
- .spyOn(utilities, 'getShopifyImageDimensions')
- .mockReturnValue(mockDimensions);
- const component = mount();
+ vi.spyOn(utilities, 'getShopifyImageDimensions').mockReturnValue(
+ mockDimensions
+ );
- expect(component).toContainReactComponent('img', {
- width: mockDimensions.width,
- height: mockDimensions.height,
- });
+ render();
+
+ const image = screen.getByRole('img');
- // @ts-expect-error clear the mock that was created earlier
- utilities.getShopifyImageDimensions.mockRestore();
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('width', `${mockDimensions.width}`);
+ expect(image).toHaveAttribute('height', `${mockDimensions.height}`);
});
it('renders an `img` element without `width` and `height` attributes when invalid dimensions are provided', () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
});
const options = {scale: 2 as const};
@@ -86,22 +82,22 @@ describe('', () => {
height: null,
};
- jest
- .spyOn(utilities, 'getShopifyImageDimensions')
- .mockReturnValue(mockDimensions);
- const component = mount();
+ vi.spyOn(utilities, 'getShopifyImageDimensions').mockReturnValue(
+ mockDimensions
+ );
+
+ render();
- const img = component.find('img');
- expect(img?.prop('width')).toBeUndefined();
- expect(img?.prop('height')).toBeUndefined();
+ const image = screen.getByRole('img');
- // @ts-expect-error This was mocked out and needs to be restored
- utilities.getShopifyImageDimensions.mockRestore();
+ expect(image).toBeInTheDocument();
+ expect(image).not.toHaveAttribute('width');
+ expect(image).not.toHaveAttribute('height');
});
describe('Loaders', () => {
it('calls `shopifyImageLoader()` when no `loader` prop is provided', () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
});
@@ -110,39 +106,44 @@ describe('', () => {
const options = {width: 100, height: 200, scale: 2 as const};
- const shopifyImageLoaderSpy = jest
+ const shopifyImageLoaderSpy = vi
.spyOn(utilities, 'shopifyImageLoader')
.mockReturnValue(transformedSrc);
- const component = mount();
+ render();
expect(shopifyImageLoaderSpy).toHaveBeenCalledWith({
- src: image.url,
+ src: previewImage.url,
...options,
});
- expect(component).toContainReactComponent('img', {
- src: transformedSrc,
- });
- // @ts-expect-error This was mocked out and needs to be restored
- utilities.shopifyImageLoader.mockRestore();
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('src', transformedSrc);
});
});
it('allows passthrough props', () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
});
- const component = mount(
-
+ render(
+
);
- expect(component).toContainReactComponent('img', {
- className: 'fancyImage',
- id: '123',
- alt: 'Fancy image',
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveClass('fancyImage');
+ expect(image).toHaveAttribute('id', '123');
+ expect(image).toHaveAttribute('alt', 'Fancy image');
});
it('generates a default srcset', () => {
@@ -151,17 +152,18 @@ describe('', () => {
const expectedSrcset = sizes
.map((size) => `${mockUrl}?width=${size} ${size}w`)
.join(', ');
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: mockUrl,
width: 2560,
height: 2560,
});
- const component = mount();
+ render();
- expect(component).toContainReactComponent('img', {
- srcSet: expectedSrcset,
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('srcSet', expectedSrcset);
});
it('generates a default srcset up to the image height and width', () => {
@@ -170,157 +172,177 @@ describe('', () => {
const expectedSrcset = sizes
.map((size) => `${mockUrl}?width=${size} ${size}w`)
.join(', ');
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: mockUrl,
width: 832,
height: 832,
});
- const component = mount();
+ render();
- expect(component).toContainReactComponent('img', {
- srcSet: expectedSrcset,
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('srcSet', expectedSrcset);
});
it(`uses scale to multiply the srcset width but not the element width, and when crop is missing, does not include height in srcset`, () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
width: 500,
height: 500,
});
- const component = mount(
-
- );
+ render();
- expect(component).toContainReactComponent('img', {
- width: 500,
- height: 500,
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute(
+ 'srcSet',
// height is not applied if there is no crop
// width is not doulbe of the passed width, but instead double of the value in 'sizes_array' / '[number]w'
- srcSet: `${image.url}?width=704 352w`,
- });
+ `${previewImage.url}?width=704 352w`
+ );
+ expect(image).toHaveAttribute('width', '500');
+ expect(image).toHaveAttribute('height', '500');
});
it(`uses scale to multiply the srcset width but not the element width, and when crop is there, includes height in srcset`, () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
width: 500,
height: 500,
});
- const component = mount(
+ render(
);
- expect(component).toContainReactComponent('img', {
- width: 500,
- height: 250,
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute(
+ 'srcSet',
// height is the aspect ratio (of width + height) * srcSet width, so in this case it should be half of width
- srcSet: `${image.url}?width=704&height=352&crop=bottom 352w`,
- });
+ `${previewImage.url}?width=704&height=352&crop=bottom 352w`
+ );
+ expect(image).toHaveAttribute('width', '500');
+ expect(image).toHaveAttribute('height', '250');
});
it(`uses scale to multiply the srcset width but not the element width, and when crop is there, includes height in srcset using data.width / data.height for the aspect ratio`, () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
width: 500,
height: 500,
});
- const component = mount(
-
+ render(
+
);
- expect(component).toContainReactComponent('img', {
- width: 500,
- height: 500,
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute(
+ 'srcSet',
// height is the aspect ratio (of data.width + data.height) * srcSet width, so in this case it should be the same as width
- srcSet: `${image.url}?width=704&height=704&crop=bottom 352w`,
- });
+ `${previewImage.url}?width=704&height=704&crop=bottom 352w`
+ );
+ expect(image).toHaveAttribute('width', '500');
+ expect(image).toHaveAttribute('height', '500');
});
it(`uses scale to multiply the srcset width but not the element width, and when crop is there, calculates height based on aspect ratio in srcset`, () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
width: 500,
height: 1000,
});
- const component = mount(
-
+ render(
+
);
- expect(component).toContainReactComponent('img', {
- width: 500,
- height: 1000,
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute(
+ 'srcSet',
// height is the aspect ratio (of data.width + data.height) * srcSet width, so in this case it should be double the width
- srcSet: `${image.url}?width=704&height=1408&crop=bottom 352w`,
- });
+ `${previewImage.url}?width=704&height=1408&crop=bottom 352w`
+ );
+ expect(image).toHaveAttribute('width', '500');
+ expect(image).toHaveAttribute('height', '1000');
});
it(`should pass through width (as an inline prop) when it's a string, and use the first size in the size array for the URL width`, () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
width: 100,
height: 100,
});
- const component = mount();
+ render();
- expect(component).toContainReactComponent('img', {
- width: '100%',
- src: `${image.url}?width=352`,
- height: undefined, // make sure height isn't NaN
- });
+ const image = screen.getByRole('img');
+
+ console.log(image.getAttribute('srcSet'));
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('src', `${previewImage.url}?width=352`);
+ expect(image).toHaveAttribute('width', '100%');
+ expect(image).not.toHaveAttribute('height');
});
it(`should pass through width (as part of loaderOptions) when it's a string, and use the first size in the size array for the URL width`, () => {
- const image = getPreviewImage({
+ const previewImage = getPreviewImage({
url: 'https://cdn.shopify.com/someimage.jpg',
width: 100,
height: 100,
});
- const component = mount(
-
- );
+ render();
- expect(component).toContainReactComponent('img', {
- width: '100%',
- src: `${image.url}?width=352`,
- height: undefined, // make sure height isn't NaN
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('src', `${previewImage.url}?width=352`);
+ expect(image).toHaveAttribute('width', '100%');
+ expect(image).not.toHaveAttribute('height');
});
});
describe('External image', () => {
it('renders an `img` element', () => {
const {url: src, altText, id, width, height} = getPreviewImage();
- const component = mount(
+
+ render(
);
- expect(component).toContainReactComponent('img', {
- src,
- alt: altText,
- id,
- width,
- height,
- loading: 'lazy',
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('src', src);
+ expect(image).toHaveAttribute('id', id);
+ expect(image).toHaveAttribute('alt', altText);
+ expect(image).toHaveAttribute('width', `${width}`);
+ expect(image).toHaveAttribute('height', `${height}`);
+ expect(image).toHaveAttribute('loading', 'lazy');
});
it('renders an `img` element with provided `loading` value', () => {
const {url: src, id, width, height} = getPreviewImage();
const loading = 'eager';
- const component = mount(
+
+ render(
', () => {
/>
);
- expect(component).toContainReactComponent('img', {
- loading,
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('loading', loading);
});
describe('Width and height checks', () => {
- let consoleErrorSpy: jest.SpyInstance;
-
- beforeEach(() => {
- consoleErrorSpy = jest.spyOn(console, 'error');
- consoleErrorSpy.mockImplementation(() => {});
- });
-
- afterEach(() => {
- consoleErrorSpy.mockRestore();
- });
-
it('throws an error when the `width` is set to zero', () => {
const {url: src, id} = getPreviewImage();
const width = 0;
const height = 100;
expect(() => {
- mount(
+ render(
);
}).toThrowError(
@@ -368,7 +380,7 @@ describe('', () => {
const height = 0;
expect(() => {
- mount(
+ render(
);
}).toThrowError(
@@ -387,14 +399,14 @@ describe('', () => {
url: 'https://cdn.shopify.com/someimage.jpg',
});
const transformedSrc = 'https://cdn.shopify.com/someimage_100x200@2x.jpg';
- const loaderMock = jest.fn().mockReturnValue(transformedSrc);
+ const loaderMock = vi.fn().mockReturnValue(transformedSrc);
const loaderOptions = {
width: 100,
height: 200,
scale: 2 as const,
};
- const component = mount(
+ render(
', () => {
/>
);
- expect(component).toContainReactComponent('img', {
- src: transformedSrc,
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('src', transformedSrc);
expect(loaderMock).toHaveBeenCalledWith({
src,
@@ -418,7 +431,7 @@ describe('', () => {
it('allows passthrough props', () => {
const {url: src, width, height} = getPreviewImage();
- const component = mount(
+ render(
', () => {
/>
);
- expect(component).toContainReactComponent('img', {
- className: 'fancyImage',
- id: '123',
- alt: 'Fancy image',
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('id', '123');
+ expect(image).toHaveAttribute('alt', 'Fancy image');
+ expect(image).toHaveClass('fancyImage');
});
it('generates a srcset when a loader and a widths prop are provided', () => {
@@ -466,7 +480,7 @@ describe('', () => {
)
.join(', ');
- const component = mount(
+ render(
', () => {
/>
);
- expect(component).toContainReactComponent('img', {
- srcSet: expectedSrcset,
- });
+ const image = screen.getByRole('img');
+
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('srcSet', expectedSrcset);
});
});
- // eslint-disable-next-line jest/expect-expect
it.skip(`typescript types`, () => {
// this test is actually just using //@ts-expect-error as the assertion, and don't need to execute in order to have TS validation on them
// I don't love this idea, but at the moment I also don't have other great ideas for how to easily test our component TS types
diff --git a/packages/hydrogen/src/components/ShopPayButton/tests/ShopPayButton.client.vitest.tsx b/packages/hydrogen/src/components/ShopPayButton/tests/ShopPayButton.client.vitest.tsx
index 43c5086dc1..a4289849f9 100644
--- a/packages/hydrogen/src/components/ShopPayButton/tests/ShopPayButton.client.vitest.tsx
+++ b/packages/hydrogen/src/components/ShopPayButton/tests/ShopPayButton.client.vitest.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import {vi, type SpyInstance} from 'vitest';
+import {vi} from 'vitest';
import {render} from '@testing-library/react';
import {ShopifyTestProviders} from '../../../utilities/tests/provider-helpers.js';
import {