-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: ✨ add environment and permissions management
feat: ✨ wip components for environment managing feat: 🚧 adding api implementation fix: 🐛 show permissionForm only when environment is created test: 🧪 add component tests feat: 👔 disable delete permission for owner fix: 🐛 use flatMap to iterate over two arrays fix: 🐛 flatMap didn't work as expected test: ✅ full e2e tests for environments and permissions refactor: 🧪 update createRandomDbSetup so it matches data.js format test: 🧪 fix permission-form ct test: ✅ update component test for permission fix: 👔 permission level goes from 0 to 3, 0 by default, 3 for owner test: 🧪 wip permission TU is failing test: 🧪 wip : skipping failing TU and CT test: 🧪 skip failing e2e test, SIGSEGV feat: ✨ add delete trigger for environment test: 🧪 failing to set ownerId in permission spec test: 🧪 try fixing ct and e2e tests feat: 👔 permissions should be enabled only for permitted users test: ✅ update component tests feat: 👔 cannot update nor delete permission if not permitted - controller side test: ✅ add test for getOwner route
- Loading branch information
1 parent
a5a5129
commit 3c76eac
Showing
43 changed files
with
1,271 additions
and
292 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
apps/client/cypress/components/specs/permission-form.ct.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import VueDsfr from '@gouvminint/vue-dsfr' | ||
import { createPinia } from 'pinia' | ||
import '@gouvminint/vue-dsfr/styles' | ||
import '@/main.css' | ||
import * as icons from '@/icons.js' | ||
import PermissionForm from '@/components/PermissionForm.vue' | ||
import { createRandomDbSetup, getRandomUser } from 'test-utils' | ||
import { useProjectStore } from '@/stores/project.js' | ||
import { useUserStore } from '@/stores/user.js' | ||
|
||
describe('PermissionForm.vue', () => { | ||
it('Should mount a PermissionForm', () => { | ||
const pinia = createPinia() | ||
|
||
const randomDbSetup = createRandomDbSetup({ nbUsers: 3, envs: ['dev'] }) | ||
const projectStore = useProjectStore(pinia) | ||
const userStore = useUserStore(pinia) | ||
|
||
projectStore.selectedProject = randomDbSetup.project | ||
projectStore.selectedProjectOwner = randomDbSetup.users[0] | ||
userStore.userProfile = randomDbSetup.users[1] | ||
|
||
const environment = projectStore.selectedProject.environments[0] | ||
const userToLicence = getRandomUser() | ||
randomDbSetup.project.users = [userToLicence, ...randomDbSetup.project.users] | ||
|
||
const props = { | ||
environment, | ||
} | ||
|
||
const extensions = { | ||
use: [ | ||
[ | ||
VueDsfr, { icons: Object.values(icons) }, | ||
], | ||
], | ||
global: { | ||
plugins: [pinia], | ||
}, | ||
} | ||
|
||
cy.mount(PermissionForm, { extensions, props }) | ||
|
||
cy.getByDataTestid('permissionsFieldset') | ||
.should('contain', `Droits des utilisateurs sur l'environnement de ${props.environment?.name}`) | ||
cy.get('li') | ||
.should('have.length', props.environment.permissions.length) | ||
cy.get('li:first') | ||
.within(() => { | ||
cy.getByDataTestid('userEmail') | ||
.should('contain', props.environment.permissions[0].user.email) | ||
.get('input#range') | ||
.should('have.value', props.environment.permissions[0].level) | ||
.and('be.disabled') | ||
.getByDataTestid('deletePermissionBtn') | ||
.should('have.attr', 'title', 'Les droits du owner ne peuvent être retirés') | ||
.and('be.disabled') | ||
}) | ||
cy.get('li:nth-of-type(2)') | ||
.within(() => { | ||
cy.getByDataTestid('userEmail') | ||
.should('contain', props.environment.permissions[1].user.email) | ||
.get('input#range') | ||
.should('have.value', props.environment.permissions[1].level) | ||
.and('be.enabled') | ||
.getByDataTestid('deletePermissionBtn') | ||
.should('have.attr', 'title', `Retirer les droits de ${props.environment.permissions[1].user.email}`) | ||
.and('be.enabled') | ||
}) | ||
cy.getByDataTestid('newPermissionFieldset') | ||
.should('contain', 'Accréditer un membre du projet') | ||
.within(() => { | ||
cy.get('label') | ||
.should('contain', `E-mail de l'utilisateur à accréditer sur l'environnement de ${props.environment?.name}`) | ||
cy.get('datalist#suggestionList') | ||
.find('option') | ||
.should('have.length', randomDbSetup.project.users.length - props.environment.permissions.length) | ||
.should('have.value', userToLicence.email) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import VueDsfr from '@gouvminint/vue-dsfr' | ||
import { createPinia } from 'pinia' | ||
import '@gouvminint/vue-dsfr/styles' | ||
import '@/main.css' | ||
import * as icons from '@/icons.js' | ||
import RangeInput from '@/components/RangeInput.vue' | ||
import { levels } from 'shared/src/utils/iterables.js' | ||
|
||
describe('RangeInput.vue', () => { | ||
it('Should mount a RangeInput', () => { | ||
const pinia = createPinia() | ||
|
||
const props = { | ||
label: 'RangeInput CT test', | ||
level: 1, | ||
levels, | ||
} | ||
|
||
const extensions = { | ||
use: [ | ||
[ | ||
VueDsfr, { icons: Object.values(icons) }, | ||
], | ||
], | ||
global: { | ||
plugins: [pinia], | ||
}, | ||
} | ||
|
||
cy.mount(RangeInput, { extensions, props }) | ||
|
||
cy.get('label[for="range"]') | ||
.should('have.length', 1) | ||
.and('contain', 'RangeInput CT test') | ||
.and('not.contain', '*') | ||
cy.get('input[list="rangeList"]') | ||
.should('have.value', props.level) | ||
cy.get('datalist#rangeList') | ||
.should('have.length', 1) | ||
.find('option') | ||
.should('have.length', levels.length) | ||
cy.get('option:first') | ||
.should('have.attr', 'label', levels[0]) | ||
}) | ||
}) |
42 changes: 42 additions & 0 deletions
42
apps/client/cypress/components/specs/suggestion-input.ct.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import VueDsfr from '@gouvminint/vue-dsfr' | ||
import { createPinia } from 'pinia' | ||
import '@gouvminint/vue-dsfr/styles' | ||
import '@/main.css' | ||
import * as icons from '@/icons.js' | ||
import SuggestionInput from '@/components/SuggestionInput.vue' | ||
import { createRandomDbSetup } from 'test-utils' | ||
|
||
describe('SuggestionInput.vue', () => { | ||
it('Should mount a SuggestionInput', () => { | ||
const pinia = createPinia() | ||
|
||
const randomDbSetup = createRandomDbSetup({ nbUsers: 5 }) | ||
|
||
const props = { | ||
suggestions: randomDbSetup.users.map(user => user.email), | ||
} | ||
|
||
const extensions = { | ||
use: [ | ||
[ | ||
VueDsfr, { icons: Object.values(icons) }, | ||
], | ||
], | ||
global: { | ||
plugins: [pinia], | ||
}, | ||
} | ||
|
||
cy.mount(SuggestionInput, { extensions, props }) | ||
|
||
cy.get('input[list="suggestionList"]') | ||
.should('have.length', 1) | ||
.and('have.value', '') | ||
.clear() | ||
.type(props.suggestions[0].slice(0, 2)) | ||
cy.get('datalist#suggestionList') | ||
.should('have.length', 1) | ||
.find('option') | ||
.should('have.length', props.suggestions.length) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,42 @@ | ||
|
||
import { getProjectbyId, getUserById } from '../support/func.js' | ||
|
||
describe('Add environments into project', () => { | ||
const project = { name: 'project11' } | ||
const project0 = { name: 'project11' } | ||
const project1 = getProjectbyId('011e7860-04d7-461f-912d-334c622d38b3') | ||
const user = getUserById('cb8e5b4b-7b7b-40f5-935f-594f48ae6566') | ||
const environments = ['prod', 'dev'] | ||
|
||
before(() => { | ||
cy.kcLogin('test') | ||
|
||
cy.createProject(project) | ||
cy.createProject(project0) | ||
|
||
cy.getByDataTestid('menuMyProjects').click() | ||
.getByDataTestid(`projectTile-${project.name}`).click() | ||
.getByDataTestid(`projectTile-${project0.name}`).click() | ||
}) | ||
|
||
beforeEach(() => { | ||
cy.kcLogin('test') | ||
}) | ||
|
||
it('Should add environments to an existing project', () => { | ||
const environments = ['prod', 'dev'] | ||
cy.addEnvironment(project0, environments) | ||
cy.assertAddEnvironment(project0, environments) | ||
}) | ||
|
||
it('Should delete an environment', () => { | ||
cy.deleteEnvironment(project0, environments[1]) | ||
}) | ||
|
||
cy.addEnvironment(project, environments) | ||
cy.assertAddEnvironment(project, environments) | ||
it('Should not be able to delete an environment if not owner', () => { | ||
cy.kcLogin((user.firstName.slice(0, 1) + user.lastName).toLowerCase()) | ||
.goToProjects() | ||
.getByDataTestid(`projectTile-${project1.name}`).click() | ||
.getByDataTestid('menuEnvironments').click() | ||
.getByDataTestid(`environmentTile-${environments[0]}`) | ||
.click() | ||
.url().should('contain', '/environments') | ||
.getByDataTestid('deleteEnvironmentZone').should('not.exist') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { | ||
getProjectbyId, | ||
getUserById, | ||
} from '../support/func.js' | ||
|
||
describe('Manage permissions for environment', () => { | ||
const project = getProjectbyId('011e7860-04d7-461f-912d-334c622d38b3') | ||
const owner = getUserById('cb8e5b4b-7b7b-40f5-935f-594f48ae6565') | ||
const user0 = getUserById('cb8e5b4b-7b7b-40f5-935f-594f48ae6566') | ||
const user1 = getUserById('cb8e5b4b-7b7b-40f5-935f-594f48ae6567') | ||
|
||
before(() => { | ||
cy.kcLogin('test') | ||
|
||
cy.goToProjects() | ||
|
||
cy.getByDataTestid('menuMyProjects').click() | ||
.getByDataTestid(`projectTile-${project.name}`).click() | ||
}) | ||
|
||
beforeEach(() => { | ||
cy.kcLogin('test') | ||
}) | ||
|
||
it('Should not be able to update permissions if not permitted on environment', () => { | ||
const environment = 'staging' | ||
|
||
cy.kcLogin((user0.firstName.slice(0, 1) + user0.lastName).toLowerCase()) | ||
.goToProjects() | ||
.getByDataTestid(`projectTile-${project.name}`).click() | ||
.getByDataTestid('menuEnvironments').click() | ||
.getByDataTestid(`environmentTile-${environment}`) | ||
.click() | ||
.url().should('contain', '/environments') | ||
.getByDataTestid('deleteEnvironmentZone').should('not.exist') | ||
|
||
cy.assertPermission(project, environment, [{ email: owner.email, isOwner: true }]) | ||
|
||
cy.getByDataTestid('permissionSuggestionInput').find('input') | ||
.should('be.disabled') | ||
.getByDataTestid('deletePermissionBtn') | ||
.should('be.disabled') | ||
.getByDataTestid('permissionLevelRange') | ||
.should('be.disabled') | ||
}) | ||
|
||
it('Should add permissions to an existing environment', () => { | ||
const environment = 'staging' | ||
|
||
cy.assertAddEnvironment(project, [environment]) | ||
cy.addPermission(project, environment, user0.email) | ||
cy.assertPermission(project, environment, [{ email: owner.email, isOwner: true }, { email: user0.email, isOwner: false }]) | ||
|
||
cy.getByDataTestid('permissionSuggestionInput') | ||
.should('not.exist') | ||
|
||
cy.addProjectMember(project, user1.email) | ||
|
||
cy.goToProjects() | ||
.getByDataTestid(`projectTile-${project.name}`).click() | ||
.getByDataTestid('menuEnvironments').click() | ||
.getByDataTestid(`environmentTile-${environment}`) | ||
.click() | ||
|
||
cy.get('[data-testid^="userPermissionLi-"]') | ||
.should('have.length', 2) | ||
.getByDataTestid('permissionSuggestionInput').first() | ||
.should('be.visible') | ||
.clear() | ||
|
||
cy.addPermission(project, environment, user1.email) | ||
cy.getByDataTestid(`userPermissionLi-${user1.email}`) | ||
.should('exist') | ||
}) | ||
|
||
it.skip('Should update existing permissions', () => { | ||
cy.intercept('PUT', `/api/v1/projects/${project.id}/environments/*/permissions`).as('putPermission') | ||
const environment = 'staging' | ||
|
||
cy.assertAddEnvironment(project, [environment]) | ||
cy.assertPermission(project, environment, [{ email: owner.email, isOwner: true }, { email: user0.email, isOwner: false }, { email: user1.email, isOwner: false }]) | ||
|
||
cy.getByDataTestid('permissionSuggestionInput') | ||
.should('not.exist') | ||
|
||
// TODO : Interragir avec input[type=range] | ||
// https://docs.cypress.io/api/commands/trigger#Interact-with-a-range-input-slider | ||
cy.getByDataTestid(`userPermissionLi-${user1.email}`).within(() => { | ||
cy.getByDataTestid('permissionLevelRange') | ||
.find('input[type=range]') | ||
.invoke('val', 0) | ||
.trigger('change') | ||
}) | ||
.wait('@putPermission') | ||
.its('response.statusCode').should('eq', 200) | ||
}) | ||
|
||
it('Should remove a permission', () => { | ||
cy.intercept('DELETE', `/api/v1/projects/${project.id}/environments/*/permissions/${user1.id}`).as('deletePermission') | ||
const environment = 'staging' | ||
|
||
cy.assertAddEnvironment(project, [environment]) | ||
cy.assertPermission(project, environment, [{ email: owner.email, isOwner: true }, { email: user0.email, isOwner: false }, { email: user1.email, isOwner: false }]) | ||
|
||
cy.getByDataTestid('permissionSuggestionInput') | ||
.should('not.exist') | ||
|
||
cy.getByDataTestid(`userPermissionLi-${user1.email}`).within(() => { | ||
cy.getByDataTestid('deletePermissionBtn') | ||
.click() | ||
}) | ||
.wait('@deletePermission') | ||
.its('response.statusCode').should('eq', 200) | ||
|
||
cy.get('[data-testid^="userPermissionLi-"]') | ||
.should('have.length', 2) | ||
.getByDataTestid('permissionSuggestionInput') | ||
.should('be.visible') | ||
.getByDataTestid(`userPermissionLi-${user1.email}`) | ||
.should('not.exist') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.