22import { Provider } from 'react-redux' ;
33import { BrowserRouter as Router } from 'react-router-dom' ;
44import configureStore from 'redux-mock-store' ;
5- import { fireEvent , render , screen } from '@testing-library/react' ;
5+ import {
6+ fireEvent , render , screen , waitFor , act ,
7+ } from '@testing-library/react' ;
68import * as auth from '@edx/frontend-platform/auth' ;
79import { IntlProvider } from '@edx/frontend-platform/i18n' ;
810import NotificationPreferences from './NotificationPreferences' ;
@@ -33,33 +35,50 @@ const defaultPreferences = {
3335 appId : 'discussion' ,
3436 web : false ,
3537 push : false ,
36- mobile : false ,
38+ email : false ,
3739 } ,
3840 {
3941 id : 'newComment' ,
4042 appId : 'discussion' ,
4143 web : false ,
4244 push : false ,
43- mobile : false ,
45+ email : false ,
4446 } ,
4547 {
4648 id : 'newAssignment' ,
4749 appId : 'coursework' ,
4850 web : false ,
4951 push : false ,
50- mobile : false ,
52+ email : false ,
5153 } ,
5254 {
5355 id : 'newGrade' ,
5456 appId : 'coursework' ,
5557 web : false ,
5658 push : false ,
57- mobile : false ,
59+ email : false ,
5860 } ,
5961 ] ,
6062 nonEditable : { } ,
6163} ;
6264
65+ const updateChannelPreferences = ( toggleVal = false ) => ( {
66+ preferences : [
67+ {
68+ id : 'newPost' , appId : 'discussion' , web : toggleVal , push : toggleVal , email : toggleVal ,
69+ } ,
70+ {
71+ id : 'newComment' , appId : 'discussion' , web : toggleVal , push : toggleVal , email : toggleVal ,
72+ } ,
73+ {
74+ id : 'newAssignment' , appId : 'coursework' , web : toggleVal , push : toggleVal , email : toggleVal ,
75+ } ,
76+ {
77+ id : 'newGrade' , appId : 'coursework' , web : toggleVal , push : toggleVal , email : toggleVal ,
78+ } ,
79+ ] ,
80+ } ) ;
81+
6382const setupStore = ( override = { } ) => {
6483 const storeState = defaultState ;
6584 storeState . courses = {
@@ -78,17 +97,19 @@ const setupStore = (override = {}) => {
7897 return store ;
7998} ;
8099
81- const renderComponent = ( store = { } ) => render (
100+ const renderComponent = ( store = { } ) => (
82101 < Router >
83102 < IntlProvider locale = "en" >
84103 < Provider store = { store } >
85104 < NotificationPreferences />
86105 </ Provider >
87106 </ IntlProvider >
88- </ Router > ,
107+ </ Router >
89108) ;
109+
90110describe ( 'Notification Preferences' , ( ) => {
91111 let store ;
112+
92113 beforeEach ( ( ) => {
93114 store = setupStore ( {
94115 ...defaultPreferences ,
@@ -108,29 +129,30 @@ describe('Notification Preferences', () => {
108129 afterEach ( ( ) => jest . clearAllMocks ( ) ) ;
109130
110131 it ( 'tests if all notification apps are listed' , async ( ) => {
111- await renderComponent ( store ) ;
132+ await render ( renderComponent ( store ) ) ;
112133 expect ( screen . queryAllByTestId ( 'notification-app' ) ) . toHaveLength ( 2 ) ;
113134 } ) ;
135+
114136 it ( 'show spinner if api call is in progress' , async ( ) => {
115137 store = setupStore ( { status : LOADING_STATUS } ) ;
116- await renderComponent ( store ) ;
138+ await render ( renderComponent ( store ) ) ;
117139 expect ( screen . queryByTestId ( 'loading-spinner' ) ) . toBeInTheDocument ( ) ;
118140 } ) ;
119141
120142 it ( 'tests if all notification preferences are listed' , async ( ) => {
121- await renderComponent ( store ) ;
143+ await render ( renderComponent ( store ) ) ;
122144 expect ( screen . queryAllByTestId ( 'notification-preference' ) ) . toHaveLength ( 4 ) ;
123145 } ) ;
124146
125147 it ( 'update group on click' , async ( ) => {
126- const wrapper = await renderComponent ( store ) ;
148+ const wrapper = await render ( renderComponent ( store ) ) ;
127149 const element = wrapper . container . querySelector ( '#discussion-app-toggle' ) ;
128150 await fireEvent . click ( element ) ;
129151 expect ( mockDispatch ) . toHaveBeenCalled ( ) ;
130152 } ) ;
131153
132154 it ( 'update preference on click' , async ( ) => {
133- const wrapper = await renderComponent ( store ) ;
155+ const wrapper = await render ( renderComponent ( store ) ) ;
134156 const element = wrapper . container . querySelector ( '#newPost-web' ) ;
135157 expect ( element ) . not . toBeChecked ( ) ;
136158 await fireEvent . click ( element ) ;
@@ -139,7 +161,43 @@ describe('Notification Preferences', () => {
139161
140162 it ( 'show not found page if invalid course id is entered in url' , async ( ) => {
141163 store = setupStore ( { status : FAILURE_STATUS , selectedCourse : 'invalid-course-id' } ) ;
142- await renderComponent ( store ) ;
164+ await render ( renderComponent ( store ) ) ;
143165 expect ( screen . queryByTestId ( 'not-found-page' ) ) . toBeInTheDocument ( ) ;
144166 } ) ;
167+
168+ it . each ( [ false , true ] ) (
169+ 'updates all preferences in the column on web channel click when toggle state is - %s' ,
170+ async ( toggleState ) => {
171+ store = setupStore ( updateChannelPreferences ( toggleState ) ) ;
172+ const wrapper = render ( renderComponent ( store ) ) ;
173+
174+ const getCheckbox = ( id ) => screen . queryByTestId ( `${ id } -web` ) ;
175+ const checkboxes = [ 'newPost' , 'newComment' , 'newAssignment' , 'newGrade' ] ;
176+
177+ const verifyState = ( expectedState ) => {
178+ checkboxes . forEach ( ( checkbox ) => {
179+ if ( expectedState ) {
180+ expect ( getCheckbox ( checkbox ) ) . toBeChecked ( ) ;
181+ } else {
182+ expect ( getCheckbox ( checkbox ) ) . not . toBeChecked ( ) ;
183+ }
184+ } ) ;
185+ } ;
186+
187+ verifyState ( toggleState ) ;
188+
189+ const element = screen . queryAllByText ( 'Web' ) [ 0 ] ;
190+
191+ await act ( async ( ) => {
192+ await fireEvent . click ( element ) ;
193+ } ) ;
194+
195+ store = setupStore ( updateChannelPreferences ( ! toggleState ) ) ;
196+ wrapper . rerender ( renderComponent ( store ) ) ;
197+
198+ await waitFor ( ( ) => {
199+ verifyState ( ! toggleState ) ;
200+ } ) ;
201+ } ,
202+ ) ;
145203} ) ;
0 commit comments