@@ -3,13 +3,25 @@ import {
33} from '@src/testUtils' ;
44import { CourseAuthoringProvider } from '@src/CourseAuthoringContext' ;
55import { getCourseSettingsApiUrl } from '@src/data/api' ;
6+ import { mockWaffleFlags } from '@src/data/apiHooks.mock' ;
7+ import { useUserPermissionsWithAuthzCourse } from '@src/authz/hooks' ;
68
79import gradingSettings from './__mocks__/gradingSettings' ;
810import { getGradingSettingsApiUrl } from './data/api' ;
911import * as apiHooks from './data/apiHooks' ;
1012import GradingSettings from './GradingSettings' ;
1113import messages from './messages' ;
1214
15+ jest . mock ( '@src/authz/hooks' , ( ) => ( {
16+ useUserPermissionsWithAuthzCourse : jest . fn ( ) . mockReturnValue ( {
17+ isLoading : false ,
18+ permissions : {
19+ canViewGradingSettings : true ,
20+ canEditGradingSettings : true ,
21+ } ,
22+ } ) ,
23+ } ) ) ;
24+
1325const courseId = '123' ;
1426let axiosMock ;
1527
@@ -125,3 +137,74 @@ describe('<GradingSettings />', () => {
125137 expect ( screen . getByTestId ( 'connectionErrorAlert' ) ) . toBeInTheDocument ( ) ;
126138 } ) ;
127139} ) ;
140+
141+ describe ( '<GradingSettings /> permissions' , ( ) => {
142+ const setupMocks = ( ) => {
143+ const mocks = initializeMocks ( ) ;
144+ Object . defineProperty ( window , 'scrollTo' , { value : jest . fn ( ) , writable : true } ) ;
145+ const { axiosMock : mock } = mocks ;
146+ mock . onGet ( getGradingSettingsApiUrl ( courseId ) ) . reply ( 200 , gradingSettings ) ;
147+ mock . onPost ( getGradingSettingsApiUrl ( courseId ) ) . reply ( 200 , { } ) ;
148+ mock . onGet ( getCourseSettingsApiUrl ( courseId ) ) . reply ( 200 , { } ) ;
149+ return mock ;
150+ } ;
151+
152+ beforeEach ( ( ) => {
153+ jest . mocked ( useUserPermissionsWithAuthzCourse ) . mockReturnValue ( {
154+ isLoading : false ,
155+ permissions : { canViewGradingSettings : true , canEditGradingSettings : true } ,
156+ } ) ;
157+ } ) ;
158+
159+ it ( 'should render normally when authz flag is disabled (no regression)' , async ( ) => {
160+ mockWaffleFlags ( { enableAuthzCourseAuthoring : false } ) ;
161+ setupMocks ( ) ;
162+ render ( < RootWrapper /> ) ;
163+ expect ( await screen . findAllByText ( messages . headingTitle . defaultMessage ) ) . not . toHaveLength ( 0 ) ;
164+ } ) ;
165+
166+ it ( 'should render normally when user has view and edit permissions' , async ( ) => {
167+ mockWaffleFlags ( { enableAuthzCourseAuthoring : true } ) ;
168+ setupMocks ( ) ;
169+ render ( < RootWrapper /> ) ;
170+ expect ( await screen . findAllByText ( messages . headingTitle . defaultMessage ) ) . not . toHaveLength ( 0 ) ;
171+ } ) ;
172+
173+ it ( 'should show permission denied alert when user lacks view permission' , async ( ) => {
174+ mockWaffleFlags ( { enableAuthzCourseAuthoring : true } ) ;
175+ jest . mocked ( useUserPermissionsWithAuthzCourse ) . mockReturnValue ( {
176+ isLoading : false ,
177+ permissions : { canViewGradingSettings : false , canEditGradingSettings : false } ,
178+ } ) ;
179+ setupMocks ( ) ;
180+ render ( < RootWrapper /> ) ;
181+ expect ( await screen . findByTestId ( 'permissionDeniedAlert' ) ) . toBeInTheDocument ( ) ;
182+ } ) ;
183+
184+ it ( 'should disable inputs when user has view but not edit permission' , async ( ) => {
185+ mockWaffleFlags ( { enableAuthzCourseAuthoring : true } ) ;
186+ jest . mocked ( useUserPermissionsWithAuthzCourse ) . mockReturnValue ( {
187+ isLoading : false ,
188+ permissions : { canViewGradingSettings : true , canEditGradingSettings : false } ,
189+ } ) ;
190+ setupMocks ( ) ;
191+ render ( < RootWrapper /> ) ;
192+ const segmentInputs = await screen . findAllByTestId ( 'grading-scale-segment-input' ) ;
193+ segmentInputs . forEach ( ( input ) => expect ( input ) . toBeDisabled ( ) ) ;
194+ } ) ;
195+
196+ it ( 'should disable save button when user lacks edit permission' , async ( ) => {
197+ mockWaffleFlags ( { enableAuthzCourseAuthoring : true } ) ;
198+ jest . mocked ( useUserPermissionsWithAuthzCourse ) . mockReturnValue ( {
199+ isLoading : false ,
200+ permissions : { canViewGradingSettings : true , canEditGradingSettings : false } ,
201+ } ) ;
202+ setupMocks ( ) ;
203+ render ( < RootWrapper /> ) ;
204+ const segmentInputs = await screen . findAllByTestId ( 'grading-scale-segment-input' ) ;
205+ // Trigger a change to show the save alert
206+ fireEvent . change ( segmentInputs [ 1 ] , { target : { value : 'Test' } } ) ;
207+ const saveBtn = screen . getByTestId ( 'grading-settings-save-alert' ) . querySelector ( 'button[type="button"]:last-child' ) ;
208+ expect ( saveBtn ) . toBeDisabled ( ) ;
209+ } ) ;
210+ } ) ;
0 commit comments