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