Initial TrueGrowth source import
This commit is contained in:
158
packages/drawnix/src/components/media-library/AssetItem.test.tsx
Normal file
158
packages/drawnix/src/components/media-library/AssetItem.test.tsx
Normal file
@@ -0,0 +1,158 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import type React from 'react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { AssetItem } from './AssetItem';
|
||||
import { AssetSource, AssetType, type Asset } from '../../types/asset.types';
|
||||
|
||||
vi.mock('tdesign-react', () => ({
|
||||
Checkbox: ({ checked, onChange }: any) => (
|
||||
<input
|
||||
aria-label="选择资产"
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={(event) => onChange?.(event.target.checked)}
|
||||
/>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('../lazy-image', () => ({
|
||||
LazyImage: ({ src, alt, className }: any) => (
|
||||
<img src={src} alt={alt} className={className} />
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('../shared/VideoPosterPreview', () => ({
|
||||
VideoPosterPreview: ({ src, poster, alt, className }: any) => (
|
||||
<img
|
||||
src={poster || src}
|
||||
alt={alt}
|
||||
className={`video-poster-preview__media ${className || ''}`}
|
||||
/>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('../shared/hover', () => ({
|
||||
HoverTip: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
||||
}));
|
||||
|
||||
vi.mock('../../hooks/useAssetSize', () => ({
|
||||
useAssetSize: (_id: string, _url: string, size?: number) => size,
|
||||
}));
|
||||
|
||||
vi.mock('../../hooks/useThumbnailUrl', () => ({
|
||||
useThumbnailUrl: (url: string) => url,
|
||||
}));
|
||||
|
||||
vi.mock('../../hooks/useUnifiedCache', () => ({
|
||||
useUnifiedCache: () => ({
|
||||
isCached: true,
|
||||
cacheWarning: undefined,
|
||||
}),
|
||||
}));
|
||||
|
||||
const baseAsset = {
|
||||
source: AssetSource.LOCAL,
|
||||
createdAt: 1,
|
||||
size: 4096,
|
||||
};
|
||||
|
||||
const videoAsset: Asset = {
|
||||
...baseAsset,
|
||||
id: 'video-asset',
|
||||
type: AssetType.VIDEO,
|
||||
url: '/media/demo.mp4',
|
||||
thumbnail: '/media/demo-poster.jpg',
|
||||
name: '视频素材',
|
||||
mimeType: 'video/mp4',
|
||||
};
|
||||
|
||||
const audioAsset: Asset = {
|
||||
...baseAsset,
|
||||
id: 'audio-asset',
|
||||
type: AssetType.AUDIO,
|
||||
url: '/media/demo.mp3',
|
||||
thumbnail: '/media/demo-cover.jpg',
|
||||
name: '音频素材',
|
||||
mimeType: 'audio/mpeg',
|
||||
};
|
||||
|
||||
function renderAssetItem(asset: Asset) {
|
||||
return render(
|
||||
<AssetItem
|
||||
asset={asset}
|
||||
viewMode="grid"
|
||||
isSelected={false}
|
||||
onSelect={vi.fn()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
describe('AssetItem hover preview', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(window.HTMLMediaElement.prototype, 'play').mockResolvedValue();
|
||||
vi.spyOn(window.HTMLMediaElement.prototype, 'pause').mockImplementation(
|
||||
() => undefined
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('plays video on hover and restores the poster on mouse leave', async () => {
|
||||
const { container } = renderAssetItem(videoAsset);
|
||||
const item = container.querySelector('.asset-item') as HTMLElement;
|
||||
|
||||
expect(container.querySelector('.asset-item__hover-video')).toBeNull();
|
||||
|
||||
fireEvent.mouseEnter(item);
|
||||
|
||||
const hoverVideo = await waitFor(() => {
|
||||
const node = container.querySelector('.asset-item__hover-video');
|
||||
expect(node).toBeInstanceOf(HTMLVideoElement);
|
||||
return node as HTMLVideoElement;
|
||||
});
|
||||
|
||||
expect(hoverVideo.getAttribute('src')).toBe(videoAsset.url);
|
||||
expect(hoverVideo.muted).toBe(true);
|
||||
expect(hoverVideo.loop).toBe(true);
|
||||
await waitFor(() => {
|
||||
expect(window.HTMLMediaElement.prototype.play).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
fireEvent.mouseLeave(item);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(container.querySelector('.asset-item__hover-video')).toBeNull();
|
||||
});
|
||||
expect(screen.getByAltText(videoAsset.name)).not.toBeNull();
|
||||
});
|
||||
|
||||
it('plays audio on hover and restores the cover on mouse leave', async () => {
|
||||
const { container } = renderAssetItem(audioAsset);
|
||||
const item = container.querySelector('.asset-item') as HTMLElement;
|
||||
|
||||
expect(container.querySelector('.asset-item__hover-audio')).toBeNull();
|
||||
expect(screen.getByAltText(audioAsset.name)).not.toBeNull();
|
||||
|
||||
fireEvent.mouseEnter(item);
|
||||
|
||||
const hoverAudio = await waitFor(() => {
|
||||
const node = container.querySelector('.asset-item__hover-audio');
|
||||
expect(node).toBeInstanceOf(HTMLAudioElement);
|
||||
return node as HTMLAudioElement;
|
||||
});
|
||||
|
||||
expect(hoverAudio.getAttribute('src')).toBe(audioAsset.url);
|
||||
await waitFor(() => {
|
||||
expect(window.HTMLMediaElement.prototype.play).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
fireEvent.mouseLeave(item);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(container.querySelector('.asset-item__hover-audio')).toBeNull();
|
||||
});
|
||||
expect(screen.getByAltText(audioAsset.name)).not.toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user