@@ -31,10 +31,16 @@ describe("setupDrumActions", () => {
3131 } ;
3232 global . DEFAULTDRUM = "defaultDrum" ;
3333 global . DRUMNAMES = { drum1 : [ "d1" , "drum1" ] , drum2 : [ "d2" , "drum2" ] } ;
34- global . NOISENAMES = { noise1 : [ "n1" , "noise1" ] } ;
34+ global . NOISENAMES = { noise1 : [ "n1" , "noise1" ] , noise2 : [ "n2" , "noise2" ] } ;
3535 global . DEFAULTVOLUME = 100 ;
3636 global . last = jest . fn ( array => array [ array . length - 1 ] ) ;
3737 global . _ = jest . fn ( msg => msg ) ;
38+ global . MusicBlocks = {
39+ isRun : false
40+ } ;
41+ global . Mouse = {
42+ getMouseFromTurtle : jest . fn ( )
43+ } ;
3844 } ) ;
3945
4046 beforeEach ( ( ) => {
@@ -51,6 +57,7 @@ describe("setupDrumActions", () => {
5157 clearNoteParams : jest . fn ( ) ,
5258 inRhythmRuler : false ,
5359 rhythmRuler : { Drums : [ ] , Rulers : [ ] } ,
60+ _currentDrumBlock : null
5461 } ,
5562 errorMsg : jest . fn ( ) ,
5663 } ;
@@ -65,72 +72,239 @@ describe("setupDrumActions", () => {
6572 noteBeatValues : { } ,
6673 beatFactor : 1 ,
6774 pushedNote : false ,
75+ pitchDrumTable : { }
6876 } ,
6977 } ;
7078
7179 activity . turtles . ithTurtle . mockReturnValue ( targetTurtle ) ;
80+ global . MusicBlocks . isRun = false ;
81+ global . Mouse . getMouseFromTurtle . mockReturnValue ( null ) ;
7282 setupDrumActions ( activity ) ;
7383 } ) ;
7484
75- it ( "should return the correct drum name" , ( ) => {
76- const result = Singer . DrumActions . GetDrumname ( "d1" ) ;
77- expect ( result ) . toBe ( "drum1" ) ;
85+ describe ( "GetDrumname" , ( ) => {
86+ it ( "should return the correct drum name when given nickname" , ( ) => {
87+ const result = Singer . DrumActions . GetDrumname ( "d1" ) ;
88+ expect ( result ) . toBe ( "drum1" ) ;
89+ } ) ;
90+
91+ it ( "should return the default drum for unknown drums" , ( ) => {
92+ const result = Singer . DrumActions . GetDrumname ( "unknown" ) ;
93+ expect ( result ) . toBe ( DEFAULTDRUM ) ;
94+ } ) ;
7895
79- const result2 = Singer . DrumActions . GetDrumname ( "unknown" ) ;
80- expect ( result2 ) . toBe ( DEFAULTDRUM ) ;
81- } ) ;
96+ it ( "should return http URLs directly" , ( ) => {
97+ const httpDrum = "https://example.com/drum.wav" ;
98+ const result = Singer . DrumActions . GetDrumname ( httpDrum ) ;
99+ expect ( result ) . toBe ( httpDrum ) ;
100+ } ) ;
82101
83- it ( "should play a standalone drum sound" , ( ) => {
84- if ( ! targetTurtle . singer . noteDrums [ 1 ] ) targetTurtle . singer . noteDrums [ 1 ] = [ ] ;
85- Singer . DrumActions . playDrum ( "d1" , 0 , 1 ) ;
86- expect ( Singer . processNote ) . toHaveBeenCalledWith (
87- activity ,
88- expect . any ( Number ) ,
89- false ,
90- expect . anything ( ) ,
91- 0 ,
92- expect . any ( Function )
93- ) ;
94- expect ( activity . logo . clearNoteParams ) . toHaveBeenCalledWith ( targetTurtle , 1 , [ ] ) ;
95- expect ( targetTurtle . singer . inNoteBlock ) . toContain ( 1 ) ;
96- expect ( targetTurtle . singer . noteDrums [ 1 ] ) . toContain ( "drum1" ) ;
97- expect ( targetTurtle . singer . pushedNote ) . toBe ( true ) ;
102+ it ( "should handle direct drum names" , ( ) => {
103+ const result = Singer . DrumActions . GetDrumname ( "drum1" ) ;
104+ expect ( result ) . toBe ( "drum1" ) ;
105+ } ) ;
98106 } ) ;
99-
100107
101- it ( "should add a drum to an existing note block" , ( ) => {
102- targetTurtle . singer . inNoteBlock . push ( 2 ) ;
103- targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
104- Singer . DrumActions . playDrum ( "d1" , 0 , 1 ) ;
105- expect ( targetTurtle . singer . noteDrums [ 2 ] ) . toContain ( "drum1" ) ;
106- } ) ;
108+ describe ( "playDrum" , ( ) => {
109+ it ( "should play a standalone drum sound" , ( ) => {
110+ if ( ! targetTurtle . singer . noteDrums [ 1 ] ) targetTurtle . singer . noteDrums [ 1 ] = [ ] ;
111+ Singer . DrumActions . playDrum ( "d1" , 0 , 1 ) ;
112+ expect ( Singer . processNote ) . toHaveBeenCalledWith (
113+ activity ,
114+ expect . any ( Number ) ,
115+ false ,
116+ expect . anything ( ) ,
117+ 0 ,
118+ expect . any ( Function )
119+ ) ;
120+ expect ( activity . logo . clearNoteParams ) . toHaveBeenCalledWith ( targetTurtle , 1 , [ ] ) ;
121+ expect ( targetTurtle . singer . inNoteBlock ) . toContain ( 1 ) ;
122+ expect ( targetTurtle . singer . noteDrums [ 1 ] ) . toContain ( "drum1" ) ;
123+ expect ( targetTurtle . singer . pushedNote ) . toBe ( true ) ;
124+ } ) ;
125+
126+ it ( "should add a drum to an existing note block" , ( ) => {
127+ targetTurtle . singer . inNoteBlock . push ( 2 ) ;
128+ targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
129+ Singer . DrumActions . playDrum ( "d1" , 0 , 1 ) ;
130+ expect ( targetTurtle . singer . noteDrums [ 2 ] ) . toContain ( "drum1" ) ;
131+ } ) ;
107132
108- it ( "should set the drum style and add a listener" , ( ) => {
109- Singer . DrumActions . setDrum ( "d1" , 0 , 1 ) ;
110- expect ( targetTurtle . singer . drumStyle ) . toContain ( "drum1" ) ;
111- expect ( activity . logo . setDispatchBlock ) . toHaveBeenCalledWith ( 1 , 0 , "_setdrum_0" ) ;
112- expect ( activity . logo . setTurtleListener ) . toHaveBeenCalledWith ( 0 , "_setdrum_0" , expect . any ( Function ) ) ;
113- } ) ;
133+ it ( "should use the drum style if one is set" , ( ) => {
134+ targetTurtle . singer . inNoteBlock . push ( 2 ) ;
135+ targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
136+ targetTurtle . singer . drumStyle . push ( "drum2" ) ;
137+
138+ Singer . DrumActions . playDrum ( "d1" , 0 , 1 ) ;
139+
140+ expect ( targetTurtle . singer . noteDrums [ 2 ] ) . toContain ( "drum2" ) ;
141+ expect ( targetTurtle . singer . noteDrums [ 2 ] ) . not . toContain ( "drum1" ) ;
142+ } ) ;
114143
115- it ( "should map pitch to drum" , ( ) => {
116- Singer . DrumActions . mapPitchToDrum ( "d1" , 0 , 1 ) ;
117- expect ( targetTurtle . singer . drumStyle ) . toContain ( "drum1" ) ;
118- expect ( activity . logo . setDispatchBlock ) . toHaveBeenCalledWith ( 1 , 0 , "_mapdrum_0" ) ;
119- expect ( activity . logo . setTurtleListener ) . toHaveBeenCalledWith ( 0 , "_mapdrum_0" , expect . any ( Function ) ) ;
144+ it ( "should initialize synthVolume if not defined" , ( ) => {
145+ targetTurtle . singer . inNoteBlock . push ( 2 ) ;
146+ targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
147+ targetTurtle . singer . synthVolume = { } ;
148+
149+ Singer . DrumActions . playDrum ( "d1" , 0 , 1 ) ;
150+
151+ expect ( targetTurtle . singer . synthVolume [ "drum1" ] ) . toEqual ( [ DEFAULTVOLUME ] ) ;
152+ expect ( targetTurtle . singer . crescendoInitialVolume [ "drum1" ] ) . toEqual ( [ DEFAULTVOLUME ] ) ;
153+ } ) ;
154+
155+ it ( "should not overwrite existing synthVolume and crescendoInitialVolume" , ( ) => {
156+ targetTurtle . singer . inNoteBlock . push ( 5 ) ;
157+ targetTurtle . singer . noteDrums [ 5 ] = [ ] ;
158+ targetTurtle . singer . synthVolume = { drum1 : [ 30 ] } ;
159+ targetTurtle . singer . crescendoInitialVolume = { drum1 : [ 40 ] } ;
160+ Singer . DrumActions . playDrum ( "d1" , 0 , 5 ) ;
161+ expect ( targetTurtle . singer . synthVolume [ "drum1" ] ) . toEqual ( [ 30 ] ) ;
162+ expect ( targetTurtle . singer . crescendoInitialVolume [ "drum1" ] ) . toEqual ( [ 40 ] ) ;
163+ } ) ;
164+
165+ it ( "should remove the block from inNoteBlock when the callback is invoked" , ( ) => {
166+ if ( ! targetTurtle . singer . noteDrums [ 2 ] ) targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
167+ Singer . DrumActions . playDrum ( "d1" , 0 , 2 ) ;
168+ expect ( targetTurtle . singer . inNoteBlock ) . toContain ( 2 ) ;
169+ const callback = Singer . processNote . mock . calls [ 0 ] [ 5 ] ;
170+ callback ( ) ;
171+ expect ( targetTurtle . singer . inNoteBlock ) . not . toContain ( 2 ) ;
172+ } ) ;
120173 } ) ;
121174
122- it ( "should play noise in a note block" , ( ) => {
123- targetTurtle . singer . inNoteBlock . push ( 2 ) ;
124- targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
125- targetTurtle . singer . noteBeatValues [ 2 ] = [ ] ;
126- Singer . DrumActions . playNoise ( "n1" , 0 , 1 ) ;
127- expect ( targetTurtle . singer . noteDrums [ 2 ] ) . toContain ( "noise1" ) ;
128- expect ( targetTurtle . singer . noteBeatValues [ 2 ] ) . toContain ( 1 ) ;
129- expect ( targetTurtle . singer . pushedNote ) . toBe ( true ) ;
175+ const actionConfigs = [
176+ [ 'setDrum' , '_setdrum_0' , true ] ,
177+ [ 'mapPitchToDrum' , '_mapdrum_0' , false ] ,
178+ ] ;
179+ describe . each ( actionConfigs ) ( "%s" , ( actionName , prefix , resetPitchDrumTable ) => {
180+ beforeEach ( ( ) => {
181+ targetTurtle . singer . drumStyle = [ ] ;
182+ targetTurtle . singer . pitchDrumTable = { } ;
183+ activity . logo . setDispatchBlock . mockClear ( ) ;
184+ activity . logo . setTurtleListener . mockClear ( ) ;
185+ global . MusicBlocks . isRun = false ;
186+ global . Mouse . getMouseFromTurtle . mockReturnValue ( null ) ;
187+ } ) ;
188+
189+ it ( 'sets drum style and listener' , ( ) => {
190+ Singer . DrumActions [ actionName ] ( "d1" , 0 , 1 ) ;
191+ expect ( targetTurtle . singer . drumStyle ) . toContain ( 'drum1' ) ;
192+ expect ( activity . logo . setDispatchBlock ) . toHaveBeenCalledWith ( 1 , 0 , prefix ) ;
193+ expect ( activity . logo . setTurtleListener ) . toHaveBeenCalledWith ( 0 , prefix , expect . any ( Function ) ) ;
194+ } ) ;
195+
196+ it ( 'handles MusicBlocks.isRun case' , ( ) => {
197+ const mockMouse = { MB : { listeners : [ ] } } ;
198+ global . MusicBlocks . isRun = true ;
199+ global . Mouse . getMouseFromTurtle . mockReturnValue ( mockMouse ) ;
200+ Singer . DrumActions [ actionName ] ( 'd1' , 0 ) ;
201+ expect ( targetTurtle . singer . drumStyle ) . toContain ( 'drum1' ) ;
202+ expect ( mockMouse . MB . listeners ) . toContain ( prefix ) ;
203+ } ) ;
204+
205+ it ( 'handles direct drum name input' , ( ) => {
206+ Singer . DrumActions [ actionName ] ( 'drum2' , 0 , 1 ) ;
207+ expect ( targetTurtle . singer . drumStyle ) . toContain ( 'drum2' ) ;
208+ } ) ;
209+
210+ it ( 'handles rhythm ruler' , ( ) => {
211+ activity . logo . inRhythmRuler = true ;
212+ Singer . DrumActions [ actionName ] ( 'd1' , 0 , 1 ) ;
213+ expect ( activity . logo . _currentDrumBlock ) . toBe ( 1 ) ;
214+ expect ( activity . logo . rhythmRuler . Drums ) . toContain ( 1 ) ;
215+ expect ( activity . logo . rhythmRuler . Rulers ) . toHaveLength ( 1 ) ;
216+ } ) ;
217+
218+ it ( 'removes drumStyle on listener' , ( ) => {
219+ Singer . DrumActions [ actionName ] ( 'd1' , 0 , 1 ) ;
220+ const listenerFn = activity . logo . setTurtleListener . mock . calls [ 0 ] [ 2 ] ;
221+ listenerFn ( ) ;
222+ expect ( targetTurtle . singer . drumStyle ) . toHaveLength ( 0 ) ;
223+ if ( resetPitchDrumTable ) {
224+ expect ( targetTurtle . singer . pitchDrumTable ) . toEqual ( { } ) ;
225+ }
226+ } ) ;
227+
228+ it ( 'only adds listener when blk undefined and not running' , ( ) => {
229+ Singer . DrumActions [ actionName ] ( 'd1' , 0 ) ;
230+ expect ( activity . logo . setDispatchBlock ) . not . toHaveBeenCalled ( ) ;
231+ expect ( global . Mouse . getMouseFromTurtle ) . not . toHaveBeenCalled ( ) ;
232+ expect ( activity . logo . setTurtleListener ) . toHaveBeenCalledWith (
233+ 0 ,
234+ expect . any ( String ) ,
235+ expect . any ( Function )
236+ ) ;
237+ } ) ;
238+
239+ it ( 'skips mouse listener when isRun and mouse null' , ( ) => {
240+ global . MusicBlocks . isRun = true ;
241+ global . Mouse . getMouseFromTurtle . mockReturnValue ( null ) ;
242+ Singer . DrumActions [ actionName ] ( 'd1' , 0 ) ;
243+ expect ( activity . logo . setDispatchBlock ) . not . toHaveBeenCalled ( ) ;
244+ expect ( global . Mouse . getMouseFromTurtle ) . toHaveBeenCalledWith ( expect . any ( Object ) ) ;
245+ expect ( activity . logo . setTurtleListener ) . toHaveBeenCalledWith (
246+ 0 ,
247+ expect . any ( String ) ,
248+ expect . any ( Function )
249+ ) ;
250+ } ) ;
130251 } ) ;
131252
132- it ( "should throw an error for standalone noise block" , ( ) => {
133- Singer . DrumActions . playNoise ( "n1" , 0 , 1 ) ;
134- expect ( activity . errorMsg ) . toHaveBeenCalledWith ( "Noise Block: Did you mean to use a Note block?" , 1 ) ;
253+ describe ( "playNoise" , ( ) => {
254+ it ( "should play noise in a note block" , ( ) => {
255+ targetTurtle . singer . inNoteBlock . push ( 2 ) ;
256+ targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
257+ targetTurtle . singer . noteBeatValues [ 2 ] = [ ] ;
258+ Singer . DrumActions . playNoise ( "n1" , 0 , 1 ) ;
259+ expect ( targetTurtle . singer . noteDrums [ 2 ] ) . toContain ( "noise1" ) ;
260+ expect ( targetTurtle . singer . noteBeatValues [ 2 ] ) . toContain ( 1 ) ;
261+ expect ( targetTurtle . singer . pushedNote ) . toBe ( true ) ;
262+ } ) ;
263+
264+ it ( "should throw an error for standalone noise block" , ( ) => {
265+ Singer . DrumActions . playNoise ( "n1" , 0 , 1 ) ;
266+ expect ( activity . errorMsg ) . toHaveBeenCalledWith ( "Noise Block: Did you mean to use a Note block?" , 1 ) ;
267+ } ) ;
268+
269+ it ( "should handle direct noise name input" , ( ) => {
270+ targetTurtle . singer . inNoteBlock . push ( 2 ) ;
271+ targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
272+ targetTurtle . singer . noteBeatValues [ 2 ] = [ ] ;
273+
274+ Singer . DrumActions . playNoise ( "noise2" , 0 , 1 ) ;
275+
276+ expect ( targetTurtle . singer . noteDrums [ 2 ] ) . toContain ( "noise2" ) ;
277+ } ) ;
278+
279+ it ( "should initialize synthVolume if not defined" , ( ) => {
280+ targetTurtle . singer . inNoteBlock . push ( 2 ) ;
281+ targetTurtle . singer . noteDrums [ 2 ] = [ ] ;
282+ targetTurtle . singer . noteBeatValues [ 2 ] = [ ] ;
283+ targetTurtle . singer . synthVolume = { } ;
284+
285+ Singer . DrumActions . playNoise ( "n1" , 0 , 1 ) ;
286+
287+ expect ( targetTurtle . singer . synthVolume [ "noise1" ] ) . toEqual ( [ DEFAULTVOLUME ] ) ;
288+ expect ( targetTurtle . singer . crescendoInitialVolume [ "noise1" ] ) . toEqual ( [ DEFAULTVOLUME ] ) ;
289+ } ) ;
290+
291+ it ( "should push unknown noise names directly" , ( ) => {
292+ targetTurtle . singer . inNoteBlock . push ( 3 ) ;
293+ targetTurtle . singer . noteDrums [ 3 ] = [ ] ;
294+ targetTurtle . singer . noteBeatValues [ 3 ] = [ ] ;
295+ Singer . DrumActions . playNoise ( "foo" , 0 , 3 ) ;
296+ expect ( targetTurtle . singer . noteDrums [ 3 ] ) . toContain ( "foo" ) ;
297+ } ) ;
298+
299+ it ( "should not reinitialize synthVolume if already defined" , ( ) => {
300+ targetTurtle . singer . inNoteBlock . push ( 4 ) ;
301+ targetTurtle . singer . noteDrums [ 4 ] = [ ] ;
302+ targetTurtle . singer . noteBeatValues [ 4 ] = [ ] ;
303+ targetTurtle . singer . synthVolume = { noise1 : [ 50 ] } ;
304+ targetTurtle . singer . crescendoInitialVolume = { noise1 : [ 60 ] } ;
305+ Singer . DrumActions . playNoise ( "n1" , 0 , 4 ) ;
306+ expect ( targetTurtle . singer . synthVolume [ "noise1" ] ) . toEqual ( [ 50 ] ) ;
307+ expect ( targetTurtle . singer . crescendoInitialVolume [ "noise1" ] ) . toEqual ( [ 60 ] ) ;
308+ } ) ;
135309 } ) ;
136- } ) ;
310+ } ) ;
0 commit comments