@nextsparkjs/theme-default 0.1.0-beta.24 → 0.1.0-beta.26

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/theme-default",
3
- "version": "0.1.0-beta.24",
3
+ "version": "0.1.0-beta.26",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./config/theme.config.ts",
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Mock for @nextsparkjs/core/components/ui/badge
3
+ */
4
+ const React = require('react')
5
+
6
+ const Badge = ({ children, variant = 'default', className = '', ...props }) => {
7
+ return React.createElement('span', {
8
+ className: `badge badge-${variant} ${className}`.trim(),
9
+ 'data-testid': 'badge',
10
+ ...props,
11
+ }, children)
12
+ }
13
+
14
+ module.exports = { Badge }
15
+ module.exports.Badge = Badge
16
+ module.exports.default = Badge
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Mock for @nextsparkjs/core/lib/db
3
+ */
4
+
5
+ const queryWithRLS = jest.fn().mockResolvedValue([])
6
+ const mutateWithRLS = jest.fn().mockResolvedValue({ rowCount: 1 })
7
+
8
+ module.exports = {
9
+ queryWithRLS,
10
+ mutateWithRLS,
11
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Mock Permissions Registry for Jest tests
3
+ */
4
+
5
+ export type Permission = string
6
+
7
+ export interface ResolvedPermission {
8
+ id: string
9
+ label: string
10
+ description: string
11
+ category: string
12
+ roles: string[]
13
+ dangerous: boolean
14
+ source: 'core' | 'theme'
15
+ disabled?: boolean
16
+ }
17
+
18
+ export interface PermissionUISection {
19
+ id: string
20
+ label: string
21
+ description: string
22
+ categories: string[]
23
+ }
24
+
25
+ export interface RolesConfig {
26
+ additionalRoles?: string[]
27
+ hierarchy?: Record<string, number>
28
+ displayNames?: Record<string, string>
29
+ descriptions?: Record<string, string>
30
+ }
31
+
32
+ // Mock permissions data
33
+ export const ALL_RESOLVED_PERMISSIONS: ResolvedPermission[] = [
34
+ {
35
+ id: 'tasks.create',
36
+ label: 'Create tasks',
37
+ description: 'Can create new tasks',
38
+ category: 'Tasks',
39
+ roles: ['owner', 'admin', 'member'],
40
+ dangerous: false,
41
+ source: 'theme',
42
+ },
43
+ {
44
+ id: 'tasks.read',
45
+ label: 'View tasks',
46
+ description: 'Can view task details',
47
+ category: 'Tasks',
48
+ roles: ['owner', 'admin', 'member'],
49
+ dangerous: false,
50
+ source: 'theme',
51
+ },
52
+ {
53
+ id: 'tasks.update',
54
+ label: 'Edit tasks',
55
+ description: 'Can modify task information',
56
+ category: 'Tasks',
57
+ roles: ['owner', 'admin', 'member'],
58
+ dangerous: false,
59
+ source: 'theme',
60
+ },
61
+ {
62
+ id: 'tasks.delete',
63
+ label: 'Delete tasks',
64
+ description: 'Can delete tasks',
65
+ category: 'Tasks',
66
+ roles: ['owner', 'admin'],
67
+ dangerous: true,
68
+ source: 'theme',
69
+ },
70
+ ]
71
+
72
+ export const ALL_PERMISSIONS: Permission[] = ALL_RESOLVED_PERMISSIONS.map(p => p.id)
73
+
74
+ export const ALL_PERMISSIONS_SET = new Set(ALL_PERMISSIONS)
75
+
76
+ export const AVAILABLE_ROLES: readonly string[] = ['owner', 'admin', 'member', 'viewer']
77
+
78
+ export const ROLE_HIERARCHY: Record<string, number> = {
79
+ owner: 100,
80
+ admin: 50,
81
+ member: 10,
82
+ viewer: 1,
83
+ }
84
+
85
+ export const ROLE_DISPLAY_NAMES: Record<string, string> = {
86
+ owner: 'common.teamRoles.owner',
87
+ admin: 'common.teamRoles.admin',
88
+ member: 'common.teamRoles.member',
89
+ viewer: 'common.teamRoles.viewer',
90
+ }
91
+
92
+ export const ROLE_DESCRIPTIONS: Record<string, string> = {
93
+ owner: 'Full team control, cannot be removed',
94
+ admin: 'Manage team members and settings',
95
+ member: 'Standard team access',
96
+ viewer: 'Read-only access to team resources',
97
+ }
98
+
99
+ export const CUSTOM_ROLES: RolesConfig = {
100
+ additionalRoles: [],
101
+ hierarchy: {},
102
+ displayNames: {},
103
+ descriptions: {},
104
+ }
105
+
106
+ export const PERMISSIONS_BY_ROLE: Record<string, Set<Permission>> = {
107
+ owner: new Set(ALL_PERMISSIONS),
108
+ admin: new Set(['tasks.create', 'tasks.read', 'tasks.update', 'tasks.delete']),
109
+ member: new Set(['tasks.create', 'tasks.read', 'tasks.update']),
110
+ viewer: new Set(['tasks.read']),
111
+ }
112
+
113
+ export const ROLE_PERMISSIONS_ARRAY: Record<string, Permission[]> = {
114
+ owner: [...ALL_PERMISSIONS],
115
+ admin: ['tasks.create', 'tasks.read', 'tasks.update', 'tasks.delete'],
116
+ member: ['tasks.create', 'tasks.read', 'tasks.update'],
117
+ viewer: ['tasks.read'],
118
+ }
119
+
120
+ export const PERMISSIONS_BY_CATEGORY: Record<string, ResolvedPermission[]> = {
121
+ Tasks: ALL_RESOLVED_PERMISSIONS,
122
+ }
123
+
124
+ export const FULL_MATRIX: Record<Permission, Record<string, boolean>> = {}
125
+ for (const perm of ALL_RESOLVED_PERMISSIONS) {
126
+ FULL_MATRIX[perm.id] = {}
127
+ for (const role of AVAILABLE_ROLES) {
128
+ FULL_MATRIX[perm.id][role] = PERMISSIONS_BY_ROLE[role]?.has(perm.id) ?? false
129
+ }
130
+ }
131
+
132
+ export const UI_SECTIONS: PermissionUISection[] = [
133
+ {
134
+ id: 'entities',
135
+ label: 'Entities',
136
+ description: 'Entity-specific permissions',
137
+ categories: ['Tasks'],
138
+ },
139
+ ]
140
+
141
+ export const TEAM_PERMISSIONS_RAW = []
142
+ export const TEAM_PERMISSIONS_BY_ROLE: Record<string, string[]> = {}
143
+
144
+ export const PERMISSIONS_METADATA = {
145
+ totalPermissions: ALL_PERMISSIONS.length,
146
+ corePermissions: 0,
147
+ teamPermissions: 0,
148
+ featurePermissions: 0,
149
+ entityPermissions: ALL_RESOLVED_PERMISSIONS.length,
150
+ customRoles: 0,
151
+ availableRoles: AVAILABLE_ROLES.length,
152
+ categories: Object.keys(PERMISSIONS_BY_CATEGORY).length,
153
+ generatedAt: new Date().toISOString(),
154
+ theme: 'default',
155
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Mock Theme Registry for Jest tests
3
+ */
4
+
5
+ export interface ThemeEntity {
6
+ name: string
7
+ source: string
8
+ config: any
9
+ }
10
+
11
+ export interface ThemeRouteFile {
12
+ path: string
13
+ type: 'api' | 'page'
14
+ methods?: string[]
15
+ }
16
+
17
+ export interface ThemeRegistryEntry {
18
+ name: string
19
+ slug: string
20
+ displayName: string
21
+ description: string
22
+ version: string
23
+ entities: ThemeEntity[]
24
+ routes: ThemeRouteFile[]
25
+ middlewares: any[]
26
+ plugins: string[]
27
+ path: string
28
+ }
29
+
30
+ export const THEME_REGISTRY: Record<string, ThemeRegistryEntry> = {
31
+ default: {
32
+ name: 'default',
33
+ slug: 'default',
34
+ displayName: 'Default Theme',
35
+ description: 'Default theme for NextSpark',
36
+ version: '1.0.0',
37
+ entities: [
38
+ { name: 'posts', source: 'default', config: { name: 'posts', label: 'Posts' } }
39
+ ],
40
+ routes: [
41
+ { path: '/api/v1/posts', type: 'api', methods: ['GET', 'POST'] }
42
+ ],
43
+ middlewares: [],
44
+ plugins: [],
45
+ path: 'contents/themes/default',
46
+ },
47
+ }
48
+
49
+ export type ThemeName = keyof typeof THEME_REGISTRY | string
50
+
51
+ export const THEME_METADATA = {
52
+ generated: new Date().toISOString(),
53
+ activeTheme: 'default',
54
+ totalThemes: Object.keys(THEME_REGISTRY).length,
55
+ totalThemeEntities: 1,
56
+ totalThemeRoutes: 1,
57
+ themes: Object.keys(THEME_REGISTRY),
58
+ }
59
+
60
+ // Helper function for getting active theme
61
+ export function getActiveTheme(): ThemeRegistryEntry | undefined {
62
+ return THEME_REGISTRY[THEME_METADATA.activeTheme]
63
+ }
64
+
65
+ // Helper function for getting theme by name
66
+ export function getTheme(name: string): ThemeRegistryEntry | undefined {
67
+ return THEME_REGISTRY[name]
68
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Mock for next/image
3
+ */
4
+ const React = require('react')
5
+
6
+ const Image = ({ src, alt, ...props }) => {
7
+ return React.createElement('img', {
8
+ src: typeof src === 'object' ? src.src : src,
9
+ alt: alt || '',
10
+ ...props,
11
+ })
12
+ }
13
+
14
+ module.exports = Image
15
+ module.exports.default = Image
@@ -27,9 +27,18 @@ const projectRoot = isNpmMode ? npmModeRoot : monorepoAppRoot
27
27
  // Module name mapper based on mode
28
28
  const moduleNameMapper = isNpmMode
29
29
  ? {
30
- // NPM mode: resolve from node_modules
31
- '^@nextsparkjs/core/(.*)$': '@nextsparkjs/core/$1',
32
- '^@nextsparkjs/core$': '@nextsparkjs/core',
30
+ // NPM mode: Mock core UI components (ESM can't be transformed by Jest)
31
+ '^@nextsparkjs/core/components/ui/badge$': path.join(themeTestsRoot, '__mocks__/@nextsparkjs/core/components/ui/badge.js'),
32
+ // NPM mode: Mock core lib modules that are ESM
33
+ '^@nextsparkjs/core/lib/db$': path.join(themeTestsRoot, '__mocks__/@nextsparkjs/core/lib/db.js'),
34
+ // NPM mode: explicitly resolve @nextsparkjs/core subpaths to dist directory
35
+ // Jest doesn't respect package.json exports, so we map directly to dist files
36
+ '^@nextsparkjs/core/lib/(.*)$': '<rootDir>/node_modules/@nextsparkjs/core/dist/lib/$1',
37
+ '^@nextsparkjs/core/hooks/(.*)$': '<rootDir>/node_modules/@nextsparkjs/core/dist/hooks/$1',
38
+ '^@nextsparkjs/core/components/(.*)$': '<rootDir>/node_modules/@nextsparkjs/core/dist/components/$1',
39
+ '^@nextsparkjs/core/(.*)$': '<rootDir>/node_modules/@nextsparkjs/core/dist/$1',
40
+ '^@nextsparkjs/core$': '<rootDir>/node_modules/@nextsparkjs/core/dist/index.js',
41
+ '^@nextsparkjs/registries/(.*)$': path.join(themeTestsRoot, '__mocks__/@nextsparkjs/registries/$1'),
33
42
  '^@/contents/(.*)$': '<rootDir>/contents/$1',
34
43
  '^@/entities/(.*)$': '<rootDir>/contents/entities/$1',
35
44
  '^@/plugins/(.*)$': '<rootDir>/contents/plugins/$1',
@@ -37,6 +46,7 @@ const moduleNameMapper = isNpmMode
37
46
  '^@/(.*)$': '<rootDir>/$1',
38
47
  // Mocks from theme-local folder
39
48
  'next/server': path.join(themeTestsRoot, '__mocks__/next-server.js'),
49
+ 'next/image': path.join(themeTestsRoot, '__mocks__/next/image.js'),
40
50
  '^jose$': path.join(themeTestsRoot, '__mocks__/jose.js'),
41
51
  '^jose/(.*)$': path.join(themeTestsRoot, '__mocks__/jose.js'),
42
52
  }
@@ -44,6 +54,7 @@ const moduleNameMapper = isNpmMode
44
54
  // Monorepo mode: resolve from packages/core/src (rootDir is apps/dev)
45
55
  '^@nextsparkjs/core/(.*)$': '<rootDir>/../../packages/core/src/$1',
46
56
  '^@nextsparkjs/core$': '<rootDir>/../../packages/core/src',
57
+ '^@nextsparkjs/registries/(.*)$': '<rootDir>/../../packages/core/tests/jest/__mocks__/@nextsparkjs/registries/$1',
47
58
  '^@/contents/(.*)$': '<rootDir>/contents/$1',
48
59
  '^@/entities/(.*)$': '<rootDir>/contents/entities/$1',
49
60
  '^@/plugins/(.*)$': '<rootDir>/contents/plugins/$1',
@@ -96,7 +107,7 @@ module.exports = {
96
107
  // Transform configuration
97
108
  transform: {
98
109
  '^.+\\.(ts|tsx)$': ['ts-jest', {
99
- tsconfig: path.join(projectRoot, 'tsconfig.json'),
110
+ tsconfig: path.join(themeTestsRoot, 'tsconfig.jest.json'),
100
111
  }],
101
112
  },
102
113
 
@@ -127,7 +127,8 @@ describe('Streaming Service', () => {
127
127
  const chunk: StreamChunk = { type: 'token', content: 'test' }
128
128
  const result = encoder.encode(chunk)
129
129
 
130
- expect(result).toBeInstanceOf(Uint8Array)
130
+ // Use constructor name check to avoid jsdom cross-realm issues
131
+ expect(result.constructor.name).toBe('Uint8Array')
131
132
  })
132
133
  })
133
134
 
@@ -142,7 +143,8 @@ describe('Streaming Service', () => {
142
143
  it('should return Uint8Array', () => {
143
144
  const result = encoder.encodeDone()
144
145
 
145
- expect(result).toBeInstanceOf(Uint8Array)
146
+ // Use constructor name check to avoid jsdom cross-realm issues
147
+ expect(result.constructor.name).toBe('Uint8Array')
146
148
  })
147
149
  })
148
150
  })
