mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-09-20 10:39:58 +08:00
385 lines
9.2 KiB
TypeScript
385 lines
9.2 KiB
TypeScript
import { nextTick } from 'vue';
|
|
import { DOMWrapper } from '@vue/test-utils/dist/domWrapper';
|
|
import {
|
|
mount,
|
|
later,
|
|
trigger,
|
|
triggerDrag,
|
|
mockGetBoundingClientRect,
|
|
} from '../../../test';
|
|
import { ImagePreview } from '../function-call';
|
|
import ImagePreviewComponent from '../ImagePreview';
|
|
|
|
const images = [
|
|
'https://img.yzcdn.cn/1.png',
|
|
'https://img.yzcdn.cn/2.png',
|
|
'https://img.yzcdn.cn/3.png',
|
|
];
|
|
|
|
function triggerTwoFingerTouchmove(
|
|
el: Element | DOMWrapper<Element>,
|
|
x: number,
|
|
y: number
|
|
) {
|
|
trigger(el, 'touchmove', -x, -y, { x, y });
|
|
}
|
|
|
|
function triggerZoom(
|
|
el: Element | DOMWrapper<Element>,
|
|
x: number,
|
|
y: number,
|
|
direction = 'in'
|
|
) {
|
|
trigger(el, 'touchstart', 0, 0, { x, y });
|
|
|
|
if (direction === 'in') {
|
|
triggerTwoFingerTouchmove(el, x / 4, y / 4);
|
|
triggerTwoFingerTouchmove(el, x / 3, y / 3);
|
|
triggerTwoFingerTouchmove(el, x / 2, y / 2);
|
|
triggerTwoFingerTouchmove(el, x, y);
|
|
} else if (direction === 'out') {
|
|
triggerTwoFingerTouchmove(el, x, y);
|
|
triggerTwoFingerTouchmove(el, x / 2, y / 2);
|
|
triggerTwoFingerTouchmove(el, x / 3, y / 3);
|
|
triggerTwoFingerTouchmove(el, x / 4, y / 4);
|
|
}
|
|
|
|
trigger(el, 'touchend', 0, 0, { touchList: [] });
|
|
}
|
|
|
|
test('should swipe to currect index after calling the swipeTo method', async () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
images,
|
|
},
|
|
});
|
|
|
|
await later();
|
|
(wrapper.vm as Record<string, any>).swipeTo(2);
|
|
|
|
await later(100);
|
|
expect(wrapper.find('.van-image-preview__index').html()).toMatchSnapshot();
|
|
});
|
|
|
|
test('should allow to use the teleport prop', () => {
|
|
const root = document.createElement('div');
|
|
mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
teleport: root,
|
|
},
|
|
});
|
|
|
|
expect(root.querySelector('.van-image-preview')).toBeTruthy();
|
|
});
|
|
|
|
test('should render cover slot correctly', () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
},
|
|
slots: {
|
|
cover: () => 'Custom Cover',
|
|
},
|
|
});
|
|
|
|
expect(wrapper.html()).toMatchSnapshot();
|
|
});
|
|
|
|
test('should render index slot correctly', () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
},
|
|
slots: {
|
|
index: ({ index }) => `Custom Index: ${index}`,
|
|
},
|
|
});
|
|
|
|
expect(wrapper.find('.van-image-preview__index').html()).toMatchSnapshot();
|
|
});
|
|
|
|
test('should render close icon when using closeable prop', () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
images,
|
|
closeable: true,
|
|
},
|
|
});
|
|
|
|
wrapper.find('.van-image-preview__close-icon').trigger('click');
|
|
expect(wrapper.emitted<[boolean]>('update:show')![0][0]).toEqual(false);
|
|
});
|
|
|
|
test('should change close icon when using close-icon prop', () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
closeable: true,
|
|
closeIcon: 'success',
|
|
},
|
|
});
|
|
|
|
expect(
|
|
wrapper.find('.van-image-preview__close-icon').html()
|
|
).toMatchSnapshot();
|
|
});
|
|
|
|
test('should change close icon position when using close-icon-position prop', () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
closeable: true,
|
|
closeIconPosition: 'top-left',
|
|
},
|
|
});
|
|
|
|
expect(
|
|
wrapper.find('.van-image-preview__close-icon').html()
|
|
).toMatchSnapshot();
|
|
});
|
|
|
|
test('should hide index when show-index prop is false', async () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
show: true,
|
|
},
|
|
});
|
|
expect(wrapper.find('.van-image-preview__index').exists()).toBeTruthy();
|
|
|
|
await wrapper.setProps({ showIndex: false });
|
|
expect(wrapper.find('.van-image-preview__index').exists()).toBeFalsy();
|
|
});
|
|
|
|
test('should hide ImagePreview after popstate', async () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
images,
|
|
show: true,
|
|
},
|
|
});
|
|
|
|
window.dispatchEvent(new Event('popstate'));
|
|
expect(wrapper.emitted<[boolean]>('update:show')![0][0]).toBeFalsy();
|
|
});
|
|
|
|
test('should not hide ImagePreview after popstate when close-on-popstate is false', async () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
images,
|
|
show: true,
|
|
closeOnPopstate: false,
|
|
},
|
|
});
|
|
|
|
window.dispatchEvent(new Event('popstate'));
|
|
expect(wrapper.emitted('update:show')).toBeFalsy();
|
|
});
|
|
|
|
test('render image', async () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: { images, show: true },
|
|
});
|
|
|
|
expect(wrapper.html()).toMatchSnapshot();
|
|
|
|
await later();
|
|
|
|
const swipe = wrapper.find('.van-swipe-item');
|
|
await triggerDrag(swipe, 500, 0);
|
|
expect(wrapper.emitted('update:show')).toBeFalsy();
|
|
expect(wrapper.emitted('change')![0]).toEqual([2]);
|
|
|
|
triggerDrag(swipe, 0, 0);
|
|
await later(250);
|
|
expect(wrapper.emitted('update:show')![0]).toEqual([false]);
|
|
});
|
|
|
|
test('before close prop', async () => {
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
images,
|
|
show: true,
|
|
beforeClose: () => true,
|
|
},
|
|
});
|
|
|
|
const swipe = wrapper.find('.van-swipe__track');
|
|
|
|
// should not emit input or close event when tapped
|
|
triggerDrag(swipe, 0, 0);
|
|
await later(250);
|
|
expect(wrapper.emitted('input')).toBeFalsy();
|
|
expect(wrapper.emitted('close')).toBeFalsy();
|
|
|
|
await wrapper.setProps({ show: false });
|
|
expect(wrapper.emitted('update:show')![0]).toBeTruthy();
|
|
expect(wrapper.emitted('close')![0]).toBeTruthy();
|
|
});
|
|
|
|
test('function call', async () => {
|
|
ImagePreview({ images });
|
|
ImagePreview({ images: images.slice(0, 1) });
|
|
|
|
await later();
|
|
await nextTick();
|
|
const wrapper = document.querySelector(
|
|
'.van-image-preview'
|
|
) as HTMLDivElement;
|
|
const swipe = wrapper.querySelector('.van-swipe__track') as HTMLDivElement;
|
|
triggerDrag(swipe, 0, 0);
|
|
|
|
expect(wrapper.querySelectorAll('img').length).toEqual(1);
|
|
});
|
|
|
|
test('double click', async () => {
|
|
const onScale = jest.fn();
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
images,
|
|
show: true,
|
|
onScale,
|
|
},
|
|
});
|
|
|
|
await later();
|
|
const swipe = wrapper.find('.van-swipe-item');
|
|
triggerDrag(swipe, 0, 0);
|
|
triggerDrag(swipe, 0, 0);
|
|
expect(onScale).toHaveBeenCalledWith({
|
|
index: 0,
|
|
scale: 2,
|
|
});
|
|
|
|
await later();
|
|
triggerDrag(swipe, 0, 0);
|
|
triggerDrag(swipe, 0, 0);
|
|
expect(onScale).toHaveBeenLastCalledWith({
|
|
index: 0,
|
|
scale: 1,
|
|
});
|
|
});
|
|
|
|
test('onClose option', async () => {
|
|
const onClose = jest.fn();
|
|
const instance = ImagePreview({
|
|
images,
|
|
startPosition: 1,
|
|
onClose,
|
|
});
|
|
|
|
await instance?.close();
|
|
|
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
expect(onClose).toHaveBeenCalledWith({
|
|
index: 0,
|
|
url: images[0],
|
|
});
|
|
});
|
|
|
|
test('onChange option', async () => {
|
|
const onChange = jest.fn();
|
|
ImagePreview({
|
|
images,
|
|
startPosition: 0,
|
|
onChange,
|
|
});
|
|
|
|
await nextTick();
|
|
const swipe = document.querySelector('.van-swipe__track') as HTMLDivElement;
|
|
triggerDrag(swipe, 1000, 0);
|
|
expect(onChange).toHaveBeenCalledWith(2);
|
|
});
|
|
|
|
test('onScale option', async () => {
|
|
const restore = mockGetBoundingClientRect({ width: 100 });
|
|
ImagePreview({
|
|
images,
|
|
startPosition: 0,
|
|
onScale({ index, scale }) {
|
|
expect(index).toEqual(2);
|
|
expect(scale <= 2).toBeTruthy();
|
|
},
|
|
});
|
|
|
|
await later();
|
|
const image = document.querySelector('img') as HTMLImageElement;
|
|
triggerZoom(image, 300, 300);
|
|
restore();
|
|
});
|
|
|
|
test('zoom in and drag image to move', async () => {
|
|
const restore = mockGetBoundingClientRect({ width: 100, height: 100 });
|
|
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: { images, show: true },
|
|
});
|
|
|
|
await later();
|
|
const image = wrapper.find('img');
|
|
triggerZoom(image, 300, 300);
|
|
|
|
// mock image size
|
|
['naturalWidth', 'naturalHeight'].forEach((key) => {
|
|
Object.defineProperty(image.element, key, { value: 300 });
|
|
});
|
|
|
|
// drag image before load
|
|
triggerDrag(image, 300, 300);
|
|
expect(wrapper.find('.van-image').html()).toMatchSnapshot();
|
|
|
|
// drag image after load
|
|
image.trigger('load');
|
|
triggerDrag(image, 300, 300);
|
|
expect(wrapper.find('.van-image').html()).toMatchSnapshot();
|
|
|
|
restore();
|
|
});
|
|
|
|
test('zoom out', async () => {
|
|
const restore = mockGetBoundingClientRect({ width: 100, height: 100 });
|
|
|
|
const onScale = jest.fn();
|
|
const wrapper = mount(ImagePreviewComponent, {
|
|
props: {
|
|
images,
|
|
show: true,
|
|
onScale,
|
|
},
|
|
});
|
|
|
|
await later();
|
|
const image = wrapper.find('.van-image');
|
|
triggerZoom(image, 300, 300, 'out');
|
|
|
|
expect(onScale).toHaveBeenLastCalledWith({ index: 0, scale: 1 });
|
|
|
|
restore();
|
|
});
|
|
|
|
test('should allow to use the teleport option', async () => {
|
|
const element = document.createElement('div');
|
|
element.id = 'parent-node';
|
|
document.body.appendChild(element);
|
|
ImagePreview({ images, teleport: element });
|
|
|
|
await later();
|
|
await nextTick();
|
|
const wrapperDiv = document.querySelector(
|
|
'.van-image-preview'
|
|
) as HTMLDivElement;
|
|
expect(wrapperDiv.parentElement?.parentElement?.id).toEqual(element.id);
|
|
document.body.removeChild(element);
|
|
|
|
ImagePreview(images);
|
|
|
|
await later();
|
|
await nextTick();
|
|
const wrapperBody = document.querySelector(
|
|
'.van-image-preview'
|
|
) as HTMLDivElement;
|
|
expect(wrapperBody.parentElement?.parentElement).toEqual(document.body);
|
|
});
|