@jskit-ai/users-web 0.1.52 → 0.1.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/package.descriptor.mjs +14 -96
  2. package/package.json +16 -11
  3. package/src/client/account-settings/sections.js +74 -0
  4. package/src/client/composables/account-settings/accountSettingsRuntimeHelpers.js +2 -38
  5. package/src/client/composables/crud/crudLookupFieldRuntime.js +2 -2
  6. package/src/client/composables/internal/crudListParentTitleSupport.js +1 -1
  7. package/src/client/composables/internal/useOperationScope.js +12 -12
  8. package/src/client/composables/records/useAddEdit.js +2 -2
  9. package/src/client/composables/records/useList.js +3 -3
  10. package/src/client/composables/records/useView.js +2 -2
  11. package/src/client/composables/support/scopeHelpers.js +19 -19
  12. package/src/client/composables/useAccess.js +3 -3
  13. package/src/client/composables/useAccountSettingsRuntime.js +8 -156
  14. package/src/client/composables/useCommand.js +2 -2
  15. package/src/client/composables/useCrudListParentTitle.js +2 -2
  16. package/src/client/composables/usePaths.js +50 -38
  17. package/src/client/composables/useScopeRuntime.js +55 -27
  18. package/src/client/composables/useSurfaceRouteContext.js +1 -7
  19. package/src/client/index.js +0 -1
  20. package/src/client/lib/bootstrap.js +0 -63
  21. package/src/client/lib/httpClient.js +2 -59
  22. package/src/client/lib/theme.js +12 -189
  23. package/src/client/providers/UsersWebClientProvider.js +2 -25
  24. package/src/client/providers/bootUsersWebClientProvider.js +28 -0
  25. package/src/shared/toolsOutletContracts.js +1 -8
  26. package/templates/src/components/account/settings/AccountSettingsClientElement.vue +33 -21
  27. package/test/accountSettingsSections.test.js +79 -0
  28. package/test/exportsContract.test.js +2 -2
  29. package/test/scopeHelpers.test.js +6 -6
  30. package/test/settingsPlacementContract.test.js +4 -49
  31. package/test/theme.test.js +0 -56
  32. package/src/client/components/ConsoleSettingsClientElement.vue +0 -24
  33. package/src/client/components/MembersAdminClientElement.vue +0 -400
  34. package/src/client/components/UsersProfileSurfaceSwitchMenuItem.vue +0 -39
  35. package/src/client/components/UsersWorkspaceMembersMenuItem.vue +0 -36
  36. package/src/client/components/UsersWorkspacePermissionMenuItem.vue +0 -90
  37. package/src/client/components/UsersWorkspaceSelector.vue +0 -248
  38. package/src/client/components/UsersWorkspaceSettingsMenuItem.vue +0 -39
  39. package/src/client/components/UsersWorkspaceToolsWidget.vue +0 -12
  40. package/src/client/components/WorkspaceMembersClientElement.vue +0 -655
  41. package/src/client/components/WorkspaceProfileClientElement.vue +0 -116
  42. package/src/client/components/WorkspaceSettingsClientElement.vue +0 -102
  43. package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +0 -265
  44. package/src/client/components/WorkspacesClientElement.vue +0 -509
  45. package/src/client/composables/account-settings/accountSettingsInvitesRuntime.js +0 -88
  46. package/src/client/composables/useBootstrapQuery.js +0 -52
  47. package/src/client/composables/useWorkspaceRouteContext.js +0 -28
  48. package/src/client/composables/useWorkspaceSurfaceId.js +0 -43
  49. package/src/client/lib/menuIcons.js +0 -210
  50. package/src/client/lib/profileSurfaceMenuLinks.js +0 -142
  51. package/src/client/lib/surfaceAccessPolicy.js +0 -350
  52. package/src/client/lib/workspaceLinkResolver.js +0 -207
  53. package/src/client/lib/workspaceSurfaceContext.js +0 -82
  54. package/src/client/lib/workspaceSurfacePaths.js +0 -163
  55. package/src/client/providers/UsersWorkspacesClientProvider.js +0 -24
  56. package/src/client/runtime/bootstrapPlacementRouteGuards.js +0 -371
  57. package/src/client/runtime/bootstrapPlacementRuntime.js +0 -463
  58. package/src/client/runtime/bootstrapPlacementRuntimeConstants.js +0 -28
  59. package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +0 -147
  60. package/src/client/support/menuLinkTarget.js +0 -93
  61. package/src/client/support/realtimeWorkspace.js +0 -21
  62. package/src/client/support/runtimeNormalization.js +0 -27
  63. package/src/client/support/workspaceQueryKeys.js +0 -15
  64. package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +0 -77
  65. package/templates/src/pages/console/settings/index.vue +0 -8
  66. package/templates/src/pages/console/settings.vue +0 -32
  67. package/test/bootstrapPlacementRuntime.test.js +0 -1095
  68. package/test/menuIcons.test.js +0 -35
  69. package/test/menuLinkTarget.test.js +0 -116
  70. package/test/profileSurfaceMenuLinks.test.js +0 -207
  71. package/test/surfaceAccessPolicy.test.js +0 -129
  72. package/test/workspaceLinkResolver.test.js +0 -61
  73. package/test/workspaceSurfacePaths.test.js +0 -39
