merge: 강행 은퇴 하야 예약턴 입력을 반영
This commit is contained in:
@@ -119,6 +119,7 @@ describe('buildTurnCommandTable', () => {
|
||||
'che_단련',
|
||||
'che_숙련전환',
|
||||
'che_견문',
|
||||
'che_은퇴',
|
||||
'che_장비매매',
|
||||
'che_군량매매',
|
||||
'che_내정특기초기화',
|
||||
@@ -135,9 +136,67 @@ describe('buildTurnCommandTable', () => {
|
||||
'che_주민선정',
|
||||
],
|
||||
군사: ['che_징병', 'che_모병', 'che_훈련', 'che_사기진작', 'che_출병', 'che_집합', 'che_소집해제'],
|
||||
인사: ['che_이동', 'che_인재탐색', 'che_귀환', 'che_임관', 'che_랜덤임관'],
|
||||
인사: ['che_이동', 'che_강행', 'che_인재탐색', 'che_귀환', 'che_임관', 'che_랜덤임관'],
|
||||
계략: ['che_화계'],
|
||||
국가: ['che_증여', 'che_헌납', 'che_물자조달', 'che_거병', 'che_건국', 'che_선양', 'che_해산'],
|
||||
국가: [
|
||||
'che_증여',
|
||||
'che_헌납',
|
||||
'che_물자조달',
|
||||
'che_하야',
|
||||
'che_거병',
|
||||
'che_건국',
|
||||
'che_선양',
|
||||
'che_해산',
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('projects the Ref availability boundaries for force move, retirement, and resignation', async () => {
|
||||
const buildTable = (general: GeneralRow, nation: NationRow | null = buildNation()) =>
|
||||
buildTurnCommandTable({
|
||||
worldState: buildWorldState(),
|
||||
general,
|
||||
city: buildCity(),
|
||||
nation,
|
||||
nationGenerals: null,
|
||||
});
|
||||
const findCommand = (table: Awaited<ReturnType<typeof buildTable>>, key: string) =>
|
||||
table.general.flatMap((group) => group.values).find((command) => command.key === key);
|
||||
|
||||
const ordinary = await buildTable(buildGeneral());
|
||||
expect(findCommand(ordinary, 'che_강행')).toMatchObject({
|
||||
name: '강행',
|
||||
reqArg: true,
|
||||
possible: true,
|
||||
inputFields: [{ key: 'destCityId', optionSource: 'cities' }],
|
||||
});
|
||||
expect(findCommand(ordinary, 'che_은퇴')).toMatchObject({
|
||||
name: '은퇴',
|
||||
possible: false,
|
||||
status: 'blocked',
|
||||
reason: '나이가 60세 이상이어야 합니다.',
|
||||
});
|
||||
expect(findCommand(ordinary, 'che_하야')).toMatchObject({
|
||||
name: '하야',
|
||||
possible: true,
|
||||
status: 'available',
|
||||
});
|
||||
|
||||
const oldEnough = await buildTable({ ...buildGeneral(), age: 60 } as GeneralRow);
|
||||
expect(findCommand(oldEnough, 'che_은퇴')).toMatchObject({ possible: true, status: 'available' });
|
||||
|
||||
const ruler = await buildTable({ ...buildGeneral(), officerLevel: 12 } as GeneralRow);
|
||||
expect(findCommand(ruler, 'che_하야')).toMatchObject({
|
||||
possible: false,
|
||||
status: 'blocked',
|
||||
reason: expect.stringContaining('군주'),
|
||||
});
|
||||
|
||||
const neutral = await buildTable({ ...buildGeneral(), nationId: 0, officerLevel: 0 } as GeneralRow, null);
|
||||
expect(findCommand(neutral, 'che_하야')).toMatchObject({
|
||||
possible: false,
|
||||
status: 'blocked',
|
||||
reason: '재야입니다.',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -18,13 +18,16 @@ const GENERAL_AI_ACTIONS = [
|
||||
|
||||
const NATION_AI_ACTIONS = ['che_몰수', 'che_발령', 'che_선전포고', 'che_천도', 'che_포상'] as const;
|
||||
const GENERAL_REF_EDITOR_ACTIONS = [
|
||||
'che_은퇴',
|
||||
'che_임관',
|
||||
'che_랜덤임관',
|
||||
'che_강행',
|
||||
'che_징병',
|
||||
'che_출병',
|
||||
'che_농지개간',
|
||||
'che_화계',
|
||||
'che_증여',
|
||||
'che_하야',
|
||||
'che_장비매매',
|
||||
] as const;
|
||||
const NATION_REF_EDITOR_ACTIONS = ['che_포상', 'che_발령', 'che_증축', 'che_필사즉생'] as const;
|
||||
|
||||
@@ -294,7 +294,7 @@ const chiefCenter = {
|
||||
})),
|
||||
};
|
||||
|
||||
const install = async (page: Page, rejectGeneral = false) => {
|
||||
const install = async (page: Page, rejectGeneral = false, commandTableResponse: unknown = commandTable) => {
|
||||
const requests: unknown[] = [];
|
||||
const generalTurns = turns(30);
|
||||
const nationTurns = turns(12);
|
||||
@@ -344,7 +344,7 @@ const install = async (page: Page, rejectGeneral = false) => {
|
||||
? {
|
||||
kind: 'snapshot',
|
||||
revision: 'BBBBBBBBBBBBBBBBBBBBBB',
|
||||
data: commandTable,
|
||||
data: commandTableResponse,
|
||||
}
|
||||
: { kind: 'unchanged', revision: 'BBBBBBBBBBBBBBBBBBBBBB' },
|
||||
boardAccess: initial
|
||||
@@ -400,7 +400,7 @@ const install = async (page: Page, rejectGeneral = false) => {
|
||||
myCity: 1,
|
||||
myNation: 1,
|
||||
});
|
||||
if (name === 'turns.getCommandTable') return response(commandTable);
|
||||
if (name === 'turns.getCommandTable') return response(commandTableResponse);
|
||||
if (name === 'nation.getChiefCenter') return response(chiefCenter);
|
||||
if (name === 'turns.reserved.getGeneral')
|
||||
return response({ turns: generalTurns, revision: generalRevision });
|
||||
@@ -461,6 +461,117 @@ const install = async (page: Page, rejectGeneral = false) => {
|
||||
return requests;
|
||||
};
|
||||
|
||||
test('reserves force move, retirement, and resignation from the user command picker', async ({ page }) => {
|
||||
const specialCommandTable = {
|
||||
general: [
|
||||
{
|
||||
category: '개인',
|
||||
values: [
|
||||
{
|
||||
key: 'che_은퇴',
|
||||
name: '은퇴',
|
||||
reqArg: false,
|
||||
possible: false,
|
||||
status: 'blocked',
|
||||
reason: '나이가 60세 이상이어야 합니다.',
|
||||
inputFields: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
category: '인사',
|
||||
values: [
|
||||
{
|
||||
key: 'che_강행',
|
||||
name: '강행',
|
||||
reqArg: true,
|
||||
possible: true,
|
||||
status: 'available',
|
||||
inputFields: [
|
||||
{
|
||||
key: 'destCityId',
|
||||
label: '대상 도시',
|
||||
kind: 'select',
|
||||
required: true,
|
||||
optionSource: 'cities',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
category: '국가',
|
||||
values: [
|
||||
{
|
||||
key: 'che_하야',
|
||||
name: '하야',
|
||||
reqArg: false,
|
||||
possible: true,
|
||||
status: 'available',
|
||||
inputFields: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
nation: [],
|
||||
inputOptions,
|
||||
};
|
||||
const requests = await install(page, false, specialCommandTable);
|
||||
await page.setViewportSize({ width: 1200, height: 900 });
|
||||
await page.goto('/');
|
||||
|
||||
const editor = page.locator('[data-command-scope="general"]');
|
||||
|
||||
await editor.getByRole('button', { name: '1턴 명령 입력', exact: true }).click();
|
||||
let picker = page.getByTestId('command-picker');
|
||||
const retirement = picker.getByRole('button', { name: '은퇴', exact: true });
|
||||
await expect(retirement).toHaveClass(/blocked/);
|
||||
await expect(retirement).toHaveAttribute('title', '나이가 60세 이상이어야 합니다.');
|
||||
await retirement.hover();
|
||||
await retirement.focus();
|
||||
await expect(retirement).toBeFocused();
|
||||
await picker.screenshot({ path: test.info().outputPath('special-user-commands-desktop-1200.png') });
|
||||
await retirement.click();
|
||||
await expect(editor.locator('.action-column > div').nth(0)).toHaveText('은퇴');
|
||||
|
||||
await editor.getByRole('button', { name: '2턴 명령 입력', exact: true }).click();
|
||||
picker = page.getByTestId('command-picker');
|
||||
await picker.getByRole('button', { name: '국가', exact: true }).click();
|
||||
await picker.getByRole('button', { name: '하야', exact: true }).click();
|
||||
await expect(editor.locator('.action-column > div').nth(1)).toHaveText('하야');
|
||||
|
||||
await editor.getByRole('button', { name: '3턴 명령 입력', exact: true }).click();
|
||||
picker = page.getByTestId('command-picker');
|
||||
await picker.getByRole('button', { name: '인사', exact: true }).click();
|
||||
await picker.getByRole('button', { name: '강행', exact: true }).click();
|
||||
const forceMoveForm = picker.getByTestId('command-argument-form');
|
||||
await expect(forceMoveForm.getByTestId('command-argument-guidance')).toContainText('선택한 도시로 강행합니다.');
|
||||
await forceMoveForm.locator('select').selectOption('2');
|
||||
await picker.getByRole('button', { name: '입력', exact: true }).click();
|
||||
await expect(editor.locator('.action-column > div').nth(2)).toHaveText('강행');
|
||||
|
||||
const serialized = JSON.stringify(requests);
|
||||
expect(serialized).toContain('"action":"che_은퇴","args":{}');
|
||||
expect(serialized).toContain('"action":"che_하야","args":{}');
|
||||
expect(serialized).toContain('"action":"che_강행","args":{"destCityId":2}');
|
||||
|
||||
await page.setViewportSize({ width: 500, height: 900 });
|
||||
await editor.getByRole('button', { name: '4턴 명령 입력', exact: true }).click();
|
||||
picker = page.getByTestId('command-picker');
|
||||
await expect(picker.locator('.category-btn')).toHaveText(['개인', '인사', '국가']);
|
||||
const mobileGeometry = await picker.evaluate((element) => ({
|
||||
width: element.getBoundingClientRect().width,
|
||||
horizontalOverflow: element.scrollWidth - element.clientWidth,
|
||||
categoryColumns: getComputedStyle(element.querySelector<HTMLElement>('.category-list')!).gridTemplateColumns,
|
||||
}));
|
||||
expect(mobileGeometry.width).toBeLessThanOrEqual(500);
|
||||
expect(mobileGeometry.horizontalOverflow).toBeLessThanOrEqual(0);
|
||||
expect(mobileGeometry.categoryColumns.split(' ')).toHaveLength(3);
|
||||
await picker.getByRole('button', { name: '개인', exact: true }).click();
|
||||
await expect(picker.getByRole('button', { name: '은퇴', exact: true })).toBeVisible();
|
||||
await picker.screenshot({ path: test.info().outputPath('special-user-commands-mobile-500.png') });
|
||||
});
|
||||
|
||||
test('enters general and nation command arguments and sends exact values', async ({ page }) => {
|
||||
const requests = await install(page);
|
||||
await page.setViewportSize({ width: 1200, height: 900 });
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"che_사기진작",
|
||||
"che_요양",
|
||||
"che_견문",
|
||||
"che_은퇴",
|
||||
"che_내정특기초기화",
|
||||
"che_전투특기초기화",
|
||||
"che_장비매매",
|
||||
@@ -34,6 +35,8 @@
|
||||
"che_증여",
|
||||
"che_헌납",
|
||||
"che_이동",
|
||||
"che_강행",
|
||||
"che_하야",
|
||||
"che_선양",
|
||||
"che_해산",
|
||||
"휴식"
|
||||
|
||||
Reference in New Issue
Block a user