fix(jump-hop): isolate draft runs from public leaderboard
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { expect, test, vi } from 'vitest';
|
||||
import { beforeEach, expect, test, vi } from 'vitest';
|
||||
|
||||
import type { JumpHopWorkProfileResponse } from '../../../packages/shared/src/contracts/jumpHop';
|
||||
import { useJumpHopLeaderboard } from '../../services/jump-hop/useJumpHopLeaderboard';
|
||||
@@ -11,6 +11,16 @@ vi.mock('../../services/jump-hop/useJumpHopLeaderboard', () => ({
|
||||
useJumpHopLeaderboard: vi.fn(),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.mocked(useJumpHopLeaderboard).mockReturnValue({
|
||||
leaderboard: null,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
refresh: vi.fn(),
|
||||
});
|
||||
});
|
||||
|
||||
test('跳一跳结果页展示排行榜列表', () => {
|
||||
vi.mocked(useJumpHopLeaderboard).mockReturnValue({
|
||||
leaderboard: {
|
||||
@@ -40,7 +50,7 @@ test('跳一跳结果页展示排行榜列表', () => {
|
||||
|
||||
render(
|
||||
<JumpHopResultView
|
||||
profile={buildProfile()}
|
||||
profile={buildProfile({ publicationStatus: 'published' })}
|
||||
onBack={() => {}}
|
||||
onEdit={() => {}}
|
||||
onStartTestRun={() => {}}
|
||||
@@ -57,13 +67,6 @@ test('跳一跳结果页展示排行榜列表', () => {
|
||||
});
|
||||
|
||||
test('跳一跳结果页默认角色预览使用陶泥儿透明 logo', () => {
|
||||
vi.mocked(useJumpHopLeaderboard).mockReturnValue({
|
||||
leaderboard: null,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
refresh: vi.fn(),
|
||||
});
|
||||
|
||||
render(
|
||||
<JumpHopResultView
|
||||
profile={buildProfile()}
|
||||
@@ -80,7 +83,27 @@ test('跳一跳结果页默认角色预览使用陶泥儿透明 logo', () => {
|
||||
);
|
||||
});
|
||||
|
||||
function buildProfile(): JumpHopWorkProfileResponse {
|
||||
test('跳一跳草稿结果页不请求公开排行榜', () => {
|
||||
render(
|
||||
<JumpHopResultView
|
||||
profile={buildProfile({ publicationStatus: 'draft' })}
|
||||
onBack={() => {}}
|
||||
onEdit={() => {}}
|
||||
onStartTestRun={() => {}}
|
||||
onPublish={() => {}}
|
||||
onRegenerateTiles={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(useJumpHopLeaderboard).not.toHaveBeenCalled();
|
||||
expect(screen.queryByText('排行榜')).toBeNull();
|
||||
});
|
||||
|
||||
function buildProfile(
|
||||
options: {
|
||||
publicationStatus?: JumpHopWorkProfileResponse['summary']['publicationStatus'];
|
||||
} = {},
|
||||
): JumpHopWorkProfileResponse {
|
||||
return {
|
||||
summary: {
|
||||
runtimeKind: 'jump-hop',
|
||||
@@ -95,7 +118,7 @@ function buildProfile(): JumpHopWorkProfileResponse {
|
||||
difficulty: 'standard',
|
||||
stylePreset: 'minimal-blocks',
|
||||
coverImageSrc: null,
|
||||
publicationStatus: 'draft',
|
||||
publicationStatus: options.publicationStatus ?? 'draft',
|
||||
playCount: 0,
|
||||
updatedAt: '2026-05-27T00:00:00Z',
|
||||
publishedAt: null,
|
||||
|
||||
@@ -272,6 +272,8 @@ export function JumpHopResultView({
|
||||
const profileId = isWorkProfile
|
||||
? profile.summary.profileId
|
||||
: safeDraft.profileId;
|
||||
const canShowLeaderboard =
|
||||
isWorkProfile && profile.summary.publicationStatus === 'published';
|
||||
const titleSource = isWorkProfile
|
||||
? profile.summary.workTitle
|
||||
: profile.workTitle;
|
||||
@@ -365,7 +367,9 @@ export function JumpHopResultView({
|
||||
<div className="text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]">
|
||||
结果操作
|
||||
</div>
|
||||
<JumpHopResultLeaderboard profileId={profileId} />
|
||||
{canShowLeaderboard ? (
|
||||
<JumpHopResultLeaderboard profileId={profileId} />
|
||||
) : null}
|
||||
{error ? (
|
||||
<div className="platform-banner platform-banner--danger mt-3 rounded-2xl text-sm leading-6">
|
||||
{error}
|
||||
|
||||
@@ -278,7 +278,7 @@ test('跳一跳运行态失败后在弹窗中展示排行榜', () => {
|
||||
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
profile={buildProfile()}
|
||||
profile={buildProfile({ publicationStatus: 'published' })}
|
||||
run={buildFailedRun()}
|
||||
runtimeRequestOptions={runtimeRequestOptions}
|
||||
onJump={vi.fn().mockResolvedValue(undefined)}
|
||||
@@ -298,6 +298,21 @@ test('跳一跳运行态失败后在弹窗中展示排行榜', () => {
|
||||
expect(within(leaderboard).getByText('00:08')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('跳一跳草稿运行失败后不请求公开排行榜', () => {
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
profile={buildProfile({ publicationStatus: 'draft' })}
|
||||
run={buildFailedRun()}
|
||||
onJump={vi.fn().mockResolvedValue(undefined)}
|
||||
onRestart={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(useJumpHopLeaderboard).not.toHaveBeenCalled();
|
||||
expect(screen.getByRole('dialog', { name: '失败' })).toBeTruthy();
|
||||
expect(screen.queryByTestId('jump-hop-runtime-leaderboard')).toBeNull();
|
||||
});
|
||||
|
||||
test('跳一跳角色层永远压在地块层之上', () => {
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
@@ -943,6 +958,7 @@ function buildProfile(options: {
|
||||
tileAssets?: JumpHopWorkProfileResponse['tileAssets'];
|
||||
coverComposite?: string | null;
|
||||
coverImageSrc?: string | null;
|
||||
publicationStatus?: JumpHopWorkProfileResponse['summary']['publicationStatus'];
|
||||
} = {}): JumpHopWorkProfileResponse {
|
||||
const characterAsset = {
|
||||
assetId: 'builtin',
|
||||
@@ -968,7 +984,7 @@ function buildProfile(options: {
|
||||
difficulty: 'standard',
|
||||
stylePreset: 'minimal-blocks',
|
||||
coverImageSrc: options.coverImageSrc ?? null,
|
||||
publicationStatus: 'draft',
|
||||
publicationStatus: options.publicationStatus ?? 'draft',
|
||||
playCount: 0,
|
||||
updatedAt: '2026-05-27T00:00:00Z',
|
||||
publishedAt: null,
|
||||
|
||||
@@ -843,7 +843,9 @@ export function JumpHopRuntimeShell({
|
||||
const jumpFeedbackForDisplay = getJumpHopJumpFeedbackLabel(stageRun);
|
||||
const isSettled =
|
||||
stageRun?.status === 'failed' || stageRun?.status === 'cleared';
|
||||
const shouldShowFailureLeaderboard = stageRun?.status === 'failed';
|
||||
const shouldShowFailureLeaderboard =
|
||||
stageRun?.status === 'failed' &&
|
||||
profile?.summary.publicationStatus === 'published';
|
||||
const successfulJumpCount = stageRun?.successfulJumpCount ?? 0;
|
||||
const durationLabel = formatJumpHopDurationLabel(
|
||||
getJumpHopRunDurationMs(stageRun, nowMs),
|
||||
|
||||
Reference in New Issue
Block a user