55
66import { describe , expect , it , vi } from "vitest" ;
77
8- import type {
9- INoteStyle , IPolyrhythm , ITimeParamsView , Mutable
10- } from "../../src/core/types/general.js" ;
11- import type {
12- ICallbackEvent , IInterval , ILoopInterval , ITimeCoordinator , ITrackPlayer
13- } from "../../src/player/types.js" ;
8+ import type { INoteStyle , IPolyrhythm , ITimeParams , Mutable } from "../../src/core/types/general.js" ;
9+ import type { ICallbackEvent , IInterval , ILoopInterval , } from "../../src/player/types.js" ;
1410
1511// Simple subscribable helper with publish capability for tests
1612type Sub = ( ...args : unknown [ ] ) => void ;
1713
1814type CallbackHelper = { callback : ( ) => void ; } & { realTime : number ; } & { identifier : unknown ; } ;
1915
20- interface PublishableSubscribable { subscribe : ( cb : Sub ) => void ; unsubscribe : ( cb : Sub ) => void ; publish : ( ) => void ; }
16+ interface PublishableSubscribable {
17+ subscribe : ( cb : Sub ) => ( ) => void ; unsubscribe : ( cb : Sub ) => void ;
18+ publish : ( ) => void ;
19+ }
20+
2121const makeSubscribable = ( ) : PublishableSubscribable => {
2222 const subs : Sub [ ] = [ ] ;
2323
2424 return {
2525 subscribe : ( cb : Sub ) => {
2626 subs . push ( cb ) ;
27+
28+ return ( ) => {
29+ const i = subs . indexOf ( cb ) ;
30+ if ( i !== - 1 ) {
31+ subs . splice ( i , 1 ) ;
32+ }
33+ } ;
2734 } ,
2835 unsubscribe : ( cb : Sub ) => {
2936 const i = subs . indexOf ( cb ) ;
@@ -41,11 +48,11 @@ const makeSubscribable = (): PublishableSubscribable => {
4148
4249// Mock TimeCoordinator used by ArrangementPlayer
4350vi . mock ( "../../src/player/TimeCoordinator.js" , ( ) => {
44- class MockTimeCoordinator implements ITimeCoordinator {
51+ class MockTimeCoordinator {
4552 public realTimeLength : RealTime ;
4653 private readonly subs = makeSubscribable ( ) ;
4754
48- public constructor ( _timeParams : ITimeParamsView ) {
55+ public constructor ( _timeParams : ITimeParams ) {
4956 this . realTimeLength = 1 ;
5057 }
5158
@@ -92,12 +99,12 @@ vi.mock("../../src/player/TimeCoordinator.js", () => {
9299
93100// Mock TrackPlayer used inside ArrangementPlayer
94101vi . mock ( "../../src/player/TrackPlayer.js" , ( ) => {
95- class MockTrackPlayer implements ITrackPlayer {
102+ class MockTrackPlayer {
96103 public soloMute : null | "solo" | "mute" = null ;
97104 public readonly currentPolyrhythmNotePublisher = makeSubscribable ( ) ;
98105 public stopped = false ;
99106 private readonly subs = makeSubscribable ( ) ;
100- public constructor ( public track : ISbDmTrack , _tc : ITimeCoordinator ) { }
107+ public constructor ( public track : ISbDmTrack , _tc : TimeCoordinator ) { }
101108
102109 public get currentPolyrhythmNote ( ) : ISbDmNote | null {
103110 return null ;
@@ -114,7 +121,7 @@ vi.mock("../../src/player/TrackPlayer.js", () => {
114121 }
115122 } ) ;
116123
117- return events as unknown as ReturnType < ITrackPlayer [ "getEvents" ] > ;
124+ return events ;
118125 }
119126
120127 public subscribe ( cb : Sub ) : void {
@@ -159,7 +166,7 @@ const makeNote = (track: ISbDmTrack, timing: ITiming, noteStyle?: INoteStyle,
159166const makeArrangement = ( trackCount : number ) : ISbDmArrangement & { _publish : ( ) => void ; } => {
160167 const arrangementSubs = makeSubscribable ( ) ;
161168 const timeParamsSubs = makeSubscribable ( ) ;
162- const timeParams : ITimeParamsView & { _publish : ( ) => void ; } = {
169+ const timeParams : ITimeParams & { _publish : ( ) => void ; } = {
163170 timeSignature : "4/4" ,
164171 tempo : 120 ,
165172 length : 1 ,
@@ -202,7 +209,7 @@ const makeArrangement = (trackCount: number): ISbDmArrangement & { _publish: ()
202209 id : i ,
203210 filePath : `path/to/image${ i } .png` ,
204211 } ,
205- colourGroup : "blue" ,
212+ color : "blue" ,
206213 noteStyles : { } ,
207214 ...makeSubscribable ( )
208215 } ;
@@ -265,6 +272,8 @@ import {
265272} from "../../src/core/ScoreBookDataModel.js" ;
266273import { ArrangementPlayer } from "../../src/player/ArrangementPlayer.js" ;
267274import { getNewId } from "../../src/core/utils.js" ;
275+ import type { TimeCoordinator } from "../../src/player/TimeCoordinator.js" ;
276+ import type { TrackPlayer } from "../../src/player/TrackPlayer.js" ;
268277
269278describe ( "ArrangementPlayer" , ( ) => {
270279 it ( "creates track players and computes audible set (no solo)" , ( ) => {
@@ -278,7 +287,7 @@ describe("ArrangementPlayer", () => {
278287 it ( "audible set reacts to solo/mute changes via subscriptions" , ( ) => {
279288 const arrangement = makeArrangement ( 3 ) ;
280289 const player = new ArrangementPlayer ( arrangement ) ;
281- const tps = Array . from ( player . trackPlayers . values ( ) ) as Array < ITrackPlayer & { publish : ( ) => void ; } > ;
290+ const tps = Array . from ( player . trackPlayers . values ( ) ) as Array < TrackPlayer & { publish : ( ) => void ; } > ;
282291
283292 // Solo the second track
284293 tps [ 1 ] . soloMute = "solo" ;
@@ -331,7 +340,8 @@ describe("ArrangementPlayer", () => {
331340 const arrangement = makeArrangement ( 1 ) ;
332341 const player = new ArrangementPlayer ( arrangement ) ;
333342
334- // Interval crosses loop boundary (length=1): [0.9, 1.2]
343+ // Interval crosses loop boundary (length=1): [0.9, 1.2].
344+ // @ts -expect-error Accessing internal for test purposes
335345 const events = player . getEvents ( { start : 0.9 , end : 1.2 } ) ;
336346 expect ( events . length ) . toBeGreaterThan ( 0 ) ;
337347 // Ensure sorted order
@@ -344,7 +354,7 @@ describe("ArrangementPlayer", () => {
344354 return ( "callback" in e ) && ( "identifier" in e ) ;
345355 } ) ;
346356 const currentTimingUpdates : number [ ] = [ ] ;
347- player . currentTimingPublisher . subscribe ( ( ) => {
357+ player . subscribe ( ( ) => {
348358 currentTimingUpdates . push ( 1 ) ;
349359 } ) ;
350360 cb ?. callback ( ) ;
@@ -356,7 +366,8 @@ describe("ArrangementPlayer", () => {
356366 const arrangement = makeArrangement ( 2 ) ;
357367 const player = new ArrangementPlayer ( arrangement ) ;
358368
359- // Prime currentTiming by firing a timing callback
369+ // Prime currentTiming by firing a timing callback.
370+ // @ts -expect-error Accessing internal for test purposes
360371 const events = player . getEvents ( { start : 0 , end : 0.5 } ) ;
361372 const timingCb = events . find ( ( e ) : e is ICallbackEvent & { identifier : unknown ; } => {
362373 return ( "callback" in e ) && ( "identifier" in e ) ;
@@ -368,7 +379,7 @@ describe("ArrangementPlayer", () => {
368379 player . onStop ( ) ;
369380 expect ( player . currentTiming ) . toBeNull ( ) ;
370381
371- const tps = Array . from ( player . trackPlayers . values ( ) ) as Array < ITrackPlayer & { stopped : boolean ; } > ;
382+ const tps = Array . from ( player . trackPlayers . values ( ) ) as Array < TrackPlayer & { stopped : boolean ; } > ;
372383 tps . forEach ( ( tp ) => {
373384 expect ( tp . stopped ) . toBe ( true ) ;
374385 } ) ;
0 commit comments