等待推荐页运行态全部资源

推荐页 ready 持续观察运行态图片、背景、音视频和资源 pending 标记
资源换签与玩法图集解析中通过隐藏标记阻止遮罩提前消失
补齐拼图、跳一跳、抓大鹅和敲木鱼运行态资源等待接入
补充推荐页资源等待回归测试和团队文档
This commit is contained in:
2026-06-08 17:49:28 +08:00
parent ccb5023197
commit 52c6f4282f
12 changed files with 802 additions and 125 deletions

View File

@@ -9,7 +9,7 @@ import {
within,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { afterEach, expect, test, vi } from 'vitest';
import type {
@@ -4095,6 +4095,11 @@ test('mobile recommend runtime cover does not swap to a late signed cover', asyn
test('mobile recommend cover waits until runtime images are ready', async () => {
vi.useFakeTimers();
const animationCallbacks: FrameRequestCallback[] = [];
const flushAnimationFrames = () => {
act(() => {
animationCallbacks.splice(0).forEach((callback) => callback(16));
});
};
Object.defineProperty(window, 'requestAnimationFrame', {
configurable: true,
writable: true,
@@ -4137,6 +4142,102 @@ test('mobile recommend cover waits until runtime images are ready', async () =>
await act(async () => {
vi.advanceTimersByTime(520);
});
flushAnimationFrames();
flushAnimationFrames();
await act(async () => undefined);
expect(
document.querySelector('.platform-recommend-runtime-cover')?.className,
).toContain('platform-recommend-runtime-cover--hidden');
});
test('mobile recommend cover waits for async runtime resources beyond the main image', async () => {
vi.useFakeTimers();
const animationCallbacks: FrameRequestCallback[] = [];
const flushAnimationFrames = () => {
act(() => {
animationCallbacks.splice(0).forEach((callback) => callback(16));
});
};
Object.defineProperty(window, 'requestAnimationFrame', {
configurable: true,
writable: true,
value: vi.fn((callback: FrameRequestCallback) => {
animationCallbacks.push(callback);
return animationCallbacks.length;
}),
});
Object.defineProperty(window, 'cancelAnimationFrame', {
configurable: true,
writable: true,
value: vi.fn(),
});
function AsyncRuntimeAssets() {
const [showExtraResource, setShowExtraResource] = useState(false);
useEffect(() => {
const timeoutId = window.setTimeout(() => {
setShowExtraResource(true);
}, 100);
return () => window.clearTimeout(timeoutId);
}, []);
return (
<div>
<img src="/runtime-main.png" alt="runtime main" />
{showExtraResource ? (
<img src="/runtime-extra.png" alt="runtime extra" />
) : (
<span
hidden
data-runtime-resource-pending="true"
data-runtime-resource-src="/runtime-extra.png"
/>
)}
</div>
);
}
renderLoggedOutHomeView(vi.fn(), {
latestEntries: [puzzlePublicEntry],
activeRecommendEntryKey: 'puzzle:user-2:puzzle-profile-public-1',
isRecommendRuntimeReady: true,
recommendRuntimeContent: <AsyncRuntimeAssets />,
});
fireEvent.load(screen.getByAltText('runtime main'));
flushAnimationFrames();
await act(async () => {
vi.advanceTimersByTime(100);
});
await act(async () => undefined);
flushAnimationFrames();
flushAnimationFrames();
expect(screen.getByAltText('runtime extra')).toBeTruthy();
await act(async () => {
vi.advanceTimersByTime(80);
});
flushAnimationFrames();
await act(async () => {
vi.advanceTimersByTime(520);
});
flushAnimationFrames();
expect(
document.querySelector('.platform-recommend-runtime-cover')?.className,
).not.toContain('platform-recommend-runtime-cover--hidden');
fireEvent.load(screen.getByAltText('runtime extra'));
flushAnimationFrames();
await act(async () => {
vi.advanceTimersByTime(80);
});
flushAnimationFrames();
flushAnimationFrames();
await act(async () => undefined);
expect(
document.querySelector('.platform-recommend-runtime-cover')?.className,
@@ -4144,7 +4245,24 @@ test('mobile recommend cover waits until runtime images are ready', async () =>
});
test('mobile recommend keeps runtime visual stable when active entry changes', async () => {
vi.useFakeTimers();
const animationCallbacks: FrameRequestCallback[] = [];
const flushAnimationFrames = () => {
act(() => {
animationCallbacks.splice(0).forEach((callback) => callback(16));
});
};
const settleRecommendRuntimeReady = async () => {
await act(async () => {
vi.advanceTimersByTime(80);
});
flushAnimationFrames();
flushAnimationFrames();
await act(async () => {
vi.advanceTimersByTime(520);
});
await act(async () => undefined);
};
Object.defineProperty(window, 'requestAnimationFrame', {
configurable: true,
writable: true,
@@ -4183,14 +4301,10 @@ test('mobile recommend keeps runtime visual stable when active entry changes', a
isRecommendRuntimeReady: true,
});
act(() => {
animationCallbacks.splice(0).forEach((callback) => callback(16));
});
await waitFor(() => {
expect(
document.querySelector('.platform-recommend-runtime-cover')?.className,
).toContain('platform-recommend-runtime-cover--hidden');
});
await settleRecommendRuntimeReady();
expect(
document.querySelector('.platform-recommend-runtime-cover')?.className,
).toContain('platform-recommend-runtime-cover--hidden');
rerender(
<AuthUiContext.Provider
@@ -4243,6 +4357,7 @@ test('mobile recommend keeps runtime visual stable when active entry changes', a
/>
</AuthUiContext.Provider>,
);
await act(async () => undefined);
const rail = document.querySelector(
'.platform-recommend-swipe-rail',