@@ -40,6 +40,13 @@ const tag2 = 'tag2'
4040const tag3 = 'tag3'
4141
4242const tag4 = 'tag4'
43+ const tag5 = 'tag5'
44+ const tag6 = 'tag6'
45+
46+ const partInstanceId3 = protectString < PartInstanceId > ( 'partInstance3' )
47+ const partInstanceId4 = protectString < PartInstanceId > ( 'partInstance4' )
48+ const pieceInstanceId4 = protectString < PieceInstanceId > ( 'pieceInstance4' )
49+ const pieceInstanceId5 = protectString < PieceInstanceId > ( 'pieceInstance5' )
4350
4451function createAndPopulateMockCache ( ) : ContentCache {
4552 const newCache : ContentCache = {
@@ -233,4 +240,164 @@ describe('TagsService', () => {
233240
234241 expect ( result ) . toEqual ( true )
235242 } )
243+
244+ test ( 'piece in previousPartsInfo[0] (most-recent previous) is treated as on-air' , ( ) => {
245+ // partInstanceId3 = previous (index 0), partInstanceId0 = current
246+ const testee = createTestee ( )
247+ const cache : ContentCache = {
248+ RundownPlaylists : new ReactiveCacheCollection ( 'rundownPlaylists' ) ,
249+ ShowStyleBases : new ReactiveCacheCollection ( 'showStyleBases' ) ,
250+ PieceInstances : new ReactiveCacheCollection ( 'pieceInstances' ) ,
251+ PartInstances : new ReactiveCacheCollection ( 'partInstances' ) ,
252+ }
253+ cache . RundownPlaylists . insert ( {
254+ _id : playlistId ,
255+ activationId,
256+ previousPartsInfo : [ { partInstanceId : partInstanceId3 } ] ,
257+ currentPartInfo : { partInstanceId : partInstanceId0 } ,
258+ nextPartInfo : { partInstanceId : partInstanceId1 } ,
259+ } as DBRundownPlaylist )
260+ cache . ShowStyleBases . insert ( {
261+ _id : showStyleBaseId ,
262+ sourceLayersWithOverrides : wrapDefaultObject (
263+ normalizeArray (
264+ [
265+ literal < ISourceLayer > ( {
266+ _id : sourceLayerId0 ,
267+ _rank : 0 ,
268+ name : 'Camera' ,
269+ type : SourceLayerType . CAMERA ,
270+ } ) ,
271+ ] ,
272+ '_id'
273+ )
274+ ) ,
275+ } as DBShowStyleBase )
276+ // Piece in the previous part — started playback, not yet stopped
277+ cache . PieceInstances . insert ( {
278+ _id : pieceInstanceId4 ,
279+ piece : {
280+ tags : [ tag5 ] ,
281+ sourceLayerId : sourceLayerId0 ,
282+ enable : { start : 0 } ,
283+ lifespan : PieceLifespan . WithinPart ,
284+ } ,
285+ partInstanceId : partInstanceId3 ,
286+ plannedStartedPlayback : 1000 ,
287+ } as PieceInstance )
288+ // Piece in the current part
289+ cache . PieceInstances . insert ( {
290+ _id : pieceInstanceId0 ,
291+ piece : {
292+ tags : [ tag0 ] ,
293+ sourceLayerId : sourceLayerId0 ,
294+ enable : { start : 0 } ,
295+ lifespan : PieceLifespan . WithinPart ,
296+ } ,
297+ partInstanceId : partInstanceId0 ,
298+ } as PieceInstance )
299+ cache . PartInstances . insert ( { _id : partInstanceId3 } as DBPartInstance )
300+ cache . PartInstances . insert ( { _id : partInstanceId0 } as DBPartInstance )
301+ cache . PartInstances . insert ( { _id : partInstanceId1 } as DBPartInstance )
302+
303+ testee . updatePieceInstances ( cache , showStyleBaseId )
304+
305+ // tag5 is from previous part → on-air; tag0 is from current → on-air; neither is next
306+ expect ( testee . getTallyStateFromTags ( { currentPieceTags : [ tag5 ] } as IWrappedAdLib ) ) . toEqual ( {
307+ isActive : true ,
308+ isNext : false ,
309+ } )
310+ expect ( testee . getTallyStateFromTags ( { currentPieceTags : [ tag0 ] } as IWrappedAdLib ) ) . toEqual ( {
311+ isActive : true ,
312+ isNext : false ,
313+ } )
314+ } )
315+
316+ test ( 'pieces in all entries of previousPartsInfo are treated as on-air' , ( ) => {
317+ // partInstanceId4 = older previous (index 1), partInstanceId3 = recent previous (index 0), partInstanceId0 = current
318+ const testee = createTestee ( )
319+ const cache : ContentCache = {
320+ RundownPlaylists : new ReactiveCacheCollection ( 'rundownPlaylists' ) ,
321+ ShowStyleBases : new ReactiveCacheCollection ( 'showStyleBases' ) ,
322+ PieceInstances : new ReactiveCacheCollection ( 'pieceInstances' ) ,
323+ PartInstances : new ReactiveCacheCollection ( 'partInstances' ) ,
324+ }
325+ cache . RundownPlaylists . insert ( {
326+ _id : playlistId ,
327+ activationId,
328+ // most-recent-first: index 0 = partInstanceId3, index 1 = partInstanceId4
329+ previousPartsInfo : [ { partInstanceId : partInstanceId3 } , { partInstanceId : partInstanceId4 } ] ,
330+ currentPartInfo : { partInstanceId : partInstanceId0 } ,
331+ } as DBRundownPlaylist )
332+ cache . ShowStyleBases . insert ( {
333+ _id : showStyleBaseId ,
334+ sourceLayersWithOverrides : wrapDefaultObject (
335+ normalizeArray (
336+ [
337+ literal < ISourceLayer > ( {
338+ _id : sourceLayerId0 ,
339+ _rank : 0 ,
340+ name : 'Camera' ,
341+ type : SourceLayerType . CAMERA ,
342+ } ) ,
343+ ] ,
344+ '_id'
345+ )
346+ ) ,
347+ } as DBShowStyleBase )
348+ // Piece in the most-recent previous part (index 0)
349+ cache . PieceInstances . insert ( {
350+ _id : pieceInstanceId4 ,
351+ piece : {
352+ tags : [ tag5 ] ,
353+ sourceLayerId : sourceLayerId0 ,
354+ enable : { start : 0 } ,
355+ lifespan : PieceLifespan . WithinPart ,
356+ } ,
357+ partInstanceId : partInstanceId3 ,
358+ plannedStartedPlayback : 1000 ,
359+ } as PieceInstance )
360+ // Piece in the older previous part (index 1) — still has started playback, not stopped
361+ cache . PieceInstances . insert ( {
362+ _id : pieceInstanceId5 ,
363+ piece : {
364+ tags : [ tag6 ] ,
365+ sourceLayerId : sourceLayerId0 ,
366+ enable : { start : 0 } ,
367+ lifespan : PieceLifespan . WithinPart ,
368+ } ,
369+ partInstanceId : partInstanceId4 ,
370+ plannedStartedPlayback : 500 ,
371+ } as PieceInstance )
372+ // Piece in the current part
373+ cache . PieceInstances . insert ( {
374+ _id : pieceInstanceId0 ,
375+ piece : {
376+ tags : [ tag0 ] ,
377+ sourceLayerId : sourceLayerId0 ,
378+ enable : { start : 0 } ,
379+ lifespan : PieceLifespan . WithinPart ,
380+ } ,
381+ partInstanceId : partInstanceId0 ,
382+ } as PieceInstance )
383+ cache . PartInstances . insert ( { _id : partInstanceId4 } as DBPartInstance )
384+ cache . PartInstances . insert ( { _id : partInstanceId3 } as DBPartInstance )
385+ cache . PartInstances . insert ( { _id : partInstanceId0 } as DBPartInstance )
386+
387+ testee . updatePieceInstances ( cache , showStyleBaseId )
388+
389+ // All three tags should be on-air
390+ expect ( testee . getTallyStateFromTags ( { currentPieceTags : [ tag5 ] } as IWrappedAdLib ) ) . toEqual ( {
391+ isActive : true ,
392+ isNext : false ,
393+ } )
394+ expect ( testee . getTallyStateFromTags ( { currentPieceTags : [ tag6 ] } as IWrappedAdLib ) ) . toEqual ( {
395+ isActive : true ,
396+ isNext : false ,
397+ } )
398+ expect ( testee . getTallyStateFromTags ( { currentPieceTags : [ tag0 ] } as IWrappedAdLib ) ) . toEqual ( {
399+ isActive : true ,
400+ isNext : false ,
401+ } )
402+ } )
236403} )
0 commit comments