11using FluentAssertions ;
2+ using KristofferStrube . Blazor . DOM ;
23
34namespace IntegrationTests . AudioNodeTests ;
45
@@ -25,7 +26,7 @@ public async Task GetBufferAsync_ShouldReturnNull_WhenItHasNoBuffer()
2526 }
2627
2728 [ Test ]
28- public async Task GetBufferAsync_ShouldReturnBuffer_WhenItHasBuffer ( )
29+ public async Task GetBufferAsync_ShouldRetrieveBuffer_WhenItHasBuffer ( )
2930 {
3031 // Arrange
3132 await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
@@ -42,4 +43,301 @@ public async Task GetBufferAsync_ShouldReturnBuffer_WhenItHasBuffer()
4243 // Assert
4344 _ = readBuffer . Should ( ) . NotBeNull ( ) ;
4445 }
46+
47+ [ Test ]
48+ public async Task SetBufferAsync_ShouldUpdateBuffer_WhenItHasNotBeenSetAlready ( )
49+ {
50+ // Arrange
51+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
52+
53+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context ) ;
54+ await using AudioBuffer buffer = await AudioBuffer . CreateAsync ( JSRuntime , new AudioBufferOptions ( ) { Length = 1 , SampleRate = 8000 } ) ;
55+
56+ // Act
57+ await node . SetBufferAsync ( buffer ) ;
58+
59+ // Assert
60+ AudioBuffer ? readBuffer = await node . GetBufferAsync ( ) ;
61+ _ = readBuffer . Should ( ) . NotBeNull ( ) ;
62+ }
63+
64+ [ Test ]
65+ public async Task SetBufferAsync_WithNullArgument_ShouldUpdateBuffer_WhenItHasAlreadyBeenSet ( )
66+ {
67+ // Arrange
68+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
69+
70+ await using AudioBuffer buffer = await AudioBuffer . CreateAsync ( JSRuntime , new AudioBufferOptions ( ) { Length = 1 , SampleRate = 8000 } ) ;
71+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
72+ {
73+ Buffer = buffer
74+ } ) ;
75+
76+ // Act
77+ await node . SetBufferAsync ( null ) ;
78+
79+ // Assert
80+ AudioBuffer ? readBuffer = await node . GetBufferAsync ( ) ;
81+ _ = readBuffer . Should ( ) . BeNull ( ) ;
82+ }
83+
84+ [ Test ]
85+ [ TestCase ( 1 ) ]
86+ [ TestCase ( - 2 ) ]
87+ public async Task GetPlaybackRateAsync_RetrievesPlaybackRate ( float playbackRate )
88+ {
89+ // Arrange
90+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
91+
92+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
93+ {
94+ PlaybackRate = playbackRate
95+ } ) ;
96+
97+ // Act
98+ await using AudioParam detuneParameter = await node . GetPlaybackRateAsync ( ) ;
99+ float readPlaybackRate = await detuneParameter . GetValueAsync ( ) ;
100+
101+ // Assert
102+ _ = readPlaybackRate . Should ( ) . Be ( playbackRate ) ;
103+ }
104+
105+ [ Test ]
106+ [ TestCase ( 1 ) ]
107+ [ TestCase ( - 2 ) ]
108+ public async Task GetDetuneAsync_RetrievesDetune ( float detune )
109+ {
110+ // Arrange
111+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
112+
113+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
114+ {
115+ Detune = detune
116+ } ) ;
117+
118+ // Act
119+ await using AudioParam detuneParameter = await node . GetDetuneAsync ( ) ;
120+ float readDetune = await detuneParameter . GetValueAsync ( ) ;
121+
122+ // Assert
123+ _ = readDetune . Should ( ) . Be ( detune ) ;
124+ }
125+
126+ [ Test ]
127+ [ TestCase ( true ) ]
128+ [ TestCase ( false ) ]
129+ public async Task GetLoopAsync_RetrievesLoop ( bool loop )
130+ {
131+ // Arrange
132+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
133+
134+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
135+ {
136+ Loop = loop
137+ } ) ;
138+
139+ // Act
140+ bool readLoop = await node . GetLoopAsync ( ) ;
141+
142+ // Assert
143+ _ = readLoop . Should ( ) . Be ( loop ) ;
144+ }
145+
146+ [ Test ]
147+ [ TestCase ( true ) ]
148+ [ TestCase ( false ) ]
149+ public async Task SetLoopAsync_UpdatesLoop ( bool loop )
150+ {
151+ // Arrange
152+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
153+
154+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
155+ {
156+ Loop = ! loop
157+ } ) ;
158+ bool readLoopBeforeSetting = await node . GetLoopAsync ( ) ;
159+
160+ // Act
161+ await node . SetLoopAsync ( loop ) ;
162+
163+ // Assert
164+ bool readLoopAfterSetting = await node . GetLoopAsync ( ) ;
165+ _ = readLoopBeforeSetting . Should ( ) . Be ( ! loop ) ;
166+ _ = readLoopAfterSetting . Should ( ) . Be ( loop ) ;
167+ }
168+
169+ [ Test ]
170+ [ TestCase ( 100 ) ]
171+ [ TestCase ( - 3 ) ]
172+ public async Task GetLoopStartAsync_RetrievesLoopStart ( double loopStart )
173+ {
174+ // Arrange
175+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
176+
177+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
178+ {
179+ LoopStart = loopStart
180+ } ) ;
181+
182+ // Act
183+ double readLoopStart = await node . GetLoopStartAsync ( ) ;
184+
185+ // Assert
186+ _ = readLoopStart . Should ( ) . Be ( loopStart ) ;
187+ }
188+
189+ [ Test ]
190+ [ TestCase ( 100 ) ]
191+ [ TestCase ( - 3 ) ]
192+ public async Task SetLoopStartAsync_UpdatesLoopStart ( double loopStart )
193+ {
194+ // Arrange
195+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
196+
197+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context ) ;
198+
199+ // Act
200+ await node . SetLoopStartAsync ( loopStart ) ;
201+
202+ // Assert
203+ double readLoopStart = await node . GetLoopStartAsync ( ) ;
204+ _ = readLoopStart . Should ( ) . Be ( loopStart ) ;
205+ }
206+
207+ [ Test ]
208+ [ TestCase ( 100 ) ]
209+ [ TestCase ( - 3 ) ]
210+ public async Task GetLoopEndAsync_RetrievesLoopEnd ( double loopEnd )
211+ {
212+ // Arrange
213+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
214+
215+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
216+ {
217+ LoopEnd = loopEnd
218+ } ) ;
219+
220+ // Act
221+ double readLoopEnd = await node . GetLoopEndAsync ( ) ;
222+
223+ // Assert
224+ _ = readLoopEnd . Should ( ) . Be ( loopEnd ) ;
225+ }
226+
227+ [ Test ]
228+ [ TestCase ( 100 ) ]
229+ [ TestCase ( - 3 ) ]
230+ public async Task SetLoopEndAsync_UpdatesLoopEnd ( double loopEnd )
231+ {
232+ // Arrange
233+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
234+
235+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context ) ;
236+
237+ // Act
238+ await node . SetLoopEndAsync ( loopEnd ) ;
239+
240+ // Assert
241+ double readLoopEnd = await node . GetLoopEndAsync ( ) ;
242+ _ = readLoopEnd . Should ( ) . Be ( loopEnd ) ;
243+ }
244+
245+ [ Test ]
246+ public async Task StartAsync_WithNoArguments_StartsNodeImmediately ( )
247+ {
248+ // Arrange
249+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
250+
251+ await using AudioBuffer buffer = await AudioBuffer . CreateAsync ( JSRuntime , new AudioBufferOptions ( )
252+ {
253+ SampleRate = 8000 ,
254+ Length = 1
255+ } ) ;
256+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
257+ {
258+ Buffer = buffer
259+ } ) ;
260+
261+ bool eventListenerTriggered = false ;
262+ await using EventListener < Event > onEndedListener = await EventListener < Event > . CreateAsync ( JSRuntime , e => eventListenerTriggered = true ) ;
263+ await node . AddOnEndedEventListenerAsync ( onEndedListener ) ;
264+
265+ // Act
266+ await node . StartAsync ( ) ;
267+
268+ // Assert
269+ await Task . Delay ( 100 ) ;
270+ _ = eventListenerTriggered . Should ( ) . BeTrue ( ) ;
271+ await node . RemoveOnEndedEventListenerAsync ( onEndedListener ) ;
272+ }
273+
274+ [ Test ]
275+ [ TestCase ( 0.2 ) ]
276+ [ TestCase ( 0.4 ) ]
277+ public async Task StartAsync_WithWhenArgument_StartsNodeThen ( double whenOffset )
278+ {
279+ // Arrange
280+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
281+
282+ await using AudioBuffer buffer = await AudioBuffer . CreateAsync ( JSRuntime , new AudioBufferOptions ( )
283+ {
284+ SampleRate = 8000 ,
285+ Length = 1
286+ } ) ;
287+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
288+ {
289+ Buffer = buffer
290+ } ) ;
291+
292+ bool eventListenerTriggered = false ;
293+ await using EventListener < Event > onEndedListener = await EventListener < Event > . CreateAsync ( JSRuntime , e => eventListenerTriggered = true ) ;
294+ await node . AddOnEndedEventListenerAsync ( onEndedListener ) ;
295+
296+ // Act
297+ double time = await context . GetCurrentTimeAsync ( ) ;
298+ await node . StartAsync ( when : time + whenOffset ) ;
299+
300+ // Assert
301+ await Task . Delay ( TimeSpan . FromSeconds ( whenOffset - 0.1 ) ) ;
302+ _ = eventListenerTriggered . Should ( ) . BeFalse ( ) ;
303+ await Task . Delay ( TimeSpan . FromSeconds ( 0.2 ) ) ;
304+ _ = eventListenerTriggered . Should ( ) . BeTrue ( ) ;
305+ await node . RemoveOnEndedEventListenerAsync ( onEndedListener ) ;
306+ }
307+
308+ [ Test ]
309+ [ TestCase ( 0.2 ) ]
310+ [ TestCase ( 0.7 ) ]
311+ public async Task StartAsync_WithOffsetParameter_StartsOffsetInBuffer ( double offset )
312+ {
313+ // Arrange
314+ await using AudioContext context = await AudioContext . CreateAsync ( JSRuntime ) ;
315+
316+ await using AudioBuffer buffer = await AudioBuffer . CreateAsync ( JSRuntime , new AudioBufferOptions ( )
317+ {
318+ SampleRate = 8000 ,
319+ Length = 8000 * 1 ,
320+ } ) ;
321+
322+ var a = await buffer . GetDurationAsync ( ) ;
323+
324+ await using AudioBufferSourceNode node = await AudioBufferSourceNode . CreateAsync ( JSRuntime , context , new ( )
325+ {
326+ Buffer = buffer
327+ } ) ;
328+
329+ bool eventListenerTriggered = false ;
330+ await using EventListener < Event > onEndedListener = await EventListener < Event > . CreateAsync ( JSRuntime , e => eventListenerTriggered = true ) ;
331+ await node . AddOnEndedEventListenerAsync ( onEndedListener ) ;
332+
333+ // Act
334+ await node . StartAsync ( when : 0 , offset : offset ) ;
335+
336+ // Assert
337+ await Task . Delay ( TimeSpan . FromSeconds ( 1 - offset - 0.1 ) ) ;
338+ _ = eventListenerTriggered . Should ( ) . BeFalse ( ) ;
339+ await Task . Delay ( TimeSpan . FromSeconds ( offset + 0.1 ) ) ;
340+ _ = eventListenerTriggered . Should ( ) . BeTrue ( ) ;
341+ await node . RemoveOnEndedEventListenerAsync ( onEndedListener ) ;
342+ }
45343}
0 commit comments