fix(frontend): unify legacy button composition

This commit is contained in:
2026-08-02 05:08:57 +00:00
parent 43ec211ff8
commit 96d80fb766
10 changed files with 324 additions and 163 deletions
+3 -2
View File
@@ -259,13 +259,14 @@ test('renders the legacy desktop grid with matching computed geometry and states
});
const kickButton = page.getByRole('button', { name: '부대원 추방...' }).first();
expect(await kickButton.evaluate((button) => getComputedStyle(button).backgroundColor)).toBe('rgb(68, 68, 68)');
await kickButton.hover();
const hoverStyle = await kickButton.evaluate((button) => ({
cursor: getComputedStyle(button).cursor,
filter: getComputedStyle(button).filter,
borderBottomWidth: getComputedStyle(button).borderBottomWidth,
}));
expect(hoverStyle.cursor).toBe('pointer');
expect(hoverStyle.filter).not.toBe('none');
expect(hoverStyle.borderBottomWidth).toBe('3px');
await page.locator('.troopMember').nth(1).hover();
await expect(page.getByRole('tooltip')).toContainText('조운');
+1 -30
View File
@@ -1,5 +1,6 @@
@import 'tailwindcss';
@import './styles/tokens.css';
@import './styles/legacy-controls.css';
@import './styles/game-shell.css';
@import './styles/ref-shell.css';
@@ -44,33 +45,3 @@ textarea {
background-color: #172a52;
background-image: var(--sammo-texture-blue);
}
.legacy-button {
display: inline-block;
border: 1px solid #12195b;
border-radius: 3px;
background: #141c65;
color: #fff;
padding: 5px 10px;
font-weight: 700;
line-height: 1.5;
cursor: pointer;
}
.legacy-button:hover,
.legacy-button:focus,
.legacy-button:active {
border-color: #0f154c;
background: #101651;
color: #fff;
}
.legacy-button:focus-visible {
outline: 2px solid #f39c12;
outline-offset: 1px;
}
.legacy-button:disabled {
cursor: default;
opacity: 0.65;
}
@@ -0,0 +1,117 @@
.legacy-button {
display: inline-block;
box-sizing: border-box;
border: 1px solid var(--sammo-button-base1-border);
border-radius: 3px;
padding: 5px 10px;
background: var(--sammo-button-base1-bg);
color: #fff;
font: inherit;
font-weight: 700;
line-height: 1.5;
text-align: center;
text-decoration: none;
cursor: pointer;
}
.legacy-button:hover,
.legacy-button:focus,
.legacy-button:active {
border-color: var(--sammo-button-base1-hover-border);
background: var(--sammo-button-base1-hover-bg);
color: #fff;
}
.legacy-button:focus-visible {
outline: 2px solid var(--sammo-color-accent);
outline-offset: 1px;
}
.legacy-button:disabled,
.legacy-button[aria-disabled='true'] {
cursor: default;
opacity: 0.65;
}
/*
* Ref Bootstrap 5.2 + Lumen button family. The modifier describes the legacy
* semantic role; width and placement remain in the owning scoped component.
*/
.legacy-button:is(
.legacy-button--primary,
.legacy-button--secondary,
.legacy-button--danger,
.legacy-button--info,
.legacy-button--navigation
) {
--legacy-button-bg: var(--sammo-button-primary-bg);
--legacy-button-border: var(--sammo-button-primary-border);
min-height: 35.5px;
margin-top: 0;
border-color: var(--legacy-button-border);
border-style: solid;
border-width: 0 1px 4px;
border-radius: 5.25px;
padding: 5.25px 10.5px;
background: var(--legacy-button-bg);
color: #fff;
line-height: 21px;
}
.legacy-button.legacy-button--secondary {
--legacy-button-bg: var(--sammo-button-secondary-bg);
--legacy-button-border: var(--sammo-button-secondary-border);
}
.legacy-button.legacy-button--danger {
--legacy-button-bg: var(--sammo-button-danger-bg);
--legacy-button-border: var(--sammo-button-danger-border);
}
.legacy-button.legacy-button--info {
--legacy-button-bg: var(--sammo-button-info-bg);
--legacy-button-border: var(--sammo-button-info-border);
}
.legacy-button.legacy-button--navigation {
--legacy-button-bg: var(--sammo-button-navigation-bg);
--legacy-button-border: var(--sammo-button-navigation-border);
}
.legacy-button:is(
.legacy-button--primary,
.legacy-button--secondary,
.legacy-button--danger,
.legacy-button--info,
.legacy-button--navigation
):not(:disabled, [aria-disabled='true']):hover {
margin-top: 1px;
border-color: var(--legacy-button-border);
border-bottom-width: 3px;
background: var(--legacy-button-bg);
}
.legacy-button:is(
.legacy-button--primary,
.legacy-button--secondary,
.legacy-button--danger,
.legacy-button--info,
.legacy-button--navigation
):not(:disabled, [aria-disabled='true']):active {
margin-top: 2px;
border-color: var(--legacy-button-border);
border-bottom-width: 2px;
background: var(--legacy-button-bg);
box-shadow: none;
}
.legacy-button:is(
.legacy-button--primary,
.legacy-button--secondary,
.legacy-button--danger,
.legacy-button--info,
.legacy-button--navigation
):focus {
border-color: var(--legacy-button-border);
background: var(--legacy-button-bg);
}
@@ -6,6 +6,20 @@
--sammo-color-border: rgba(201, 164, 90, 0.4);
--sammo-color-action-bg: rgba(16, 16, 16, 0.6);
--sammo-color-error: #f5b7b1;
--sammo-button-base1-bg: #141c65;
--sammo-button-base1-border: #12195b;
--sammo-button-base1-hover-bg: #101651;
--sammo-button-base1-hover-border: #0f154c;
--sammo-button-primary-bg: #375a7f;
--sammo-button-primary-border: #325172;
--sammo-button-secondary-bg: #444;
--sammo-button-secondary-border: #3d3d3d;
--sammo-button-danger-bg: #e74c3c;
--sammo-button-danger-border: #d04436;
--sammo-button-info-bg: #3498db;
--sammo-button-info-border: #2f89c5;
--sammo-button-navigation-bg: #00582c;
--sammo-button-navigation-border: #004f28;
--sammo-texture-walnut: url('/image/game/back_walnut.jpg');
--sammo-texture-green: url('/image/game/back_green.jpg');
--sammo-texture-blue: url('/image/game/back_blue.jpg');
+39 -17
View File
@@ -427,9 +427,16 @@ onMounted(() => {
<template>
<header class="top-back-bar legacy-bg0">
<RouterLink class="top-button legacy-button" to="/">돌아가기</RouterLink>
<RouterLink class="top-button legacy-button legacy-button--navigation" to="/">돌아가기</RouterLink>
<strong>유산 관리</strong>
<button class="top-button legacy-button" type="button" :disabled="loading" @click="loadStatus">갱신</button>
<button
class="top-button legacy-button legacy-button--navigation"
type="button"
:disabled="loading"
@click="loadStatus"
>
갱신
</button>
</header>
<main id="container" class="inherit-page legacy-bg0">
@@ -490,7 +497,7 @@ onMounted(() => {
></small
>
<button
class="legacy-button buy-button"
class="legacy-button legacy-button--primary buy-button"
:disabled="isUnited || actionBusy"
@click="reserveSpecialWar"
>
@@ -524,7 +531,7 @@ onMounted(() => {
}}</small
>
<button
class="legacy-button buy-button"
class="legacy-button legacy-button--primary buy-button"
:disabled="isUnited || actionBusy"
@click="openUniqueAuction"
>
@@ -539,7 +546,11 @@ onMounted(() => {
<article class="shop-item simple-item">
<div class="control-row">
<span>랜덤 초기화</span
><button class="legacy-button" :disabled="isUnited || actionBusy" @click="resetTurnTime">
><button
class="legacy-button legacy-button--primary"
:disabled="isUnited || actionBusy"
@click="resetTurnTime"
>
구입
</button>
</div>
@@ -552,7 +563,11 @@ onMounted(() => {
<article class="shop-item simple-item">
<div class="control-row">
<span>랜덤 유니크 획득</span
><button class="legacy-button" :disabled="isUnited || actionBusy" @click="buyRandomUnique">
><button
class="legacy-button legacy-button--primary"
:disabled="isUnited || actionBusy"
@click="buyRandomUnique"
>
구입
</button>
</div>
@@ -565,7 +580,11 @@ onMounted(() => {
<article class="shop-item simple-item">
<div class="control-row">
<span>즉시 전투 특기 초기화</span
><button class="legacy-button" :disabled="isUnited || actionBusy" @click="resetSpecialWar">
><button
class="legacy-button legacy-button--primary"
:disabled="isUnited || actionBusy"
@click="resetSpecialWar"
>
구입
</button>
</div>
@@ -596,14 +615,14 @@ onMounted(() => {
>
<div class="dual-buttons">
<button
class="legacy-button secondary"
class="legacy-button legacy-button--secondary"
:disabled="actionBusy"
@click="buffTargets[key] = status.buffLevels[key] ?? 0"
>
리셋
</button>
<button
class="legacy-button"
class="legacy-button legacy-button--primary"
:disabled="isUnited || actionBusy"
@click="buyHiddenBuff(key)"
>
@@ -635,7 +654,11 @@ onMounted(() => {
>필요 포인트: {{ status.inheritConst.inheritCheckOwnerPoint }}</b
></small
>
<button class="legacy-button buy-button" :disabled="isUnited || actionBusy" @click="checkOwner">
<button
class="legacy-button legacy-button--primary buy-button"
:disabled="isUnited || actionBusy"
@click="checkOwner"
>
소유자 찾기
</button>
<p v-if="ownerResult" class="owner-result">
@@ -689,7 +712,7 @@ onMounted(() => {
><br /><span v-if="resetStatErrors.length">{{ resetStatErrors[0] }}</span></small
>
<button
class="legacy-button buy-button"
class="legacy-button legacy-button--primary buy-button"
:disabled="isUnited || actionBusy || resetStatErrors.length > 0"
@click="resetStats"
>
@@ -707,7 +730,11 @@ onMounted(() => {
<small>[{{ new Date(entry.createdAt).toLocaleString('ko-KR') }}]</small>
<span>{{ entry.text }}</span>
</div>
<button class="legacy-button more-button" :disabled="logLoading || logEnd" @click="loadLogs()">
<button
class="legacy-button legacy-button--secondary more-button"
:disabled="logLoading || logEnd"
@click="loadLogs()"
>
가져오기
</button>
</section>
@@ -872,11 +899,6 @@ onMounted(() => {
grid-template-columns: 1fr 1fr;
}
.legacy-button.secondary {
border-color: #51585e;
background: #5c636a;
}
.bottom-actions .shop-item:first-child {
grid-column: 1;
}
+23 -45
View File
@@ -213,8 +213,13 @@ onMounted(() => {
<template>
<main id="container" class="pageVote bg0">
<header class="back_bar bg0">
<RouterLink class="btn btn-sammo-base2 back_btn" to="/"> 닫기</RouterLink>
<button class="btn btn-sammo-base2 reload_btn" type="button" :disabled="loading" @click="reloadVote">
<RouterLink class="legacy-button legacy-button--navigation back_btn" to="/"> 닫기</RouterLink>
<button
class="legacy-button legacy-button--navigation reload_btn"
type="button"
:disabled="loading"
@click="reloadVote"
>
갱신
</button>
<h2 class="title"></h2>
@@ -305,7 +310,9 @@ onMounted(() => {
<template v-if="canVote">
<td class="text-center">투표</td>
<td colspan="2">
<button class="btn btn-primary vote-submit" @click="submitVote">투표</button>
<button class="legacy-button legacy-button--secondary vote-submit" @click="submitVote">
투표
</button>
</td>
</template>
<td v-else colspan="3" class="text-center">결산</td>
@@ -348,7 +355,11 @@ onMounted(() => {
<tfoot>
<tr>
<td></td>
<td><button class="btn btn-primary comment-submit" type="submit">댓글 달기</button></td>
<td>
<button class="legacy-button legacy-button--secondary comment-submit" type="submit">
댓글 달기
</button>
</td>
<td colspan="2">
<input v-model="myComment" class="form-control" maxlength="200" aria-label="댓글" />
</td>
@@ -395,13 +406,15 @@ onMounted(() => {
</div>
</div>
<div class="admin-submit">
<button class="btn btn-primary" type="button" @click="submitNewVote">제출</button>
<button class="legacy-button legacy-button--secondary" type="button" @click="submitNewVote">
제출
</button>
</div>
</template>
</div>
<footer class="bottom_bar bg0">
<RouterLink class="btn btn-sammo-base2 back_btn" to="/"> 닫기</RouterLink>
<RouterLink class="legacy-button legacy-button--navigation back_btn" to="/"> 닫기</RouterLink>
</footer>
</main>
</template>
@@ -438,54 +451,19 @@ onMounted(() => {
margin: 0;
}
.btn {
min-height: 35.5px;
padding: 5.25px 10.5px;
border: 1px solid transparent;
border-radius: 5.25px;
color: #fff;
font: inherit;
cursor: pointer;
}
.btn:hover {
filter: brightness(1.15);
}
.btn:focus-visible {
outline: 2px solid #8ab4f8;
outline-offset: -2px;
}
.btn:active {
transform: translateY(1px);
}
.btn:disabled {
opacity: 0.65;
cursor: default;
}
.btn-sammo-base2 {
.back_btn,
.reload_btn {
height: 32px;
min-height: 32px;
margin-right: 2px;
border-color: #004f28;
background: #00582c;
font-weight: 600;
text-align: center;
text-decoration: none;
}
.back_bar .btn-sammo-base2 {
.back_bar .back_btn,
.back_bar .reload_btn {
width: 88px;
}
.btn-primary {
border-color: #0d6efd;
background: #0d6efd;
}
#vote-title {
font-size: 1.8em;
line-height: 1.5;
+42 -64
View File
@@ -177,8 +177,15 @@ onMounted(() => {
<template>
<main id="container" class="legacy-troop-page">
<header class="topBackBar bg0">
<RouterLink class="btn legacyNavButton backLink" to="/">돌아가기</RouterLink>
<button class="btn legacyNavButton reloadButton" type="button" :disabled="loading" @click="refresh">
<RouterLink class="legacy-button legacy-button--navigation legacyNavButton backLink" to="/"
>돌아가기</RouterLink
>
<button
class="legacy-button legacy-button--navigation legacyNavButton reloadButton"
type="button"
:disabled="loading"
@click="refresh"
>
갱신
</button>
<h2>부대 편성</h2>
@@ -242,25 +249,33 @@ onMounted(() => {
<div class="troopAction">
<div v-if="dialogKind === null || dialogTroopId !== troop.id" class="actionButtons">
<button v-if="data.me.troopId === 0" class="btn btn-primary" @click="joinTroop(troop)">
<button
v-if="data.me.troopId === 0"
class="legacy-button legacy-button--primary"
@click="joinTroop(troop)"
>
부대 탑승
</button>
<button
v-if="data.me.troopId === troop.id"
class="btn"
:class="data.me.id === data.me.troopId ? 'btn-danger' : 'btn-primary'"
class="legacy-button"
:class="data.me.id === data.me.troopId ? 'legacy-button--danger' : 'legacy-button--primary'"
@click="exitTroop(troop)"
>
{{ data.me.id === data.me.troopId ? '부대 해산' : '부대 탈퇴' }}
</button>
<button
v-if="data.me.troopId === troop.id && data.me.id === data.me.troopId"
class="btn btn-secondary"
class="legacy-button legacy-button--secondary"
@click="openKick(troop)"
>
부대원 추방...
</button>
<button v-if="data.permission >= 4" class="btn btn-info" @click="openRename(troop)">
<button
v-if="data.permission >= 4"
class="legacy-button legacy-button--info"
@click="openRename(troop)"
>
부대명 변경...
</button>
</div>
@@ -270,10 +285,12 @@ onMounted(() => {
<input v-model.trim="editName" class="formControl" type="text" aria-label=" 부대명" />
</div>
<div class="subBtnCancel">
<button class="btn btn-secondary" @click="closeDialog">취소</button>
<button class="legacy-button legacy-button--secondary" @click="closeDialog">취소</button>
</div>
<div class="subBtnOK">
<button class="btn btn-primary" @click="renameTroop(troop)">변경</button>
<button class="legacy-button legacy-button--primary" @click="renameTroop(troop)">
변경
</button>
</div>
</div>
<div v-else class="subDialog kickDialog">
@@ -290,10 +307,12 @@ onMounted(() => {
</select>
</div>
<div class="subBtnCancel">
<button class="btn btn-secondary" @click="closeDialog">취소</button>
<button class="legacy-button legacy-button--secondary" @click="closeDialog">취소</button>
</div>
<div class="subBtnOK">
<button class="btn btn-primary" @click="kickMember(troop)">추방</button>
<button class="legacy-button legacy-button--primary" @click="kickMember(troop)">
추방
</button>
</div>
</div>
</div>
@@ -305,12 +324,16 @@ onMounted(() => {
<div v-if="data.me.troopId === 0" class="makeNewTroop">
<div class="makeTitle bg1 center">부대 창설</div>
<input v-model.trim="createName" class="formControl troopNameField" type="text" aria-label="부대명" />
<button class="btn btn-secondary createButton" @click="makeTroop">부대 창설</button>
<button class="legacy-button legacy-button--secondary createButton" @click="makeTroop">
부대 창설
</button>
</div>
</div>
<footer class="bottomBar bg0">
<RouterLink class="btn legacyNavButton backLink" to="/">돌아가기</RouterLink>
<RouterLink class="legacy-button legacy-button--navigation legacyNavButton backLink" to="/"
>돌아가기</RouterLink
>
<div></div>
</footer>
<div v-if="popupMember" id="generalPopup" :style="{ top: `${popupTop}px` }" role="tooltip">
@@ -359,14 +382,11 @@ onMounted(() => {
text-align: center;
}
.btn.legacyNavButton {
.legacyNavButton {
height: 32px;
min-height: 32px;
margin-right: 2px;
border-color: #004f28;
color: #fff;
background: #00582c;
font-weight: 600;
text-decoration: none;
}
.notice {
@@ -490,51 +510,6 @@ onMounted(() => {
grid-row: 1/3;
}
.btn {
min-height: 31px;
padding: 0.2em 0.75em;
border: 1px solid #777;
border-radius: 4px;
color: #eee;
background: #555;
font: inherit;
cursor: pointer;
}
.btn:hover {
filter: brightness(1.15);
}
.btn:focus-visible {
outline: 2px solid #8ab4f8;
outline-offset: -2px;
}
.btn:active {
transform: translateY(1px);
}
.btn-primary {
border-color: #0d6efd;
background: #0d6efd;
}
.btn-danger {
border-color: #dc3545;
background: #dc3545;
}
.btn-info {
border-color: #0dcaf0;
color: #111;
background: #0dcaf0;
}
.btn-secondary {
border-color: #6c757d;
background: #6c757d;
}
.formControl {
width: 100%;
min-height: 31px;
@@ -561,6 +536,9 @@ onMounted(() => {
.bottomBar .legacyNavButton {
width: 70px;
margin: 0;
padding-right: 5px;
padding-left: 5px;
white-space: nowrap;
}
@media (min-width: 501px) {
@@ -624,7 +602,7 @@ onMounted(() => {
@media (max-width: 500px) {
.legacy-troop-page {
width: 511px;
width: 500px;
}
#generalPopup {
+33
View File
@@ -22,6 +22,39 @@ loads the following layers:
4. Scoped SFC styles: page-specific grids, fixed table dimensions, selectors,
and state styling. These remain closest to the DOM contract they implement.
`styles/legacy-controls.css` is the shared control layer between tokens and the
two shell layers. It owns only control geometry and state rules that are proven
identical in the Ref Bootstrap/Lumen family. A page still owns control width,
grid placement, and any visual family that is not Bootstrap/Lumen.
## Button composition
Choose the Ref visual family before choosing a semantic color. Buttons from
different historical families are not made identical merely because they have
the same label.
| Ref family | Core composition | Use |
| ---------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------- |
| Bootstrap/Lumen primary | `.legacy-button.legacy-button--primary` | commit, purchase, submit, or another affirmative mutation |
| Bootstrap/Lumen secondary | `.legacy-button.legacy-button--secondary` | reset, cancel, neutral toggle, or load-more |
| Bootstrap/Lumen danger | `.legacy-button.legacy-button--danger` | destructive action only when Ref uses `variant="danger"` |
| Bootstrap/Lumen info | `.legacy-button.legacy-button--info` | informational or edit action only when Ref uses `variant="info"` |
| `btn-sammo-base2` navigation | `.legacy-button.legacy-button--navigation` | page back/close and paired reload controls |
| page-specific/native control | feature-namespaced scoped class | only when Ref computed geometry or interaction differs from the Bootstrap/Lumen family |
The base class supplies accessible link/button normalization and the historical
`base1` fallback used by already measured screens. New Bootstrap/Lumen controls
must add an explicit semantic modifier; do not infer a mutation role from a
label such as `구입` in page CSS. A disabled control keeps its semantic color
and uses the shared opacity/cursor state. Hover and active use the Ref Lumen
bottom-border movement rather than an unrelated brightness filter.
Only layout belongs in the SFC: width, grid column, margins required by the
page, and breakpoint-specific placement. Color, border, font weight,
hover/focus/active, and disabled presentation belong in
`legacy-controls.css` when the Ref family is shared. Generic `.btn`, `button`,
or `.primary` rules must not be promoted globally.
## Class naming
- `.game-shell`, `.game-shell__header`, `.game-shell__actions`: flexible
@@ -167,6 +167,8 @@ test.describe('inheritance management legacy parity', () => {
const container = getComputedStyle(document.querySelector<HTMLElement>('#container')!);
const title = getComputedStyle(document.querySelector<HTMLElement>('.section-title')!);
const button = getComputedStyle(document.querySelector<HTMLElement>('.buy-button')!);
const navigation = getComputedStyle(document.querySelector<HTMLElement>('.top-button')!);
const secondary = getComputedStyle(document.querySelector<HTMLElement>('.dual-buttons button')!);
return {
container: rect('#container'),
firstPoint: rect('#inherit_sum'),
@@ -175,6 +177,9 @@ test.describe('inheritance management legacy parity', () => {
backgroundImage: container.backgroundImage,
titleBackgroundImage: title.backgroundImage,
buttonBackground: button.backgroundColor,
buttonBorderBottomWidth: button.borderBottomWidth,
navigationBackground: navigation.backgroundColor,
secondaryBackground: secondary.backgroundColor,
};
});
@@ -185,14 +190,42 @@ test.describe('inheritance management legacy parity', () => {
expect(desktop.fontSize).toBe('14px');
expect(desktop.backgroundImage).toContain('back_walnut.jpg');
expect(desktop.titleBackgroundImage).toContain('back_green.jpg');
expect(desktop.buttonBackground).toBe('rgb(55, 90, 127)');
expect(desktop.buttonBorderBottomWidth).toBe('4px');
expect(desktop.navigationBackground).toBe('rgb(0, 88, 44)');
expect(desktop.secondaryBackground).toBe('rgb(68, 68, 68)');
const buyButton = page.locator('.buy-button').first();
const beforeHover = await buyButton.evaluate((element) => getComputedStyle(element).backgroundColor);
const beforeHover = await buyButton.evaluate((element) => {
const style = getComputedStyle(element);
return { background: style.backgroundColor, borderBottomWidth: style.borderBottomWidth };
});
await buyButton.hover();
const afterHover = await buyButton.evaluate((element) => getComputedStyle(element).backgroundColor);
expect(afterHover).not.toBe(beforeHover);
const afterHover = await buyButton.evaluate((element) => {
const style = getComputedStyle(element);
return { background: style.backgroundColor, borderBottomWidth: style.borderBottomWidth };
});
expect(afterHover.background).toBe(beforeHover.background);
expect(afterHover.borderBottomWidth).toBe('3px');
await buyButton.hover({ position: { x: 70, y: 20 } });
await page.mouse.down();
await expect
.poll(() => buyButton.evaluate((element) => getComputedStyle(element).borderBottomWidth))
.toBe('2px');
await page.mouse.up();
await buyButton.focus();
await expect(buyButton).toBeFocused();
await page.keyboard.press('Tab');
await page.keyboard.press('Shift+Tab');
await expect(buyButton).toBeFocused();
await expect.poll(() => buyButton.evaluate((element) => getComputedStyle(element).outlineStyle)).toBe('solid');
await buyButton.evaluate((element) => element.setAttribute('disabled', ''));
await expect.poll(() => buyButton.evaluate((element) => getComputedStyle(element).opacity)).toBe('0.65');
await buyButton.evaluate((element) => element.removeAttribute('disabled'));
await page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur());
if (artifactRoot) {
await page.screenshot({ path: resolve(artifactRoot, 'inherit-core-desktop.png'), fullPage: true });
@@ -214,6 +247,10 @@ test.describe('inheritance management legacy parity', () => {
expect(mobile.containerWidth).toBe(500);
expect(mobile.firstWidth).toBeCloseTo(482, 0);
expect(mobile.stacked).toBe(true);
if (artifactRoot) {
await page.screenshot({ path: resolve(artifactRoot, 'inherit-core-mobile.png'), fullPage: true });
}
});
test('submits a legacy buff purchase and refreshes status and logs', async ({ page }) => {
@@ -1014,6 +1014,12 @@ test.describe('survey legacy parity', () => {
fontSize: getComputedStyle(title).fontSize,
backgroundImage: getComputedStyle(title).backgroundImage,
},
voteButton: {
backgroundColor: getComputedStyle(document.querySelector<HTMLElement>('.vote-submit')!)
.backgroundColor,
borderBottomWidth: getComputedStyle(document.querySelector<HTMLElement>('.vote-submit')!)
.borderBottomWidth,
},
};
});
@@ -1027,6 +1033,10 @@ test.describe('survey legacy parity', () => {
expect(geometry.title.height).toBeCloseTo(37.8, 0);
expect(geometry.title.fontSize).toBe('25.2px');
expect(geometry.title.backgroundImage).toContain('back_blue.jpg');
expect(geometry.voteButton).toEqual({
backgroundColor: 'rgb(68, 68, 68)',
borderBottomWidth: '4px',
});
const secondOption = page.locator('#v-vote-1');
await secondOption.check();
@@ -1035,9 +1045,9 @@ test.describe('survey legacy parity', () => {
await expect(secondOption).toBeFocused();
const voteButton = page.getByRole('button', { name: '투표', exact: true });
const beforeHover = await voteButton.evaluate((element) => getComputedStyle(element).filter);
const beforeHover = await voteButton.evaluate((element) => getComputedStyle(element).borderBottomWidth);
await voteButton.hover();
const afterHover = await voteButton.evaluate((element) => getComputedStyle(element).filter);
const afterHover = await voteButton.evaluate((element) => getComputedStyle(element).borderBottomWidth);
expect(afterHover).not.toBe(beforeHover);
});
}