test(frontend) : RBAC #345 - vitest setup + usePermissions unit tests
This commit is contained in:
2503
frontend/package-lock.json
generated
2503
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,9 @@
|
|||||||
"postinstall": "nuxt prepare",
|
"postinstall": "nuxt prepare",
|
||||||
"build:dist": "nuxt generate && rm -rf dist && cp -R .output/public dist",
|
"build:dist": "nuxt generate && rm -rf dist && cp -R .output/public dist",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint . --fix"
|
"lint:fix": "eslint . --fix",
|
||||||
|
"test": "vitest run",
|
||||||
|
"test:watch": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@malio/layer-ui": "^1.2.3",
|
"@malio/layer-ui": "^1.2.3",
|
||||||
@@ -28,8 +30,11 @@
|
|||||||
"@nuxt/eslint-config": "^1.9.0",
|
"@nuxt/eslint-config": "^1.9.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.44.1",
|
"@typescript-eslint/eslint-plugin": "^8.44.1",
|
||||||
"@typescript-eslint/parser": "^8.44.1",
|
"@typescript-eslint/parser": "^8.44.1",
|
||||||
|
"@vue/test-utils": "^2.4.6",
|
||||||
"eslint": "^9.36.0",
|
"eslint": "^9.36.0",
|
||||||
"eslint-plugin-vue": "^10.5.0",
|
"eslint-plugin-vue": "^10.5.0",
|
||||||
|
"happy-dom": "^20.9.0",
|
||||||
|
"vitest": "^4.1.4",
|
||||||
"vue-eslint-parser": "^10.2.0"
|
"vue-eslint-parser": "^10.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
frontend/shared/composables/__tests__/usePermissions.test.ts
Normal file
65
frontend/shared/composables/__tests__/usePermissions.test.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||||
|
import { usePermissions } from '../usePermissions'
|
||||||
|
|
||||||
|
// Mock du store auth : le composable ne depend que de auth.user.
|
||||||
|
const mockUser = vi.hoisted(() => ({
|
||||||
|
value: null as { isAdmin: boolean; effectivePermissions: string[] } | null,
|
||||||
|
}))
|
||||||
|
|
||||||
|
vi.mock('~/shared/stores/auth', () => ({
|
||||||
|
useAuthStore: () => ({
|
||||||
|
get user() {
|
||||||
|
return mockUser.value
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('usePermissions', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockUser.value = null
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuse toute permission quand aucun utilisateur n\'est connecte', () => {
|
||||||
|
const { can, canAny, canAll } = usePermissions()
|
||||||
|
expect(can('core.users.view')).toBe(false)
|
||||||
|
expect(canAny(['core.users.view', 'core.roles.view'])).toBe(false)
|
||||||
|
expect(canAll(['core.users.view'])).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('accorde toutes les permissions a un admin via le bypass', () => {
|
||||||
|
mockUser.value = { isAdmin: true, effectivePermissions: [] }
|
||||||
|
const { can, canAll } = usePermissions()
|
||||||
|
expect(can('core.users.view')).toBe(true)
|
||||||
|
expect(can('module.inexistante.action')).toBe(true)
|
||||||
|
expect(canAll(['a.b.c', 'd.e.f'])).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('accorde une permission presente dans effectivePermissions', () => {
|
||||||
|
mockUser.value = { isAdmin: false, effectivePermissions: ['core.users.view'] }
|
||||||
|
const { can } = usePermissions()
|
||||||
|
expect(can('core.users.view')).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuse une permission absente pour un non-admin', () => {
|
||||||
|
mockUser.value = { isAdmin: false, effectivePermissions: ['core.users.view'] }
|
||||||
|
const { can } = usePermissions()
|
||||||
|
expect(can('core.roles.manage')).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('canAny retourne true si au moins un code matche', () => {
|
||||||
|
mockUser.value = { isAdmin: false, effectivePermissions: ['core.users.view'] }
|
||||||
|
const { canAny } = usePermissions()
|
||||||
|
expect(canAny(['core.roles.manage', 'core.users.view'])).toBe(true)
|
||||||
|
expect(canAny(['core.roles.manage', 'core.permissions.view'])).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('canAll retourne true uniquement si tous les codes matchent', () => {
|
||||||
|
mockUser.value = {
|
||||||
|
isAdmin: false,
|
||||||
|
effectivePermissions: ['core.users.view', 'core.roles.view'],
|
||||||
|
}
|
||||||
|
const { canAll } = usePermissions()
|
||||||
|
expect(canAll(['core.users.view', 'core.roles.view'])).toBe(true)
|
||||||
|
expect(canAll(['core.users.view', 'core.roles.manage'])).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
15
frontend/vitest.config.ts
Normal file
15
frontend/vitest.config.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
environment: 'happy-dom',
|
||||||
|
globals: true,
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'~': fileURLToPath(new URL('./', import.meta.url)),
|
||||||
|
'@': fileURLToPath(new URL('./', import.meta.url)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user