유스케이스 TDD 16테마 스펙과 접근성 제품 결함 수정
- 지원 티켓 작성 UI 신설(설정)·관리자 해결 노트 입력 신설(Admin): 서버 계약은 있었으나 웹 진입점이 없던 2결함 - a11y: outline 채널 포커스 링(ui/shell css), 세션바 44px 터치 타깃, 청록 하드코딩 그라디언트를 테마 토큰으로 교체, 설정 라벨/헤딩/대비·리뷰 44px·모바일 오버플로 수정 - uc-*.spec.ts 16테마 239 시나리오 신규(수집 1109 tests/61 files), 기존 스펙 5종 계약 드리프트 교정 - breakpoint-sweep: widthsFor 솎아내기가 실기기 대표 폭(360/390/1024)을 탈락시키는 테스트 결함 수정 — keep 시드를 전체 DEVICE_WIDTHS로, 3연폭 예외는 솎아내기 발생 여부 기준으로 - 검증: tsc PASS, 병렬 게이트 1040 passed(데스크톱 밀도 충돌 1건 해소 후 focused 68/68 GREEN), 직렬 게이트 52/5/4 삼각화 — breakpoint(테스트 결함)·kb(낡은 dev API 재기동)·voice(일시적) 해소, 교사 재평가 2건은 엔진 구독 한도(resets 3pm)로 skip 후 재검증 대기 - 문서/SSOT: HANDOFF·TODO·대시보드·testing 가이드 동기화, 증거 usecase-tdd-2026-08-18.json, SSOT 체커 PASS(59)
This commit is contained in:
parent
4771b97c3a
commit
cf899b7f15
37 changed files with 11989 additions and 67 deletions
|
|
@ -10,6 +10,13 @@ interface AdminUsageBreakdown {
|
|||
tokens_in: number;
|
||||
tokens_out: number;
|
||||
cost_usd: number;
|
||||
recorded_cost_usd: number;
|
||||
estimated_cost_usd: number;
|
||||
token_metered_turns: number;
|
||||
token_unmetered_turns: number;
|
||||
cost_basis: "provider_estimate" | "provider_reported" | "reference_rate" | "unavailable";
|
||||
rate_label?: string | null;
|
||||
rate_source_url?: string | null;
|
||||
}
|
||||
|
||||
interface AdminUsageDailyCost {
|
||||
|
|
@ -38,9 +45,13 @@ interface AdminUsageResponse {
|
|||
window_days: number;
|
||||
total_turns: number;
|
||||
metered_turns: number;
|
||||
token_metered_turns: number;
|
||||
token_unmetered_turns: number;
|
||||
tokens_in: number;
|
||||
tokens_out: number;
|
||||
cost_usd: number;
|
||||
recorded_cost_usd: number;
|
||||
estimated_cost_usd: number;
|
||||
budget: {
|
||||
limit_usd: number;
|
||||
used_ratio: number;
|
||||
|
|
@ -74,9 +85,14 @@ function usageFixture(
|
|||
window_days: days,
|
||||
total_turns: 0,
|
||||
metered_turns: 0,
|
||||
token_metered_turns: 0,
|
||||
token_unmetered_turns: 0,
|
||||
tokens_in: 0,
|
||||
tokens_out: 0,
|
||||
cost_usd: 0,
|
||||
// 실 API는 cost_usd = recorded + estimated 로 집계한다. 기본은 전액 기록값으로 둔다.
|
||||
recorded_cost_usd: overrides.cost_usd ?? 0,
|
||||
estimated_cost_usd: 0,
|
||||
budget: { limit_usd: 0, used_ratio: 0, remaining_usd: null, status: "disabled" },
|
||||
evaluator_cache: {
|
||||
enabled: false,
|
||||
|
|
@ -381,7 +397,8 @@ test.describe("full sweep: admin ai operations", () => {
|
|||
await page.getByRole("button", { name: "7일" }).click();
|
||||
await expect(page.getByRole("button", { name: "7일" })).toHaveAttribute("aria-pressed", "true");
|
||||
await expect(ledger).toContainText("$1.11");
|
||||
await expect(ledger).toContainText("7일 DB 집계");
|
||||
// 재설계된 원장 카드: 데이터 로드 후에는 "N일 DB 집계" 대신 기록·참조 분해를 표시한다.
|
||||
await expect(ledger).toContainText("기록 $1.11 · 참조 $0");
|
||||
|
||||
// 늦게 도착한 90일 응답은 active 플래그로 무시되어야 한다.
|
||||
slowWindow.resolve();
|
||||
|
|
@ -405,6 +422,8 @@ test.describe("full sweep: admin ai operations", () => {
|
|||
usageFixture(days, {
|
||||
total_turns: 40,
|
||||
metered_turns: 30,
|
||||
token_metered_turns: 24,
|
||||
token_unmetered_turns: 6,
|
||||
tokens_in: 125_000,
|
||||
tokens_out: 18_500,
|
||||
cost_usd: 6.6212,
|
||||
|
|
@ -424,9 +443,15 @@ test.describe("full sweep: admin ai operations", () => {
|
|||
provider: "openai",
|
||||
model: "gpt-5-mini",
|
||||
turns: 30,
|
||||
token_metered_turns: 24,
|
||||
token_unmetered_turns: 6,
|
||||
tokens_in: 125_000,
|
||||
tokens_out: 18_500,
|
||||
cost_usd: 6.6212,
|
||||
recorded_cost_usd: 6.6212,
|
||||
estimated_cost_usd: 0,
|
||||
cost_basis: "provider_reported",
|
||||
rate_label: null,
|
||||
},
|
||||
],
|
||||
daily_cost: [
|
||||
|
|
@ -440,14 +465,15 @@ test.describe("full sweep: admin ai operations", () => {
|
|||
|
||||
await page.goto("/admin/ai");
|
||||
|
||||
// DB 계량 커버리지 트랙: metered/total 비율과 미계량 턴 안내.
|
||||
// 토큰 계량 커버리지 트랙: token_metered/metered 비율과 토큰 미수집·DB 원장 미연결 안내.
|
||||
const budgetPanel = page.locator(".aic-budget");
|
||||
await expect(budgetPanel).toContainText("DB 계량 커버리지");
|
||||
await expect(budgetPanel).toContainText("75%");
|
||||
await expect(budgetPanel.locator('[aria-label="DB 계량 커버리지 75%"]')).toHaveCount(1);
|
||||
await expect(budgetPanel).toContainText("토큰 계량 커버리지");
|
||||
await expect(budgetPanel).toContainText("80%");
|
||||
await expect(budgetPanel.locator('[aria-label="토큰 계량 커버리지 80%"]')).toHaveCount(1);
|
||||
await expect(budgetPanel).toContainText(
|
||||
"10개 턴은 provider·model·token·cost 계량 필드가 없습니다.",
|
||||
"6개 원장 호출은 과거 토큰 미수집 건이라 복원 없이 미계량으로 남깁니다.",
|
||||
);
|
||||
await expect(budgetPanel).toContainText("DB 원장 미연결 10턴");
|
||||
|
||||
// 일별 비용 차트: role=img aria-label, 날짜·비용 툴팁, 막대 개수.
|
||||
const chart = page.locator(".aic-chart[role='img']");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue