create-mercato-app 0.4.6-develop-0c668dfcae → 0.4.6-develop-e10452e5ca

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": "create-mercato-app",
3
- "version": "0.4.6-develop-0c668dfcae",
3
+ "version": "0.4.6-develop-e10452e5ca",
4
4
  "type": "module",
5
5
  "description": "Create a new Open Mercato application",
6
6
  "main": "./dist/index.js",
@@ -1,108 +0,0 @@
1
- /**
2
- * Tests the backend catch-all route guarding for requireFeatures.
3
- */
4
- import React from 'react'
5
- import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
6
- // Avoid loading the full generated modules (which pull example modules and DSL)
7
- jest.mock('@/generated/modules.generated', () => ({ modules: [] }))
8
-
9
- import BackendCatchAll from '@/app/(backend)/backend/[...slug]/page'
10
-
11
- // Mock UI breadcrumb component to avoid UI package dependency
12
- jest.mock('@open-mercato/ui/backend/AppShell', () => ({
13
- ApplyBreadcrumb: () => React.createElement('div', null, 'Breadcrumb'),
14
- }))
15
-
16
- // Mock UI CrudForm to avoid importing ESM-only deps like remark-gfm in Jest
17
- jest.mock('@open-mercato/ui/backend/CrudForm', () => ({
18
- CrudForm: () => React.createElement('form', null, React.createElement('div', null, 'CrudFormMock')),
19
- }))
20
-
21
- const cookieStore = { get: jest.fn() }
22
- const cookiesMock = jest.fn(() => cookieStore)
23
- jest.mock('next/headers', () => ({
24
- cookies: () => cookiesMock(),
25
- }))
26
-
27
- // Mock registry to return a match with requireFeatures
28
- jest.mock('@open-mercato/shared/modules/registry', () => ({
29
- findBackendMatch: jest.fn(() => ({
30
- route: {
31
- requireAuth: true,
32
- requireRoles: [],
33
- requireFeatures: ['entities.records.view'],
34
- title: 'Test',
35
- Component: () => React.createElement('div', null, 'OK'),
36
- },
37
- params: {},
38
- })),
39
- }))
40
-
41
- // Mock auth cookie reader
42
- jest.mock('@open-mercato/shared/lib/auth/server', () => ({
43
- getAuthFromCookies: jest.fn(),
44
- }))
45
-
46
- // Mock DI container
47
- const mockRbac = {
48
- userHasAllFeatures: jest.fn<
49
- ReturnType<RbacService['userHasAllFeatures']>,
50
- Parameters<RbacService['userHasAllFeatures']>
51
- >()
52
- }
53
- jest.mock('@open-mercato/shared/lib/di/container', () => ({
54
- createRequestContainer: async () => ({
55
- resolve: (key: string) => (key === 'rbacService' ? mockRbac : null),
56
- }),
57
- }))
58
-
59
- // Mock next/navigation redirect and notFound
60
- const redirect = jest.fn((href?: string) => { throw new Error('REDIRECT ' + href) })
61
- const notFound = jest.fn(() => { throw new Error('NOT_FOUND') })
62
- jest.mock('next/navigation', () => ({
63
- redirect: (href?: string) => redirect(href),
64
- notFound: () => notFound(),
65
- }))
66
-
67
- type GetAuthFromCookies = typeof import('@open-mercato/shared/lib/auth/server')['getAuthFromCookies']
68
-
69
- async function setAuthMock(value: Awaited<ReturnType<GetAuthFromCookies>>) {
70
- const authModule = await import('@open-mercato/shared/lib/auth/server')
71
- const mocked = authModule.getAuthFromCookies as jest.MockedFunction<GetAuthFromCookies>
72
- mocked.mockResolvedValue(value)
73
- }
74
-
75
- describe('Backend requireFeatures guard', () => {
76
- beforeEach(() => {
77
- jest.clearAllMocks()
78
- mockRbac.userHasAllFeatures.mockResolvedValue(true)
79
- cookieStore.get.mockReset()
80
- cookieStore.get.mockReturnValue(undefined)
81
- cookiesMock.mockClear()
82
- })
83
-
84
- it('renders component when features are satisfied', async () => {
85
- await setAuthMock({ sub: 'u1', tenantId: 't1', orgId: 'o1', roles: [] })
86
-
87
- const el = await BackendCatchAll({ params: Promise.resolve({ slug: ['entities', 'records'] }) })
88
- expect(el).toBeTruthy()
89
- expect(redirect).not.toHaveBeenCalled()
90
- })
91
-
92
- it('redirects to refresh if not authenticated', async () => {
93
- await setAuthMock(null)
94
-
95
- await expect(
96
- BackendCatchAll({ params: Promise.resolve({ slug: ['entities', 'records'] }) })
97
- ).rejects.toThrow(/REDIRECT \/api\/auth\/session\/refresh/)
98
- })
99
-
100
- it('redirects to login when RBAC denies required features', async () => {
101
- await setAuthMock({ sub: 'u1', tenantId: 't1', orgId: 'o1', roles: [] })
102
- mockRbac.userHasAllFeatures.mockResolvedValueOnce(false)
103
-
104
- await expect(
105
- BackendCatchAll({ params: Promise.resolve({ slug: ['entities', 'records'] }) })
106
- ).rejects.toThrow(/REDIRECT \/login\?requireFeature=/)
107
- })
108
- })