This commit is contained in:
2026-05-01 20:29:09 +08:00
parent 8718472dbd
commit 87fbf41fab
137 changed files with 2922 additions and 989 deletions

View File

@@ -6,11 +6,12 @@ import { expect, test, vi } from 'vitest';
import type { PuzzleRunSnapshot } from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
import { AuthUiContext } from '../auth/AuthUiContext';
import {
PuzzleRuntimeShell,
buildMergedGroupOutlinePath,
resolveDraggedMergedGroupLayer,
resolveDraggedPieceCellLayer,
resolveDraggedPieceLayer,
} from './PuzzleRuntimeShell';
} from './puzzleRuntimeShape';
import { PuzzleRuntimeShell } from './PuzzleRuntimeShell';
vi.mock('../../hooks/useResolvedAssetReadUrl', () => ({
useResolvedAssetReadUrl: (src: string | null) => ({
@@ -450,16 +451,44 @@ test('合并块按实际拼块外轮廓描边', () => {
expect(outlinedPieces).toHaveLength(3);
expect(container.querySelector('.ring-2.ring-emerald-100\\/58')).toBeNull();
expect(outlinedPieces[0]?.className).toContain('border-r-0');
expect(outlinedPieces[0]?.className).toContain('border-b-0');
expect(outlinedPieces[0]?.className).toContain('rounded-tl-[0.85rem]');
expect(outlinedPieces[0]?.className).toContain('rounded-br-[0.35rem]');
expect(outlinedPieces[1]?.className).toContain('border-l-0');
expect(outlinedPieces[1]?.className).toContain('rounded-tr-[0.85rem]');
expect(outlinedPieces[1]?.className).toContain('rounded-bl-[0.35rem]');
expect(outlinedPieces[2]?.className).toContain('border-t-0');
expect(outlinedPieces[2]?.className).toContain('rounded-tr-[0.35rem]');
expect(outlinedPieces[2]?.className).toContain('rounded-bl-[0.85rem]');
expect(
container.querySelector('[data-merged-group-outline="true"]'),
).toBeTruthy();
const outlineStroke = container.querySelector(
'[data-merged-group-outline-stroke="true"]',
);
expect(outlineStroke).toBeTruthy();
expect(outlineStroke?.getAttribute('d')).toContain('Q 2 1 1.84 1');
expect(outlineStroke?.getAttribute('d')).toContain('Q 1 1 1 1.16');
expect((outlinedPieces[0] as HTMLElement).style.clipPath).toBe('');
const clippedLayer = container.querySelector(
'[style*="clip-path"]',
) as HTMLElement | null;
expect(clippedLayer?.style.clipPath).toContain('url(#');
});
test('合并块轮廓路径为内凹角生成圆角曲线', () => {
const outlinePath = buildMergedGroupOutlinePath({
rowSpan: 2,
colSpan: 2,
pieces: [
{
localRow: 0,
localCol: 0,
},
{
localRow: 0,
localCol: 1,
},
{
localRow: 1,
localCol: 0,
},
],
});
expect(outlinePath).toContain('Q 2 1 1.84 1');
expect(outlinePath).toContain('Q 1 1 1 1.16');
});
test('基础单块使用圆角裁剪图片', () => {
@@ -634,7 +663,7 @@ test('道具确认弹窗暂停时间,提示只演示不直接移动拼块', as
fireEvent.click(screen.getByRole('button', { name: '提示' }));
expect(screen.getByRole('dialog', { name: '使用提示' })).toBeTruthy();
expect(screen.getByText('消耗 1 陶泥币')).toBeTruthy();
expect(screen.getByText('消耗 1 光点')).toBeTruthy();
expect(onPauseChange).toHaveBeenLastCalledWith(true);
await act(async () => {
@@ -651,7 +680,7 @@ test('道具确认弹窗暂停时间,提示只演示不直接移动拼块', as
test('道具使用失败时保留确认弹窗和暂停态', async () => {
const onPauseChange = vi.fn();
const onUseProp = vi.fn().mockRejectedValue(new Error('陶泥币余额不足'));
const onUseProp = vi.fn().mockRejectedValue(new Error('光点余额不足'));
const playingRun: PuzzleRunSnapshot = {
...clearedRun,
currentLevel: {
@@ -684,7 +713,7 @@ test('道具使用失败时保留确认弹窗和暂停态', async () => {
});
expect(screen.getByRole('dialog', { name: '冻结时间' })).toBeTruthy();
expect(screen.getByText('陶泥币余额不足')).toBeTruthy();
expect(screen.getByText('光点余额不足')).toBeTruthy();
expect(onPauseChange).toHaveBeenLastCalledWith(true);
});
@@ -836,7 +865,7 @@ test('失败弹窗支持重开当前关和续时确认', async () => {
within(failedDialog).getByRole('button', { name: '继续1分钟' }),
);
expect(screen.getByRole('dialog', { name: '继续1分钟' })).toBeTruthy();
expect(screen.getByText('消耗 1 陶泥币')).toBeTruthy();
expect(screen.getByText('消耗 1 光点')).toBeTruthy();
await act(async () => {
fireEvent.click(screen.getByRole('button', { name: '确定' }));
@@ -846,7 +875,7 @@ test('失败弹窗支持重开当前关和续时确认', async () => {
});
test('失败续时扣费失败时保留确认弹窗', async () => {
const onUseProp = vi.fn().mockRejectedValue(new Error('陶泥币余额不足'));
const onUseProp = vi.fn().mockRejectedValue(new Error('光点余额不足'));
const failedRun: PuzzleRunSnapshot = {
...clearedRun,
currentLevel: {
@@ -878,7 +907,7 @@ test('失败续时扣费失败时保留确认弹窗', async () => {
});
expect(screen.getByRole('dialog', { name: '继续1分钟' })).toBeTruthy();
expect(screen.getByText('陶泥币余额不足')).toBeTruthy();
expect(screen.getByText('光点余额不足')).toBeTruthy();
});
test('查看原图开关打开覆盖层并在关闭后恢复计时', async () => {