1
- import { shallow } from '@edx/react-unit-test-utils' ;
1
+ import { render , screen } from '@testing-library/react' ;
2
+ import '@testing-library/jest-dom' ;
3
+ import { IntlProvider } from '@edx/frontend-platform/i18n' ;
4
+
2
5
import {
3
6
useIsPageDataLoaded ,
4
7
useIsORAConfigLoaded ,
5
8
usePageDataError ,
6
9
useORAConfigDataError ,
7
10
} from 'hooks/app' ;
11
+
8
12
import AppContainer from '.' ;
9
13
14
+ jest . unmock ( '@openedx/paragon' ) ;
15
+ jest . unmock ( 'react' ) ;
16
+ jest . unmock ( '@edx/frontend-platform/i18n' ) ;
17
+
18
+ jest . mock ( '@edx/frontend-platform/i18n' , ( ) => ( {
19
+ ...jest . requireActual ( '@edx/frontend-platform/i18n' ) ,
20
+ getLocale : jest . fn ( ) . mockReturnValue ( 'en' ) ,
21
+ configure : jest . fn ( ) ,
22
+ } ) ) ;
23
+
24
+ jest . mock ( '@edx/frontend-platform/react' , ( ) => ( {
25
+ ...jest . requireActual ( '@edx/frontend-platform/react' ) ,
26
+ // eslint-disable-next-line react/prop-types
27
+ ErrorPage : ( { message } ) => < div role = "alert" > { message } </ div > ,
28
+ } ) ) ;
29
+
10
30
jest . mock ( 'hooks/app' , ( ) => ( {
11
31
useIsPageDataLoaded : jest . fn ( ) . mockReturnValue ( true ) ,
12
32
useIsORAConfigLoaded : jest . fn ( ) . mockReturnValue ( true ) ,
@@ -16,44 +36,215 @@ jest.mock('hooks/app', () => ({
16
36
17
37
describe ( '<AppContainer />' , ( ) => {
18
38
const props = {
19
- children : < div > children</ div > ,
39
+ children : < div > Test children content </ div > ,
20
40
} ;
21
41
22
- it ( 'render default' , ( ) => {
23
- const wrapper = shallow ( < AppContainer { ...props } /> ) ;
24
- expect ( wrapper . snapshot ) . toMatchSnapshot ( ) ;
25
- expect ( wrapper . instance . findByType ( 'Spinner' ) ) . toHaveLength ( 0 ) ;
26
- } ) ;
27
-
28
- describe ( 'render error' , ( ) => {
29
- it ( 'pageDataError' , ( ) => {
30
- usePageDataError . mockReturnValueOnce ( { response : { data : { error : { errorCode : 'error' } } } } ) ;
31
- const wrapper = shallow ( < AppContainer { ...props } /> ) ;
32
- expect ( wrapper . snapshot ) . toMatchSnapshot ( ) ;
33
- expect ( wrapper . instance . findByType ( 'ErrorPage' ) ) . toHaveLength ( 1 ) ;
34
- } ) ;
35
-
36
- it ( 'oraConfigDataError' , ( ) => {
37
- useORAConfigDataError . mockReturnValueOnce ( { response : { data : { error : { errorCode : 'error' } } } } ) ;
38
- const wrapper = shallow ( < AppContainer { ...props } /> ) ;
39
- expect ( wrapper . snapshot ) . toMatchSnapshot ( ) ;
40
- expect ( wrapper . instance . findByType ( 'ErrorPage' ) ) . toHaveLength ( 1 ) ;
41
- } ) ;
42
- } ) ;
43
-
44
- describe ( 'render loading' , ( ) => {
45
- it ( 'isPageDataLoaded' , ( ) => {
46
- useIsPageDataLoaded . mockReturnValueOnce ( false ) ;
47
- const wrapper = shallow ( < AppContainer { ...props } /> ) ;
48
- expect ( wrapper . snapshot ) . toMatchSnapshot ( ) ;
49
- expect ( wrapper . instance . findByType ( 'Spinner' ) ) . toHaveLength ( 1 ) ;
50
- } ) ;
51
-
52
- it ( 'isORAConfigLoaded' , ( ) => {
53
- useIsORAConfigLoaded . mockReturnValueOnce ( false ) ;
54
- const wrapper = shallow ( < AppContainer { ...props } /> ) ;
55
- expect ( wrapper . snapshot ) . toMatchSnapshot ( ) ;
56
- expect ( wrapper . instance . findByType ( 'Spinner' ) ) . toHaveLength ( 1 ) ;
57
- } ) ;
42
+ const renderWithIntl = ( component ) => render ( < IntlProvider locale = "en" > { component } </ IntlProvider > ) ;
43
+
44
+ beforeEach ( ( ) => {
45
+ useIsPageDataLoaded . mockReturnValue ( true ) ;
46
+ useIsORAConfigLoaded . mockReturnValue ( true ) ;
47
+ usePageDataError . mockReturnValue ( null ) ;
48
+ useORAConfigDataError . mockReturnValue ( null ) ;
49
+ } ) ;
50
+
51
+ afterEach ( ( ) => {
52
+ jest . clearAllMocks ( ) ;
53
+ } ) ;
54
+
55
+ it ( 'renders children when data is loaded and no errors' , ( ) => {
56
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
57
+
58
+ expect ( screen . getByText ( 'Test children content' ) ) . toBeInTheDocument ( ) ;
59
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ; // No spinner
60
+ } ) ;
61
+
62
+ it ( 'renders spinner when page data is not loaded' , ( ) => {
63
+ useIsPageDataLoaded . mockReturnValue ( false ) ;
64
+
65
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
66
+
67
+ expect ( screen . getByRole ( 'status' ) ) . toBeInTheDocument ( ) ;
68
+ expect ( screen . getByText ( 'loading' ) ) . toBeInTheDocument ( ) ;
69
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
70
+ } ) ;
71
+
72
+ it ( 'renders spinner when ORA config is not loaded' , ( ) => {
73
+ useIsORAConfigLoaded . mockReturnValue ( false ) ;
74
+
75
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
76
+
77
+ expect ( screen . getByRole ( 'status' ) ) . toBeInTheDocument ( ) ;
78
+ expect ( screen . getByText ( 'loading' ) ) . toBeInTheDocument ( ) ;
79
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
80
+ } ) ;
81
+
82
+ it ( 'renders with correct container styling' , ( ) => {
83
+ const { container } = renderWithIntl ( < AppContainer { ...props } /> ) ;
84
+
85
+ const containerDiv = container . querySelector ( '.w-100.h-100' ) ;
86
+ expect ( containerDiv ) . toBeInTheDocument ( ) ;
87
+ } ) ;
88
+
89
+ it ( 'renders spinner with correct classes when loading' , ( ) => {
90
+ useIsPageDataLoaded . mockReturnValue ( false ) ;
91
+
92
+ const { container } = renderWithIntl ( < AppContainer { ...props } /> ) ;
93
+
94
+ const spinner = container . querySelector ( '.app-loading' ) ;
95
+ expect ( spinner ) . toBeInTheDocument ( ) ;
96
+ expect ( spinner ) . toHaveClass ( 'spinner-border' ) ;
97
+ } ) ;
98
+
99
+ it ( 'renders error page when page data error occurs' , ( ) => {
100
+ const mockError = {
101
+ response : {
102
+ data : {
103
+ error : {
104
+ errorCode : 'ERR_INVALID_STATE_FOR_ASSESSMENT' ,
105
+ } ,
106
+ } ,
107
+ } ,
108
+ } ;
109
+ usePageDataError . mockReturnValue ( mockError ) ;
110
+
111
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
112
+
113
+ const errorMessage = 'This step is not available. Unable to retrieve the assessment.' ;
114
+ expect ( screen . getByRole ( 'alert' ) ) . toBeInTheDocument ( ) ;
115
+ expect ( screen . getByText ( errorMessage ) ) . toBeInTheDocument ( ) ;
116
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
117
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ;
118
+ } ) ;
119
+
120
+ it ( 'renders error page when ORA config error occurs' , ( ) => {
121
+ const mockError = {
122
+ response : {
123
+ data : {
124
+ error : {
125
+ errorCode : 'ERR_INVALID_STATE_FOR_ASSESSMENT' ,
126
+ } ,
127
+ } ,
128
+ } ,
129
+ } ;
130
+ useORAConfigDataError . mockReturnValue ( mockError ) ;
131
+
132
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
133
+
134
+ const errorMessage = 'This step is not available. Unable to retrieve the assessment.' ;
135
+ expect ( screen . getByRole ( 'alert' ) ) . toBeInTheDocument ( ) ;
136
+ expect ( screen . getByText ( errorMessage ) ) . toBeInTheDocument ( ) ;
137
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
138
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ;
139
+ } ) ;
140
+
141
+ it ( 'renders unknown error message when error has unknown error code' , ( ) => {
142
+ const mockError = {
143
+ response : {
144
+ data : {
145
+ error : {
146
+ errorCode : 'UNKNOWN_ERROR_CODE' ,
147
+ } ,
148
+ } ,
149
+ } ,
150
+ } ;
151
+ usePageDataError . mockReturnValue ( mockError ) ;
152
+
153
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
154
+
155
+ const errorMessage = 'An unknown error occurred. Please try again.' ;
156
+ expect ( screen . getByRole ( 'alert' ) ) . toBeInTheDocument ( ) ;
157
+ expect ( screen . getByText ( errorMessage ) ) . toBeInTheDocument ( ) ;
158
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
159
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ;
160
+ } ) ;
161
+
162
+ it ( 'renders unknown error message when error has no error code' , ( ) => {
163
+ const mockError = {
164
+ response : {
165
+ data : {
166
+ error : { } ,
167
+ } ,
168
+ } ,
169
+ } ;
170
+ usePageDataError . mockReturnValue ( mockError ) ;
171
+
172
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
173
+
174
+ const errorMessage = 'An unknown error occurred. Please try again.' ;
175
+ expect ( screen . getByRole ( 'alert' ) ) . toBeInTheDocument ( ) ;
176
+ expect ( screen . getByText ( errorMessage ) ) . toBeInTheDocument ( ) ;
177
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
178
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ;
179
+ } ) ;
180
+
181
+ it ( 'renders unknown error message when error has no response data' , ( ) => {
182
+ const mockError = {
183
+ response : { } ,
184
+ } ;
185
+ usePageDataError . mockReturnValue ( mockError ) ;
186
+
187
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
188
+
189
+ const errorMessage = 'An unknown error occurred. Please try again.' ;
190
+ expect ( screen . getByRole ( 'alert' ) ) . toBeInTheDocument ( ) ;
191
+ expect ( screen . getByText ( errorMessage ) ) . toBeInTheDocument ( ) ;
192
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
193
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ;
194
+ } ) ;
195
+
196
+ it ( 'renders unknown error message when error has no response' , ( ) => {
197
+ const mockError = { } ;
198
+ usePageDataError . mockReturnValue ( mockError ) ;
199
+
200
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
201
+
202
+ const errorMessage = 'An unknown error occurred. Please try again.' ;
203
+ expect ( screen . getByRole ( 'alert' ) ) . toBeInTheDocument ( ) ;
204
+ expect ( screen . getByText ( errorMessage ) ) . toBeInTheDocument ( ) ;
205
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
206
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ;
207
+ } ) ;
208
+
209
+ it ( 'prioritizes page data error over ORA config error when both exist' , ( ) => {
210
+ const pageDataError = {
211
+ response : {
212
+ data : {
213
+ error : {
214
+ errorCode : 'ERR_INVALID_STATE_FOR_ASSESSMENT' ,
215
+ } ,
216
+ } ,
217
+ } ,
218
+ } ;
219
+ const oraConfigError = {
220
+ response : {
221
+ data : {
222
+ error : {
223
+ errorCode : 'DIFFERENT_ERROR' ,
224
+ } ,
225
+ } ,
226
+ } ,
227
+ } ;
228
+ usePageDataError . mockReturnValue ( pageDataError ) ;
229
+ useORAConfigDataError . mockReturnValue ( oraConfigError ) ;
230
+
231
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
232
+
233
+ const errorMessage = 'This step is not available. Unable to retrieve the assessment.' ;
234
+ expect ( screen . getByRole ( 'alert' ) ) . toBeInTheDocument ( ) ;
235
+ expect ( screen . getByText ( errorMessage ) ) . toBeInTheDocument ( ) ;
236
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
237
+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( ) ;
238
+ } ) ;
239
+
240
+ it ( 'renders spinner when both config and page data are not loaded' , ( ) => {
241
+ useIsPageDataLoaded . mockReturnValue ( false ) ;
242
+ useIsORAConfigLoaded . mockReturnValue ( false ) ;
243
+
244
+ renderWithIntl ( < AppContainer { ...props } /> ) ;
245
+
246
+ expect ( screen . getByRole ( 'status' ) ) . toBeInTheDocument ( ) ;
247
+ expect ( screen . getByText ( 'loading' ) ) . toBeInTheDocument ( ) ;
248
+ expect ( screen . queryByText ( 'Test children content' ) ) . not . toBeInTheDocument ( ) ;
58
249
} ) ;
59
250
} ) ;
0 commit comments