diff --git a/src/image/__test__/__snapshots__/index.test.jsx.snap b/src/image/__test__/__snapshots__/index.test.jsx.snap
new file mode 100644
index 000000000..91f2e6185
--- /dev/null
+++ b/src/image/__test__/__snapshots__/index.test.jsx.snap
@@ -0,0 +1,15 @@
+// Vitest Snapshot v1
+
+exports[`Image > props > : lazy 1`] = `
+
+
+
+
+`;
diff --git a/src/image/__test__/index.test.jsx b/src/image/__test__/index.test.jsx
index 47907ee72..08c252e76 100644
--- a/src/image/__test__/index.test.jsx
+++ b/src/image/__test__/index.test.jsx
@@ -1,86 +1,144 @@
import { mount } from '@vue/test-utils';
-import { describe, it, expect } from 'vitest';
-import Image from '../image.vue';
+import { vi, describe, it, expect } from 'vitest';
import { LoadingIcon } from 'tdesign-icons-vue-next';
import { nextTick } from 'vue';
-import { vi } from 'vitest';
+import Image from '../image.vue';
+import { MockIntersectionObserver } from './utils';
+const prefix = 't'
+const name = `${prefix}-image`;
const IMAGE = 'https://tdesign.gtimg.com/site/upload1.png';
const FAIL_IMAGE = 'https://123.jpg';
const fitList = ['fill', 'contain', 'cover', 'none', 'scale-down'];
const shapeList = ['circle', 'round', 'square'];
const positionList = ['top', 'bottom', 'center', 'left', 'right'];
-describe('Image.vue', () => {
- it('create', async () => {
- const wrapper = mount(() => );
- const img = wrapper.find('.t-image__img');
- expect(wrapper.classes()).toContain('t-image');
- expect(img.exists()).toBeTruthy();
- expect(img.attributes('src')).toBe(IMAGE);
+describe('Image', () => {
+ beforeAll(() => {
+ window.IntersectionObserver = MockIntersectionObserver;
});
- it('alt render', async () => {
- const wrapper = mount(() => );
- const img = wrapper.find('.t-image__img');
- expect(wrapper.classes()).toContain('t-image');
- expect(img.attributes('alt')).toBe('图片');
- });
+ describe('props', () => {
+ it(': lazy', async () => {
+ const wrapper = mount(() => );
+ await nextTick();
+ const $image = wrapper.find(`.${name}__img`);
+ expect(wrapper.find(`.${name}__status`).exists()).toBeTruthy();
+ // 触发 IntersectionObserver , 但图片加载完成不会触发 Load 回调,
+ $image.trigger('resize');
+ await nextTick();
+ expect($image.attributes('src')).toBe(IMAGE);
+ // 手动触发 图片加载完成的回调函数
+ await $image.trigger('Load');
+ expect(wrapper.element).toMatchSnapshot();
+ expect(wrapper.find(`.${name}__status`).exists()).toBeFalsy();
+ });
- it('fit render', async () => {
- fitList.forEach((fit) => {
- const wrapper = mount(() => );
- const img = wrapper.find('.t-image__img');
- expect(img.attributes('style')).toContain(`object-fit: ${fit}`);
+ it(': alt', async () => {
+ const wrapper = mount(() => );
+ const $image = wrapper.find(`.${name}__img`);
+ expect(wrapper.classes()).toContain(`${name}`);
+ expect($image.attributes('alt')).toBe('图片');
});
- });
- it('shape render', async () => {
- shapeList.forEach((shape) => {
- const wrapper = mount(() => );
- expect(wrapper.classes()).toContain(`t-image--${shape}`);
+ it(': fit', async () => {
+ const wrapper = mount(Image, {
+ props: {
+ fit: '',
+ src: IMAGE,
+ }
+ })
+ const $image = wrapper.find(`.${name}__img`);
+ // fit = ''
+ fitList.forEach(item => {
+ expect($image.attributes('style').includes(`object-fit: ${item}`)).toBeFalsy();
+ })
+
+ const fit = 'cover';
+ await wrapper.setProps({
+ fit,
+ });
+ // fit = 'square'
+ expect($image.attributes('style')).toContain(`object-fit: ${fit}`);
});
- });
- it('position render', async () => {
- positionList.forEach((position) => {
- const wrapper = mount(() => );
- const img = wrapper.find('.t-image__img');
- expect(img.attributes('style')).toContain(`object-position: ${position}`);
+ it(': shape', async () => {
+ const wrapper = mount(Image, {
+ props: {
+ shape: '',
+ src: IMAGE,
+ }
+ })
+ const $image = wrapper.findComponent(Image);
+
+ // shape = ''
+ shapeList.forEach(item => {
+ expect($image.classes().includes(`${name}--${item}`)).toBeFalsy();
+ })
+
+ const shape = 'square';
+ await wrapper.setProps({
+ shape,
+ });
+ // shape = 'square'
+ expect($image.classes()).toContain(`${name}--${shape}`);
});
- });
- it('loading render', async () => {
- const slots = {
- loading: () => ,
- };
- const wrapper = mount(() => );
- const status = wrapper.find('.t-image__status');
- expect(status.exists()).toBeTruthy();
- expect(wrapper.findComponent(LoadingIcon).exists()).toBeTruthy();
- });
+ it(': position', async () => {
+ positionList.forEach((position) => {
+ const wrapper = mount(() => );
+ const $image = wrapper.find('.t-image__img');
+ expect($image.attributes('style')).toContain(`object-position: ${position}`);
+ });
+ });
- it('error render', async () => {
- const onError = vi.fn();
- const slots = {
- error: () => '加载失败',
- };
- const wrapper = mount(() => );
- const img = wrapper.find('.t-image__img');
- const status = wrapper.find('.t-image__status');
- await nextTick();
- await img.trigger('error');
- expect(status.exists()).toBeTruthy();
- // expect(status.text()).toBe('加载失败');
- // expect(onError).toBeCalled();
- });
+ it(': loading', async () => {
+ const slots = {
+ loading: () => ,
+ };
+ const wrapper = mount(() => );
+ const $status = wrapper.find(`.${name}__status`);
+ expect($status.exists()).toBeTruthy();
+ expect(wrapper.findComponent(LoadingIcon).exists()).toBeTruthy();
+ });
- it('load render', async () => {
- const onLoad = vi.fn();
- const wrapper = mount(() => );
- const img = wrapper.find('.t-image__img');
- await nextTick();
- img.trigger('load');
- // expect(onLoad).toBeCalled();
+ it(': src', async () => {
+ const onError = vi.fn();
+ const wrapper = mount(() => );
+ await nextTick();
+ const $image = wrapper.find(`.${name}__img`);
+ // 手动触发 图片加载失败的回调函数
+ await $image.trigger('Error');
+ expect(wrapper.find(`.${name}__status`).exists()).toBeTruthy();
+ // src = '',不会触发 error
+ expect(onError).toBeCalledTimes(0);
+ });
+
+ it(': onError', async () => {
+ const onError = vi.fn();
+ const slots = {
+ error: () => '加载失败',
+ };
+ const wrapper = mount(() => );
+ await nextTick();
+ const $image = wrapper.find(`.${name}__img`);
+ // 手动触发 图片加载失败的回调函数
+ await $image.trigger('Error');
+ const status = wrapper.find(`.${name}__status`);
+ expect(status.exists()).toBeTruthy();
+ expect(status.text()).toBe('加载失败');
+ expect(onError).toBeCalledTimes(1);
+ });
+
+ it(': onLoad', async () => {
+ const onLoad = vi.fn();
+ const wrapper = mount(() => );
+ await nextTick();
+ const $image = wrapper.find(`.${name}__img`);
+ expect($image.attributes('src')).toBe(IMAGE);
+ // 手动触发 图片加载完成的回调函数
+ await $image.trigger('Load');
+ expect(onLoad).toBeCalledTimes(1);
+ });
});
});
diff --git a/src/image/__test__/utils.ts b/src/image/__test__/utils.ts
new file mode 100644
index 000000000..c28acdf80
--- /dev/null
+++ b/src/image/__test__/utils.ts
@@ -0,0 +1,34 @@
+interface IntersectionObserverCallback {
+ (entries: IntersectionObserverEntry[], observer: IntersectionObserver): void;
+}
+
+export class MockIntersectionObserver {
+ _callback: Function;
+
+ _element!: HTMLElement;
+
+ constructor(callback: Function) {
+ this._callback = callback;
+ }
+
+ observe(element: HTMLElement) {
+ this._element = element;
+ this._element.addEventListener('resize', this.trigger);
+ }
+
+ unobserve() {
+ this._element.removeEventListener('resize', this.trigger);
+ }
+
+ disconnect() {
+ this._element.removeEventListener('resize', this.trigger);
+ }
+
+ trigger = (event: UIEvent) => {
+ this._callback([
+ {
+ isIntersecting: true,
+ },
+ ]);
+ };
+}