修复快速编辑草稿回填用例的竞态:面板先出现、Lexical 的值后落
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 smoke (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 smoke (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
- 同一条用例在 CI run 2702 与本地一次全量里各命中过一次「expected '' to include '把角色头发改成红色'」:面板(dialog)一出现就同步读 textContent,编辑器值还没落 - 回填类断言统一改走 expectPanelPromptContains(内部 waitFor),不再赌时序 - 「提交后重开是空面板」那条否定断言改用 composerValue 读(它先让编辑器落值),避免空串让断言空过 - 连跑该文件 9 次 + 全量 3 次(173 文件 / 1826 通过 / 18 跳过)均全绿
This commit is contained in:
@@ -3,6 +3,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import type { GameCreationAppManifest } from '../../../packages/shared/src/contracts/gameCreationApp';
|
||||
import {
|
||||
composerValue,
|
||||
createGameCreationAppManifest,
|
||||
findResourceSelectButton,
|
||||
fireEvent,
|
||||
@@ -368,6 +369,17 @@ function panelPromptText(panel: HTMLElement) {
|
||||
return within(panel).getByLabelText('快速编辑提示词').textContent ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 「重开面板后提示词应当回填」不能同步读。
|
||||
*
|
||||
* 面板(dialog)先出现,Lexical 的编辑器值随后才落;同步读 `textContent` 在并发跑全量时
|
||||
* 会偶发读到空串——CI run 2702 与本地一次全量各命中过一次(同一条用例、`expected '' to
|
||||
* include '把角色头发改成红色'`)。这里等值真的落位,不再赌时序。
|
||||
*/
|
||||
async function expectPanelPromptContains(panel: HTMLElement, expected: string) {
|
||||
await waitFor(() => expect(panelPromptText(panel)).toContain(expected));
|
||||
}
|
||||
|
||||
/** 关掉画布浮层:Esc 与点外部同一条既有链路(`clearResourceCanvasFocus`)。 */
|
||||
async function dismissPanel() {
|
||||
fireEvent.keyDown(document, { key: 'Escape' });
|
||||
@@ -408,7 +420,7 @@ describe('快速编辑草稿的保留与恢复', () => {
|
||||
await dismissPanel();
|
||||
|
||||
const reopened = await openQuickEditPanel('source-art.png');
|
||||
expect(panelPromptText(reopened)).toContain('把夜色改成星空');
|
||||
await expectPanelPromptContains(reopened, '把夜色改成星空');
|
||||
expect(
|
||||
document.querySelector('[data-resource-reference-id="source-rules"]'),
|
||||
).not.toBeNull();
|
||||
@@ -438,13 +450,15 @@ describe('快速编辑草稿的保留与恢复', () => {
|
||||
);
|
||||
|
||||
await dismissPanel();
|
||||
expect(
|
||||
panelPromptText(await openQuickEditPanel('source-art.png')),
|
||||
).toContain('第一张的草稿');
|
||||
await expectPanelPromptContains(
|
||||
await openQuickEditPanel('source-art.png'),
|
||||
'第一张的草稿',
|
||||
);
|
||||
await dismissPanel();
|
||||
expect(
|
||||
panelPromptText(await openQuickEditPanel('source-art-2.png')),
|
||||
).toContain('第二张的草稿');
|
||||
await expectPanelPromptContains(
|
||||
await openQuickEditPanel('source-art-2.png'),
|
||||
'第二张的草稿',
|
||||
);
|
||||
});
|
||||
|
||||
it('恢复入口按草稿计数,「继续编辑」重开面板并回填,丢弃后入口消失', async () => {
|
||||
@@ -486,7 +500,7 @@ describe('快速编辑草稿的保留与恢复', () => {
|
||||
const resumed = await screen.findByRole('dialog', {
|
||||
name: '快速编辑图片',
|
||||
});
|
||||
expect(panelPromptText(resumed)).toContain('把角色头发改成红色');
|
||||
await expectPanelPromptContains(resumed, '把角色头发改成红色');
|
||||
await dismissPanel();
|
||||
|
||||
fireEvent.click(
|
||||
@@ -539,7 +553,7 @@ describe('快速编辑草稿的保留与恢复', () => {
|
||||
).not.toBeNull();
|
||||
|
||||
const resumed = await openQuickEditPanel('source-art.png');
|
||||
expect(panelPromptText(resumed)).toContain('把夜色改成星空');
|
||||
await expectPanelPromptContains(resumed, '把夜色改成星空');
|
||||
});
|
||||
|
||||
it('正规化换掉卡片投影后,草稿跟着资源走、重开在正式素材上继续', async () => {
|
||||
@@ -605,7 +619,7 @@ describe('快速编辑草稿的保留与恢复', () => {
|
||||
// 旧卡片已经不在画布上:草稿按**路径**归属,新投影的正式素材卡照样命中,否则这一笔
|
||||
// 就再也点不到。
|
||||
const reopened = await openQuickEditPanel('task-art.png');
|
||||
expect(panelPromptText(reopened)).toContain('把夜色改成星空');
|
||||
await expectPanelPromptContains(reopened, '把夜色改成星空');
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -664,7 +678,7 @@ describe('快速编辑草稿的保留与恢复', () => {
|
||||
);
|
||||
|
||||
const reopened = await openQuickEditPanel('task-art.png');
|
||||
expect(panelPromptText(reopened)).toContain('把夜色改成星空');
|
||||
await expectPanelPromptContains(reopened, '把夜色改成星空');
|
||||
});
|
||||
|
||||
it('原生恢复队列与本地草稿共用同一枚入口,两边都能继续', async () => {
|
||||
@@ -732,7 +746,11 @@ describe('快速编辑草稿的保留与恢复', () => {
|
||||
);
|
||||
|
||||
const reopened = await openQuickEditPanel('source-art.png');
|
||||
expect(panelPromptText(reopened)).not.toContain('把夜色改成星空');
|
||||
// 用 `composerValue` 读(它内部先让 Lexical 落值):同步读会在值未落时拿到空串,
|
||||
// 让这条否定断言空过——那正是上面那条回填断言的同一类竞态。
|
||||
expect(
|
||||
await composerValue(within(reopened).getByLabelText('快速编辑提示词')),
|
||||
).not.toContain('把夜色改成星空');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -815,7 +833,7 @@ describe('提交中的快速编辑进「生成任务」侧栏', () => {
|
||||
|
||||
// 回到第一张:草稿照旧回填,但这一笔已经在跑——再点提交必须被拦下。
|
||||
const reopened = await openQuickEditPanel('source-art.png');
|
||||
expect(panelPromptText(reopened)).toContain('把嘴改小一点');
|
||||
await expectPanelPromptContains(reopened, '把嘴改小一点');
|
||||
fireEvent.click(within(reopened).getByRole('button', { name: '修改' }));
|
||||
expect(
|
||||
await within(reopened).findByText(
|
||||
|
||||
Reference in New Issue
Block a user