토너먼트 대진 장수에 능력치와 배당 표시
This commit is contained in:
@@ -1177,3 +1177,61 @@ test('closed betting keeps investment and return visible without submit controls
|
|||||||
await page.getByRole('tab', { name: '16강', exact: true }).click();
|
await page.getByRole('tab', { name: '16강', exact: true }).click();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const width of [1365, 801, 390, 320]) {
|
||||||
|
test(`tournament candidates show stat and live odds at ${width}px`, async ({ page }, testInfo) => {
|
||||||
|
await page.setViewportSize({ width, height: 900 });
|
||||||
|
const realtimeState = { tournamentStage: 7, totalAmount: 2800 };
|
||||||
|
await installFixture(page, { tournamentType: 3, tournamentStage: 7, realtimeState });
|
||||||
|
await page.goto('tournament');
|
||||||
|
await page.waitForLoadState('networkidle');
|
||||||
|
await page.evaluate(() => document.fonts.ready);
|
||||||
|
const bracket = page.locator(width > 800 ? '.desktop-bracket' : '.mobile-bracket');
|
||||||
|
const cards = bracket.locator(width > 800 ? '.desktop-bracket-name' : '.mobile-bracket-name');
|
||||||
|
await expect(cards.first().locator('.bracket-core-stat')).toHaveText('지력 80');
|
||||||
|
await expect(cards.first().locator('.bracket-odds')).toHaveText('배당 28.00');
|
||||||
|
const geometry = await cards.evaluateAll((elements) =>
|
||||||
|
elements.map((card) => ({
|
||||||
|
card: card.getBoundingClientRect().toJSON(),
|
||||||
|
fields: [
|
||||||
|
...card.querySelectorAll<HTMLElement>(
|
||||||
|
'.general-identity-icon, .general-identity-name, .bracket-core-stat, .bracket-odds'
|
||||||
|
),
|
||||||
|
].map((el) => ({
|
||||||
|
className: el.className,
|
||||||
|
rect: el.getBoundingClientRect().toJSON(),
|
||||||
|
fontSize: getComputedStyle(el).fontSize,
|
||||||
|
scrollWidth: el.scrollWidth,
|
||||||
|
clientWidth: el.clientWidth,
|
||||||
|
})),
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
for (const { card, fields } of geometry) {
|
||||||
|
for (const field of fields) {
|
||||||
|
expect(field.rect.left).toBeGreaterThanOrEqual(card.left);
|
||||||
|
expect(field.rect.right).toBeLessThanOrEqual(card.right);
|
||||||
|
expect(field.rect.top).toBeGreaterThanOrEqual(card.top);
|
||||||
|
expect(field.rect.bottom).toBeLessThanOrEqual(card.bottom);
|
||||||
|
if (field.className === 'general-identity-icon') expect(field.rect.width).toBe(64);
|
||||||
|
if (field.className === 'bracket-core-stat' || field.className === 'bracket-odds') {
|
||||||
|
expect(field.fontSize).toBe('14px');
|
||||||
|
expect(field.scrollWidth).toBeLessThanOrEqual(field.clientWidth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await writeFile(testInfo.outputPath('tournament-info-geometry.json'), JSON.stringify(geometry, null, 2));
|
||||||
|
await writeFile(testInfo.outputPath('tournament-info-dom.html'), await bracket.evaluate((el) => el.outerHTML));
|
||||||
|
await page.screenshot({ path: testInfo.outputPath('tournament-info.png'), fullPage: true });
|
||||||
|
if (width <= 800) {
|
||||||
|
for (const label of ['8강', '4강', '결승', '우승']) {
|
||||||
|
await bracket.getByRole('tab', { name: label, exact: true }).click();
|
||||||
|
await expect(cards.first().locator('.bracket-core-stat')).toHaveText('지력 80');
|
||||||
|
await expect(cards.first().locator('.bracket-odds')).toHaveText('배당 28.00');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realtimeState.totalAmount = 5600;
|
||||||
|
await page.getByRole('button', { name: '갱신', exact: true }).click();
|
||||||
|
await expect(cards.first().locator('.bracket-odds')).toHaveText('배당 56.00');
|
||||||
|
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(width);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ const connections = computed(() =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const odds = (id: number | null) => {
|
const odds = (id: number | null) => {
|
||||||
if (id === null) return '0';
|
if (id === null || props.betTotals === undefined) return '-';
|
||||||
const amount = props.betTotals?.[id] ?? 0;
|
const amount = props.betTotals?.[id] ?? 0;
|
||||||
if (!amount) return '∞';
|
if (!amount) return '∞';
|
||||||
return (props.totalBet / amount).toFixed(2);
|
return (props.totalBet / amount).toFixed(2);
|
||||||
@@ -158,11 +158,19 @@ const mobilePairs = computed(() => {
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<GeneralIdentity
|
<GeneralIdentity
|
||||||
|
class="bracket-info-identity"
|
||||||
:name="slot.name"
|
:name="slot.name"
|
||||||
:picture="slot.picture"
|
:picture="slot.picture"
|
||||||
:image-server="slot.imageServer"
|
:image-server="slot.imageServer"
|
||||||
:npc-state="slot.npcState"
|
:npc-state="slot.npcState"
|
||||||
/>
|
>
|
||||||
|
<template v-if="slot.id !== null" #details>
|
||||||
|
<span v-if="coreStat(slot)" class="bracket-core-stat">
|
||||||
|
{{ coreStat(slot)?.label }} {{ coreStat(slot)?.value }}
|
||||||
|
</span>
|
||||||
|
<span class="bracket-odds">배당 {{ odds(slot.id) }}</span>
|
||||||
|
</template>
|
||||||
|
</GeneralIdentity>
|
||||||
<slot
|
<slot
|
||||||
v-if="columnIndex === 0 && bettingOpen && slot.id !== null"
|
v-if="columnIndex === 0 && bettingOpen && slot.id !== null"
|
||||||
name="bet-controls"
|
name="bet-controls"
|
||||||
@@ -210,16 +218,22 @@ const mobilePairs = computed(() => {
|
|||||||
:data-general-id="slot.id ?? undefined"
|
:data-general-id="slot.id ?? undefined"
|
||||||
>
|
>
|
||||||
<GeneralIdentity
|
<GeneralIdentity
|
||||||
:class="{ 'bracket-candidate-identity': activeMobileRound === 0 && bettingMode }"
|
:class="{
|
||||||
|
'bracket-candidate-identity': activeMobileRound === 0 && bettingMode,
|
||||||
|
'bracket-info-identity': !bettingMode || activeMobileRound !== 0,
|
||||||
|
}"
|
||||||
:name="slot.name"
|
:name="slot.name"
|
||||||
:picture="slot.picture"
|
:picture="slot.picture"
|
||||||
:image-server="slot.imageServer"
|
:image-server="slot.imageServer"
|
||||||
:npc-state="slot.npcState"
|
:npc-state="slot.npcState"
|
||||||
>
|
>
|
||||||
<template v-if="activeMobileRound === 0 && bettingMode" #details>
|
<template v-if="slot.id !== null" #details>
|
||||||
<span v-if="coreStat(slot)" class="bracket-core-stat">
|
<span v-if="coreStat(slot)" class="bracket-core-stat">
|
||||||
{{ coreStat(slot)?.label }} {{ coreStat(slot)?.value }}
|
{{ coreStat(slot)?.label }} {{ coreStat(slot)?.value }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-if="!bettingMode || activeMobileRound !== 0" class="bracket-odds">
|
||||||
|
배당 {{ odds(slot.id) }}
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</GeneralIdentity>
|
</GeneralIdentity>
|
||||||
<div v-if="activeMobileRound === 0 && bettingMode" class="bracket-bet-summary">
|
<div v-if="activeMobileRound === 0 && bettingMode" class="bracket-bet-summary">
|
||||||
@@ -496,4 +510,16 @@ const mobilePairs = computed(() => {
|
|||||||
gap: 10px 18px;
|
gap: 10px 18px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.bracket-info-identity :deep(.general-identity-name) {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
.bracket-info-identity :deep(.general-identity-details) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: left;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { trpc } from '../utils/trpc';
|
|||||||
import { resolveTournamentSectionVisibility, resolveTournamentStageName } from '../utils/tournamentStatus';
|
import { resolveTournamentSectionVisibility, resolveTournamentStageName } from '../utils/tournamentStatus';
|
||||||
|
|
||||||
const tournamentPages = useTournamentPagesStore();
|
const tournamentPages = useTournamentPagesStore();
|
||||||
const { snapshot, loading, error } = storeToRefs(tournamentPages);
|
const { snapshot, betting, loading, error } = storeToRefs(tournamentPages);
|
||||||
type Snapshot = NonNullable<typeof snapshot.value>;
|
type Snapshot = NonNullable<typeof snapshot.value>;
|
||||||
const myGeneralId = ref(0);
|
const myGeneralId = ref(0);
|
||||||
const adminEnabled = ref(false);
|
const adminEnabled = ref(false);
|
||||||
@@ -229,6 +229,8 @@ const start = async () => {
|
|||||||
:matches="snapshot?.matches ?? []"
|
:matches="snapshot?.matches ?? []"
|
||||||
:winner-id="snapshot?.state?.winnerId"
|
:winner-id="snapshot?.state?.winnerId"
|
||||||
:tournament-type="snapshot?.state?.type ?? 0"
|
:tournament-type="snapshot?.state?.type ?? 0"
|
||||||
|
:bet-totals="betting?.totals"
|
||||||
|
:total-bet="betting?.totalAmount ?? 0"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<section v-if="currentMatch" class="fight bg0" aria-label="현재 토너먼트 전투 로그">
|
<section v-if="currentMatch" class="fight bg0" aria-label="현재 토너먼트 전투 로그">
|
||||||
|
|||||||
Reference in New Issue
Block a user