@@ -1,35 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import {
4
- mdiAccountCogOutline,
5
- mdiConsoleNetworkOutline,
6
- mdiCogOutline,
7
- mdiFolderOutline,
8
- mdiLogin,
9
- mdiShieldCrownOutline,
10
- mdiViewDashboardOutline,
11
- mdiViewListOutline
12
- } from "@mdi/js";
13
- import {
14
- resolveMenuLinkIcon,
15
- resolveSurfaceSwitchIcon
16
- } from "../src/client/lib/menuIcons.js";
17
-
18
- test("resolveSurfaceSwitchIcon prefers explicit icon and maps known surfaces", () => {
19
- assert.equal(resolveSurfaceSwitchIcon("admin"), mdiShieldCrownOutline);
20
- assert.equal(resolveSurfaceSwitchIcon("console"), mdiConsoleNetworkOutline);
21
- assert.equal(resolveSurfaceSwitchIcon("admin", "custom-icon"), "custom-icon");
22
- assert.equal(resolveSurfaceSwitchIcon("admin", "mdi-cog-outline"), mdiCogOutline);
23
- });
24
-
25
- test("resolveMenuLinkIcon resolves settings/login fallbacks and generic default", () => {
26
- assert.equal(resolveMenuLinkIcon({ icon: "mdi-cog-outline" }), mdiCogOutline);
27
- assert.equal(resolveMenuLinkIcon({ to: "/account" }), mdiAccountCogOutline);
28
- assert.equal(resolveMenuLinkIcon({ label: "Sign in" }), mdiLogin);
29
- assert.equal(resolveMenuLinkIcon({ label: "Go to admin" }), mdiShieldCrownOutline);
30
- assert.equal(resolveMenuLinkIcon({ label: "Workspace", to: "/w/acme" }), mdiViewDashboardOutline);
31
- assert.equal(resolveMenuLinkIcon({ to: "/projects" }), mdiFolderOutline);
32
- assert.equal(resolveMenuLinkIcon({ label: "Settings", to: "/workspace/settings" }), mdiCogOutline);
33
- assert.equal(resolveMenuLinkIcon({ label: "Anything else", to: "/foo" }), mdiFolderOutline);
34
- assert.equal(resolveMenuLinkIcon({ label: "Anything else" }), mdiViewListOutline);
35
- });
@@ -1,116 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import {
4
- normalizeMenuLinkPathname,
5
- resolveMenuLinkTarget
6
- } from "../src/client/support/menuLinkTarget.js";
7
-
8
- const WORKSPACE_PLACEMENT_CONTEXT = Object.freeze({
9
- surfaceConfig: {
10
- enabledSurfaceIds: ["admin"],
11
- surfacesById: {
12
- admin: {
13
- id: "admin",
14
- requiresWorkspace: true
15
- }
16
- }
17
- }
18
- });
19
-
20
- const MIXED_PLACEMENT_CONTEXT = Object.freeze({
21
- surfaceConfig: {
22
- enabledSurfaceIds: ["app", "admin"],
23
- surfacesById: {
24
- app: {
25
- id: "app",
26
- requiresWorkspace: false
27
- },
28
- admin: {
29
- id: "admin",
30
- requiresWorkspace: true
31
- }
32
- }
33
- }
34
- });
35
-
36
- function createPageResolver() {
37
- return function resolvePagePath(relativePath = "", options = {}) {
38
- return `page:${String(options.surface || "")}:${String(relativePath || "")}`;
39
- };
40
- }
41
-
42
- test("resolveMenuLinkTarget resolves suffix targets when no explicit to is provided", () => {
43
- assert.equal(
44
- resolveMenuLinkTarget({
45
- surface: "admin",
46
- placementContext: WORKSPACE_PLACEMENT_CONTEXT,
47
- workspaceSuffix: "/practice/vets",
48
- nonWorkspaceSuffix: "/practice/vets",
49
- resolvePagePath: createPageResolver()
50
- }),
51
- "page:admin:/practice/vets"
52
- );
53
- });
54
-
55
- test("resolveMenuLinkTarget resolves relative targets through suffix templates", () => {
56
- assert.equal(
57
- resolveMenuLinkTarget({
58
- to: "./notes",
59
- surface: "admin",
60
- placementContext: WORKSPACE_PLACEMENT_CONTEXT,
61
- workspaceSuffix: "/contacts/[contactId]/notes",
62
- nonWorkspaceSuffix: "/contacts/[contactId]/notes",
63
- routeParams: {
64
- contactId: 42
65
- },
66
- resolvePagePath: createPageResolver()
67
- }),
68
- "page:admin:/contacts/42/notes"
69
- );
70
- });
71
-
72
- test("resolveMenuLinkTarget returns empty string for unresolved relative targets", () => {
73
- assert.equal(
74
- resolveMenuLinkTarget({
75
- to: "./notes",
76
- surface: "admin",
77
- placementContext: WORKSPACE_PLACEMENT_CONTEXT,
78
- workspaceSuffix: "/contacts/[contactId]/notes",
79
- nonWorkspaceSuffix: "/contacts/[contactId]/notes",
80
- resolvePagePath: createPageResolver()
81
- }),
82
- ""
83
- );
84
- });
85
-
86
- test("resolveMenuLinkTarget keeps absolute targets unchanged", () => {
87
- assert.equal(
88
- resolveMenuLinkTarget({
89
- to: "/practice/vets",
90
- surface: "admin",
91
- placementContext: WORKSPACE_PLACEMENT_CONTEXT,
92
- workspaceSuffix: "/ignored",
93
- nonWorkspaceSuffix: "/ignored",
94
- resolvePagePath: createPageResolver()
95
- }),
96
- "/practice/vets"
97
- );
98
- });
99
-
100
- test("resolveMenuLinkTarget uses non-workspace suffix for non-workspace surfaces", () => {
101
- assert.equal(
102
- resolveMenuLinkTarget({
103
- surface: "app",
104
- currentSurfaceId: "admin",
105
- placementContext: MIXED_PLACEMENT_CONTEXT,
106
- workspaceSuffix: "/workspace-only",
107
- nonWorkspaceSuffix: "/public-page",
108
- resolvePagePath: createPageResolver()
109
- }),
110
- "page:app:/public-page"
111
- );
112
- });
113
-
114
- test("normalizeMenuLinkPathname removes query strings and hashes", () => {
115
- assert.equal(normalizeMenuLinkPathname("/practice/vets?tab=all#section"), "/practice/vets");
116
- });
@@ -1,207 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { mdiShieldCrownOutline } from "@mdi/js";
4
- import {
5
- hasWorkspaceMembership,
6
- resolvePrimarySurfaceSwitchLink,
7
- resolveProfileSurfaceMenuLinks
8
- } from "../src/client/lib/profileSurfaceMenuLinks.js";
9
-
10
- function createPlacementContext({
11
- workspace = null,
12
- workspaces = [],
13
- authenticated = true,
14
- consoleOwner = false
15
- } = {}) {
16
- return {
17
- auth: {
18
- authenticated
19
- },
20
- workspace,
21
- workspaces,
22
- permissions: [],
23
- surfaceAccess: {
24
- consoleowner: consoleOwner
25
- },
26
- surfaceAccessPolicies: {
27
- public: {},
28
- workspace_member: {
29
- requireAuth: true,
30
- requireWorkspaceMembership: true
31
- },
32
- console_owner: {
33
- requireAuth: true,
34
- requireFlagsAll: ["console_owner"]
35
- }
36
- },
37
- surfaceConfig: {
38
- tenancyMode: "workspaces",
39
- defaultSurfaceId: "app",
40
- enabledSurfaceIds: ["home", "app", "admin", "console"],
41
- surfacesById: {
42
- home: {
43
- id: "home",
44
- enabled: true,
45
- pagesRoot: "",
46
- routeBase: "/",
47
- requiresAuth: false,
48
- requiresWorkspace: false,
49
- accessPolicyId: "public"
50
- },
51
- app: {
52
- id: "app",
53
- enabled: true,
54
- pagesRoot: "w/[workspaceSlug]",
55
- routeBase: "/w/:workspaceSlug",
56
- requiresAuth: true,
57
- requiresWorkspace: true,
58
- accessPolicyId: "workspace_member"
59
- },
60
- admin: {
61
- id: "admin",
62
- enabled: true,
63
- pagesRoot: "w/[workspaceSlug]/admin",
64
- routeBase: "/w/:workspaceSlug/admin",
65
- requiresAuth: true,
66
- requiresWorkspace: true,
67
- accessPolicyId: "workspace_member"
68
- },
69
- console: {
70
- id: "console",
71
- enabled: true,
72
- pagesRoot: "console",
73
- routeBase: "/console",
74
- requiresAuth: true,
75
- requiresWorkspace: false,
76
- accessPolicyId: "console_owner"
77
- }
78
- }
79
- }
80
- };
81
- }
82
-
83
- const originalWindow = globalThis.window;
84
-
85
- test.afterEach(() => {
86
- if (typeof originalWindow === "undefined") {
87
- delete globalThis.window;
88
- return;
89
- }
90
- globalThis.window = originalWindow;
91
- });
92
-
93
- test("hasWorkspaceMembership matches context.workspace slug", () => {
94
- const context = createPlacementContext({
95
- workspace: {
96
- id: 1,
97
- slug: "acme"
98
- },
99
- workspaces: []
100
- });
101
-
102
- assert.equal(hasWorkspaceMembership(context, "acme"), true);
103
- });
104
-
105
- test("hasWorkspaceMembership matches context.workspaces slug", () => {
106
- const context = createPlacementContext({
107
- workspace: null,
108
- workspaces: [
109
- {
110
- id: 1,
111
- slug: "acme"
112
- }
113
- ]
114
- });
115
-
116
- assert.equal(hasWorkspaceMembership(context, "acme"), true);
117
- });
118
-
119
- test("resolvePrimarySurfaceSwitchLink shows Go to admin only for member workspace", () => {
120
- const context = createPlacementContext({
121
- workspace: {
122
- id: 1,
123
- slug: "acme"
124
- },
125
- workspaces: [
126
- {
127
- id: 1,
128
- slug: "acme"
129
- }
130
- ]
131
- });
132
-
133
- const link = resolvePrimarySurfaceSwitchLink({
134
- context,
135
- surface: "app"
136
- });
137
-
138
- assert.deepEqual(link, {
139
- id: "surface-switch.admin",
140
- label: "Go to admin",
141
- icon: mdiShieldCrownOutline,
142
- to: "/w/acme/admin"
143
- });
144
- });
145
-
146
- test("resolvePrimarySurfaceSwitchLink hides workspace switch when slug is only in URL and user is not member", () => {
147
- globalThis.window = {
148
- location: {
149
- pathname: "/w/acme/admin",
150
- search: "",
151
- hash: ""
152
- }
153
- };
154
-
155
- const context = createPlacementContext({
156
- workspace: null,
157
- workspaces: []
158
- });
159
-
160
- const link = resolvePrimarySurfaceSwitchLink({
161
- context,
162
- surface: "admin"
163
- });
164
-
165
- assert.equal(link, null);
166
- });
167
-
168
- test("resolveProfileSurfaceMenuLinks includes console switch only for console owners", () => {
169
- const nonOwnerContext = createPlacementContext({
170
- workspace: {
171
- id: 1,
172
- slug: "acme"
173
- },
174
- workspaces: [
175
- {
176
- id: 1,
177
- slug: "acme"
178
- }
179
- ],
180
- consoleOwner: false
181
- });
182
- const ownerContext = createPlacementContext({
183
- workspace: {
184
- id: 1,
185
- slug: "acme"
186
- },
187
- workspaces: [
188
- {
189
- id: 1,
190
- slug: "acme"
191
- }
192
- ],
193
- consoleOwner: true
194
- });
195
-
196
- const nonOwnerLinks = resolveProfileSurfaceMenuLinks({
197
- context: nonOwnerContext,
198
- surface: "app"
199
- });
200
- const ownerLinks = resolveProfileSurfaceMenuLinks({
201
- context: ownerContext,
202
- surface: "app"
203
- });
204
-
205
- assert.equal(nonOwnerLinks.some((entry) => entry.id === "surface-switch.console"), false);
206
- assert.equal(ownerLinks.some((entry) => entry.id === "surface-switch.console"), true);
207
- });
@@ -1,129 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { evaluateSurfaceAccess } from "../src/client/lib/surfaceAccessPolicy.js";
4
-
5
- function createContext(overrides = {}) {
6
- return {
7
- auth: {
8
- authenticated: true
9
- },
10
- workspaces: [
11
- {
12
- id: 1,
13
- slug: "acme"
14
- }
15
- ],
16
- permissions: [],
17
- surfaceAccess: {
18
- consoleowner: false
19
- },
20
- surfaceAccessPolicies: {
21
- public: {},
22
- workspace_member: {
23
- requireAuth: true,
24
- requireWorkspaceMembership: true
25
- },
26
- console_owner: {
27
- requireAuth: true,
28
- requireFlagsAll: ["console_owner"]
29
- }
30
- },
31
- surfaceConfig: {
32
- defaultSurfaceId: "home",
33
- enabledSurfaceIds: ["home", "app", "console"],
34
- surfacesById: {
35
- home: {
36
- id: "home",
37
- enabled: true,
38
- routeBase: "/home",
39
- requiresWorkspace: false,
40
- accessPolicyId: "public"
41
- },
42
- app: {
43
- id: "app",
44
- enabled: true,
45
- routeBase: "/w/:workspaceSlug",
46
- requiresWorkspace: true,
47
- accessPolicyId: "workspace_member"
48
- },
49
- console: {
50
- id: "console",
51
- enabled: true,
52
- routeBase: "/console",
53
- requiresWorkspace: false,
54
- accessPolicyId: "console_owner"
55
- }
56
- }
57
- },
58
- ...overrides
59
- };
60
- }
61
-
62
- test("evaluateSurfaceAccess allows workspace member surfaces for accessible workspace", () => {
63
- const decision = evaluateSurfaceAccess({
64
- context: createContext(),
65
- surfaceId: "app",
66
- workspaceSlug: "acme"
67
- });
68
-
69
- assert.equal(decision.allowed, true);
70
- });
71
-
72
- test("evaluateSurfaceAccess denies workspace member surfaces for inaccessible workspace", () => {
73
- const decision = evaluateSurfaceAccess({
74
- context: createContext(),
75
- surfaceId: "app",
76
- workspaceSlug: "missing"
77
- });
78
-
79
- assert.equal(decision.allowed, false);
80
- assert.equal(decision.reason, "surface-access-workspace-membership-required");
81
- });
82
-
83
- test("evaluateSurfaceAccess allows unknown workspace membership when allowOnUnknown=true", () => {
84
- const context = createContext();
85
- delete context.workspaces;
86
-
87
- const decision = evaluateSurfaceAccess({
88
- context,
89
- surfaceId: "app",
90
- workspaceSlug: "acme",
91
- allowOnUnknown: true
92
- });
93
-
94
- assert.equal(decision.allowed, true);
95
- assert.equal(decision.pending, true);
96
- });
97
-
98
- test("evaluateSurfaceAccess enforces bootstrap surface access flags", () => {
99
- const deniedDecision = evaluateSurfaceAccess({
100
- context: createContext(),
101
- surfaceId: "console"
102
- });
103
- assert.equal(deniedDecision.allowed, false);
104
-
105
- const allowedDecision = evaluateSurfaceAccess({
106
- context: createContext({
107
- surfaceAccess: {
108
- consoleowner: true
109
- }
110
- }),
111
- surfaceId: "console"
112
- });
113
- assert.equal(allowedDecision.allowed, true);
114
- });
115
-
116
- test("evaluateSurfaceAccess denies workspace route with not_found status", () => {
117
- const decision = evaluateSurfaceAccess({
118
- context: createContext({
119
- workspaceBootstrapStatuses: {
120
- acme: "not_found"
121
- }
122
- }),
123
- surfaceId: "app",
124
- workspaceSlug: "acme"
125
- });
126
-
127
- assert.equal(decision.allowed, false);
128
- assert.equal(decision.reason, "surface-access-workspace-not-found");
129
- });
@@ -1,61 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { resolveWorkspaceShellLinkPath } from "../src/client/lib/workspaceLinkResolver.js";
4
-
5
- function createContext({ defaultSurfaceId = "dashboard", enabledSurfaceIds = ["dashboard"], surfacesById = {} } = {}) {
6
- return {
7
- surfaceConfig: {
8
- defaultSurfaceId,
9
- enabledSurfaceIds,
10
- surfacesById
11
- }
12
- };
13
- }
14
-
15
- test("resolveWorkspaceShellLinkPath resolves workspace path for known workspace surfaces", () => {
16
- const context = {
17
- surfaceConfig: {
18
- defaultSurfaceId: "dashboard",
19
- enabledSurfaceIds: ["dashboard"],
20
- surfacesById: {
21
- dashboard: {
22
- routeBase: "/dashboard",
23
- requiresWorkspace: true
24
- }
25
- }
26
- }
27
- };
28
-
29
- const path = resolveWorkspaceShellLinkPath({
30
- context,
31
- surface: "dashboard",
32
- mode: "workspace",
33
- workspaceSlug: "acme"
34
- });
35
-
36
- assert.equal(path, "/w/acme");
37
- });
38
-
39
- test("resolveWorkspaceShellLinkPath returns empty path for unknown non-default workspace surface", () => {
40
- const context = createContext();
41
- const path = resolveWorkspaceShellLinkPath({
42
- context,
43
- surface: "admin",
44
- mode: "workspace",
45
- workspaceSlug: "acme"
46
- });
47
-
48
- assert.equal(path, "");
49
- });
50
-
51
- test("resolveWorkspaceShellLinkPath returns empty path for unknown console-like surface ids", () => {
52
- const context = createContext();
53
- const path = resolveWorkspaceShellLinkPath({
54
- context,
55
- surface: "console",
56
- mode: "workspace",
57
- workspaceSlug: "acme"
58
- });
59
-
60
- assert.equal(path, "");
61
- });
@@ -1,39 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
-
4
- import {
5
- resolveAccountSettingsPathFromPlacementContext,
6
- resolveSurfaceWorkspacePathFromPlacementContext
7
- } from "../src/client/lib/workspaceSurfacePaths.js";
8
-
9
- test("resolveSurfaceWorkspacePathFromPlacementContext returns empty path without workspace slug", () => {
10
- const context = {
11
- surfaceConfig: {
12
- defaultSurfaceId: "home",
13
- enabledSurfaceIds: ["home", "app", "admin", "console"],
14
- surfacesById: {
15
- home: { id: "home", routeBase: "/home", requiresWorkspace: false },
16
- app: { id: "app", routeBase: "/w/:workspaceSlug", requiresWorkspace: true },
17
- admin: { id: "admin", routeBase: "/w/:workspaceSlug/admin", requiresWorkspace: true },
18
- console: { id: "console", routeBase: "/console", requiresWorkspace: false }
19
- }
20
- }
21
- };
22
-
23
- assert.equal(resolveSurfaceWorkspacePathFromPlacementContext(context, "app", "", "/"), "");
24
- });
25
-
26
- test("resolveAccountSettingsPathFromPlacementContext uses account surface route when available", () => {
27
- const context = {
28
- surfaceConfig: {
29
- defaultSurfaceId: "home",
30
- enabledSurfaceIds: ["home", "account"],
31
- surfacesById: {
32
- home: { id: "home", routeBase: "/home", requiresWorkspace: false },
33
- account: { id: "account", routeBase: "/profile", requiresWorkspace: false }
34
- }
35
- }
36
- };
37
-
38
- assert.equal(resolveAccountSettingsPathFromPlacementContext(context), "/profile");
39
- });