@@ -122,7 +122,12 @@ describe('ProjectVariables', () => {
122122 projectsStore . personalProject = {
123123 id : 'personal-project-id' ,
124124 name : 'Current Project' ,
125- scopes : [ 'projectVariable:create' , 'projectVariable:read' ] ,
125+ scopes : [
126+ 'projectVariable:create' ,
127+ 'projectVariable:read' ,
128+ 'projectVariable:update' ,
129+ 'projectVariable:delete' ,
130+ ] ,
126131 } as Project ;
127132 projectsStore . currentProject = projectsStore . personalProject ;
128133
@@ -423,7 +428,7 @@ describe('ProjectVariables', () => {
423428 } ) ;
424429
425430 describe ( 'permissions' , ( ) => {
426- it ( 'should disable edit button when user lacks update permission' , async ( ) => {
431+ it ( 'should disable edit button when user lacks both global and project update permission' , async ( ) => {
427432 const usersStore = mockedStore ( useUsersStore ) ;
428433 usersStore . currentUser = { globalScopes : [ 'variable:read' , 'variable:list' ] } as IUser ;
429434
@@ -439,6 +444,13 @@ describe('ProjectVariables', () => {
439444 } ,
440445 ] ;
441446
447+ const projectsStore = mockedStore ( useProjectsStore ) ;
448+ projectsStore . currentProject = {
449+ id : 'project-id' ,
450+ name : 'Test Project' ,
451+ scopes : [ 'projectVariable:read' , 'projectVariable:list' ] ,
452+ } as Project ;
453+
442454 const { getByTestId } = renderComponent ( ) ;
443455 await waitFor ( ( ) => expect ( getByTestId ( 'variables-row' ) ) . toBeVisible ( ) ) ;
444456
@@ -447,7 +459,7 @@ describe('ProjectVariables', () => {
447459 expect ( editButton ) . toBeDisabled ( ) ;
448460 } ) ;
449461
450- it ( 'should disable delete button when user lacks delete permission' , async ( ) => {
462+ it ( 'should disable delete button when user lacks both global and project delete permission' , async ( ) => {
451463 const usersStore = mockedStore ( useUsersStore ) ;
452464 usersStore . currentUser = { globalScopes : [ 'variable:read' , 'variable:list' ] } as IUser ;
453465
@@ -463,6 +475,13 @@ describe('ProjectVariables', () => {
463475 } ,
464476 ] ;
465477
478+ const projectsStore = mockedStore ( useProjectsStore ) ;
479+ projectsStore . currentProject = {
480+ id : 'project-id' ,
481+ name : 'Test Project' ,
482+ scopes : [ 'projectVariable:read' , 'projectVariable:list' ] ,
483+ } as Project ;
484+
466485 const { getByTestId } = renderComponent ( ) ;
467486
468487 await waitFor ( ( ) => expect ( getByTestId ( 'variables-row' ) ) . toBeVisible ( ) ) ;
@@ -471,6 +490,136 @@ describe('ProjectVariables', () => {
471490 const deleteButton = getByTestId ( 'variable-row-delete-button' ) ;
472491 expect ( deleteButton ) . toBeDisabled ( ) ;
473492 } ) ;
493+
494+ it ( 'should enable edit button when user has global update permission' , async ( ) => {
495+ const usersStore = mockedStore ( useUsersStore ) ;
496+ usersStore . currentUser = {
497+ globalScopes : [ 'variable:read' , 'variable:list' , 'variable:update' ] ,
498+ } as IUser ;
499+
500+ const settingsStore = mockedStore ( useSettingsStore ) ;
501+ settingsStore . settings . enterprise [ EnterpriseEditionFeature . Variables ] = true ;
502+
503+ const environmentsStore = mockedStore ( useEnvironmentsStore ) ;
504+ environmentsStore . variables = [
505+ {
506+ id : '1' ,
507+ key : 'TEST_VAR' ,
508+ value : 'value' ,
509+ } ,
510+ ] ;
511+
512+ const projectsStore = mockedStore ( useProjectsStore ) ;
513+ projectsStore . currentProject = {
514+ id : 'project-id' ,
515+ name : 'Test Project' ,
516+ scopes : [ 'projectVariable:read' , 'projectVariable:list' ] ,
517+ } as Project ;
518+
519+ const { getByTestId } = renderComponent ( ) ;
520+ await waitFor ( ( ) => expect ( getByTestId ( 'variables-row' ) ) . toBeVisible ( ) ) ;
521+
522+ await userEvent . hover ( getByTestId ( 'variables-row' ) ) ;
523+ const editButton = getByTestId ( 'variable-row-edit-button' ) ;
524+ expect ( editButton ) . not . toBeDisabled ( ) ;
525+ } ) ;
526+
527+ it ( 'should enable edit button when user has project update permission' , async ( ) => {
528+ const usersStore = mockedStore ( useUsersStore ) ;
529+ usersStore . currentUser = { globalScopes : [ 'variable:read' , 'variable:list' ] } as IUser ;
530+
531+ const settingsStore = mockedStore ( useSettingsStore ) ;
532+ settingsStore . settings . enterprise [ EnterpriseEditionFeature . Variables ] = true ;
533+
534+ const environmentsStore = mockedStore ( useEnvironmentsStore ) ;
535+ environmentsStore . variables = [
536+ {
537+ id : '1' ,
538+ key : 'TEST_VAR' ,
539+ value : 'value' ,
540+ } ,
541+ ] ;
542+
543+ const projectsStore = mockedStore ( useProjectsStore ) ;
544+ projectsStore . currentProject = {
545+ id : 'project-id' ,
546+ name : 'Test Project' ,
547+ scopes : [ 'projectVariable:read' , 'projectVariable:list' , 'projectVariable:update' ] ,
548+ } as Project ;
549+
550+ const { getByTestId } = renderComponent ( ) ;
551+ await waitFor ( ( ) => expect ( getByTestId ( 'variables-row' ) ) . toBeVisible ( ) ) ;
552+
553+ await userEvent . hover ( getByTestId ( 'variables-row' ) ) ;
554+ const editButton = getByTestId ( 'variable-row-edit-button' ) ;
555+ expect ( editButton ) . not . toBeDisabled ( ) ;
556+ } ) ;
557+
558+ it ( 'should enable delete button when user has global delete permission' , async ( ) => {
559+ const usersStore = mockedStore ( useUsersStore ) ;
560+ usersStore . currentUser = {
561+ globalScopes : [ 'variable:read' , 'variable:list' , 'variable:delete' ] ,
562+ } as IUser ;
563+
564+ const settingsStore = mockedStore ( useSettingsStore ) ;
565+ settingsStore . settings . enterprise [ EnterpriseEditionFeature . Variables ] = true ;
566+
567+ const environmentsStore = mockedStore ( useEnvironmentsStore ) ;
568+ environmentsStore . variables = [
569+ {
570+ id : '1' ,
571+ key : 'TEST_VAR' ,
572+ value : 'value' ,
573+ } ,
574+ ] ;
575+
576+ const projectsStore = mockedStore ( useProjectsStore ) ;
577+ projectsStore . currentProject = {
578+ id : 'project-id' ,
579+ name : 'Test Project' ,
580+ scopes : [ 'projectVariable:read' , 'projectVariable:list' ] ,
581+ } as Project ;
582+
583+ const { getByTestId } = renderComponent ( ) ;
584+
585+ await waitFor ( ( ) => expect ( getByTestId ( 'variables-row' ) ) . toBeVisible ( ) ) ;
586+
587+ await userEvent . hover ( getByTestId ( 'variables-row' ) ) ;
588+ const deleteButton = getByTestId ( 'variable-row-delete-button' ) ;
589+ expect ( deleteButton ) . not . toBeDisabled ( ) ;
590+ } ) ;
591+
592+ it ( 'should enable delete button when user has project delete permission' , async ( ) => {
593+ const usersStore = mockedStore ( useUsersStore ) ;
594+ usersStore . currentUser = { globalScopes : [ 'variable:read' , 'variable:list' ] } as IUser ;
595+
596+ const settingsStore = mockedStore ( useSettingsStore ) ;
597+ settingsStore . settings . enterprise [ EnterpriseEditionFeature . Variables ] = true ;
598+
599+ const environmentsStore = mockedStore ( useEnvironmentsStore ) ;
600+ environmentsStore . variables = [
601+ {
602+ id : '1' ,
603+ key : 'TEST_VAR' ,
604+ value : 'value' ,
605+ } ,
606+ ] ;
607+
608+ const projectsStore = mockedStore ( useProjectsStore ) ;
609+ projectsStore . currentProject = {
610+ id : 'project-id' ,
611+ name : 'Test Project' ,
612+ scopes : [ 'projectVariable:read' , 'projectVariable:list' , 'projectVariable:delete' ] ,
613+ } as Project ;
614+
615+ const { getByTestId } = renderComponent ( ) ;
616+
617+ await waitFor ( ( ) => expect ( getByTestId ( 'variables-row' ) ) . toBeVisible ( ) ) ;
618+
619+ await userEvent . hover ( getByTestId ( 'variables-row' ) ) ;
620+ const deleteButton = getByTestId ( 'variable-row-delete-button' ) ;
621+ expect ( deleteButton ) . not . toBeDisabled ( ) ;
622+ } ) ;
474623 } ) ;
475624
476625 describe ( 'scope column visibility' , ( ) => {
0 commit comments