forked from baron/baron-sso
웍스 동기화 이력확인 기능추가
This commit is contained in:
23
.playwright-mcp/page-2026-06-01T04-26-41-512Z.yml
Normal file
23
.playwright-mcp/page-2026-06-01T04-26-41-512Z.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
- generic [ref=e4]:
|
||||||
|
- generic [ref=e5]:
|
||||||
|
- img [ref=e7]
|
||||||
|
- generic [ref=e9]:
|
||||||
|
- heading "Baron SSO" [level=1] [ref=e10]
|
||||||
|
- paragraph [ref=e11]: Admin Control Plane
|
||||||
|
- generic [ref=e12]:
|
||||||
|
- generic [ref=e13]:
|
||||||
|
- heading "관리자 로그인" [level=3] [ref=e14]:
|
||||||
|
- img [ref=e15]
|
||||||
|
- text: 관리자 로그인
|
||||||
|
- paragraph [ref=e18]: Baron 통합 인증(SSO)을 통해 관리자 페이지에 접속합니다.
|
||||||
|
- generic [ref=e19]:
|
||||||
|
- button "SSO 계정으로 로그인" [ref=e20] [cursor=pointer]:
|
||||||
|
- img [ref=e21]
|
||||||
|
- text: SSO 계정으로 로그인
|
||||||
|
- img [ref=e23]
|
||||||
|
- paragraph [ref=e27]:
|
||||||
|
- text: 관리자 전역 세션은 보안을 위해 15분간 유지됩니다.
|
||||||
|
- text: 민감한 작업 시 재인증을 요구할 수 있습니다.
|
||||||
|
- paragraph [ref=e32]:
|
||||||
|
- text: 인증 정보가 없거나 로그인이 되지 않는 경우
|
||||||
|
- text: 시스템 관리자에게 문의하세요.
|
||||||
6
.playwright-mcp/page-2026-06-01T04-26-49-730Z.yml
Normal file
6
.playwright-mcp/page-2026-06-01T04-26-49-730Z.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
- generic [ref=e1]:
|
||||||
|
- button "Enable accessibility" [ref=e2]
|
||||||
|
- main:
|
||||||
|
- heading "Baron SW Portal" [level=1]
|
||||||
|
- paragraph: Loading sign-in
|
||||||
|
- generic: Sign in
|
||||||
0
.playwright-mcp/page-2026-06-01T07-15-49-591Z.yml
Normal file
0
.playwright-mcp/page-2026-06-01T07-15-49-591Z.yml
Normal file
@@ -54,6 +54,7 @@ import {
|
|||||||
retryWorksmobileJob,
|
retryWorksmobileJob,
|
||||||
type WorksmobileComparisonItem,
|
type WorksmobileComparisonItem,
|
||||||
type WorksmobileCredentialBatch,
|
type WorksmobileCredentialBatch,
|
||||||
|
type WorksmobileOutboxItem,
|
||||||
} from "../../../lib/adminApi";
|
} from "../../../lib/adminApi";
|
||||||
import { t } from "../../../lib/i18n";
|
import { t } from "../../../lib/i18n";
|
||||||
import {
|
import {
|
||||||
@@ -93,6 +94,70 @@ export function createWorksmobileCredentialBatchId() {
|
|||||||
return `worksmobile-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
return `worksmobile-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function worksmobileJobPayloadString(job: WorksmobileOutboxItem, key: string) {
|
||||||
|
const value = job.payload?.[key];
|
||||||
|
return typeof value === "string" ? value.trim() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function worksmobileJobRequestSummary(job: WorksmobileOutboxItem) {
|
||||||
|
const summary = job.payload?.requestSummary;
|
||||||
|
if (!summary || typeof summary !== "object" || Array.isArray(summary)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return summary as Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function worksmobileSummaryString(
|
||||||
|
summary: Record<string, unknown>,
|
||||||
|
key: string,
|
||||||
|
) {
|
||||||
|
const value = summary[key];
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
if (typeof value === "number" && Number.isFinite(value)) {
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatWorksmobileJobTarget(job: WorksmobileOutboxItem) {
|
||||||
|
const summary = worksmobileJobRequestSummary(job);
|
||||||
|
return (
|
||||||
|
worksmobileJobPayloadString(job, "displayName") ||
|
||||||
|
worksmobileSummaryString(summary, "displayName") ||
|
||||||
|
worksmobileSummaryString(summary, "orgUnitName") ||
|
||||||
|
worksmobileJobPayloadString(job, "name") ||
|
||||||
|
worksmobileJobPayloadString(job, "loginEmail") ||
|
||||||
|
worksmobileJobPayloadString(job, "email") ||
|
||||||
|
job.resourceId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatWorksmobileJobTargetSubtext(job: WorksmobileOutboxItem) {
|
||||||
|
const summary = worksmobileJobRequestSummary(job);
|
||||||
|
return (
|
||||||
|
worksmobileJobPayloadString(job, "loginEmail") ||
|
||||||
|
worksmobileSummaryString(summary, "email") ||
|
||||||
|
worksmobileJobPayloadString(job, "email") ||
|
||||||
|
worksmobileJobPayloadString(job, "externalKey") ||
|
||||||
|
worksmobileSummaryString(summary, "orgUnitExternalKey") ||
|
||||||
|
job.resourceId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatWorksmobileJobSummaryParts(job: WorksmobileOutboxItem) {
|
||||||
|
const summary = worksmobileJobRequestSummary(job);
|
||||||
|
const parts = [
|
||||||
|
worksmobileJobPayloadString(job, "primaryLeafOrgName"),
|
||||||
|
worksmobileJobPayloadString(job, "matchLocalPart"),
|
||||||
|
worksmobileSummaryString(summary, "parentOrgUnitId"),
|
||||||
|
worksmobileSummaryString(summary, "employeeNumber"),
|
||||||
|
worksmobileSummaryString(summary, "task"),
|
||||||
|
].filter(Boolean);
|
||||||
|
return Array.from(new Set(parts));
|
||||||
|
}
|
||||||
|
|
||||||
export function TenantWorksmobilePage() {
|
export function TenantWorksmobilePage() {
|
||||||
const params = useParams<{ tenantId: string }>();
|
const params = useParams<{ tenantId: string }>();
|
||||||
const tenantId = params.tenantId ?? "";
|
const tenantId = params.tenantId ?? "";
|
||||||
@@ -643,9 +708,10 @@ export function TenantWorksmobilePage() {
|
|||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>resource</TableHead>
|
<TableHead>대상</TableHead>
|
||||||
<TableHead>action</TableHead>
|
<TableHead>작업</TableHead>
|
||||||
<TableHead>status</TableHead>
|
<TableHead>변경 요약</TableHead>
|
||||||
|
<TableHead>상태</TableHead>
|
||||||
<TableHead>retry</TableHead>
|
<TableHead>retry</TableHead>
|
||||||
<TableHead className="w-24" />
|
<TableHead className="w-24" />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -654,9 +720,31 @@ export function TenantWorksmobilePage() {
|
|||||||
{(overview?.recentJobs ?? []).map((job) => (
|
{(overview?.recentJobs ?? []).map((job) => (
|
||||||
<TableRow key={job.id}>
|
<TableRow key={job.id}>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{job.resourceType}:{job.resourceId}
|
<div className="font-medium">
|
||||||
|
{formatWorksmobileJobTarget(job)}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-muted-foreground">
|
||||||
|
{job.resourceType}:
|
||||||
|
{formatWorksmobileJobTargetSubtext(job)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Badge variant="outline">{job.action}</Badge>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="flex max-w-md flex-wrap gap-1">
|
||||||
|
{formatWorksmobileJobSummaryParts(job).map((part) => (
|
||||||
|
<Badge key={part} variant="secondary">
|
||||||
|
{part}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
{formatWorksmobileJobSummaryParts(job).length === 0 && (
|
||||||
|
<span className="text-xs text-muted-foreground">
|
||||||
|
{job.resourceId}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{job.action}</TableCell>
|
|
||||||
<TableCell>{job.status}</TableCell>
|
<TableCell>{job.status}</TableCell>
|
||||||
<TableCell>{job.retryCount}</TableCell>
|
<TableCell>{job.retryCount}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ export type WorksmobileOutboxItem = {
|
|||||||
resourceType: string;
|
resourceType: string;
|
||||||
resourceId: string;
|
resourceId: string;
|
||||||
action: string;
|
action: string;
|
||||||
|
payload?: Record<string, unknown>;
|
||||||
status: string;
|
status: string;
|
||||||
retryCount: number;
|
retryCount: number;
|
||||||
lastError?: string;
|
lastError?: string;
|
||||||
|
|||||||
@@ -634,6 +634,35 @@ test.describe("Worksmobile tenant management", () => {
|
|||||||
retryCount: 1,
|
retryCount: 1,
|
||||||
createdAt: "2026-05-01T00:00:00Z",
|
createdAt: "2026-05-01T00:00:00Z",
|
||||||
updatedAt: "2026-05-01T00:00:00Z",
|
updatedAt: "2026-05-01T00:00:00Z",
|
||||||
|
payload: {
|
||||||
|
loginEmail: "changed-user@example.com",
|
||||||
|
displayName: "변경 사용자",
|
||||||
|
primaryLeafOrgName: "인재성장",
|
||||||
|
requestSummary: {
|
||||||
|
email: "changed-user@example.com",
|
||||||
|
displayName: "변경 사용자",
|
||||||
|
userExternalKey: "user-failed",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "job-org-auto",
|
||||||
|
resourceType: "ORGUNIT",
|
||||||
|
resourceId: "org-auto",
|
||||||
|
action: "UPSERT",
|
||||||
|
status: "processed",
|
||||||
|
retryCount: 0,
|
||||||
|
createdAt: "2026-05-01T00:00:00Z",
|
||||||
|
updatedAt: "2026-05-01T00:01:00Z",
|
||||||
|
payload: {
|
||||||
|
matchLocalPart: "people-growth",
|
||||||
|
requestSummary: {
|
||||||
|
orgUnitName: "인재성장",
|
||||||
|
email: "people-growth@example.com",
|
||||||
|
orgUnitExternalKey: "org-auto",
|
||||||
|
parentOrgUnitId: "externalKey:parent-org",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -764,8 +793,16 @@ test.describe("Worksmobile tenant management", () => {
|
|||||||
await page.getByRole("button", { name: "구성원 Sync" }).click();
|
await page.getByRole("button", { name: "구성원 Sync" }).click();
|
||||||
await expect.poll(() => requests).toContain("user-sync");
|
await expect.poll(() => requests).toContain("user-sync");
|
||||||
|
|
||||||
|
await expect(page.getByRole("row", { name: /변경 사용자/ })).toContainText(
|
||||||
|
"changed-user@example.com",
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
page.getByRole("row", { name: /ORGUNIT:people-growth/ }),
|
||||||
|
).toContainText("people-growth@example.com");
|
||||||
|
await expect(page.getByText("externalKey:parent-org")).toBeVisible();
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.getByRole("row", { name: /USER:user-failed/ })
|
.getByRole("row", { name: /변경 사용자/ })
|
||||||
.getByRole("button")
|
.getByRole("button")
|
||||||
.click();
|
.click();
|
||||||
await expect.poll(() => requests).toContain("retry");
|
await expect.poll(() => requests).toContain("retry");
|
||||||
|
|||||||
@@ -671,7 +671,8 @@ func TestRedactWorksmobileOutboxPayloadsRemovesInitialPasswordFromOverview(t *te
|
|||||||
|
|
||||||
redacted := redactWorksmobileOutboxPayloads(jobs)
|
redacted := redactWorksmobileOutboxPayloads(jobs)
|
||||||
|
|
||||||
require.Nil(t, redacted[0].Payload)
|
require.Equal(t, "tester@samaneng.com", redacted[0].Payload["loginEmail"])
|
||||||
|
require.NotContains(t, redacted[0].Payload, "initialPassword")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompareWorksmobileUsersHidesMatchedByDefault(t *testing.T) {
|
func TestCompareWorksmobileUsersHidesMatchedByDefault(t *testing.T) {
|
||||||
|
|||||||
@@ -180,13 +180,119 @@ func worksmobileDirectoryAuthConfigured() bool {
|
|||||||
|
|
||||||
func redactWorksmobileOutboxPayloads(jobs []domain.WorksmobileOutbox) []domain.WorksmobileOutbox {
|
func redactWorksmobileOutboxPayloads(jobs []domain.WorksmobileOutbox) []domain.WorksmobileOutbox {
|
||||||
for i := range jobs {
|
for i := range jobs {
|
||||||
if jobs[i].Payload != nil {
|
jobs[i].Payload = safeWorksmobileOutboxPayload(jobs[i].Payload)
|
||||||
jobs[i].Payload = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return jobs
|
return jobs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func safeWorksmobileOutboxPayload(payload domain.JSONMap) domain.JSONMap {
|
||||||
|
if payload == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
safe := domain.JSONMap{}
|
||||||
|
for _, key := range []string{
|
||||||
|
"tenantRootId",
|
||||||
|
"loginEmail",
|
||||||
|
"displayName",
|
||||||
|
"primaryLeafOrgName",
|
||||||
|
"credentialBatchId",
|
||||||
|
"credentialOperation",
|
||||||
|
"credentialBatchCreatedAt",
|
||||||
|
"worksmobileId",
|
||||||
|
"externalKey",
|
||||||
|
"domainId",
|
||||||
|
"name",
|
||||||
|
"email",
|
||||||
|
"matchLocalPart",
|
||||||
|
"baronStatus",
|
||||||
|
} {
|
||||||
|
if value, ok := payload[key]; ok && safeWorksmobilePayloadValue(value) != nil {
|
||||||
|
safe[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if summary := safeWorksmobileRequestSummary(payload["request"]); len(summary) > 0 {
|
||||||
|
safe["requestSummary"] = summary
|
||||||
|
}
|
||||||
|
return safe
|
||||||
|
}
|
||||||
|
|
||||||
|
func safeWorksmobilePayloadValue(value any) any {
|
||||||
|
switch v := value.(type) {
|
||||||
|
case string:
|
||||||
|
if strings.TrimSpace(v) == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func safeWorksmobileRequestSummary(request any) domain.JSONMap {
|
||||||
|
switch v := request.(type) {
|
||||||
|
case WorksmobileUserPayload:
|
||||||
|
summary := domain.JSONMap{}
|
||||||
|
safeSetWorksmobileSummary(summary, "email", v.Email)
|
||||||
|
safeSetWorksmobileSummary(summary, "displayName", v.UserName.LastName)
|
||||||
|
safeSetWorksmobileSummary(summary, "userExternalKey", v.UserExternalKey)
|
||||||
|
safeSetWorksmobileSummary(summary, "cellPhone", v.CellPhone)
|
||||||
|
safeSetWorksmobileSummary(summary, "employeeNumber", v.EmployeeNumber)
|
||||||
|
safeSetWorksmobileSummary(summary, "task", v.Task)
|
||||||
|
return summary
|
||||||
|
case WorksmobilePasswordResetPayload:
|
||||||
|
summary := domain.JSONMap{}
|
||||||
|
safeSetWorksmobileSummary(summary, "email", v.Email)
|
||||||
|
return summary
|
||||||
|
case WorksmobileOrgUnitPayload:
|
||||||
|
summary := domain.JSONMap{}
|
||||||
|
safeSetWorksmobileSummary(summary, "email", v.Email)
|
||||||
|
safeSetWorksmobileSummary(summary, "orgUnitName", v.OrgUnitName)
|
||||||
|
safeSetWorksmobileSummary(summary, "orgUnitExternalKey", v.OrgUnitExternalKey)
|
||||||
|
safeSetWorksmobileSummary(summary, "parentOrgUnitId", v.ParentOrgUnitID)
|
||||||
|
if v.DomainID > 0 {
|
||||||
|
summary["domainId"] = v.DomainID
|
||||||
|
}
|
||||||
|
return summary
|
||||||
|
case map[string]any:
|
||||||
|
return safeWorksmobileRequestSummaryFromMap(v)
|
||||||
|
case domain.JSONMap:
|
||||||
|
return safeWorksmobileRequestSummaryFromMap(map[string]any(v))
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func safeWorksmobileRequestSummaryFromMap(request map[string]any) domain.JSONMap {
|
||||||
|
summary := domain.JSONMap{}
|
||||||
|
for _, key := range []string{
|
||||||
|
"email",
|
||||||
|
"userExternalKey",
|
||||||
|
"cellPhone",
|
||||||
|
"employeeNumber",
|
||||||
|
"task",
|
||||||
|
"orgUnitName",
|
||||||
|
"orgUnitExternalKey",
|
||||||
|
"parentOrgUnitId",
|
||||||
|
"domainId",
|
||||||
|
} {
|
||||||
|
if value, ok := request[key]; ok && safeWorksmobilePayloadValue(value) != nil {
|
||||||
|
summary[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if userName, ok := request["userName"].(map[string]any); ok {
|
||||||
|
safeSetWorksmobileSummary(summary, "displayName", stringValue(userName["lastName"]))
|
||||||
|
}
|
||||||
|
return summary
|
||||||
|
}
|
||||||
|
|
||||||
|
func safeSetWorksmobileSummary(summary domain.JSONMap, key string, value string) {
|
||||||
|
if value = strings.TrimSpace(value); value != "" {
|
||||||
|
summary[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *worksmobileSyncService) GetComparison(ctx context.Context, tenantID string, includeMatched bool) (WorksmobileComparison, error) {
|
func (s *worksmobileSyncService) GetComparison(ctx context.Context, tenantID string, includeMatched bool) (WorksmobileComparison, error) {
|
||||||
root, err := s.hanmacRoot(ctx, tenantID)
|
root, err := s.hanmacRoot(ctx, tenantID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -415,6 +415,85 @@ func TestWorksmobileSyncServiceOverviewExposesAdminTenantIDForPasswordManageLink
|
|||||||
require.Equal(t, "works-tenant-1", overview.Config.AdminTenantID)
|
require.Equal(t, "works-tenant-1", overview.Config.AdminTenantID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWorksmobileSyncServiceOverviewKeepsSafeRecentJobChangeLogPayload(t *testing.T) {
|
||||||
|
root := domain.Tenant{
|
||||||
|
ID: "root-tenant",
|
||||||
|
Slug: HanmacFamilyTenantSlug,
|
||||||
|
Name: "한맥가족",
|
||||||
|
}
|
||||||
|
outboxRepo := &fakeWorksmobileOutboxRepo{
|
||||||
|
recent: []domain.WorksmobileOutbox{
|
||||||
|
{
|
||||||
|
ID: "job-user-upsert",
|
||||||
|
ResourceType: domain.WorksmobileResourceUser,
|
||||||
|
ResourceID: "user-1",
|
||||||
|
Action: domain.WorksmobileActionUpsert,
|
||||||
|
Status: domain.WorksmobileOutboxStatusProcessed,
|
||||||
|
Payload: domain.JSONMap{
|
||||||
|
"loginEmail": "changed@example.com",
|
||||||
|
"displayName": "변경 사용자",
|
||||||
|
"primaryLeafOrgName": "인재성장",
|
||||||
|
"initialPassword": "Secret123!",
|
||||||
|
"request": WorksmobileUserPayload{
|
||||||
|
Email: "changed@example.com",
|
||||||
|
UserExternalKey: "user-1",
|
||||||
|
UserName: WorksmobileUserName{LastName: "변경 사용자"},
|
||||||
|
PasswordConfig: WorksmobilePasswordConfig{Password: "Secret123!"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "job-org-upsert",
|
||||||
|
ResourceType: domain.WorksmobileResourceOrgUnit,
|
||||||
|
ResourceID: "org-1",
|
||||||
|
Action: domain.WorksmobileActionUpsert,
|
||||||
|
Status: domain.WorksmobileOutboxStatusProcessed,
|
||||||
|
Payload: domain.JSONMap{
|
||||||
|
"matchLocalPart": "people-growth",
|
||||||
|
"request": WorksmobileOrgUnitPayload{
|
||||||
|
OrgUnitName: "인재성장",
|
||||||
|
Email: "people-growth@example.com",
|
||||||
|
OrgUnitExternalKey: "org-1",
|
||||||
|
ParentOrgUnitID: "externalKey:parent-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
service := NewWorksmobileSyncService(
|
||||||
|
&fakeWorksmobileTenantService{tenants: map[string]domain.Tenant{root.ID: root}},
|
||||||
|
&fakeWorksmobileUserRepo{},
|
||||||
|
outboxRepo,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
overview, err := service.GetTenantOverview(context.Background(), root.ID)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, overview.RecentJobs, 2)
|
||||||
|
userPayload := overview.RecentJobs[0].Payload
|
||||||
|
require.Equal(t, "changed@example.com", userPayload["loginEmail"])
|
||||||
|
require.Equal(t, "변경 사용자", userPayload["displayName"])
|
||||||
|
require.Equal(t, "인재성장", userPayload["primaryLeafOrgName"])
|
||||||
|
require.NotContains(t, userPayload, "initialPassword")
|
||||||
|
require.NotContains(t, userPayload, "request")
|
||||||
|
require.Equal(t, domain.JSONMap{
|
||||||
|
"email": "changed@example.com",
|
||||||
|
"displayName": "변경 사용자",
|
||||||
|
"userExternalKey": "user-1",
|
||||||
|
}, userPayload["requestSummary"])
|
||||||
|
|
||||||
|
orgPayload := overview.RecentJobs[1].Payload
|
||||||
|
require.Equal(t, "people-growth", orgPayload["matchLocalPart"])
|
||||||
|
require.NotContains(t, orgPayload, "request")
|
||||||
|
require.Equal(t, domain.JSONMap{
|
||||||
|
"email": "people-growth@example.com",
|
||||||
|
"orgUnitName": "인재성장",
|
||||||
|
"orgUnitExternalKey": "org-1",
|
||||||
|
"parentOrgUnitId": "externalKey:parent-1",
|
||||||
|
}, orgPayload["requestSummary"])
|
||||||
|
}
|
||||||
|
|
||||||
func TestCompareWorksmobileGroupsUsesOrganizationsAndBarongroupChildCompanies(t *testing.T) {
|
func TestCompareWorksmobileGroupsUsesOrganizationsAndBarongroupChildCompanies(t *testing.T) {
|
||||||
parentID := "root-tenant"
|
parentID := "root-tenant"
|
||||||
root := domain.Tenant{
|
root := domain.Tenant{
|
||||||
|
|||||||
BIN
docs/snapshots/worksmobile-change-log-2026-06-02.png
Normal file
BIN
docs/snapshots/worksmobile-change-log-2026-06-02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
3635
orgfront/pnpm-lock.yaml
generated
Normal file
3635
orgfront/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user