@@ -360,7 +362,8 @@ describe('Streaming Service', () => {
360
362
 
361
363
  expect(results).toHaveLength(100)
362
364
  results.forEach(result => {
363
- expect(result).toBeInstanceOf(Uint8Array)
365
+ // Use constructor name check to avoid jsdom cross-realm issues
366
+ expect(result.constructor.name).toBe('Uint8Array')
364
367
  })
365
368
  })
366
369
  })
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "../../../../apps/dev/tsconfig.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx"
5
+ }
6
+ }
@@ -1,529 +0,0 @@
1
- /**
2
- * Unit Tests - Role Configuration (app.config.ts)
3
- *
4
- * Tests role configuration for Developer Area feature:
5
- * - Developer role in availableRoles array
6
- * - Developer hierarchy value (100, highest)
7
- * - Developer displayName translation key
8
- * - Developer description
9
- * - Configuration completeness
10
- *
11
- * Focus on developer role configuration validation.
12
- */
13
-
14
- import { DEFAULT_APP_CONFIG } from '@nextsparkjs/core/lib/config/app.config'
15
-
16
- describe('Role Configuration - Developer Role', () => {
17
- describe('availableRoles Array', () => {
18
- it('should include developer role', () => {
19
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
20
-
21
- expect(roles).toContain('developer')
22
- })
23
-
24
- it('should include superadmin role', () => {
25
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
26
-
27
- expect(roles).toContain('superadmin')
28
- })
29
-
30
- it('should include member role', () => {
31
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
32
-
33
- expect(roles).toContain('member')
34
- })
35
-
36
- it('should have exactly 3 roles', () => {
37
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
38
-
39
- expect(roles.length).toBe(3)
40
- })
41
-
42
- it('should have roles in correct order', () => {
43
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
44
-
45
- expect(roles).toEqual(['member', 'superadmin', 'developer'])
46
- })
47
-
48
- it('should have all roles as strings', () => {
49
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
50
-
51
- roles.forEach(role => {
52
- expect(typeof role).toBe('string')
53
- })
54
- })
55
-
56
- it('should have all roles in lowercase', () => {
57
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
58
-
59
- roles.forEach(role => {
60
- expect(role).toBe(role.toLowerCase())
61
- })
62
- })
63
-
64
- it('should not have duplicate roles', () => {
65
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
66
- const uniqueRoles = new Set(roles)
67
-
68
- expect(uniqueRoles.size).toBe(roles.length)
69
- })
70
- })
71
-
72
- describe('Role Hierarchy', () => {
73
- it('should have developer at level 100', () => {
74
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
75
-
76
- expect(hierarchy.developer).toBe(100)
77
- })
78
-
79
- it('should have superadmin at level 99', () => {
80
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
81
-
82
- expect(hierarchy.superadmin).toBe(99)
83
- })
84
-
85
- it('should have member at level 1', () => {
86
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
87
-
88
- expect(hierarchy.member).toBe(1)
89
- })
90
-
91
- it('should have developer as highest hierarchy', () => {
92
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
93
-
94
- expect(hierarchy.developer).toBeGreaterThan(hierarchy.superadmin)
95
- expect(hierarchy.developer).toBeGreaterThan(hierarchy.member)
96
- })
97
-
98
- it('should have superadmin higher than member', () => {
99
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
100
-
101
- expect(hierarchy.superadmin).toBeGreaterThan(hierarchy.member)
102
- })
103
-
104
- it('should have all hierarchy values as numbers', () => {
105
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
106
-
107
- expect(typeof hierarchy.developer).toBe('number')
108
- expect(typeof hierarchy.superadmin).toBe('number')
109
- expect(typeof hierarchy.member).toBe('number')
110
- })
111
-
112
- it('should have all hierarchy values as positive integers', () => {
113
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
114
-
115
- expect(hierarchy.developer).toBeGreaterThan(0)
116
- expect(hierarchy.superadmin).toBeGreaterThan(0)
117
- expect(hierarchy.member).toBeGreaterThan(0)
118
-
119
- expect(Number.isInteger(hierarchy.developer)).toBe(true)
120
- expect(Number.isInteger(hierarchy.superadmin)).toBe(true)
121
- expect(Number.isInteger(hierarchy.member)).toBe(true)
122
- })
123
-
124
- it('should have correct hierarchy gap between developer and superadmin', () => {
125
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
126
-
127
- // Developer (100) should be 1 level above superadmin (99)
128
- expect(hierarchy.developer - hierarchy.superadmin).toBe(1)
129
- })
130
-
131
- it('should have large gap between superadmin and member', () => {
132
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
133
-
134
- // Large gap indicates future extensibility
135
- expect(hierarchy.superadmin - hierarchy.member).toBeGreaterThan(50)
136
- })
137
-
138
- it('should have hierarchy keys matching availableRoles', () => {
139
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
140
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
141
-
142
- roles.forEach(role => {
143
- expect(hierarchy[role as keyof typeof hierarchy]).toBeDefined()
144
- expect(typeof hierarchy[role as keyof typeof hierarchy]).toBe('number')
145
- })
146
- })
147
- })
148
-
149
- describe('Display Names (Translation Keys)', () => {
150
- it('should have translation key for developer role', () => {
151
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
152
-
153
- expect(displayNames.developer).toBe('common.userRoles.developer')
154
- })
155
-
156
- it('should have translation key for superadmin role', () => {
157
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
158
-
159
- expect(displayNames.superadmin).toBe('common.userRoles.superadmin')
160
- })
161
-
162
- it('should have translation key for member role', () => {
163
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
164
-
165
- expect(displayNames.member).toBe('common.userRoles.member')
166
- })
167
-
168
- it('should have translation keys in correct format', () => {
169
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
170
-
171
- Object.values(displayNames).forEach(key => {
172
- expect(key).toMatch(/^common\.userRoles\.\w+$/)
173
- })
174
- })
175
-
176
- it('should have translation keys for all available roles', () => {
177
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
178
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
179
-
180
- roles.forEach(role => {
181
- expect(displayNames[role as keyof typeof displayNames]).toBeDefined()
182
- expect(displayNames[role as keyof typeof displayNames]).toContain('common.userRoles.')
183
- })
184
- })
185
-
186
- it('should use common namespace for all role names', () => {
187
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
188
-
189
- Object.values(displayNames).forEach(key => {
190
- expect(key).toMatch(/^common\./)
191
- })
192
- })
193
- })
194
-
195
- describe('Role Descriptions', () => {
196
- it('should have description for developer role', () => {
197
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
198
-
199
- expect(descriptions.developer).toBe('Ultimate access (platform developers only)')
200
- })
201
-
202
- it('should have description for superadmin role', () => {
203
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
204
-
205
- expect(descriptions.superadmin).toBe('Full system access (product owners only)')
206
- })
207
-
208
- it('should have description for member role', () => {
209
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
210
-
211
- expect(descriptions.member).toBe('Regular user with team-based permissions')
212
- })
213
-
214
- it('should have descriptions as non-empty strings', () => {
215
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
216
-
217
- Object.values(descriptions).forEach(description => {
218
- expect(typeof description).toBe('string')
219
- expect(description.length).toBeGreaterThan(0)
220
- })
221
- })
222
-
223
- it('should have descriptions for all available roles', () => {
224
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
225
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
226
-
227
- roles.forEach(role => {
228
- expect(descriptions[role as keyof typeof descriptions]).toBeDefined()
229
- expect(descriptions[role as keyof typeof descriptions].length).toBeGreaterThan(0)
230
- })
231
- })
232
-
233
- it('should have developer description indicating highest access', () => {
234
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
235
-
236
- expect(descriptions.developer.toLowerCase()).toContain('ultimate')
237
- })
238
-
239
- it('should have developer description indicating platform developer usage', () => {
240
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
241
-
242
- expect(descriptions.developer.toLowerCase()).toContain('developer')
243
- })
244
-
245
- it('should have superadmin description indicating product owner usage', () => {
246
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
247
-
248
- expect(descriptions.superadmin.toLowerCase()).toContain('owner')
249
- })
250
- })
251
-
252
- describe('Default Role', () => {
253
- it('should have member as default role', () => {
254
- const defaultRole = DEFAULT_APP_CONFIG.userRoles.defaultRole
255
-
256
- expect(defaultRole).toBe('member')
257
- })
258
-
259
- it('should have default role in availableRoles', () => {
260
- const defaultRole = DEFAULT_APP_CONFIG.userRoles.defaultRole
261
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
262
-
263
- expect(roles).toContain(defaultRole)
264
- })
265
-
266
- it('should not have developer as default role', () => {
267
- const defaultRole = DEFAULT_APP_CONFIG.userRoles.defaultRole
268
-
269
- expect(defaultRole).not.toBe('developer')
270
- })
271
-
272
- it('should not have superadmin as default role', () => {
273
- const defaultRole = DEFAULT_APP_CONFIG.userRoles.defaultRole
274
-
275
- expect(defaultRole).not.toBe('superadmin')
276
- })
277
- })
278
-
279
- describe('Configuration Completeness', () => {
280
- it('should have all roles in hierarchy map', () => {
281
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
282
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
283
-
284
- roles.forEach(role => {
285
- expect(hierarchy[role as keyof typeof hierarchy]).toBeDefined()
286
- })
287
- })
288
-
289
- it('should have all roles in displayNames map', () => {
290
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
291
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
292
-
293
- roles.forEach(role => {
294
- expect(displayNames[role as keyof typeof displayNames]).toBeDefined()
295
- })
296
- })
297
-
298
- it('should have all roles in descriptions map', () => {
299
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
300
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
301
-
302
- roles.forEach(role => {
303
- expect(descriptions[role as keyof typeof descriptions]).toBeDefined()
304
- })
305
- })
306
-
307
- it('should have no extra keys in hierarchy map', () => {
308
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
309
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
310
-
311
- const hierarchyKeys = Object.keys(hierarchy)
312
-
313
- expect(hierarchyKeys.length).toBe(roles.length)
314
- })
315
-
316
- it('should have no extra keys in displayNames map', () => {
317
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
318
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
319
-
320
- const displayNameKeys = Object.keys(displayNames)
321
-
322
- expect(displayNameKeys.length).toBe(roles.length)
323
- })
324
-
325
- it('should have no extra keys in descriptions map', () => {
326
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
327
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
328
-
329
- const descriptionKeys = Object.keys(descriptions)
330
-
331
- expect(descriptionKeys.length).toBe(roles.length)
332
- })
333
- })
334
- })
335
-
336
- describe('Role Configuration - Backwards Compatibility', () => {
337
- describe('Existing Roles Preserved', () => {
338
- it('should still have member role (Phase 1)', () => {
339
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
340
-
341
- expect(roles).toContain('member')
342
- })
343
-
344
- it('should still have superadmin role (Phase 2)', () => {
345
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
346
-
347
- expect(roles).toContain('superadmin')
348
- })
349
-
350
- it('should preserve member hierarchy value', () => {
351
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
352
-
353
- expect(hierarchy.member).toBe(1)
354
- })
355
-
356
- it('should preserve superadmin hierarchy value', () => {
357
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
358
-
359
- expect(hierarchy.superadmin).toBe(99)
360
- })
361
-
362
- it('should preserve default role as member', () => {
363
- const defaultRole = DEFAULT_APP_CONFIG.userRoles.defaultRole
364
-
365
- expect(defaultRole).toBe('member')
366
- })
367
- })
368
-
369
- describe('New Role Addition (Phase 3)', () => {
370
- it('should add developer role without breaking existing config', () => {
371
- const config = DEFAULT_APP_CONFIG.userRoles
372
-
373
- // All Phase 1-2 features still work
374
- expect(config.defaultRole).toBe('member')
375
- expect(config.availableRoles).toContain('member')
376
- expect(config.availableRoles).toContain('superadmin')
377
-
378
- // Phase 3 addition
379
- expect(config.availableRoles).toContain('developer')
380
- })
381
-
382
- it('should have developer hierarchy higher than existing roles', () => {
383
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
384
-
385
- expect(hierarchy.developer).toBeGreaterThan(hierarchy.superadmin)
386
- expect(hierarchy.developer).toBeGreaterThan(hierarchy.member)
387
- })
388
-
389
- it('should not affect superadmin hierarchy relative to member', () => {
390
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
391
-
392
- expect(hierarchy.superadmin).toBeGreaterThan(hierarchy.member)
393
- })
394
- })
395
- })
396
-
397
- describe('Role Configuration - Edge Cases', () => {
398
- describe('Type Safety', () => {
399
- it('should have userRoles as an object', () => {
400
- expect(typeof DEFAULT_APP_CONFIG.userRoles).toBe('object')
401
- expect(DEFAULT_APP_CONFIG.userRoles).not.toBeNull()
402
- })
403
-
404
- it('should have availableRoles as readonly array', () => {
405
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
406
-
407
- expect(Array.isArray(roles)).toBe(true)
408
- })
409
-
410
- it('should have hierarchy as object with string keys', () => {
411
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
412
-
413
- expect(typeof hierarchy).toBe('object')
414
- Object.keys(hierarchy).forEach(key => {
415
- expect(typeof key).toBe('string')
416
- })
417
- })
418
- })
419
-
420
- describe('Invalid Data Protection', () => {
421
- it('should not have empty string roles', () => {
422
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
423
-
424
- roles.forEach(role => {
425
- expect(role.length).toBeGreaterThan(0)
426
- })
427
- })
428
-
429
- it('should not have negative hierarchy values', () => {
430
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
431
-
432
- Object.values(hierarchy).forEach(value => {
433
- expect(value).toBeGreaterThan(0)
434
- })
435
- })
436
-
437
- it('should not have hierarchy values as floats', () => {
438
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
439
-
440
- Object.values(hierarchy).forEach(value => {
441
- expect(Number.isInteger(value)).toBe(true)
442
- })
443
- })
444
-
445
- it('should not have empty translation keys', () => {
446
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
447
-
448
- Object.values(displayNames).forEach(key => {
449
- expect(key.length).toBeGreaterThan(0)
450
- })
451
- })
452
-
453
- it('should not have empty descriptions', () => {
454
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
455
-
456
- Object.values(descriptions).forEach(description => {
457
- expect(description.length).toBeGreaterThan(0)
458
- })
459
- })
460
- })
461
- })
462
-
463
- describe('Real-World Configuration Usage', () => {
464
- describe('Guard Implementation Support', () => {
465
- it('should support DeveloperGuard role check', () => {
466
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
467
-
468
- // DeveloperGuard checks if role === 'developer'
469
- expect(roles).toContain('developer')
470
- })
471
-
472
- it('should support SuperAdminGuard dual role check', () => {
473
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
474
-
475
- // SuperAdminGuard allows both superadmin and developer
476
- expect(roles).toContain('superadmin')
477
- expect(roles).toContain('developer')
478
- })
479
-
480
- it('should support middleware role validation', () => {
481
- const hierarchy = DEFAULT_APP_CONFIG.userRoles.hierarchy
482
-
483
- // Middleware compares hierarchy levels
484
- expect(hierarchy.developer).toBeDefined()
485
- expect(hierarchy.superadmin).toBeDefined()
486
- expect(hierarchy.member).toBeDefined()
487
- })
488
- })
489
-
490
- describe('UI Display Support', () => {
491
- it('should provide translation keys for role selection dropdown', () => {
492
- const displayNames = DEFAULT_APP_CONFIG.userRoles.displayNames
493
-
494
- const roles = ['developer', 'superadmin', 'member'] as const
495
-
496
- roles.forEach(role => {
497
- expect(displayNames[role]).toMatch(/^common\.userRoles\.\w+$/)
498
- })
499
- })
500
-
501
- it('should provide descriptions for role info tooltips', () => {
502
- const descriptions = DEFAULT_APP_CONFIG.userRoles.descriptions
503
-
504
- const roles = ['developer', 'superadmin', 'member'] as const
505
-
506
- roles.forEach(role => {
507
- expect(descriptions[role].length).toBeGreaterThan(10) // Meaningful description
508
- })
509
- })
510
- })
511
-
512
- describe('Database Schema Support', () => {
513
- it('should have role values compatible with database enum', () => {
514
- const roles = DEFAULT_APP_CONFIG.userRoles.availableRoles
515
-
516
- // Database enum values should be lowercase strings
517
- roles.forEach(role => {
518
- expect(role).toMatch(/^[a-z]+$/)
519
- })
520
- })
521
-
522
- it('should have default role for user creation', () => {
523
- const defaultRole = DEFAULT_APP_CONFIG.userRoles.defaultRole
524
-
525
- expect(defaultRole).toBe('member')
526
- expect(DEFAULT_APP_CONFIG.userRoles.availableRoles).toContain(defaultRole)
527
- })
528
- })
529
- })
@@ -1,432 +0,0 @@
1
- /**
2
- * Unit Tests - User Role Helper Functions
3
- *
4
- * Tests role helper functions for Developer Area feature:
5
- * - isDeveloper(): Check if user is developer
6
- * - canAccessAdmin(): Check if user has Sector7 access
7
- * - hasRoleLevel(): Hierarchy comparison with developer role
8
- * - getAllRolesByHierarchy(): Verify developer is first (highest)
9
- *
10
- * Focus on developer role integration with existing role system.
11
- */
12
-
13
- import { roleHelpers, USER_ROLES, ROLE_HIERARCHY, type UserRole } from '@nextsparkjs/core/types/user.types'
14
-
15
- describe('User Role Helpers - Developer Role Integration', () => {
16
- describe('isDeveloper()', () => {
17
- it('should return true for developer role', () => {
18
- const result = roleHelpers.isDeveloper(USER_ROLES.DEVELOPER)
19
- expect(result).toBe(true)
20
- })
21
-
22
- it('should return false for superadmin role', () => {
23
- const result = roleHelpers.isDeveloper(USER_ROLES.SUPERADMIN)
24
- expect(result).toBe(false)
25
- })
26
-
27
- it('should return false for member role', () => {
28
- const result = roleHelpers.isDeveloper(USER_ROLES.MEMBER)
29
- expect(result).toBe(false)
30
- })
31
-
32
- it('should handle string literal "developer"', () => {
33
- const result = roleHelpers.isDeveloper('developer' as UserRole)
34
- expect(result).toBe(true)
35
- })
36
-
37
- it('should handle case-sensitive comparison', () => {
38
- // Should fail because role names are lowercase
39
- const result = roleHelpers.isDeveloper('Developer' as UserRole)
40
- expect(result).toBe(false)
41
- })
42
- })
43
-
44
- describe('canAccessAdmin()', () => {
45
- it('should return true for developer role', () => {
46
- const result = roleHelpers.canAccessAdmin(USER_ROLES.DEVELOPER)
47
- expect(result).toBe(true)
48
- })
49
-
50
- it('should return true for superadmin role', () => {
51
- const result = roleHelpers.canAccessAdmin(USER_ROLES.SUPERADMIN)
52
- expect(result).toBe(true)
53
- })
54
-
55
- it('should return false for member role', () => {
56
- const result = roleHelpers.canAccessAdmin(USER_ROLES.MEMBER)
57
- expect(result).toBe(false)
58
- })
59
-
60
- it('should handle string literal "developer"', () => {
61
- const result = roleHelpers.canAccessAdmin('developer' as UserRole)
62
- expect(result).toBe(true)
63
- })
64
-
65
- it('should handle string literal "superadmin"', () => {
66
- const result = roleHelpers.canAccessAdmin('superadmin' as UserRole)
67
- expect(result).toBe(true)
68
- })
69
-
70
- it('should handle both privileged roles', () => {
71
- // Verify both roles have access (dual access pattern)
72
- const developerAccess = roleHelpers.canAccessAdmin(USER_ROLES.DEVELOPER)
73
- const superadminAccess = roleHelpers.canAccessAdmin(USER_ROLES.SUPERADMIN)
74
-
75
- expect(developerAccess).toBe(true)
76
- expect(superadminAccess).toBe(true)
77
- })
78
- })
79
-
80
- describe('isSuperAdmin()', () => {
81
- it('should return true for superadmin role', () => {
82
- const result = roleHelpers.isSuperAdmin(USER_ROLES.SUPERADMIN)
83
- expect(result).toBe(true)
84
- })
85
-
86
- it('should return false for developer role', () => {
87
- // Developer is NOT superadmin (separate role)
88
- const result = roleHelpers.isSuperAdmin(USER_ROLES.DEVELOPER)
89
- expect(result).toBe(false)
90
- })
91
-
92
- it('should return false for member role', () => {
93
- const result = roleHelpers.isSuperAdmin(USER_ROLES.MEMBER)
94
- expect(result).toBe(false)
95
- })
96
- })
97
-
98
- describe('hasRoleLevel() - Developer Hierarchy', () => {
99
- it('should confirm developer has higher level than superadmin', () => {
100
- const result = roleHelpers.hasRoleLevel(USER_ROLES.DEVELOPER, USER_ROLES.SUPERADMIN)
101
- expect(result).toBe(true)
102
- })
103
-
104
- it('should confirm developer has higher level than member', () => {
105
- const result = roleHelpers.hasRoleLevel(USER_ROLES.DEVELOPER, USER_ROLES.MEMBER)
106
- expect(result).toBe(true)
107
- })
108
-
109
- it('should confirm superadmin does NOT have developer level', () => {
110
- const result = roleHelpers.hasRoleLevel(USER_ROLES.SUPERADMIN, USER_ROLES.DEVELOPER)
111
- expect(result).toBe(false)
112
- })
113
-
114
- it('should confirm member does NOT have developer level', () => {
115
- const result = roleHelpers.hasRoleLevel(USER_ROLES.MEMBER, USER_ROLES.DEVELOPER)
116
- expect(result).toBe(false)
117
- })
118
-
119
- it('should confirm developer equals developer level', () => {
120
- const result = roleHelpers.hasRoleLevel(USER_ROLES.DEVELOPER, USER_ROLES.DEVELOPER)
121
- expect(result).toBe(true)
122
- })
123
-
124
- it('should confirm superadmin has superadmin level', () => {
125
- const result = roleHelpers.hasRoleLevel(USER_ROLES.SUPERADMIN, USER_ROLES.SUPERADMIN)
126
- expect(result).toBe(true)
127
- })
128
-
129
- it('should confirm superadmin has higher level than member', () => {
130
- const result = roleHelpers.hasRoleLevel(USER_ROLES.SUPERADMIN, USER_ROLES.MEMBER)
131
- expect(result).toBe(true)
132
- })
133
-
134
- it('should confirm member does NOT have superadmin level', () => {
135
- const result = roleHelpers.hasRoleLevel(USER_ROLES.MEMBER, USER_ROLES.SUPERADMIN)
136
- expect(result).toBe(false)
137
- })
138
- })
139
-
140
- describe('getAllRolesByHierarchy() - Developer First', () => {
141
- it('should return developer as first role (highest hierarchy)', () => {
142
- const roles = roleHelpers.getAllRolesByHierarchy()
143
-
144
- expect(roles[0]).toBe(USER_ROLES.DEVELOPER)
145
- })
146
-
147
- it('should return superadmin as second role', () => {
148
- const roles = roleHelpers.getAllRolesByHierarchy()
149
-
150
- expect(roles[1]).toBe(USER_ROLES.SUPERADMIN)
151
- })
152
-
153
- it('should return member as last role (lowest hierarchy)', () => {
154
- const roles = roleHelpers.getAllRolesByHierarchy()
155
-
156
- expect(roles[roles.length - 1]).toBe(USER_ROLES.MEMBER)
157
- })
158
-
159
- it('should return all roles in descending hierarchy order', () => {
160
- const roles = roleHelpers.getAllRolesByHierarchy()
161
-
162
- expect(roles).toEqual([
163
- USER_ROLES.DEVELOPER, // 100
164
- USER_ROLES.SUPERADMIN, // 99
165
- USER_ROLES.MEMBER // 1
166
- ])
167
- })
168
-
169
- it('should return array with correct length', () => {
170
- const roles = roleHelpers.getAllRolesByHierarchy()
171
-
172
- expect(roles.length).toBe(3)
173
- })
174
-
175
- it('should not mutate original roles array', () => {
176
- const roles1 = roleHelpers.getAllRolesByHierarchy()
177
- const roles2 = roleHelpers.getAllRolesByHierarchy()
178
-
179
- expect(roles1).toEqual(roles2)
180
- expect(roles1).not.toBe(roles2) // Different array instances
181
- })
182
- })
183
-
184
- describe('getRoleDisplayKey()', () => {
185
- it('should return translation key for developer role', () => {
186
- const key = roleHelpers.getRoleDisplayKey(USER_ROLES.DEVELOPER)
187
-
188
- expect(key).toBe('common.userRoles.developer')
189
- })
190
-
191
- it('should return translation key for superadmin role', () => {
192
- const key = roleHelpers.getRoleDisplayKey(USER_ROLES.SUPERADMIN)
193
-
194
- expect(key).toBe('common.userRoles.superadmin')
195
- })
196
-
197
- it('should return translation key for member role', () => {
198
- const key = roleHelpers.getRoleDisplayKey(USER_ROLES.MEMBER)
199
-
200
- expect(key).toBe('common.userRoles.member')
201
- })
202
- })
203
- })
204
-
205
- describe('Role Hierarchy Configuration', () => {
206
- describe('ROLE_HIERARCHY Values', () => {
207
- it('should have developer at hierarchy level 100', () => {
208
- expect(ROLE_HIERARCHY.developer).toBe(100)
209
- })
210
-
211
- it('should have superadmin at hierarchy level 99', () => {
212
- expect(ROLE_HIERARCHY.superadmin).toBe(99)
213
- })
214
-
215
- it('should have member at hierarchy level 1', () => {
216
- expect(ROLE_HIERARCHY.member).toBe(1)
217
- })
218
-
219
- it('should have developer as highest hierarchy', () => {
220
- const developerLevel = ROLE_HIERARCHY.developer
221
- const superadminLevel = ROLE_HIERARCHY.superadmin
222
- const memberLevel = ROLE_HIERARCHY.member
223
-
224
- expect(developerLevel).toBeGreaterThan(superadminLevel)
225
- expect(developerLevel).toBeGreaterThan(memberLevel)
226
- })
227
-
228
- it('should have superadmin higher than member', () => {
229
- const superadminLevel = ROLE_HIERARCHY.superadmin
230
- const memberLevel = ROLE_HIERARCHY.member
231
-
232
- expect(superadminLevel).toBeGreaterThan(memberLevel)
233
- })
234
-
235
- it('should have numeric values for all roles', () => {
236
- expect(typeof ROLE_HIERARCHY.developer).toBe('number')
237
- expect(typeof ROLE_HIERARCHY.superadmin).toBe('number')
238
- expect(typeof ROLE_HIERARCHY.member).toBe('number')
239
- })
240
-
241
- it('should have positive values for all roles', () => {
242
- expect(ROLE_HIERARCHY.developer).toBeGreaterThan(0)
243
- expect(ROLE_HIERARCHY.superadmin).toBeGreaterThan(0)
244
- expect(ROLE_HIERARCHY.member).toBeGreaterThan(0)
245
- })
246
-
247
- it('should maintain expected hierarchy gap', () => {
248
- // Developer (100) is 1 level above superadmin (99)
249
- expect(ROLE_HIERARCHY.developer - ROLE_HIERARCHY.superadmin).toBe(1)
250
-
251
- // Large gap between superadmin (99) and member (1)
252
- expect(ROLE_HIERARCHY.superadmin - ROLE_HIERARCHY.member).toBe(98)
253
- })
254
- })
255
-
256
- describe('USER_ROLES Constants', () => {
257
- it('should have DEVELOPER constant', () => {
258
- expect(USER_ROLES.DEVELOPER).toBe('developer')
259
- })
260
-
261
- it('should have SUPERADMIN constant', () => {
262
- expect(USER_ROLES.SUPERADMIN).toBe('superadmin')
263
- })
264
-
265
- it('should have MEMBER constant', () => {
266
- expect(USER_ROLES.MEMBER).toBe('member')
267
- })
268
-
269
- it('should have all constants as lowercase strings', () => {
270
- expect(USER_ROLES.DEVELOPER).toBe(USER_ROLES.DEVELOPER.toLowerCase())
271
- expect(USER_ROLES.SUPERADMIN).toBe(USER_ROLES.SUPERADMIN.toLowerCase())
272
- expect(USER_ROLES.MEMBER).toBe(USER_ROLES.MEMBER.toLowerCase())
273
- })
274
- })
275
- })
276
-
277
- describe('Edge Cases and Error Handling', () => {
278
- describe('hasRoleLevel() Edge Cases', () => {
279
- it('should handle null-like values gracefully', () => {
280
- // These would fail TypeScript compile-time but test runtime behavior
281
- const result = roleHelpers.hasRoleLevel(
282
- undefined as unknown as UserRole,
283
- USER_ROLES.MEMBER
284
- )
285
-
286
- expect(result).toBe(false)
287
- })
288
-
289
- it('should handle comparing same role multiple times', () => {
290
- const result1 = roleHelpers.hasRoleLevel(USER_ROLES.DEVELOPER, USER_ROLES.DEVELOPER)
291
- const result2 = roleHelpers.hasRoleLevel(USER_ROLES.DEVELOPER, USER_ROLES.DEVELOPER)
292
-
293
- expect(result1).toBe(result2)
294
- expect(result1).toBe(true)
295
- })
296
- })
297
-
298
- describe('isDeveloper() Edge Cases', () => {
299
- it('should handle whitespace in role name', () => {
300
- const result = roleHelpers.isDeveloper(' developer ' as UserRole)
301
- expect(result).toBe(false) // Exact match required
302
- })
303
-
304
- it('should handle empty string', () => {
305
- const result = roleHelpers.isDeveloper('' as UserRole)
306
- expect(result).toBe(false)
307
- })
308
- })
309
-
310
- describe('canAccessAdmin() Edge Cases', () => {
311
- it('should handle invalid role gracefully', () => {
312
- const result = roleHelpers.canAccessAdmin('invalid-role' as UserRole)
313
- expect(result).toBe(false)
314
- })
315
-
316
- it('should handle null-like value', () => {
317
- const result = roleHelpers.canAccessAdmin(null as unknown as UserRole)
318
- expect(result).toBe(false)
319
- })
320
-
321
- it('should handle undefined', () => {
322
- const result = roleHelpers.canAccessAdmin(undefined as unknown as UserRole)
323
- expect(result).toBe(false)
324
- })
325
- })
326
- })
327
-
328
- describe('Real-World Use Cases', () => {
329
- describe('Guard Logic Simulation', () => {
330
- it('should allow developer through DeveloperGuard', () => {
331
- const userRole: UserRole = 'developer'
332
- const canAccess = roleHelpers.isDeveloper(userRole)
333
-
334
- expect(canAccess).toBe(true)
335
- })
336
-
337
- it('should block superadmin from DeveloperGuard', () => {
338
- const userRole: UserRole = 'superadmin'
339
- const canAccess = roleHelpers.isDeveloper(userRole)
340
-
341
- expect(canAccess).toBe(false)
342
- })
343
-
344
- it('should block member from DeveloperGuard', () => {
345
- const userRole: UserRole = 'member'
346
- const canAccess = roleHelpers.isDeveloper(userRole)
347
-
348
- expect(canAccess).toBe(false)
349
- })
350
-
351
- it('should allow developer through SuperAdminGuard (Sector7)', () => {
352
- const userRole: UserRole = 'developer'
353
- const canAccess = roleHelpers.canAccessAdmin(userRole)
354
-
355
- expect(canAccess).toBe(true)
356
- })
357
-
358
- it('should allow superadmin through SuperAdminGuard (Sector7)', () => {
359
- const userRole: UserRole = 'superadmin'
360
- const canAccess = roleHelpers.canAccessAdmin(userRole)
361
-
362
- expect(canAccess).toBe(true)
363
- })
364
-
365
- it('should block member from SuperAdminGuard (Sector7)', () => {
366
- const userRole: UserRole = 'member'
367
- const canAccess = roleHelpers.canAccessAdmin(userRole)
368
-
369
- expect(canAccess).toBe(false)
370
- })
371
- })
372
-
373
- describe('Permission Checks', () => {
374
- it('should grant developer access to all areas', () => {
375
- const userRole: UserRole = 'developer'
376
-
377
- const devArea = roleHelpers.isDeveloper(userRole)
378
- const sector7 = roleHelpers.canAccessAdmin(userRole)
379
- const hasAdminLevel = roleHelpers.hasRoleLevel(userRole, USER_ROLES.SUPERADMIN)
380
-
381
- expect(devArea).toBe(true)
382
- expect(sector7).toBe(true)
383
- expect(hasAdminLevel).toBe(true)
384
- })
385
-
386
- it('should grant superadmin limited access (no /dev)', () => {
387
- const userRole: UserRole = 'superadmin'
388
-
389
- const devArea = roleHelpers.isDeveloper(userRole)
390
- const sector7 = roleHelpers.canAccessAdmin(userRole)
391
- const isSuperAdmin = roleHelpers.isSuperAdmin(userRole)
392
-
393
- expect(devArea).toBe(false) // Cannot access /dev
394
- expect(sector7).toBe(true) // Can access Sector7
395
- expect(isSuperAdmin).toBe(true)
396
- })
397
-
398
- it('should grant member minimal access', () => {
399
- const userRole: UserRole = 'member'
400
-
401
- const devArea = roleHelpers.isDeveloper(userRole)
402
- const sector7 = roleHelpers.canAccessAdmin(userRole)
403
- const isSuperAdmin = roleHelpers.isSuperAdmin(userRole)
404
-
405
- expect(devArea).toBe(false)
406
- expect(sector7).toBe(false)
407
- expect(isSuperAdmin).toBe(false)
408
- })
409
- })
410
-
411
- describe('Role Display in UI', () => {
412
- it('should provide translation keys for all roles', () => {
413
- const roles = roleHelpers.getAllRolesByHierarchy()
414
-
415
- roles.forEach(role => {
416
- const key = roleHelpers.getRoleDisplayKey(role)
417
- expect(key).toContain('common.userRoles.')
418
- })
419
- })
420
-
421
- it('should list roles in correct order for admin UI', () => {
422
- const roles = roleHelpers.getAllRolesByHierarchy()
423
-
424
- // Admin UI should show roles from most powerful to least
425
- expect(roles).toEqual([
426
- 'developer',
427
- 'superadmin',
428
- 'member'
429
- ])
430
- })
431
- })
432
- })