forked from baron/baron-sso
코드체크 업데이트
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
import { createRequire } from "node:module";
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const { shouldIncludeWebKit } =
|
||||
require("../scripts/playwrightHostDeps.cjs") as {
|
||||
shouldIncludeWebKit: () => boolean;
|
||||
};
|
||||
|
||||
const configuredWorkers = process.env.PLAYWRIGHT_WORKERS
|
||||
? Number.parseInt(process.env.PLAYWRIGHT_WORKERS, 10)
|
||||
: undefined;
|
||||
@@ -57,10 +64,14 @@ export default defineConfig({
|
||||
use: { ...devices["Desktop Firefox"] },
|
||||
},
|
||||
|
||||
{
|
||||
name: "webkit",
|
||||
use: { ...devices["Desktop Safari"] },
|
||||
},
|
||||
...(shouldIncludeWebKit()
|
||||
? [
|
||||
{
|
||||
name: "webkit",
|
||||
use: { ...devices["Desktop Safari"] },
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
|
||||
@@ -35,6 +35,29 @@ if [ "${1:-}" = "--print-mode" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ensure_frontend_dependencies() {
|
||||
if [ ! -f package.json ] || [ ! -f package-lock.json ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
deps_hash="$(sha256sum package.json package-lock.json | sha256sum | awk '{print $1}')"
|
||||
else
|
||||
deps_hash="$(cksum package.json package-lock.json | cksum | awk '{print $1}')"
|
||||
fi
|
||||
deps_stamp="node_modules/.baron-deps-hash"
|
||||
installed_hash="$(cat "$deps_stamp" 2>/dev/null || true)"
|
||||
|
||||
if [ "$installed_hash" != "$deps_hash" ]; then
|
||||
echo "Installing frontend dependencies from package-lock.json..."
|
||||
npm ci
|
||||
mkdir -p node_modules
|
||||
printf '%s\n' "$deps_hash" > "$deps_stamp"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_frontend_dependencies
|
||||
|
||||
if [ "$mode" = "production" ]; then
|
||||
echo "Running in production mode with Vite preview..."
|
||||
exec sh -c "npm run build && npm run preview -- --host 0.0.0.0"
|
||||
|
||||
@@ -101,18 +101,10 @@ export function ParentTenantSelector({
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex min-h-8 flex-wrap items-center justify-between gap-2">
|
||||
<Label className="text-sm font-semibold">
|
||||
{label}
|
||||
</Label>
|
||||
<Label className="text-sm font-semibold">{label}</Label>
|
||||
{labelAction}
|
||||
</div>
|
||||
<input
|
||||
id={id}
|
||||
name={id}
|
||||
type="hidden"
|
||||
value={value}
|
||||
readOnly
|
||||
/>
|
||||
<input id={id} name={id} type="hidden" value={value} readOnly />
|
||||
<div className="flex min-h-10 flex-wrap items-center gap-2 rounded-md border border-input bg-background px-3 py-2">
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -63,7 +63,10 @@ function TenantCreatePage() {
|
||||
parentStepConfirmed || Boolean(selectedParentTenant);
|
||||
const parentContextLabel = selectedParentTenant
|
||||
? canConfigureHanmacOrg
|
||||
? t("ui.admin.tenants.create.parent_context.hanmac", "한맥가족 하위 테넌트")
|
||||
? t(
|
||||
"ui.admin.tenants.create.parent_context.hanmac",
|
||||
"한맥가족 하위 테넌트",
|
||||
)
|
||||
: t("ui.admin.tenants.create.parent_context.general", "일반 하위 테넌트")
|
||||
: parentStepConfirmed
|
||||
? t("ui.admin.tenants.create.parent_context.root", "최상위 테넌트")
|
||||
@@ -232,10 +235,7 @@ function TenantCreatePage() {
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
data-testid="tenant-visibility-slot"
|
||||
className="space-y-2"
|
||||
>
|
||||
<div data-testid="tenant-visibility-slot" className="space-y-2">
|
||||
<Label
|
||||
htmlFor="tenant-visibility"
|
||||
className="text-sm font-semibold"
|
||||
|
||||
@@ -980,7 +980,7 @@ function TenantListPage() {
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}{" "}
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
@@ -338,10 +338,7 @@ export function TenantProfilePage() {
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
data-testid="tenant-visibility-slot"
|
||||
className="space-y-2"
|
||||
>
|
||||
<div data-testid="tenant-visibility-slot" className="space-y-2">
|
||||
<Label className="text-sm font-semibold">
|
||||
{t("ui.admin.tenants.profile.visibility", "공개 범위")}
|
||||
</Label>
|
||||
|
||||
@@ -202,6 +202,11 @@ subtitle = "Subtitle"
|
||||
[msg.admin.tenants.import_preview]
|
||||
description = "Rows without tenant_id are compared with existing tenant candidates, then imported as new tenants or updates."
|
||||
|
||||
[msg.admin.tenants.parent]
|
||||
local_picker_description = "Select the tenant to use as the parent from the tenant list."
|
||||
local_picker_empty = "No selectable tenants are available."
|
||||
picker_description = "Select a tenant in org-chart to apply it as the parent tenant."
|
||||
|
||||
[msg.admin.tenants.admins]
|
||||
add_success = "Add Success"
|
||||
empty = "Empty"
|
||||
@@ -217,6 +222,7 @@ remove_success = "Owner permission revoked."
|
||||
subtitle = "List of owners with top-level permissions for this tenant."
|
||||
|
||||
[msg.admin.tenants.create]
|
||||
pick_parent_first = "Select the parent tenant first."
|
||||
subtitle = "Subtitle"
|
||||
|
||||
[msg.admin.tenants.create.form]
|
||||
@@ -908,9 +914,14 @@ title = "Domain conflict"
|
||||
candidates = "Candidates"
|
||||
confirm = "Run import"
|
||||
create_new_reset = "Create new (reset ID/slug)"
|
||||
csv_parents = "CSV Parents"
|
||||
external_id = "External ID"
|
||||
match = "Match"
|
||||
no_candidates = "No candidates"
|
||||
parent = "Parent"
|
||||
parent_companies = "Parent Companies"
|
||||
parent_company_groups = "Parent Company Groups"
|
||||
parent_organizations = "Parent Organizations"
|
||||
parent_unresolved = "Parent needs review"
|
||||
slug_exists = "slug conflict"
|
||||
title = "Confirm CSV import"
|
||||
@@ -957,11 +968,20 @@ domains_label = "Allowed Domains (Comma separated)"
|
||||
domains_placeholder = "example.com, example.kr"
|
||||
name = "Tenant name"
|
||||
parent = "Parent"
|
||||
pick_hanmac_parent = "Pick from Hanmac Family"
|
||||
pick_other_parent = "Pick another tenant"
|
||||
root_tenant = "Create as top-level tenant"
|
||||
slug = "Slug"
|
||||
slug_placeholder = "tenant-slug"
|
||||
status = "Status"
|
||||
type = "Type"
|
||||
|
||||
[ui.admin.tenants.create.parent_context]
|
||||
general = "General child tenant"
|
||||
hanmac = "Hanmac Family child tenant"
|
||||
pick_required = "Parent tenant selection required"
|
||||
root = "Top-level tenant"
|
||||
|
||||
[ui.admin.tenants.create.memo]
|
||||
title = "Title"
|
||||
|
||||
@@ -1023,11 +1043,17 @@ allowed_domains_help = "Users with these email domains will be automatically ass
|
||||
approve_button = "Approve Tenant"
|
||||
description = "Description"
|
||||
name = "Tenant Name"
|
||||
org_unit_type = "Organization detail type"
|
||||
slug = "Slug"
|
||||
status = "Status"
|
||||
subtitle = "Slug and status changes are applied immediately."
|
||||
title = "Tenant Profile"
|
||||
type = "Type"
|
||||
visibility = "Visibility"
|
||||
|
||||
[ui.admin.tenants.parent]
|
||||
local_search_placeholder = "Search tenant name or slug"
|
||||
pick_tenant = "Pick tenant"
|
||||
|
||||
[ui.admin.tenants.registry]
|
||||
title = "Tenant registry"
|
||||
|
||||
@@ -203,6 +203,11 @@ subtitle = "현재 등록된 테넌트를 확인하고 상태를 관리합니다
|
||||
[msg.admin.tenants.import_preview]
|
||||
description = "tenant_id가 없는 행은 기존 테넌트 후보와 비교한 뒤 신규 생성 또는 기존 테넌트 갱신으로 처리합니다."
|
||||
|
||||
[msg.admin.tenants.parent]
|
||||
local_picker_description = "테넌트 목록에서 상위 테넌트로 사용할 항목을 선택합니다."
|
||||
local_picker_empty = "선택할 수 있는 테넌트가 없습니다."
|
||||
picker_description = "org-chart에서 테넌트를 선택하면 상위 테넌트에 반영됩니다."
|
||||
|
||||
[msg.admin.tenants.admins]
|
||||
add_success = "관리자가 추가되었습니다."
|
||||
empty = "등록된 관리자가 없습니다."
|
||||
@@ -218,6 +223,7 @@ remove_success = "소유자 권한이 회수되었습니다."
|
||||
subtitle = "이 테넌트의 최상위 권한을 가진 소유자(조직장) 목록입니다."
|
||||
|
||||
[msg.admin.tenants.create]
|
||||
pick_parent_first = "상위 테넌트를 먼저 선택하세요."
|
||||
subtitle = "글로벌 운영 기준의 신규 테넌트를 등록합니다."
|
||||
|
||||
[msg.admin.tenants.create.form]
|
||||
@@ -910,9 +916,14 @@ title = "도메인 충돌"
|
||||
candidates = "후보"
|
||||
confirm = "가져오기 실행"
|
||||
create_new_reset = "신규 생성 (ID/slug 재설정)"
|
||||
csv_parents = "CSV 상위 테넌트"
|
||||
external_id = "외부 ID"
|
||||
match = "매칭"
|
||||
no_candidates = "후보 없음"
|
||||
parent = "상위"
|
||||
parent_companies = "상위 회사"
|
||||
parent_company_groups = "상위 그룹사"
|
||||
parent_organizations = "상위 조직"
|
||||
parent_unresolved = "부모 확인 필요"
|
||||
slug_exists = "slug 충돌"
|
||||
title = "CSV 가져오기 확인"
|
||||
@@ -959,11 +970,20 @@ domains_label = "Allowed Domains (Comma separated)"
|
||||
domains_placeholder = "example.com, example.kr"
|
||||
name = "테넌트 이름"
|
||||
parent = "상위 테넌트"
|
||||
pick_hanmac_parent = "한맥가족에서 선택"
|
||||
pick_other_parent = "다른 테넌트 선택"
|
||||
root_tenant = "최상위 테넌트로 생성"
|
||||
slug = "Slug"
|
||||
slug_placeholder = "tenant-slug"
|
||||
status = "상태"
|
||||
type = "유형"
|
||||
|
||||
[ui.admin.tenants.create.parent_context]
|
||||
general = "일반 하위 테넌트"
|
||||
hanmac = "한맥가족 하위 테넌트"
|
||||
pick_required = "상위 테넌트 선택 필요"
|
||||
root = "최상위 테넌트"
|
||||
|
||||
[ui.admin.tenants.create.memo]
|
||||
title = "정책 메모"
|
||||
|
||||
@@ -1025,11 +1045,17 @@ allowed_domains_help = "이 도메인을 가진 이메일로 가입한 사용자
|
||||
approve_button = "테넌트 승인"
|
||||
description = "설명"
|
||||
name = "테넌트 이름"
|
||||
org_unit_type = "조직 세부타입"
|
||||
slug = "슬러그 (Slug)"
|
||||
status = "상태"
|
||||
subtitle = "슬러그 및 상태 변경은 즉시 적용됩니다."
|
||||
title = "테넌트 프로필"
|
||||
type = "테넌트 유형"
|
||||
visibility = "공개 범위"
|
||||
|
||||
[ui.admin.tenants.parent]
|
||||
local_search_placeholder = "테넌트 이름 또는 슬러그 검색"
|
||||
pick_tenant = "테넌트 선택"
|
||||
|
||||
[ui.admin.tenants.registry]
|
||||
title = "Tenant registry"
|
||||
|
||||
@@ -208,6 +208,11 @@ subtitle = ""
|
||||
[msg.admin.tenants.import_preview]
|
||||
description = ""
|
||||
|
||||
[msg.admin.tenants.parent]
|
||||
local_picker_description = ""
|
||||
local_picker_empty = ""
|
||||
picker_description = ""
|
||||
|
||||
[msg.admin.tenants.admins]
|
||||
add_success = ""
|
||||
empty = ""
|
||||
@@ -223,6 +228,7 @@ remove_success = ""
|
||||
subtitle = ""
|
||||
|
||||
[msg.admin.tenants.create]
|
||||
pick_parent_first = ""
|
||||
subtitle = ""
|
||||
|
||||
[msg.admin.tenants.create.form]
|
||||
@@ -924,9 +930,14 @@ title = ""
|
||||
candidates = ""
|
||||
confirm = ""
|
||||
create_new_reset = ""
|
||||
csv_parents = ""
|
||||
external_id = ""
|
||||
match = ""
|
||||
no_candidates = ""
|
||||
parent = ""
|
||||
parent_companies = ""
|
||||
parent_company_groups = ""
|
||||
parent_organizations = ""
|
||||
parent_unresolved = ""
|
||||
slug_exists = ""
|
||||
title = ""
|
||||
@@ -973,11 +984,20 @@ domains_label = ""
|
||||
domains_placeholder = ""
|
||||
name = ""
|
||||
parent = ""
|
||||
pick_hanmac_parent = ""
|
||||
pick_other_parent = ""
|
||||
root_tenant = ""
|
||||
slug = ""
|
||||
slug_placeholder = ""
|
||||
status = ""
|
||||
type = ""
|
||||
|
||||
[ui.admin.tenants.create.parent_context]
|
||||
general = ""
|
||||
hanmac = ""
|
||||
pick_required = ""
|
||||
root = ""
|
||||
|
||||
[ui.admin.tenants.create.memo]
|
||||
title = ""
|
||||
|
||||
@@ -1044,11 +1064,17 @@ allowed_domains_help = ""
|
||||
approve_button = ""
|
||||
description = ""
|
||||
name = ""
|
||||
org_unit_type = ""
|
||||
slug = ""
|
||||
status = ""
|
||||
subtitle = ""
|
||||
title = ""
|
||||
type = ""
|
||||
visibility = ""
|
||||
|
||||
[ui.admin.tenants.parent]
|
||||
local_search_placeholder = ""
|
||||
pick_tenant = ""
|
||||
|
||||
[ui.admin.tenants.registry]
|
||||
title = ""
|
||||
|
||||
@@ -110,9 +110,7 @@ test.describe("Tenants Management", () => {
|
||||
await expect(page.locator("h2").last()).toContainText(/추가|Create/i, {
|
||||
timeout: 20000,
|
||||
});
|
||||
await page
|
||||
.getByRole("button", { name: "최상위 테넌트로 생성" })
|
||||
.click();
|
||||
await page.getByRole("button", { name: "최상위 테넌트로 생성" }).click();
|
||||
|
||||
const nameInput = page.locator('input[name="name"]').first();
|
||||
await nameInput.fill("New Tenant");
|
||||
@@ -213,9 +211,7 @@ test.describe("Tenants Management", () => {
|
||||
{
|
||||
type: "orgfront:picker:confirm",
|
||||
payload: {
|
||||
selections: [
|
||||
{ type: "tenant", id: "family-1", name: "한맥가족" },
|
||||
],
|
||||
selections: [{ type: "tenant", id: "family-1", name: "한맥가족" }],
|
||||
},
|
||||
},
|
||||
window.location.origin,
|
||||
@@ -260,7 +256,12 @@ test.describe("Tenants Management", () => {
|
||||
const headers = { "Access-Control-Allow-Origin": "*" };
|
||||
if (method === "GET") {
|
||||
return route.fulfill({
|
||||
json: { items: tenants, total: tenants.length, limit: 1000, offset: 0 },
|
||||
json: {
|
||||
items: tenants,
|
||||
total: tenants.length,
|
||||
limit: 1000,
|
||||
offset: 0,
|
||||
},
|
||||
headers,
|
||||
});
|
||||
}
|
||||
@@ -286,9 +287,7 @@ test.describe("Tenants Management", () => {
|
||||
{
|
||||
type: "orgfront:picker:confirm",
|
||||
payload: {
|
||||
selections: [
|
||||
{ type: "tenant", id: "family-1", name: "한맥가족" },
|
||||
],
|
||||
selections: [{ type: "tenant", id: "family-1", name: "한맥가족" }],
|
||||
},
|
||||
},
|
||||
window.location.origin,
|
||||
@@ -309,8 +308,8 @@ test.describe("Tenants Management", () => {
|
||||
const visibilityWidth = await page
|
||||
.getByTestId("tenant-visibility-slot")
|
||||
.evaluate((element) => element.getBoundingClientRect().width);
|
||||
const columns = await layout.evaluate((element) =>
|
||||
window.getComputedStyle(element).gridTemplateColumns,
|
||||
const columns = await layout.evaluate(
|
||||
(element) => window.getComputedStyle(element).gridTemplateColumns,
|
||||
);
|
||||
expect(columns.split(" ").length).toBe(4);
|
||||
expect(parentWidth).toBeGreaterThan(orgUnitWidth * 1.7);
|
||||
@@ -543,9 +542,7 @@ test.describe("Tenants Management", () => {
|
||||
await expect(page.locator("h2").last()).toContainText(/추가|Create/i, {
|
||||
timeout: 20000,
|
||||
});
|
||||
await page
|
||||
.getByRole("button", { name: "최상위 테넌트로 생성" })
|
||||
.click();
|
||||
await page.getByRole("button", { name: "최상위 테넌트로 생성" }).click();
|
||||
|
||||
const submitBtn = page.getByRole("button", { name: /^생성$/ });
|
||||
await expect(submitBtn).toBeDisabled();
|
||||
@@ -715,8 +712,8 @@ test.describe("Tenants Management", () => {
|
||||
await expect(layout).toContainText("조직 세부타입");
|
||||
await expect(layout).toContainText("공개 범위");
|
||||
|
||||
const columns = await layout.evaluate((element) =>
|
||||
window.getComputedStyle(element).gridTemplateColumns,
|
||||
const columns = await layout.evaluate(
|
||||
(element) => window.getComputedStyle(element).gridTemplateColumns,
|
||||
);
|
||||
expect(columns.split(" ").length).toBe(4);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user