fix: preserve rpg custom world detail profiles

This commit is contained in:
kdletters
2026-05-22 03:14:11 +08:00
parent a9d23a8a44
commit d74457faa2
19 changed files with 2726 additions and 109 deletions

View File

@@ -776,3 +776,123 @@ test('custom world opening act accepts runtime npc id references and still start
}),
);
});
test('switching between custom worlds sends the newly selected profile to runtime bootstrap', async () => {
const user = userEvent.setup();
const oldProfile = buildSavedProfile();
const openedDraftProfile = normalizeCustomWorldProfileRecord({
...oldProfile,
id: 'opened-draft-profile',
name: '星砂废都',
subtitle: '坠星沙海与废都钟楼',
summary: '本次从草稿架打开并启动的目标草稿。',
settingText: '星砂覆盖旧废都,钟楼下埋着旧约。',
playableNpcs: [
{
...oldProfile.playableNpcs[0],
id: 'opened-playable-1',
name: '砂眠',
title: '废都引路人',
},
],
});
if (!openedDraftProfile) {
throw new Error('failed to build opened draft profile');
}
const normalizedOpenedDraftProfile = openedDraftProfile;
function SwitchWorldHarness() {
const {
gameState,
handleCustomWorldSelect,
handleCharacterSelect,
} = useRpgSessionBootstrap();
const openedCharacters = buildCustomWorldPlayableCharacters(
normalizedOpenedDraftProfile,
);
const selectedCharacter = openedCharacters[0] ?? null;
return (
<div>
<button
type="button"
onClick={() => handleCustomWorldSelect(oldProfile, { mode: 'play' })}
>
</button>
<button
type="button"
onClick={() =>
handleCustomWorldSelect(normalizedOpenedDraftProfile, {
mode: 'play',
})
}
>
稿
</button>
<button
type="button"
onClick={() => {
if (selectedCharacter) {
handleCharacterSelect(selectedCharacter);
}
}}
>
稿
</button>
<pre data-testid="state-snapshot">
{JSON.stringify({
profileId: gameState.customWorldProfile?.id ?? null,
profileName: gameState.customWorldProfile?.name ?? null,
})}
</pre>
</div>
);
}
runtimeStoryClientMocks.beginRuntimeStorySession.mockResolvedValue(
buildRuntimeStoryBootstrapSnapshot({
profile: normalizedOpenedDraftProfile,
character: buildCustomWorldPlayableCharacters(
normalizedOpenedDraftProfile,
)[0]!,
}),
);
render(<SwitchWorldHarness />);
await user.click(screen.getByRole('button', { name: '选择旧世界' }));
await waitFor(() => {
expect(
JSON.parse(screen.getByTestId('state-snapshot').textContent ?? '{}')
.profileName,
).toBe('回潮群岛');
});
await user.click(screen.getByRole('button', { name: '选择打开草稿' }));
await waitFor(() => {
expect(
JSON.parse(screen.getByTestId('state-snapshot').textContent ?? '{}')
.profileName,
).toBe('星砂废都');
});
await user.click(screen.getByRole('button', { name: '确认草稿角色' }));
await waitFor(() => {
expect(runtimeStoryClientMocks.beginRuntimeStorySession).toHaveBeenCalledWith(
expect.objectContaining({
customWorldProfile: expect.objectContaining({
id: 'opened-draft-profile',
name: '星砂废都',
summary: '本次从草稿架打开并启动的目标草稿。',
}),
character: expect.objectContaining({
id: 'opened-playable-1',
name: '砂眠',
}),
}),
);
});
});