외교 제의 만료와 처리 완료를 삭제 표시에서 분리
This commit is contained in:
@@ -6545,3 +6545,97 @@ for (const role of [
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const width of [1200, 390]) {
|
||||
test(`message lifecycle states preserve body and prevent stale actions ${width}`, async ({ page }, testInfo) => {
|
||||
const makeMessage = (
|
||||
id: number,
|
||||
option: Record<string, unknown>,
|
||||
text = '210년 1월까지 불가침을 제의합니다.'
|
||||
) => ({
|
||||
...privateMessage(id, 9),
|
||||
msgType: 'diplomacy',
|
||||
src: { ...privateMessage(id, 9).src, nationId: 2 },
|
||||
text,
|
||||
option: { action: 'noAggression', ...option },
|
||||
});
|
||||
const state: NavigationFixture = {
|
||||
officerLevel: 1,
|
||||
permission: 4,
|
||||
nationLevel: 3,
|
||||
stage: 0,
|
||||
npcMode: 1,
|
||||
latestVote: null,
|
||||
generalMeCalls: 0,
|
||||
operations: [],
|
||||
messages: {
|
||||
...emptyMessages(4),
|
||||
nationId: 1,
|
||||
diplomacy: [
|
||||
makeMessage(801, { actionState: 'expired', used: true }),
|
||||
makeMessage(802, { actionState: 'resolved', used: true }),
|
||||
makeMessage(803, { invalid: true }, '삭제된 메시지입니다.'),
|
||||
makeMessage(
|
||||
804,
|
||||
{ actionState: 'expired', used: true, permissionRedacted: true },
|
||||
'조회 권한이 없는 외교 메시지입니다.'
|
||||
),
|
||||
makeMessage(805, { actionState: 'expired', used: true, action: 'stopWar' }, '종전을 제의합니다.'),
|
||||
makeMessage(806, { actionState: 'unavailable', used: true }),
|
||||
],
|
||||
},
|
||||
};
|
||||
await installFixture(page, state);
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await waitForMain(page);
|
||||
const mobileButton = page.getByRole('button', { name: '메시지', exact: true });
|
||||
if (await mobileButton.isVisible()) await mobileButton.click();
|
||||
const expected = [
|
||||
[801, '만료된 불가침메시지입니다'],
|
||||
[802, '처리 완료된 메시지입니다'],
|
||||
[803, '삭제된 메시지입니다'],
|
||||
[804, '조회 권한이 없는 외교 메시지입니다.'],
|
||||
[805, '만료된 종전 제의 메시지입니다'],
|
||||
[806, '더 이상 응답할 수 없는 메시지입니다'],
|
||||
] as const;
|
||||
for (const [id, label] of expected) {
|
||||
const plate = page.locator(`.msg-plate[data-id="${id}"]:visible`).first();
|
||||
await expect(plate).toContainText(label);
|
||||
await expect(plate.locator('.message-response')).toHaveCount(0);
|
||||
if ([801, 802, 806].includes(id)) await expect(plate).toContainText('210년 1월까지 불가침을 제의합니다.');
|
||||
if (id !== 803) await expect(plate).not.toContainText('삭제된 메시지입니다');
|
||||
if (id === 804) await expect(plate.locator('.message-action-status')).toHaveCount(0);
|
||||
}
|
||||
await expect(page.getByTestId('diplomacy-message-notice')).toHaveCount(0);
|
||||
await page.reload();
|
||||
if (await mobileButton.isVisible()) await mobileButton.click();
|
||||
await expect(page.locator('.msg-plate[data-id="801"]:visible').first()).toContainText(
|
||||
'만료된 불가침메시지입니다'
|
||||
);
|
||||
await page.evaluate(() => document.fonts.ready);
|
||||
const plates = page.locator('.DiplomacyTalk .msg-plate:visible');
|
||||
const geometry = await plates.evaluateAll((elements) =>
|
||||
elements.map((el) => {
|
||||
const r = el.getBoundingClientRect();
|
||||
return {
|
||||
id: el.getAttribute('data-id'),
|
||||
width: r.width,
|
||||
height: r.height,
|
||||
clientHeight: el.clientHeight,
|
||||
scrollHeight: el.scrollHeight,
|
||||
font: getComputedStyle(el).font,
|
||||
html: el.outerHTML,
|
||||
};
|
||||
})
|
||||
);
|
||||
expect(geometry.length).toBeGreaterThanOrEqual(6);
|
||||
expect(geometry.every((item) => item.height >= 64 && item.scrollHeight <= item.clientHeight)).toBe(true);
|
||||
await writeFile(testInfo.outputPath('lifecycle-geometry.json'), JSON.stringify(geometry, null, 2));
|
||||
await page
|
||||
.locator('.msg-plate[data-id="801"]:visible')
|
||||
.first()
|
||||
.screenshot({ path: testInfo.outputPath('expired-message.png') });
|
||||
await page.screenshot({ path: testInfo.outputPath('lifecycle-page.png'), fullPage: true });
|
||||
expect(state.operations.filter((op) => op === 'messages.respond')).toHaveLength(0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,6 +56,26 @@ const destination = computed<MessageTarget>(
|
||||
|
||||
const invalid = computed(() => props.message.option?.invalid === true);
|
||||
const permissionRedacted = computed(() => props.message.option?.permissionRedacted === true);
|
||||
const actionState = computed(() => props.message.option?.actionState);
|
||||
const actionUnavailable = computed(
|
||||
() => props.message.option?.used === true || (actionState.value != null && actionState.value !== 'pending')
|
||||
);
|
||||
const actionStatusText = computed(() => {
|
||||
if (invalid.value || permissionRedacted.value || !actionUnavailable.value) return null;
|
||||
if (actionState.value === 'expired') {
|
||||
switch (props.message.option?.action) {
|
||||
case 'noAggression':
|
||||
return '만료된 불가침메시지입니다';
|
||||
case 'stopWar':
|
||||
return '만료된 종전 제의 메시지입니다';
|
||||
case 'scout':
|
||||
return '만료된 등용 권유 메시지입니다';
|
||||
default:
|
||||
return '만료된 메시지입니다';
|
||||
}
|
||||
}
|
||||
return actionState.value === 'resolved' ? '처리 완료된 메시지입니다' : '더 이상 응답할 수 없는 메시지입니다';
|
||||
});
|
||||
const hasAction = computed(() => typeof props.message.option?.action === 'string');
|
||||
const nationDirection = computed(() => {
|
||||
if (props.message.src.nationId === destination.value.nationId) {
|
||||
@@ -275,10 +295,11 @@ onBeforeUnmount(() => {
|
||||
]"
|
||||
>
|
||||
<strong v-if="permissionRedacted" class="permission-redacted-label">권한 제한</strong>
|
||||
{{ invalid ? '삭제된 메시지입니다' : message.text }}
|
||||
{{ permissionRedacted ? message.text : invalid ? '삭제된 메시지입니다' : message.text }}
|
||||
<div v-if="actionStatusText" class="message-action-status">{{ actionStatusText }}</div>
|
||||
</div>
|
||||
|
||||
<div v-if="hasAction && !invalid" class="message-response">
|
||||
<div v-if="hasAction && !invalid && !permissionRedacted && !actionUnavailable" class="message-response">
|
||||
<button
|
||||
class="prompt-yes legacy-button legacy-button--primary"
|
||||
type="button"
|
||||
|
||||
@@ -365,6 +365,7 @@ export const useMainDashboardStore = defineStore('mainDashboard', () => {
|
||||
(message) =>
|
||||
message.src.nationId !== nextMessages.nationId &&
|
||||
!message.option?.invalid &&
|
||||
!message.option?.used &&
|
||||
!message.option?.permissionRedacted
|
||||
)
|
||||
.reduce((latest, message) => Math.max(latest, message.id), 0);
|
||||
|
||||
Reference in New Issue
Block a user