@@ -73,58 +73,267 @@ describe('StudioDetailsPanel', () => {
7373 expect ( container ) . toHaveTextContent ( 'Test Channel' ) ;
7474 } ) ;
7575
76- it ( 'does not use VDataTable' , ( ) => {
77- const { container } = render ( StudioDetailsPanel , {
78- router,
79- props : {
80- details : mockChannelDetails ,
81- isChannel : true ,
82- loading : false ,
83- } ,
84- mocks : {
85- $formatNumber : jest . fn ( n => String ( n ) ) ,
86- $formatDate : jest . fn ( ( ) => 'Test Date' ) ,
87- $tr : jest . fn ( key => key ) ,
88- } ,
76+ describe ( 'when channel has all data' , ( ) => {
77+ const fullDataChannel = {
78+ name : 'Complete Channel' ,
79+ description : 'A fully populated channel with all fields' ,
80+ thumbnail_url : 'https://example.com/thumb.jpg' ,
81+ published : true ,
82+ version : 2 ,
83+ primary_token : 'test-token-abc123' ,
84+ language : 'en' ,
85+ created : '2025-01-15T10:00:00Z' ,
86+ last_update : '2025-01-20T15:30:00Z' ,
87+ resource_count : 42 ,
88+ resource_size : 1024000000 ,
89+ kind_count : [
90+ { kind_id : 'video' , count : 20 } ,
91+ { kind_id : 'document' , count : 22 } ,
92+ ] ,
93+ levels : [ 'Level 1' , 'Level 2' , 'Level 3' ] ,
94+ categories : [ 'Category A' , 'Category B' ] ,
95+ includes : { coach_content : 1 , exercises : 1 } ,
96+ tags : [ { tag_name : 'science' } , { tag_name : 'math' } ] ,
97+ languages : [ 'English' , 'Spanish' , 'French' ] ,
98+ accessible_languages : [ 'English' ] ,
99+ authors : [ 'Author One' , 'Author Two' ] ,
100+ providers : [ 'Provider ABC' ] ,
101+ aggregators : [ 'Aggregator XYZ' ] ,
102+ licenses : [ 'CC_BY_SA_3_0' ] ,
103+ copyright_holders : [ 'Copyright Holder Inc' ] ,
104+ original_channels : [ ] ,
105+ sample_nodes : [ ] ,
106+ } ;
107+
108+ let wrapper ;
109+
110+ beforeEach ( ( ) => {
111+ wrapper = render ( StudioDetailsPanel , {
112+ router,
113+ props : {
114+ details : fullDataChannel ,
115+ isChannel : true ,
116+ loading : false ,
117+ } ,
118+ mocks : {
119+ $formatNumber : jest . fn ( n => String ( n ) ) ,
120+ $formatDate : jest . fn ( ( ) => 'Test Date' ) ,
121+ $tr : jest . fn ( key => key ) ,
122+ } ,
123+ } ) ;
124+ } ) ;
125+
126+ it ( 'should render channel name' , ( ) => {
127+ expect ( wrapper . container ) . toHaveTextContent ( 'Complete Channel' ) ;
128+ } ) ;
129+
130+ it ( 'should render channel description' , ( ) => {
131+ expect ( wrapper . container ) . toHaveTextContent ( 'A fully populated channel with all fields' ) ;
132+ } ) ;
133+
134+ it ( 'should render published status' , ( ) => {
135+ expect ( wrapper . container ) . toHaveTextContent ( 'publishedHeading' ) ;
136+ } ) ;
137+
138+ it ( 'should render version information' , ( ) => {
139+ expect ( wrapper . container ) . toHaveTextContent ( 'currentVersionHeading' ) ;
140+ expect ( wrapper . container ) . toHaveTextContent ( '2' ) ;
141+ } ) ;
142+
143+ it ( 'should render primary language' , ( ) => {
144+ expect ( wrapper . container ) . toHaveTextContent ( 'primaryLanguageHeading' ) ;
145+ } ) ;
146+
147+ it ( 'should render resource count' , ( ) => {
148+ expect ( wrapper . container ) . toHaveTextContent ( 'resourceHeading' ) ;
149+ expect ( wrapper . container ) . toHaveTextContent ( '42' ) ;
150+ } ) ;
151+
152+ it ( 'should render educational levels when present' , ( ) => {
153+ // When levels array is populated, the levelsHeading row should be rendered
154+ expect ( wrapper . container ) . toHaveTextContent ( 'levelsHeading' ) ;
155+ // Levels are rendered through the component, verify the section exists
156+ const levelRows = Array . from ( wrapper . container . querySelectorAll ( '*' ) )
157+ . filter ( el => el . textContent ?. includes ( 'levelsHeading' ) ) ;
158+ expect ( levelRows . length ) . toBeGreaterThan ( 0 ) ;
159+ } ) ;
160+
161+ it ( 'should render categories when present' , ( ) => {
162+ // When categories array is populated, the categoriesHeading row should be rendered
163+ expect ( wrapper . container ) . toHaveTextContent ( 'categoriesHeading' ) ;
164+ // Categories are rendered through the component, verify the section exists
165+ const categoryRows = Array . from ( wrapper . container . querySelectorAll ( '*' ) )
166+ . filter ( el => el . textContent ?. includes ( 'categoriesHeading' ) ) ;
167+ expect ( categoryRows . length ) . toBeGreaterThan ( 0 ) ;
168+ } ) ;
169+
170+ it ( 'should render creation date' , ( ) => {
171+ expect ( wrapper . container ) . toHaveTextContent ( 'creationHeading' ) ;
89172 } ) ;
90173
91- expect ( container . querySelector ( '.v-datatable' ) ) . not . toBeInTheDocument ( ) ;
174+ it ( 'should render channel size' , ( ) => {
175+ expect ( wrapper . container ) . toHaveTextContent ( 'sizeHeading' ) ;
176+ } ) ;
177+
178+ it ( 'should render licenses when present' , ( ) => {
179+ expect ( wrapper . container ) . toHaveTextContent ( 'licensesLabel' ) ;
180+ } ) ;
181+
182+ it ( 'should render authors when present' , ( ) => {
183+ expect ( wrapper . container ) . toHaveTextContent ( 'authorsLabel' ) ;
184+ } ) ;
185+
186+ it ( 'should render tags when present' , ( ) => {
187+ expect ( wrapper . container ) . toHaveTextContent ( 'tagsHeading' ) ;
188+ } ) ;
92189 } ) ;
93190
94- it ( 'does not use VChip' , ( ) => {
95- const { container } = render ( StudioDetailsPanel , {
96- router,
97- props : {
98- details : mockChannelDetails ,
99- isChannel : true ,
100- loading : false ,
101- } ,
102- mocks : {
103- $formatNumber : jest . fn ( n => String ( n ) ) ,
104- $formatDate : jest . fn ( ( ) => 'Test Date' ) ,
105- $tr : jest . fn ( key => key ) ,
106- } ,
191+ describe ( 'when channel has missing data' , ( ) => {
192+ const minimalChannel = {
193+ name : 'Minimal Channel' ,
194+ description : '' ,
195+ thumbnail_url : null ,
196+ published : false ,
197+ version : null ,
198+ primary_token : null ,
199+ language : null ,
200+ created : null ,
201+ last_update : null ,
202+ resource_count : 0 ,
203+ resource_size : 0 ,
204+ kind_count : [ ] ,
205+ levels : [ ] ,
206+ categories : [ ] ,
207+ includes : { coach_content : 0 , exercises : 0 } ,
208+ tags : [ ] ,
209+ languages : [ ] ,
210+ accessible_languages : [ ] ,
211+ authors : [ ] ,
212+ providers : [ ] ,
213+ aggregators : [ ] ,
214+ licenses : [ ] ,
215+ copyright_holders : [ ] ,
216+ original_channels : [ ] ,
217+ sample_nodes : [ ] ,
218+ } ;
219+
220+ let wrapper ;
221+
222+ beforeEach ( ( ) => {
223+ wrapper = render ( StudioDetailsPanel , {
224+ router,
225+ props : {
226+ details : minimalChannel ,
227+ isChannel : true ,
228+ loading : false ,
229+ } ,
230+ mocks : {
231+ $formatNumber : jest . fn ( n => String ( n ) ) ,
232+ $formatDate : jest . fn ( ( ) => 'Test Date' ) ,
233+ $tr : jest . fn ( key => key ) ,
234+ } ,
235+ } ) ;
236+ } ) ;
237+
238+ it ( 'should render channel name even when minimal' , ( ) => {
239+ expect ( wrapper . container ) . toHaveTextContent ( 'Minimal Channel' ) ;
240+ } ) ;
241+
242+ it ( 'should show placeholder icon when thumbnail is missing' , ( ) => {
243+ // Verify that the component renders without crashing
244+ // and that a placeholder is shown instead of an image
245+ expect ( wrapper . container ) . toBeInTheDocument ( ) ;
246+ } ) ;
247+
248+ it ( 'should show default text when levels are missing' , ( ) => {
249+ expect ( wrapper . container ) . toHaveTextContent ( '---' ) ;
250+ } ) ;
251+
252+ it ( 'should show default text when categories are missing' , ( ) => {
253+ expect ( wrapper . container ) . toHaveTextContent ( '---' ) ;
254+ } ) ;
255+
256+ it ( 'should not show primary language when not set' , ( ) => {
257+ // Language row should not appear if language is not set
258+ const container = wrapper . container ;
259+ const languageRows = Array . from ( container . querySelectorAll ( '*' ) )
260+ . filter ( el => el . textContent ?. includes ( 'primaryLanguageHeading' ) ) ;
261+ expect ( languageRows . length ) . toBe ( 0 ) ;
107262 } ) ;
108263
109- expect ( container . querySelector ( '.v-chip' ) ) . not . toBeInTheDocument ( ) ;
264+ it ( 'should render unpublished status when published is false' , ( ) => {
265+ expect ( wrapper . container ) . toHaveTextContent ( 'unpublishedText' ) ;
266+ } ) ;
267+
268+ it ( 'should not display token row when token is not present' , ( ) => {
269+ // Token row should not appear if primary_token is null
270+ expect ( wrapper . container ) . not . toHaveTextContent ( 'test-token' ) ;
271+ } ) ;
110272 } ) ;
111273
112- it ( 'does not use VLayout or VFlex' , ( ) => {
113- const { container } = render ( StudioDetailsPanel , {
114- router,
115- props : {
116- details : mockChannelDetails ,
117- isChannel : true ,
118- loading : false ,
119- } ,
120- mocks : {
121- $formatNumber : jest . fn ( n => String ( n ) ) ,
122- $formatDate : jest . fn ( ( ) => 'Test Date' ) ,
123- $tr : jest . fn ( key => key ) ,
124- } ,
274+ describe ( 'when channel has partial data' , ( ) => {
275+ const partialChannel = {
276+ name : 'Partial Channel' ,
277+ description : 'Some description' ,
278+ thumbnail_url : null ,
279+ published : true ,
280+ version : 1 ,
281+ primary_token : 'partial-token-xyz' ,
282+ language : 'es' ,
283+ created : '2025-01-10T10:00:00Z' ,
284+ last_update : '2025-01-18T10:00:00Z' ,
285+ resource_count : 15 ,
286+ resource_size : 512000000 ,
287+ kind_count : [ { kind_id : 'video' , count : 15 } ] ,
288+ levels : [ ] ,
289+ categories : [ 'Category C' ] ,
290+ includes : { coach_content : 0 , exercises : 1 } ,
291+ tags : [ ] ,
292+ languages : [ ] ,
293+ accessible_languages : [ ] ,
294+ authors : [ ] ,
295+ providers : [ ] ,
296+ aggregators : [ ] ,
297+ licenses : [ ] ,
298+ copyright_holders : [ ] ,
299+ original_channels : [ ] ,
300+ sample_nodes : [ ] ,
301+ } ;
302+
303+ let wrapper ;
304+
305+ beforeEach ( ( ) => {
306+ wrapper = render ( StudioDetailsPanel , {
307+ router,
308+ props : {
309+ details : partialChannel ,
310+ isChannel : true ,
311+ loading : false ,
312+ } ,
313+ mocks : {
314+ $formatNumber : jest . fn ( n => String ( n ) ) ,
315+ $formatDate : jest . fn ( ( ) => 'Test Date' ) ,
316+ $tr : jest . fn ( key => key ) ,
317+ } ,
318+ } ) ;
125319 } ) ;
126320
127- expect ( container . querySelector ( '.v-layout' ) ) . not . toBeInTheDocument ( ) ;
128- expect ( container . querySelector ( '.v-flex' ) ) . not . toBeInTheDocument ( ) ;
321+ it ( 'should render fields that have data and show placeholder for missing fields' , ( ) => {
322+ expect ( wrapper . container ) . toHaveTextContent ( 'Partial Channel' ) ;
323+ expect ( wrapper . container ) . toHaveTextContent ( 'Some description' ) ;
324+ // Categories section is rendered when data present
325+ expect ( wrapper . container ) . toHaveTextContent ( 'categoriesHeading' ) ;
326+ // Levels should show placeholder since array is empty
327+ expect ( wrapper . container ) . toHaveTextContent ( '---' ) ;
328+ } ) ;
329+
330+ it ( 'should render both data-present and data-absent states' , ( ) => {
331+ // Has categories (heading should be present)
332+ expect ( wrapper . container ) . toHaveTextContent ( 'categoriesHeading' ) ;
333+ // Missing levels
334+ expect ( wrapper . container ) . toHaveTextContent ( 'levelsHeading' ) ;
335+ // Placeholder text for missing data
336+ expect ( wrapper . container ) . toHaveTextContent ( '---' ) ;
337+ } ) ;
129338 } ) ;
130339} ) ;
0 commit comments