You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
3.1 KiB
TypeScript

// frontend/playwright/connectors.spec.ts — phase-13 외부 연동(연결 관리) E2E
// 연결 상태 표시 → 동기화 → 해제 → 임포트(미지원 graceful) + a11y.
import AxeBuilder from "@axe-core/playwright";
import { expect, test } from "@playwright/test";
import { resetSeed } from "./fixtures/seed-reset";
test.describe.configure({ mode: "serial" });
test.beforeEach(async ({ page }) => {
await resetSeed();
await page.goto("/life");
// 라이프 모듈 레일에서 '연결' 모듈로 전환
await page.locator(".subnav .mod-row", { hasText: "외부 데이터 소스" }).click();
await expect(page.getByRole("heading", { name: "연결된 데이터 소스" })).toBeVisible();
});
test("14개 커넥터 카드 + 12/14 연결됨 + 미연결 카드 표시", async ({ page }) => {
await expect(page.locator(".cn-grid .cn-card")).toHaveCount(14);
await expect(page.locator(".cn-count")).toHaveText("12/14 연결됨");
// Google Fit / KB증권 은 미연결(off + '연결 안 됨')
const fit = page.locator(".cn-card", { hasText: "Google Fit" });
await expect(fit).toHaveClass(/off/);
await expect(fit.locator(".cs-badge")).toContainText("연결 안 됨");
// 우리카드는 연결됨(동기화/해제 액션)
const woori = page.locator(".cn-card", { hasText: "우리카드" });
await expect(woori.getByRole("button", { name: /동기화/ })).toBeVisible();
await expect(woori.getByRole("button", { name: /해제/ })).toBeVisible();
});
test("동기화 → 토스트 노출", async ({ page }) => {
const work = page.locator(".cn-card", { hasText: "회사" }).first();
await work.getByRole("button", { name: /동기화/ }).click();
await expect(page.locator(".au-toast")).toContainText("새 항목");
});
test("연결 해제 → 미연결 상태로 전환", async ({ page }) => {
const toss = page.locator(".cn-card", { hasText: "토스" });
await expect(toss).not.toHaveClass(/off/);
await toss.getByRole("button", { name: /해제/ }).click();
await expect(page.locator(".au-toast")).toContainText("연결을 해제");
await expect(toss).toHaveClass(/off/);
await expect(toss.locator(".cs-badge")).toContainText("연결 안 됨");
await expect(toss.getByRole("button", { name: /연결$/ })).toBeVisible(); // [연결] 으로 전환
});
test("파일 가져오기 — 미지원 소스(mock)는 안내 토스트", async ({ page }) => {
// 기본 env(mock)에서 mock 커넥터는 import 미지원 → 400 → graceful 토스트
const kakao = page.locator(".cn-card", { hasText: "카카오뱅크" });
await kakao.locator('input[type="file"]').setInputFiles({
name: "statement.csv",
mimeType: "text/csv",
buffer: Buffer.from("거래일,가맹점,금액\n2026-06-08,쿠팡,23900\n"),
});
await expect(page.locator(".au-toast")).toContainText("가져오기를 지원하지 않아요");
});
test("연결 모듈 a11y — 위반 0건", async ({ page }) => {
const r = await new AxeBuilder({ page })
.withTags(["wcag2a", "wcag2aa", "wcag21aa"])
.disableRules(["color-contrast"])
.analyze();
expect(r.violations, JSON.stringify(r.violations, null, 2)).toEqual([]);
});