113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { act, render, screen } from '@testing-library/react';
|
|
import { createElement } from 'react';
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { RouteImageReadyGate } from './RouteImageReadyGate';
|
|
import {
|
|
collectRouteImageUrls,
|
|
extractCssImageUrls,
|
|
normalizePreloadImageUrl,
|
|
} from './routeImageReadyGateUtils';
|
|
import { RouteLoadingScreen } from './RouteLoadingScreen';
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
window.localStorage.clear();
|
|
});
|
|
|
|
describe('RouteImageReadyGate image url helpers', () => {
|
|
it('extracts urls from layered CSS image values', () => {
|
|
expect(
|
|
extractCssImageUrls(
|
|
'linear-gradient(#000,#111), url("/hero.png"), url("icons/card.webp")',
|
|
),
|
|
).toEqual(['/hero.png', 'icons/card.webp']);
|
|
});
|
|
|
|
it('normalizes preloadable urls against the current document', () => {
|
|
expect(normalizePreloadImageUrl('/cover.png')).toBe(
|
|
new URL('/cover.png', document.baseURI).href,
|
|
);
|
|
expect(normalizePreloadImageUrl('data:image/png;base64,abc')).toBe(
|
|
'data:image/png;base64,abc',
|
|
);
|
|
expect(normalizePreloadImageUrl('')).toBeNull();
|
|
});
|
|
|
|
it('collects img and CSS background urls from a route root', () => {
|
|
const root = document.createElement('section');
|
|
root.innerHTML = `
|
|
<img src="/images/card.png" />
|
|
<div style='background-image: url("/images/bg.webp")'></div>
|
|
<div style='border-image-source: url("/ui/frame.png")'></div>
|
|
`;
|
|
|
|
expect(collectRouteImageUrls(root)).toEqual([
|
|
new URL('/images/card.png', document.baseURI).href,
|
|
new URL('/images/bg.webp', document.baseURI).href,
|
|
new URL('/ui/frame.png', document.baseURI).href,
|
|
]);
|
|
});
|
|
|
|
it('reveals route content after a short cap when images stay pending', () => {
|
|
vi.useFakeTimers();
|
|
|
|
render(
|
|
createElement(
|
|
RouteImageReadyGate,
|
|
{
|
|
eyebrow: '正在载入游戏',
|
|
text: '正在载入冒险...',
|
|
},
|
|
createElement(
|
|
'section',
|
|
{
|
|
'data-testid': 'route-content',
|
|
},
|
|
createElement('img', {
|
|
src: '/generated-characters/slow-cover.png',
|
|
alt: 'slow cover',
|
|
}),
|
|
),
|
|
),
|
|
);
|
|
|
|
const content = screen.getByTestId('route-content');
|
|
const visibilityGate = content.parentElement;
|
|
expect(visibilityGate?.getAttribute('aria-hidden')).toBe('true');
|
|
expect(visibilityGate?.style.visibility).toBe('hidden');
|
|
|
|
act(() => {
|
|
vi.advanceTimersByTime(1600);
|
|
});
|
|
|
|
expect(visibilityGate?.getAttribute('aria-hidden')).toBe('false');
|
|
expect(visibilityGate?.style.visibility).toBe('visible');
|
|
});
|
|
|
|
it('uses the saved platform theme tokens for the route loading screen', () => {
|
|
window.localStorage.setItem(
|
|
'tavernrealms.settings.v1',
|
|
JSON.stringify({
|
|
version: 1,
|
|
musicVolume: 0.42,
|
|
platformTheme: 'dark',
|
|
}),
|
|
);
|
|
|
|
const { container } = render(
|
|
createElement(RouteLoadingScreen, {
|
|
eyebrow: '正在载入游戏',
|
|
text: '正在载入冒险...',
|
|
}),
|
|
);
|
|
const shell = container.firstElementChild;
|
|
|
|
expect(shell?.classList.contains('platform-theme')).toBe(true);
|
|
expect(shell?.classList.contains('platform-theme--dark')).toBe(true);
|
|
expect(shell?.className).toContain('bg-[image:var(--platform-body-fill)]');
|
|
});
|
|
});
|