feat: 운영 안정성과 세션 음성 경험 개선
This commit is contained in:
parent
facc4ad2d9
commit
c788343467
95 changed files with 8431 additions and 1785 deletions
|
|
@ -377,12 +377,12 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
await page.goto("/admin");
|
||||
|
||||
await expect(page.getByRole("heading", { name: "현재 서비스 상태" })).toBeVisible();
|
||||
const inlineError = page.locator(".ad-error");
|
||||
const inlineError = page.locator(".vgops-error");
|
||||
await expect(inlineError).toBeVisible();
|
||||
await expect(inlineError).toHaveAttribute("role", "alert");
|
||||
await expect(inlineError).toContainText("헬스 저장소 접근 불가");
|
||||
// 다른 데이터 소스는 정상이므로 화면 나머지는 렌더된다.
|
||||
await expect(page.locator(".ad-kpis").first()).toBeVisible();
|
||||
await expect(page.locator(".vgops-kpis").first()).toBeVisible();
|
||||
});
|
||||
|
||||
// 검증 checklist: admin-users-search-input
|
||||
|
|
@ -417,15 +417,15 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
|
||||
await page.goto("/admin/users");
|
||||
await page.getByRole("tab", { name: "사용자 목록" }).click();
|
||||
const rows = page.locator(".ad-user-table tbody tr");
|
||||
const rows = page.locator(".vgops-user-table tbody tr");
|
||||
await expect(rows).toHaveCount(3);
|
||||
await expect(page.locator(".ad-users-toolbar")).toContainText("3 / 3명");
|
||||
await expect(page.locator(".vgops-users-toolbar")).toContainText("3 / 3명");
|
||||
|
||||
const search = page.getByLabel("사용자 검색");
|
||||
await search.fill("교수자");
|
||||
await expect(rows).toHaveCount(1);
|
||||
await expect(rows.first()).toContainText("bob@hs.ac.kr");
|
||||
await expect(page.locator(".ad-users-toolbar")).toContainText("1 / 3명");
|
||||
await expect(page.locator(".vgops-users-toolbar")).toContainText("1 / 3명");
|
||||
|
||||
await search.fill("cohort-alpha");
|
||||
await expect(rows).toHaveCount(1);
|
||||
|
|
@ -470,7 +470,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
|
||||
await page.goto("/admin/users");
|
||||
await page.getByRole("tab", { name: "사용자 목록" }).click();
|
||||
const rows = page.locator(".ad-user-table tbody tr");
|
||||
const rows = page.locator(".vgops-user-table tbody tr");
|
||||
await expect(rows).toHaveCount(3);
|
||||
|
||||
// 기본 정렬: last_seen_at 내림차순.
|
||||
|
|
@ -515,8 +515,8 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
await page.goto("/admin/users");
|
||||
await page.getByRole("tab", { name: "사용자 목록" }).click();
|
||||
|
||||
await expect(page.locator(".ad-user-table tbody tr")).toHaveCount(40);
|
||||
await expect(page.locator(".ad-users-toolbar")).toContainText("45 / 45명");
|
||||
await expect(page.locator(".vgops-user-table tbody tr")).toHaveCount(40);
|
||||
await expect(page.locator(".vgops-users-toolbar")).toContainText("45 / 45명");
|
||||
await expect(page.getByText(/나머지\s*5명을 더 좁혀 볼 수/)).toBeVisible();
|
||||
});
|
||||
|
||||
|
|
@ -553,7 +553,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
|
||||
// 토글 → 저장 시 admin_access가 PATCH로 반영된다.
|
||||
await normalToggle.check();
|
||||
const normalRow = page.locator(".ad-user-table tbody tr").filter({ hasText: "normal@hs.ac.kr" });
|
||||
const normalRow = page.locator(".vgops-user-table tbody tr").filter({ hasText: "normal@hs.ac.kr" });
|
||||
const saveButton = normalRow.getByRole("button", { name: "저장" });
|
||||
await expect(saveButton).toBeEnabled();
|
||||
const patchPromise = page.waitForResponse(isUserPatchResponse("normal"));
|
||||
|
|
@ -604,7 +604,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
await expect(page.getByRole("heading", { name: "역할 분포" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "최근 활동" })).toBeVisible();
|
||||
|
||||
const meters = page.locator(".ad-role-meter");
|
||||
const meters = page.locator(".vgops-role-meter");
|
||||
await expect(meters).toHaveCount(3);
|
||||
await expect(meters.nth(0)).toContainText("학습자");
|
||||
await expect(meters.nth(0)).toContainText("5명");
|
||||
|
|
@ -613,10 +613,10 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
await expect(meters.nth(2)).toContainText("관리자");
|
||||
await expect(meters.nth(2)).toContainText("2명");
|
||||
|
||||
const activityRows = page.locator(".ad-activity-table > div");
|
||||
const activityRows = page.locator(".vgops-activity-table > div");
|
||||
await expect(activityRows).toHaveCount(8);
|
||||
await expect(activityRows.first()).toContainText("Activity User 1");
|
||||
await expect(page.locator(".ad-activity-table")).not.toContainText("Activity User 9");
|
||||
await expect(page.locator(".vgops-activity-table")).not.toContainText("Activity User 9");
|
||||
});
|
||||
|
||||
// 검증 checklist: admin-users-states
|
||||
|
|
@ -636,9 +636,9 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
|
||||
await page.goto("/admin/users");
|
||||
// 로딩 스켈레톤(승인 큐)이 먼저 보인다.
|
||||
await expect(page.locator(".ad-user--skeleton").first()).toBeVisible();
|
||||
await expect(page.locator(".vgops-user--skeleton").first()).toBeVisible();
|
||||
// 실패 후 InlineError가 표시된다.
|
||||
await expect(page.locator(".ad-error")).toContainText("사용자 저장소 중단");
|
||||
await expect(page.locator(".vgops-error")).toContainText("사용자 저장소 중단");
|
||||
// 앱 결함: 이 클릭에서 페이지가 무한 렌더 루프로 프리즈되어 테스트가 타임아웃된다.
|
||||
await page.getByRole("tab", { name: "사용자 목록" }).click();
|
||||
await expect(
|
||||
|
|
@ -657,8 +657,8 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
// 로딩 스켈레톤 → 실패 InlineError (클릭 없이 표시만 검증).
|
||||
mock.overrides.users = { delayMs: 1_500, status: 500, detail: "사용자 저장소 중단" };
|
||||
await page.goto("/admin/users");
|
||||
await expect(page.locator(".ad-user--skeleton").first()).toBeVisible();
|
||||
await expect(page.locator(".ad-error")).toContainText("사용자 저장소 중단");
|
||||
await expect(page.locator(".vgops-user--skeleton").first()).toBeVisible();
|
||||
await expect(page.locator(".vgops-error")).toContainText("사용자 저장소 중단");
|
||||
|
||||
// 등록 0건 빈 상태.
|
||||
delete mock.overrides.users;
|
||||
|
|
@ -673,7 +673,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
];
|
||||
await page.reload();
|
||||
await page.getByRole("tab", { name: "사용자 목록" }).click();
|
||||
await expect(page.locator(".ad-user-table tbody tr")).toHaveCount(1);
|
||||
await expect(page.locator(".vgops-user-table tbody tr")).toHaveCount(1);
|
||||
await page.getByLabel("사용자 검색").fill("no-match-full-sweep");
|
||||
await expect(page.getByText("검색 조건에 맞는 사용자가 없습니다.")).toBeVisible();
|
||||
await expect(page.getByText("아직 등록된 사용자가 없습니다.")).toHaveCount(0);
|
||||
|
|
@ -737,7 +737,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
params.get("assigned_group") === "ops",
|
||||
),
|
||||
);
|
||||
await page.locator(".ad-ticket-filter__check input").check();
|
||||
await page.locator(".vgops-ticket-filter__check input").check();
|
||||
await staleRequest;
|
||||
|
||||
await expect(clearButton).toBeEnabled();
|
||||
|
|
@ -760,7 +760,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
await expect(page.getByLabel("카테고리 필터")).toHaveValue("all");
|
||||
await expect(page.getByLabel("우선순위 필터")).toHaveValue("all");
|
||||
await expect(page.getByLabel("담당 그룹 필터")).toHaveValue("");
|
||||
await expect(page.locator(".ad-ticket-filter__check input")).not.toBeChecked();
|
||||
await expect(page.locator(".vgops-ticket-filter__check input")).not.toBeChecked();
|
||||
await expect(clearButton).toBeDisabled();
|
||||
});
|
||||
|
||||
|
|
@ -776,7 +776,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
];
|
||||
|
||||
await page.goto("/admin/tickets");
|
||||
const chips = page.locator(".ad-ticket-queues button");
|
||||
const chips = page.locator(".vgops-ticket-queues button");
|
||||
await expect(chips).toHaveCount(2);
|
||||
// 건수 내림차순: 안전(2) → 기타(1).
|
||||
await expect(chips.nth(0)).toContainText("안전");
|
||||
|
|
@ -835,7 +835,7 @@ test.describe("admin console full-sweep (fixtures)", () => {
|
|||
|
||||
mock.overrides.tickets = { status: 500, detail: "티켓 저장소 오류" };
|
||||
await page.getByRole("button", { name: "새로고침" }).click();
|
||||
const inlineError = page.locator(".ad-error");
|
||||
const inlineError = page.locator(".vgops-error");
|
||||
await expect(inlineError).toBeVisible();
|
||||
await expect(inlineError).toHaveAttribute("role", "alert");
|
||||
await expect(inlineError).toContainText("티켓 저장소 오류");
|
||||
|
|
@ -876,7 +876,7 @@ test.describe("admin console full-sweep (real API)", () => {
|
|||
await page.goto("/admin/users");
|
||||
expect((await usersResponsePromise).ok()).toBeTruthy();
|
||||
|
||||
const approvalCard = page.locator(".ad-approval").filter({ hasText: email });
|
||||
const approvalCard = page.locator(".vgops-approval").filter({ hasText: email });
|
||||
await expect(approvalCard).toBeVisible();
|
||||
await expect(approvalCard).toContainText("승인 대기");
|
||||
|
||||
|
|
@ -941,7 +941,7 @@ test.describe("admin console full-sweep (real API)", () => {
|
|||
await page.getByRole("tab", { name: "사용자 목록" }).click();
|
||||
await page.getByLabel("사용자 검색").fill(email);
|
||||
|
||||
const row = page.locator(".ad-user-table tbody tr").filter({ hasText: email });
|
||||
const row = page.locator(".vgops-user-table tbody tr").filter({ hasText: email });
|
||||
await expect(row).toBeVisible();
|
||||
|
||||
const affiliationInput = row.getByLabel(`${email} 소속`);
|
||||
|
|
@ -1019,7 +1019,7 @@ test.describe("admin console full-sweep (real API)", () => {
|
|||
await page.getByRole("tab", { name: "사용자 목록" }).click();
|
||||
await page.getByLabel("사용자 검색").fill(email);
|
||||
|
||||
const row = page.locator(".ad-user-table tbody tr").filter({ hasText: email });
|
||||
const row = page.locator(".vgops-user-table tbody tr").filter({ hasText: email });
|
||||
await expect(row).toBeVisible();
|
||||
const cohortInput = row.getByLabel(`${email} 코호트`);
|
||||
await cohortInput.fill("co-a, co-b");
|
||||
|
|
@ -1083,7 +1083,7 @@ test.describe("admin console full-sweep (real API)", () => {
|
|||
await page.goto("/admin/tickets");
|
||||
await ticketsResponsePromise;
|
||||
|
||||
const card = page.locator(".ad-ticket").filter({ hasText: subject });
|
||||
const card = page.locator(".vgops-ticket").filter({ hasText: subject });
|
||||
await expect(card).toBeVisible();
|
||||
|
||||
let patchCount = 0;
|
||||
|
|
@ -1171,7 +1171,7 @@ test.describe("admin console full-sweep (real API)", () => {
|
|||
await ticketsResponsePromise;
|
||||
|
||||
const linkedCard = page
|
||||
.locator(".ad-ticket")
|
||||
.locator(".vgops-ticket")
|
||||
.filter({ hasText: subject })
|
||||
.filter({ has: page.getByRole("button", { name: "해제" }) });
|
||||
await expect(linkedCard).toBeVisible();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue