package bootstrap import ( "encoding/json" "errors" "os" "path/filepath" "strings" "testing" ) func TestEnsureBootstrapPOSIXSkeletonInitializesEmptyRoot(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") t.Setenv("POSIX_ROOT", rootPath) if _, err := os.Stat(rootPath); !os.IsNotExist(err) { t.Fatalf("expected isolated POSIX root to start absent, got err=%v", err) } service := NewService(nil, os.Getenv("POSIX_ROOT")) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true, }, AdminSummary{ ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald", }, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } requiredPaths := []string{ filepath.Join(rootPath, "settings.json"), filepath.Join(rootPath, "layout.json"), filepath.Join(rootPath, "catalog", "packs"), filepath.Join(rootPath, "catalog", "standalone"), filepath.Join(rootPath, "departments", "department-primary-department", "settings.json"), filepath.Join(rootPath, "departments", "department-primary-department", "users.json"), filepath.Join(rootPath, "departments", "department-primary-department", "teams", "team-primary-team", "settings.json"), filepath.Join(rootPath, "departments", "department-primary-department", "teams", "team-primary-team", "users.json"), filepath.Join(rootPath, "projects", "project-primary-project", "settings.json"), filepath.Join(rootPath, "projects", "project-primary-project", "home.json"), filepath.Join(rootPath, "projects", "project-primary-project", "acl.json"), filepath.Join(rootPath, "projects", "project-primary-project", "children"), filepath.Join(rootPath, "projects", "project-primary-project", "tree"), filepath.Join(rootPath, "users", "settings.json"), filepath.Join(rootPath, "users", "data.json"), filepath.Join(rootPath, "users", "personals"), filepath.Join(rootPath, "users", "personals", "personal-ronald", "settings.json"), filepath.Join(rootPath, "users", "personals", "personal-ronald", "layout.json"), filepath.Join(rootPath, "users", "personals", "personal-ronald", "home.json"), filepath.Join(rootPath, "users", "personals", "personal-ronald", "tree"), } for _, path := range requiredPaths { if _, err := os.Stat(path); err != nil { t.Fatalf("expected path to exist %s: %v", path, err) } } settingsPayload := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "settings.json")) installationPayload, ok := settingsPayload["installation"].(map[string]any) if !ok { t.Fatalf("settings.json missing installation object: %#v", settingsPayload) } if installationPayload["name"] != "MangoPig" { t.Fatalf("expected installation name MangoPig, got %#v", installationPayload["name"]) } if installationPayload["isBootstrapped"] != true { t.Fatalf("expected installation to be bootstrapped, got %#v", installationPayload["isBootstrapped"]) } layoutPayload := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "layout.json")) homePayload, ok := layoutPayload["home"].(map[string]any) if !ok { t.Fatalf("layout.json missing home object: %#v", layoutPayload) } if homePayload["defaultProjectSlug"] != "primary-project" { t.Fatalf("expected default project slug primary-project, got %#v", homePayload["defaultProjectSlug"]) } projectSettings := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "projects", "project-primary-project", "settings.json")) if projectSettings["type"] != "project" { t.Fatalf("expected project settings type project, got %#v", projectSettings["type"]) } projectACL := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "projects", "project-primary-project", "acl.json")) if projectACL["inherits"] != true { t.Fatalf("expected project acl to inherit by default, got %#v", projectACL["inherits"]) } usersSettings := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "users", "settings.json")) if usersSettings["primaryAdminId"] != "admin-1" { t.Fatalf("expected primary admin id admin-1, got %#v", usersSettings["primaryAdminId"]) } personalSettings := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "users", "personals", "personal-ronald", "settings.json")) if personalSettings["type"] != "personal" { t.Fatalf("expected personal settings type personal, got %#v", personalSettings["type"]) } if personalSettings["name"] != "Ronald" { t.Fatalf("expected personal name Ronald, got %#v", personalSettings["name"]) } if personalSettings["slug"] != "ronald" { t.Fatalf("expected personal slug ronald, got %#v", personalSettings["slug"]) } personalHome := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "users", "personals", "personal-ronald", "home.json")) if personalHome["type"] != "personal-home" { t.Fatalf("expected personal home type personal-home, got %#v", personalHome["type"]) } if personalHome["title"] != "Ronald's Home" { t.Fatalf("expected personal home title Ronald's Home, got %#v", personalHome["title"]) } } func TestCreateProjectHierarchyFolderOnDiskCreatesExpectedFolderShape(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") service := NewService(nil, rootPath) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true}, AdminSummary{ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald"}, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } createdPath, createdSlug, err := service.createProjectHierarchyFolderOnDisk("primary-project", "", "Design System") if err != nil { t.Fatalf("createProjectHierarchyFolderOnDisk root folder: %v", err) } if createdPath != "projects/project-primary-project/children/folder-design-system" { t.Fatalf("unexpected created path: %s", createdPath) } if createdSlug != "design-system" { t.Fatalf("unexpected created slug: %s", createdSlug) } createdFolderPath := filepath.Join(rootPath, "projects", "project-primary-project", "children", "folder-design-system") for _, path := range []string{ filepath.Join(createdFolderPath, "folder.json"), filepath.Join(createdFolderPath, "acl.json"), filepath.Join(createdFolderPath, "children"), } { if _, err := os.Stat(path); err != nil { t.Fatalf("expected path to exist %s: %v", path, err) } } folderPayload := readJSONFileForTest[map[string]any](t, filepath.Join(createdFolderPath, "folder.json")) if strings.TrimSpace(asStringForTest(folderPayload["id"])) == "" { t.Fatalf("expected created folder to have stable id, got %#v", folderPayload["id"]) } if folderPayload["name"] != "Design System" { t.Fatalf("expected folder name Design System, got %#v", folderPayload["name"]) } if folderPayload["slug"] != "design-system" { t.Fatalf("expected folder slug design-system, got %#v", folderPayload["slug"]) } nestedPath, nestedSlug, err := service.createProjectHierarchyFolderOnDisk("primary-project", createdPath, "Research") if err != nil { t.Fatalf("createProjectHierarchyFolderOnDisk nested folder: %v", err) } if nestedPath != "projects/project-primary-project/children/folder-design-system/children/folder-research" { t.Fatalf("unexpected nested path: %s", nestedPath) } if nestedSlug != "research" { t.Fatalf("unexpected nested slug: %s", nestedSlug) } } func TestCreateProjectTreeFolderOnDiskCreatesExpectedFolderShape(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") service := NewService(nil, rootPath) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true}, AdminSummary{ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald"}, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } createdPath, createdSlug, err := service.createProjectTreeFolderOnDisk("primary-project", "", "Docs") if err != nil { t.Fatalf("createProjectTreeFolderOnDisk root folder: %v", err) } if createdPath != "projects/project-primary-project/tree/folder-docs" { t.Fatalf("unexpected created path: %s", createdPath) } if createdSlug != "docs" { t.Fatalf("unexpected created slug: %s", createdSlug) } createdFolderPath := filepath.Join(rootPath, "projects", "project-primary-project", "tree", "folder-docs") for _, path := range []string{ filepath.Join(createdFolderPath, "folder.json"), filepath.Join(createdFolderPath, "acl.json"), filepath.Join(createdFolderPath, "children"), } { if _, err := os.Stat(path); err != nil { t.Fatalf("expected path to exist %s: %v", path, err) } } nestedPath, nestedSlug, err := service.createProjectTreeFolderOnDisk("primary-project", createdPath, "Research") if err != nil { t.Fatalf("createProjectTreeFolderOnDisk nested folder: %v", err) } if nestedPath != "projects/project-primary-project/tree/folder-docs/children/folder-research" { t.Fatalf("unexpected nested path: %s", nestedPath) } if nestedSlug != "research" { t.Fatalf("unexpected nested slug: %s", nestedSlug) } } func TestRenameProjectHierarchyFolderOnDiskRenamesFolderShape(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") service := NewService(nil, rootPath) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true}, AdminSummary{ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald"}, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } createdPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", "", "Design System") if err != nil { t.Fatalf("createProjectHierarchyFolderOnDisk root folder: %v", err) } nestedPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", createdPath, "Research") if err != nil { t.Fatalf("createProjectHierarchyFolderOnDisk nested folder: %v", err) } previousPath, renamedPath, err := service.renameProjectHierarchyFolderOnDisk("primary-project", createdPath, "Platform Design") if err != nil { t.Fatalf("renameProjectHierarchyFolderOnDisk: %v", err) } if previousPath != createdPath { t.Fatalf("expected previous path %s, got %s", createdPath, previousPath) } if renamedPath != "projects/project-primary-project/children/folder-platform-design" { t.Fatalf("unexpected renamed path: %s", renamedPath) } if _, err := os.Stat(filepath.Join(rootPath, filepath.FromSlash(createdPath))); !os.IsNotExist(err) { t.Fatalf("expected previous folder path to be gone, got err=%v", err) } renamedFolderPath := filepath.Join(rootPath, filepath.FromSlash(renamedPath)) if _, err := os.Stat(filepath.Join(renamedFolderPath, "children", filepath.Base(nestedPath))); err != nil { t.Fatalf("expected nested child folder to move with renamed parent: %v", err) } folderPayload := readJSONFileForTest[map[string]any](t, filepath.Join(renamedFolderPath, "folder.json")) if strings.TrimSpace(asStringForTest(folderPayload["id"])) == "" { t.Fatalf("expected renamed folder to preserve stable id, got %#v", folderPayload["id"]) } if folderPayload["name"] != "Platform Design" { t.Fatalf("expected renamed folder name Platform Design, got %#v", folderPayload["name"]) } if folderPayload["slug"] != "platform-design" { t.Fatalf("expected renamed folder slug platform-design, got %#v", folderPayload["slug"]) } if folderPayload["type"] != "folder" { t.Fatalf("expected renamed folder type folder, got %#v", folderPayload["type"]) } } func TestRenameProjectTreeFolderOnDiskRenamesFolderShape(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") service := NewService(nil, rootPath) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true}, AdminSummary{ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald"}, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } createdPath, _, err := service.createProjectTreeFolderOnDisk("primary-project", "", "Docs") if err != nil { t.Fatalf("createProjectTreeFolderOnDisk root folder: %v", err) } previousPath, renamedPath, err := service.renameProjectTreeFolderOnDisk("primary-project", createdPath, "Specifications") if err != nil { t.Fatalf("renameProjectTreeFolderOnDisk: %v", err) } if previousPath != createdPath { t.Fatalf("expected previous path %s, got %s", createdPath, previousPath) } if renamedPath != "projects/project-primary-project/tree/folder-specifications" { t.Fatalf("unexpected renamed path: %s", renamedPath) } folderPayload := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, filepath.FromSlash(renamedPath), "folder.json")) if folderPayload["name"] != "Specifications" { t.Fatalf("expected renamed folder name Specifications, got %#v", folderPayload["name"]) } if folderPayload["slug"] != "specifications" { t.Fatalf("expected renamed folder slug specifications, got %#v", folderPayload["slug"]) } } func TestMoveProjectHierarchyFolderOnDiskMovesFolderToNewParent(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") service := NewService(nil, rootPath) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true}, AdminSummary{ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald"}, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } designPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", "", "Design") if err != nil { t.Fatalf("create design folder: %v", err) } operationsPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", "", "Operations") if err != nil { t.Fatalf("create operations folder: %v", err) } researchPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", designPath, "Research") if err != nil { t.Fatalf("create research folder: %v", err) } nestedPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", researchPath, "Interview Notes") if err != nil { t.Fatalf("create nested folder: %v", err) } previousPath, movedPath, err := service.moveProjectHierarchyFolderOnDisk("primary-project", researchPath, operationsPath) if err != nil { t.Fatalf("moveProjectHierarchyFolderOnDisk: %v", err) } if previousPath != researchPath { t.Fatalf("expected previous path %s, got %s", researchPath, previousPath) } if movedPath != "projects/project-primary-project/children/folder-operations/children/folder-research" { t.Fatalf("unexpected moved path: %s", movedPath) } if _, err := os.Stat(filepath.Join(rootPath, filepath.FromSlash(researchPath))); !os.IsNotExist(err) { t.Fatalf("expected previous folder path to be gone, got err=%v", err) } movedFolderPath := filepath.Join(rootPath, filepath.FromSlash(movedPath)) if _, err := os.Stat(filepath.Join(movedFolderPath, "children", filepath.Base(nestedPath))); err != nil { t.Fatalf("expected nested child folder to move with moved parent: %v", err) } folderPayload := readJSONFileForTest[map[string]any](t, filepath.Join(movedFolderPath, "folder.json")) if strings.TrimSpace(asStringForTest(folderPayload["id"])) == "" { t.Fatalf("expected moved folder to preserve stable id, got %#v", folderPayload["id"]) } if folderPayload["name"] != "Research" { t.Fatalf("expected moved folder name Research, got %#v", folderPayload["name"]) } if folderPayload["slug"] != "research" { t.Fatalf("expected moved folder slug research, got %#v", folderPayload["slug"]) } if folderPayload["type"] != "folder" { t.Fatalf("expected moved folder type folder, got %#v", folderPayload["type"]) } } func TestMoveProjectTreeFolderOnDiskMovesFolderToNewParent(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") service := NewService(nil, rootPath) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true}, AdminSummary{ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald"}, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } docsPath, _, err := service.createProjectTreeFolderOnDisk("primary-project", "", "Docs") if err != nil { t.Fatalf("create docs folder: %v", err) } archivePath, _, err := service.createProjectTreeFolderOnDisk("primary-project", "", "Archive") if err != nil { t.Fatalf("create archive folder: %v", err) } previousPath, movedPath, err := service.moveProjectTreeFolderOnDisk("primary-project", docsPath, archivePath) if err != nil { t.Fatalf("moveProjectTreeFolderOnDisk: %v", err) } if previousPath != docsPath { t.Fatalf("expected previous path %s, got %s", docsPath, previousPath) } if movedPath != "projects/project-primary-project/tree/folder-archive/children/folder-docs" { t.Fatalf("unexpected moved path: %s", movedPath) } folderPayload := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, filepath.FromSlash(movedPath), "folder.json")) if folderPayload["name"] != "Docs" { t.Fatalf("expected moved folder name Docs, got %#v", folderPayload["name"]) } if folderPayload["slug"] != "docs" { t.Fatalf("expected moved folder slug docs, got %#v", folderPayload["slug"]) } } func TestMoveProjectHierarchyFolderOnDiskRejectsDescendantTarget(t *testing.T) { rootPath := filepath.Join(t.TempDir(), "POSIX") service := NewService(nil, rootPath) err := service.ensureBootstrapPOSIXSkeleton( InstallationRecord{ID: "installation-1", Name: "MangoPig", Mode: "personal", Access: "local", Protocol: "http", Host: "localhost", IsBootstrapped: true}, AdminSummary{ID: "admin-1", Email: "ronald@example.com", DisplayName: "Ronald"}, namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"}, namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"}, namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"}, namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"}, ) if err != nil { t.Fatalf("ensure bootstrap POSIX skeleton: %v", err) } parentPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", "", "Parent") if err != nil { t.Fatalf("create parent folder: %v", err) } childPath, _, err := service.createProjectHierarchyFolderOnDisk("primary-project", parentPath, "Child") if err != nil { t.Fatalf("create child folder: %v", err) } _, _, err = service.moveProjectHierarchyFolderOnDisk("primary-project", parentPath, childPath) if !errors.Is(err, ErrInvalidProjectFolderMove) { t.Fatalf("expected ErrInvalidProjectFolderMove, got %v", err) } } func TestBuildProjectHierarchyFolderTreeBuildsNestedStructure(t *testing.T) { rows := []projectHierarchyFolderRow{ {ID: "folder-design-id", Path: "projects/project-primary-project/children/folder-design", ParentPath: projectHierarchyRootPath("primary-project"), Label: "Design"}, {ID: "folder-research-id", Path: "projects/project-primary-project/children/folder-design/children/folder-research", ParentPath: "projects/project-primary-project/children/folder-design/children", Label: "Research"}, {ID: "folder-ops-id", Path: "projects/project-primary-project/children/folder-ops", ParentPath: projectHierarchyRootPath("primary-project"), Label: "Ops"}, } folders := buildProjectHierarchyFolderTree(rows, projectHierarchyRootPath("primary-project")) if len(folders) != 2 { t.Fatalf("expected 2 top-level folders, got %d", len(folders)) } if folders[0].Label != "Design" || folders[1].Label != "Ops" { t.Fatalf("unexpected top-level folder labels: %#v", folders) } if len(folders[0].Children) != 1 || folders[0].Children[0].Label != "Research" { t.Fatalf("unexpected nested folder structure: %#v", folders[0].Children) } if folders[0].ID != "folder-design-id" || folders[0].Path != "projects/project-primary-project/children/folder-design" { t.Fatalf("expected design folder to retain stable id/path, got %#v", folders[0]) } if folders[0].Children[0].ID != "folder-research-id" || folders[1].ID != "folder-ops-id" { t.Fatalf("expected nested/top-level folder ids to be preserved, got %#v / %#v", folders[0].Children[0], folders[1]) } } func TestApplyProjectHierarchyFolderOrderingOrdersRootAndChildrenByStableID(t *testing.T) { folders := []ProjectHierarchyFolderRecord{ { ID: "folder-design-id", Path: "projects/project-primary-project/children/folder-design", Label: "Design", Children: []ProjectHierarchyFolderRecord{ {ID: "folder-research-id", Path: "projects/project-primary-project/children/folder-design/children/folder-research", Label: "Research"}, {ID: "folder-assets-id", Path: "projects/project-primary-project/children/folder-design/children/folder-assets", Label: "Assets"}, }, }, {ID: "folder-ops-id", Path: "projects/project-primary-project/children/folder-ops", Label: "Ops"}, {ID: "folder-qa-id", Path: "projects/project-primary-project/children/folder-qa", Label: "QA"}, } ordered := applyProjectHierarchyFolderOrdering(folders, map[string][]string{ projectFolderOrderRootKey: {"folder-qa-id", "folder-design-id"}, "folder-design-id": {"folder-assets-id", "folder-research-id"}, }) if len(ordered) != 3 { t.Fatalf("expected 3 ordered root folders, got %d", len(ordered)) } if ordered[0].ID != "folder-qa-id" || ordered[1].ID != "folder-design-id" || ordered[2].ID != "folder-ops-id" { t.Fatalf("unexpected ordered root ids: %#v", ordered) } if len(ordered[1].Children) != 2 { t.Fatalf("expected design folder children to be preserved, got %#v", ordered[1].Children) } if ordered[1].Children[0].ID != "folder-assets-id" || ordered[1].Children[1].ID != "folder-research-id" { t.Fatalf("unexpected ordered child ids: %#v", ordered[1].Children) } } func TestInsertFolderOrderReordersWithinSameParent(t *testing.T) { folderOrder := map[string][]string{ projectFolderOrderRootKey: {"folder-a", "folder-b", "folder-c"}, } insertFolderOrder(folderOrder, "", "folder-c", 0) got := folderOrder[projectFolderOrderRootKey] if len(got) != 3 || got[0] != "folder-c" || got[1] != "folder-a" || got[2] != "folder-b" { t.Fatalf("unexpected reordered root children: %#v", got) } } func asStringForTest(value any) string { text, _ := value.(string) return text } func readJSONFileForTest[T any](t *testing.T, path string) T { t.Helper() data, err := os.ReadFile(path) if err != nil { t.Fatalf("read %s: %v", path, err) } var payload T if err := json.Unmarshal(data, &payload); err != nil { t.Fatalf("unmarshal %s: %v", path, err) } return payload }