489 lines
21 KiB
Go
489 lines
21 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"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"),
|
|
}
|
|
|
|
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"])
|
|
}
|
|
}
|
|
|
|
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 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 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 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{
|
|
{Path: "projects/project-primary-project/children/folder-design", ParentPath: projectHierarchyRootPath("primary-project"), Label: "Design"},
|
|
{Path: "projects/project-primary-project/children/folder-design/children/folder-research", ParentPath: "projects/project-primary-project/children/folder-design/children", Label: "Research"},
|
|
{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)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|