@shopgate/pwa-common
Version:
Common library for the Shopgate Connect PWA.
234 lines (226 loc) • 7.32 kB
JavaScript
import React from 'react';
import { mount } from 'enzyme';
import { ThemeResourcesProvider } from '@shopgate/engage/core/providers';
import Widgets from "./index";
import { jsx as _jsx } from "react/jsx-runtime";
jest.useFakeTimers();
jest.mock('@shopgate/pwa-common/context', () => ({
ThemeContext: {
Provider: ({
children
}) => children
}
}));
/**
* A mock Image component.
* @returns {JSX}
*/
const Image = () => /*#__PURE__*/_jsx("img", {
alt: ""
});
/* eslint-disable react/prop-types */
/**
* A mock WidgetGrid component.
* @param {Array} children Array of children.
* @returns {JSX}
*/
const WidgetGrid = ({
children
}) => /*#__PURE__*/_jsx("div", {
className: "widget-grid",
children: children
});
/* eslint-enable react/prop-types */
const components = {
v1: {
'@shopgate/commerce-widgets/image': Image,
'@shopgate/commerce-widgets/widget-grid': WidgetGrid
}
};
/**
* @param {Object[]} widgets Widgets to be rendered.
* @returns {JSX.Element}
*/
const createWrapper = widgets => mount(/*#__PURE__*/_jsx(ThemeResourcesProvider, {
widgets: components,
components: {},
children: /*#__PURE__*/_jsx(Widgets, {
widgets: widgets
})
}));
describe('<Widgets />', () => {
it('should render a grid if height is defined', () => {
const widgets = [{
col: 0,
row: 0,
width: 12,
height: 3,
settings: {
id: 83535,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
},
type: '@shopgate/commerce-widgets/image'
}];
const wrapper = createWrapper(widgets);
expect(wrapper.find('WidgetGrid').exists()).toBe(true);
});
it('should not wrap a widget which is not a grid and has no height', () => {
const widgets = [{
col: 0,
row: 0,
width: 12,
settings: {
id: 83535,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
},
type: '@shopgate/commerce-widgets/image'
}];
const wrapper = createWrapper(widgets);
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('WidgetGrid').exists()).toBe(false);
});
it('should render a grid if the widget is of type grid', () => {
const widgets = [{
type: '@shopgate/commerce-widgets/widget-grid',
settings: {
widgets: [{
col: 0,
row: 0,
width: 12,
height: 5,
settings: {
id: '84961',
alt: '',
image: 'https://data.shopgate.com/shop_widget_images/23836/aedc545959f55e3f73851eca0ed40a75.min.jpeg',
link: '/category/'
},
type: '@shopgate/commerce-widgets/image'
}]
}
}];
const wrapper = createWrapper(widgets);
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('WidgetGrid').exists()).toBe(true);
});
it('should render only one widget when the second one is not published and third one is invalid', () => {
const widgets = [{
col: 0,
row: 0,
width: 12,
settings: {
id: 835351,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
},
type: '@shopgate/commerce-widgets/image'
}, {
col: 0,
row: 0,
width: 12,
settings: {
id: 835352,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
},
type: '@shopgate/commerce-widgets/imagefoo'
}, {
col: 0,
row: 0,
width: 12,
settings: {
published: false,
id: 835353,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
},
type: '@shopgate/commerce-widgets/image'
}];
const wrapper = createWrapper(widgets);
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('img').length).toBe(1);
});
it('should schedule a re-render when widget is scheduled', () => {
// Use a fixed point in time so "next full hour" is deterministic.
// Pick a time that's not exactly on the hour.
const base = new Date('2023-01-01T10:37:00.000Z');
jest.setSystemTime(base);
const minutesToNextFullHour = 60 - base.getMinutes(); // 23
const msToNextFullHour = minutesToNextFullHour * 60000; // 23 * 60_000
const scheduledFromMs = Date.now() + msToNextFullHour - 1;
const scheduledToMs = Date.now() + minutesToNextFullHour + 1000;
const widgets = [{
col: 0,
row: 0,
width: 12,
settings: {
id: 835351,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg',
published: true,
plan: true,
planDate: {
valid_from: new Date(scheduledFromMs).toISOString(),
valid_to: new Date(scheduledToMs).toISOString()
}
},
type: '@shopgate/commerce-widgets/image'
}];
const wrapper = createWrapper(widgets);
const instance = wrapper.find('Widgets').instance();
const clearSpy = jest.spyOn(global, 'clearTimeout');
instance.forceUpdate = jest.fn();
// Before the schedule hits, the image should not render yet.
expect(wrapper.find(Image).exists()).toBe(false);
// 1) Advance to the next full hour -> first forced update.
jest.advanceTimersByTime(msToNextFullHour);
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
// 2) The component should schedule the next tick for +60 min.
jest.advanceTimersByTime(60 * 60000);
expect(instance.forceUpdate).toHaveBeenCalledTimes(2);
// Unmount triggers cleanup of any pending timeouts.
wrapper.unmount();
expect(clearSpy).toHaveBeenCalled();
clearSpy.mockRestore();
});
it('should render only wrapper when widgets array is empty', () => {
const widgets = [];
const wrapper = createWrapper(widgets);
expect(wrapper.find('Image').exists()).toBe(false);
});
it('should render null when no widgets are passed', () => {
const wrapper = createWrapper(undefined);
expect(wrapper.find('Widgets').html()).toBe(null);
});
it('should check settings of child widgets inside widget-grid', () => {
const widgets = [{
height: 2,
id: 'index-5-@shopgate/commerce-widgets/widget-grid',
type: '@shopgate/commerce-widgets/widget-grid',
settings: {
widgets: [{
col: 0,
row: 0,
height: 2,
width: 2,
settings: {
id: 835351,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg',
published: true,
plan: false
},
type: '@shopgate/commerce-widgets/image'
}, {
col: 2,
row: 0,
height: 2,
width: 2,
settings: {
id: 835352,
image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg',
published: false,
plan: false
},
type: '@shopgate/commerce-widgets/image'
}]
}
}];
const wrapper = createWrapper(widgets);
expect(wrapper.find('img').length).toBe(1);
});
});