feat: polish jump hop themed runtime assets

This commit is contained in:
2026-06-05 22:55:40 +08:00
parent a215852381
commit cd8088d1fd
22 changed files with 719 additions and 354 deletions

View File

@@ -253,6 +253,70 @@ test('跳一跳运行态游玩中只保留得分并隐藏常驻排行榜', () =>
expect(screen.queryByRole('button', { name: /^起跳$/ })).toBeNull();
});
test('跳一跳运行态背景和游戏舞台覆盖全部界面且 HUD 使用独立主题按钮和拼图顶部样式', () => {
const backButtonAsset = {
assetId: 'jump-hop-back-button',
imageSrc: '/generated-jump-hop-assets/jump-hop-profile-test/back-button/image.png',
imageObjectKey:
'generated-jump-hop-assets/jump-hop-profile-test/back-button/image.png',
assetObjectId: 'asset-back-button',
generationProvider: 'vector-engine-gpt-image-2',
prompt: '主题返回按钮',
width: 1024,
height: 1024,
} satisfies NonNullable<JumpHopWorkProfileResponse['backButtonAsset']>;
render(
<JumpHopRuntimeShell
profile={buildProfile({ backButtonAsset })}
run={buildRun()}
onJump={vi.fn().mockResolvedValue(undefined)}
onRestart={() => {}}
/>,
);
const stage = screen.getByTestId('jump-hop-stage');
expect(stage.className).toContain('absolute');
expect(stage.className).toContain('inset-0');
expect(stage.className).toContain('h-full');
expect(stage.className).toContain('w-full');
expect(stage.className).not.toContain('rounded-[1.5rem]');
const backButton = screen.getByRole('button', { name: '返回' });
expect(backButton.className).toContain('pointer-events-auto');
expect(backButton.className).toContain('jump-hop-runtime__back-button');
expect(backButton.className).toContain('h-14');
expect(backButton.className).toContain('w-14');
expect(backButton.className).toContain('sm:h-[3.875rem]');
expect(backButton.className).toContain('sm:w-[3.875rem]');
expect(backButton.getAttribute('data-has-asset')).toBe('true');
expect(backButton.textContent).toBe('');
expect(
screen
.getByTestId('jump-hop-runtime-back-button-asset')
.getAttribute('src'),
).toBe(backButtonAsset.imageSrc);
const header = backButton.closest('header');
expect(header?.className).toContain('absolute');
expect(header?.className).toContain('top-0');
expect(header?.className).toContain('z-[130]');
expect(header?.querySelector('.puzzle-runtime-header-card')).toBeTruthy();
const titleCard = header?.querySelector('.puzzle-runtime-level-title-card');
expect(titleCard).toBeTruthy();
expect(titleCard?.className).toContain('jump-hop-runtime__score-title-card');
expect(screen.getByTestId('jump-hop-runtime-level-logo')).toBeTruthy();
expect(screen.getByText('得分')).toBeTruthy();
expect(screen.queryByText('跳一跳')).toBeNull();
const scoreCard = screen.getByTestId('jump-hop-score-card');
expect(scoreCard.className).toContain('puzzle-runtime-timer-card');
expect(scoreCard.className).toContain('puzzle-runtime-timer');
expect(scoreCard.className).toContain('jump-hop-runtime__score-value-card');
expect(scoreCard.className).toContain('justify-center');
expect(scoreCard.className).toContain('text-center');
});
test('跳一跳运行态失败后在弹窗中展示排行榜', () => {
const runtimeRequestOptions = {
runtimeGuestToken: 'runtime-guest-token',
@@ -333,7 +397,7 @@ test('跳一跳角色层永远压在地块层之上', () => {
);
});
test('跳一跳落点辅助标识会随着拖拽方向和距离实时移动', async () => {
test('跳一跳拖拽时隐藏落点辅助标识但保留弹弓拉线', async () => {
const onJump = vi.fn().mockResolvedValue(undefined);
render(
@@ -354,8 +418,6 @@ test('跳一跳落点辅助标识会随着拖拽方向和距离实时移动', as
});
});
expect(screen.queryByTestId('jump-hop-landing-assist')).toBeNull();
await act(async () => {
dispatchPointerEvent(stage, 'pointermove', {
pointerId: 1,
@@ -364,11 +426,8 @@ test('跳一跳落点辅助标识会随着拖拽方向和距离实时移动', as
});
});
const firstAssist = screen.getByTestId('jump-hop-landing-assist');
const firstLeft = firstAssist.style.left;
const firstTop = firstAssist.style.top;
expect(firstAssist.getAttribute('data-target-index')).toBe('1');
expect(firstLeft).not.toBe('62.288%');
expect(screen.queryByTestId('jump-hop-landing-assist')).toBeNull();
expect(stage.querySelector('.jump-hop-runtime__slingshot-guide')).toBeTruthy();
await act(async () => {
dispatchPointerEvent(stage, 'pointermove', {
@@ -378,9 +437,8 @@ test('跳一跳落点辅助标识会随着拖拽方向和距离实时移动', as
});
});
const secondAssist = screen.getByTestId('jump-hop-landing-assist');
expect(secondAssist.style.left).not.toBe(firstLeft);
expect(secondAssist.style.top).not.toBe(firstTop);
expect(screen.queryByTestId('jump-hop-landing-assist')).toBeNull();
expect(stage.querySelector('.jump-hop-runtime__slingshot-guide')).toBeTruthy();
});
test('跳一跳运行态直接渲染生成的地块切片图片', () => {
@@ -958,6 +1016,7 @@ function buildProfile(options: {
tileAssets?: JumpHopWorkProfileResponse['tileAssets'];
coverComposite?: string | null;
coverImageSrc?: string | null;
backButtonAsset?: JumpHopWorkProfileResponse['backButtonAsset'];
publicationStatus?: JumpHopWorkProfileResponse['summary']['publicationStatus'];
} = {}): JumpHopWorkProfileResponse {
const characterAsset = {
@@ -1016,6 +1075,7 @@ function buildProfile(options: {
tileAssets: options.tileAssets ?? [],
path: buildRun().path,
coverComposite: options.coverComposite ?? null,
backButtonAsset: options.backButtonAsset ?? null,
generationStatus: 'ready',
},
path: buildRun().path,
@@ -1029,6 +1089,7 @@ function buildProfile(options: {
characterAsset,
tileAtlasAsset: characterAsset,
tileAssets: options.tileAssets ?? [],
backButtonAsset: options.backButtonAsset ?? null,
};
}