1
0
forked from baron/baron-sso

chore: snapshot local state before dev merge

This commit is contained in:
2026-06-17 21:25:42 +09:00
parent b2808759d2
commit 49560e8a8c
107 changed files with 8958 additions and 939 deletions

View File

@@ -1,4 +1,5 @@
import { expect, test } from "@playwright/test";
import { captureEvidence } from "./helpers/evidence";
function tenant(
id: string,
@@ -31,6 +32,12 @@ function user(id: string, name: string, companyCode: string) {
role: "user",
status: "active",
companyCode,
tenant: {
id: companyCode,
slug: companyCode,
type: "USER_GROUP",
name: companyCode,
},
grade: "사원",
createdAt: "2026-04-01T00:00:00.000Z",
updatedAt: "2026-04-01T00:00:00.000Z",
@@ -333,6 +340,139 @@ test("org chart orders managers before top executive members by rank priority",
]);
});
test("org chart renders an IS3 super admin when an org appointment exists", async ({
page,
}) => {
await page.route("**/api/v1/public/orgchart**", async (route) => {
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
sharedWith: "Playwright",
tenants: [
tenant("hanmac-family", "한맥가족", "hanmac-family"),
tenant(
"gpdtdc",
"총괄기획&기술개발센터",
"gpdtdc",
"hanmac-family",
"COMPANY",
),
tenant("gpd", "총괄기획실", "gpd", "gpdtdc", "ORGANIZATION"),
tenant(
"intigrated-system",
"통합시스템",
"intigrated-system",
"gpd",
"ORGANIZATION",
{ visibility: "public", orgUnitType: "디비전" },
),
tenant("is-3", "IS3", "is-3", "intigrated-system", "ORGANIZATION", {
visibility: "public",
orgUnitType: "팀",
}),
],
users: [
{
id: "675a3d46-45ad-4e8c-8c22-959a38302826",
email: "cyhan@samaneng.com",
name: "한치영",
role: "super_admin",
status: "active",
tenantSlug: "is-3",
companyCode: "is-3",
tenant: undefined,
grade: "",
metadata: {
additionalAppointments: [
{
grade: "책임",
isManager: true,
isPrimary: true,
tenantId: "is-3",
tenantName: "IS3",
tenantSlug: "is-3",
},
],
},
createdAt: "2026-06-16T00:00:00.000Z",
updatedAt: "2026-06-16T00:00:00.000Z",
},
{
...user("is3-executive", "상위직급", "is-3"),
grade: "전무이사",
},
],
}),
});
});
await page.goto("/chart?token=is3-manager");
const is3Node = page.locator('[data-testid="orgchart-node-is-3"]');
await expect(is3Node).toBeVisible();
await expect(
is3Node.locator(
'[data-testid="orgchart-member-675a3d46-45ad-4e8c-8c22-959a38302826"]',
),
).toContainText("한치영 책임");
await expect(
is3Node.locator('[data-testid="orgchart-member-is3-executive"]'),
).toContainText("상위직급 전무");
const orderedMemberIds = await is3Node
.locator('[data-testid^="orgchart-member-"]')
.evaluateAll((elements) =>
elements.map((element) => element.getAttribute("data-testid")),
);
expect(orderedMemberIds).toEqual([
"orgchart-member-675a3d46-45ad-4e8c-8c22-959a38302826",
"orgchart-member-is3-executive",
]);
});
test("org chart ignores stale scalar org fields without a membership source", async ({
page,
}) => {
await page.route("**/api/v1/public/orgchart**", async (route) => {
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
sharedWith: "Playwright",
tenants: [
tenant("hanmac-family", "한맥가족", "hanmac-family"),
tenant("is-1", "IS1", "is-1", "hanmac-family", "ORGANIZATION"),
tenant("is-2", "IS2", "is-2", "hanmac-family", "ORGANIZATION"),
tenant("is-3", "IS3", "is-3", "hanmac-family", "ORGANIZATION"),
],
users: [
{
id: "stale-system-admin",
email: "stale-system-admin@example.com",
name: "Stale System Admin",
role: "system_admin",
status: "active",
tenantSlug: "is-2",
companyCode: "is-1",
tenant: undefined,
joinedTenants: undefined,
metadata: { additionalAppointments: [] },
grade: "사원",
createdAt: "2026-06-16T00:00:00.000Z",
updatedAt: "2026-06-16T00:00:00.000Z",
},
],
}),
});
});
await page.goto("/chart?token=stale-scalar");
await expect(
page.locator('[data-testid="orgchart-member-stale-system-admin"]'),
).toHaveCount(0);
});
test("org chart expands organization node width so long names are not clipped", async ({
page,
}) => {
@@ -551,17 +691,31 @@ test("org chart places multi-tenant users only on leaf memberships without dupli
test("org chart allows a user in a hanmac-family descendant tenant", async ({
page,
}) => {
}, testInfo) => {
await page.setViewportSize({ width: 1600, height: 900 });
let snapshotRequests = 0;
await page.addInitScript(() => {
window.localStorage.setItem("playwright_auth_bypass", "1");
window.localStorage.setItem("dev_tenant_id", "saman-id");
});
await page.route("**/api/v1/admin/orgchart/snapshot**", async (route) => {
snapshotRequests += 1;
const url = new URL(route.request().url());
expect(route.request().headers()["x-tenant-id"]).toBe("saman-id");
expect(url.searchParams.get("cache")).toBe("redis");
if (snapshotRequests === 1) {
expect(url.searchParams.get("refresh")).toBeNull();
} else {
expect(url.searchParams.get("refresh")).toBe("true");
}
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
generatedAt:
snapshotRequests === 1
? "2026-06-17T07:10:11Z"
: "2026-06-17T08:20:21Z",
tenants: [
tenant(
"hanmac-family-id",
@@ -607,10 +761,63 @@ test("org chart allows a user in a hanmac-family descendant tenant", async ({
await expect(
page.getByRole("button", { name: "조직: 한맥가족" }),
).toBeVisible();
await expect(page.getByTestId("orgchart-selection-status-panel")).toHaveCount(
0,
);
await expect(page.getByTestId("orgchart-render-status-panel")).toHaveText(
"2026-06-17 16:10:11 KST",
);
await expect(
page.getByTestId("orgchart-render-status-panel"),
).not.toContainText("데이터 기준");
const headerBox = await page.getByTestId("orgfront-topbar").boundingBox();
const viewportWidth = page.viewportSize()?.width ?? 1600;
const statusPanelBox = await page
.getByTestId("orgchart-render-status-panel")
.boundingBox();
expect(headerBox).not.toBeNull();
expect(statusPanelBox).not.toBeNull();
expect(
viewportWidth - ((statusPanelBox?.x ?? 0) + (statusPanelBox?.width ?? 0)),
).toBeLessThanOrEqual(20);
expect(
(headerBox?.y ?? 0) +
(headerBox?.height ?? 0) -
((statusPanelBox?.y ?? 0) + (statusPanelBox?.height ?? 0)),
).toBeLessThanOrEqual(6);
await expect(page.getByTestId("orgchart-render-status-panel")).toHaveCSS(
"border-top-width",
"0px",
);
await expect(page.getByTestId("orgchart-render-status-panel")).toHaveCSS(
"box-shadow",
"none",
);
await expect(page.getByTestId("orgchart-render-status-panel")).toHaveCSS(
"background-color",
"rgba(0, 0, 0, 0)",
);
await expect(page.getByTestId("orgchart-render-status-panel")).toHaveCSS(
"opacity",
"0.72",
);
await expect(page.getByRole("button", { name: "새로고침" })).toHaveCSS(
"background-color",
"rgba(0, 0, 0, 0)",
);
await expect(page.getByRole("button", { name: "새로고침" })).toHaveCSS(
"border-top-width",
"0px",
);
await page.getByRole("button", { name: "새로고침" }).click();
await expect(page.getByTestId("orgchart-render-status-panel")).toHaveText(
"2026-06-17 17:20:21 KST",
);
const svg = page.locator('[data-testid="orgchart-vector-svg"]');
await expect(svg.getByText("한맥가족", { exact: true })).toBeVisible();
await expect(svg.getByText("삼안", { exact: true })).toBeVisible();
await expect(svg.getByText(/Saman Descendant User/)).toBeVisible();
await captureEvidence(page, testInfo, "orgchart-topbar-data-refresh-aligned");
});
test("org chart logs authenticated snapshot failures with actionable diagnostics", async ({