修复付费作品作者与管理员在详情页被误判为未购买,并去掉后台审核价格的客户端回退
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
- GameDetailPage:动作判定改为「服务端是否授予可玩入口」优先(canPlay = currentVersion.entryUrl 存在或 purchased 为 true),作者本人与管理员虽 purchased=false 但入口已下发时显示「立即玩」而不是「N 泥点购买」 - GameDistributionPages.test:新增「付费未购买但服务端已下发公开入口(作者/管理员)时显示立即玩」用例,保留既有付费未购买显示购买、付费已购买显示立即玩用例 - AdminGameDistributionReviewPage:删除 applyFrozenGameMetadata 中 priceMudPoints 的客户端回退,价格单一口径沿用服务端 version_detail_payload 写好的 game.priceMudPoints - AdminGameDistributionReviewPage.test:详情价格用例改为断言后端下发的版本冻结价(不再本地叠加冻结资料价格),历史版本无价格按免费的用例保持不变
This commit is contained in:
@@ -367,10 +367,12 @@ test('详情展示发布者和冻结资料,并试玩当前待审版本', async
|
||||
);
|
||||
});
|
||||
|
||||
test('详情优先展示待审版本冻结价格,而不是游戏行当前价格', async () => {
|
||||
test('详情价格以后端下发的版本冻结价为准,客户端不再本地叠加', async () => {
|
||||
vi.mocked(getAdminGameDistributionVersion).mockResolvedValue({
|
||||
// 游戏行当前是免费,待审版本冻结为 30 泥点:审核员要看到将要生效的价格。
|
||||
game: { ...detailResponse.game, priceMudPoints: 0 },
|
||||
// 后端 version_detail_payload 已按「待审版本冻结价优先、缺字段按 0」算好
|
||||
// game.priceMudPoints(此处待审版本冻结为 30 泥点,游戏行现价为 0);
|
||||
// 审核页只渲染该字段,不再从 frozenMetadata 里二次取价。
|
||||
game: { ...detailResponse.game, priceMudPoints: 30 },
|
||||
version: {
|
||||
...detailResponse.version,
|
||||
frozenMetadata: { title: '测试游戏', priceMudPoints: 30 },
|
||||
|
||||
@@ -98,11 +98,8 @@ function applyFrozenGameMetadata(
|
||||
typeof metadata.orientation === 'string'
|
||||
? metadata.orientation
|
||||
: game.orientation,
|
||||
// 价格随版本冻结:审核页要展示待审版本将要生效的价格,而不是游戏行当前已公开价格。
|
||||
priceMudPoints:
|
||||
typeof metadata.priceMudPoints === 'number'
|
||||
? metadata.priceMudPoints
|
||||
: game.priceMudPoints,
|
||||
// 价格不在这里二次叠加:服务端 `version_detail_payload` 已按「版本冻结价优先、
|
||||
// 缺字段按 0」把结果写进 `game.priceMudPoints`,客户端直接沿用该字段。
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -497,12 +497,15 @@ function GameDetailContent({
|
||||
const latestReviewReason = latestVersion?.reviewReason?.trim() ?? '';
|
||||
const mobilePlaybackBlocked = isMobileViewport && !game.deviceSupport.mobile;
|
||||
/**
|
||||
* 买断价与购买态:缺字段按免费/未购买兜底,付费且未购买时后端不下发可播放入口,
|
||||
* 前端也不再展示「立即玩」,改由购买动作接手。
|
||||
* 买断价与购买态:缺字段按免费/未购买兜底。
|
||||
* 购买态只是服务端视角的一部分:作者本人与管理员并不会被记为已购买
|
||||
* (`purchased=false`),但服务端仍会下发公开入口。动作判定必须以
|
||||
* 「服务端是否授予可玩入口」为准,详情页不自行推断 owner/admin 身份。
|
||||
*/
|
||||
const priceMudPoints = game.priceMudPoints ?? 0;
|
||||
const isPaidLocked =
|
||||
!ownerView && priceMudPoints > 0 && game.purchased !== true;
|
||||
const canPlay =
|
||||
Boolean(game.currentVersion?.entryUrl) || game.purchased === true;
|
||||
const isPaidLocked = !ownerView && priceMudPoints > 0 && !canPlay;
|
||||
const hasPlayableEntry = Boolean(version?.entryUrl);
|
||||
/**
|
||||
* 公开视角按「后端是否下发入口」判定可否开玩:付费未购买时入口为空。
|
||||
|
||||
@@ -288,6 +288,25 @@ describe('GameDetailPage', () => {
|
||||
expect(onPlay).toHaveBeenCalledWith('game-1');
|
||||
});
|
||||
|
||||
it('付费未购买但服务端已下发公开入口(作者/管理员)时显示立即玩而不是购买', async () => {
|
||||
const onPlay = vi.fn();
|
||||
// 作者本人与管理员不会被记为已购买(purchased=false),但后端仍授予可玩入口。
|
||||
getGameMock.mockResolvedValueOnce(
|
||||
createGame({ priceMudPoints: 120, purchased: false }),
|
||||
);
|
||||
render(
|
||||
<GameDetailPage gameId="game-1" onBack={vi.fn()} onPlay={onPlay} />,
|
||||
);
|
||||
|
||||
const playButton = await screen.findByRole('button', { name: /立即玩/u });
|
||||
expect((playButton as HTMLButtonElement).disabled).toBe(false);
|
||||
expect(screen.queryByRole('button', { name: /泥点购买/u })).toBeNull();
|
||||
expect(screen.getByText('120 泥点')).toBeTruthy();
|
||||
|
||||
fireEvent.click(playButton);
|
||||
expect(onPlay).toHaveBeenCalledWith('game-1');
|
||||
});
|
||||
|
||||
function createLockedPaidGame(): GameDistributionGame {
|
||||
return createGame({
|
||||
priceMudPoints: 120,
|
||||
|
||||
Reference in New Issue
Block a user