4 <title>Test AudioContext.suspend() and AudioContext.resume()
</title>
5 <script src=
"../resources/js-test.js"></script>
6 <script src=
"resources/compatibility.js"></script>
7 <script src=
"resources/audio-testing.js"></script>
12 description("Test suspend/resume for an (offline) AudioContext");
13 window
.jsTestIsAsync
= true;
21 var sampleRate
= 44100;
22 var durationInSeconds
= 1;
24 var audit
= Audit
.createTaskRunner();
26 // Convenience function that returns a function that calls the |passFailFunc|
27 // with the given |message|. The |passFailFunc| should be either |testPassed|
29 function handlePromise(passFailFunc
, message
) {
31 passFailFunc(message
);
35 // Task: test suspend().
36 audit
.defineTask('test-suspend', function (done
) {
38 // Test suspend/resume. Ideally this test is best with a online
39 // AudioContext, but content shell doesn't really have a working online
40 // AudioContext. Hence, use an OfflineAudioContext. Not all possible
41 // scenarios can be easily checked with an offline context instead of an
44 // Create an audio context with an oscillator.
45 shouldNotThrow("offlineContext = new OfflineAudioContext(1, durationInSeconds * sampleRate, sampleRate)");
46 osc
= offlineContext
.createOscillator();
47 osc
.connect(offlineContext
.destination
);
50 shouldBeEqualToString("offlineContext.state", "suspended");
52 // Multiple calls to suspend() should not be a problem. But we can't test
53 // that on an offline context. Thus, check that suspend() on an
54 // OfflineAudioContext rejects the promise.
55 shouldNotThrow("p1 = offlineContext.suspend()");
56 shouldBeType("p1", "Promise");
58 handlePromise(testFailed
, "offlineContext.suspend() should have been rejected for an offline context"),
60 if (e
.name
=== "InvalidAccessError") {
62 "offlineContext.suspend() was correctly rejected: " + e
);
65 "offlineContext.suspend() was correctly rejected but expected InvalidAccessError, not: " + e
);
72 // Task: test resume().
73 audit
.defineTask('test-resume', function (done
) {
75 // Multiple calls to resume should not be a problem. But we can't test
76 // that on an offline context. Thus, check that resume() on an
77 // OfflineAudioContext rejects the promise.
78 shouldNotThrow("p2 = offlineContext.resume()");
79 shouldBeType("p2", "Promise");
81 // Resume doesn't actually resume an offline context
82 shouldBeEqualToString("offlineContext.state", "suspended");
84 handlePromise(testFailed
, "offlineContext.resume() should have been rejected for an offline context"),
86 if (e
.name
=== "InvalidAccessError") {
88 "offlineContext.resume() was correctly rejected: " + e
);
91 "offlineContext.resume() was correctly rejected but expected InvalidAccessError, not: " + e
);
97 // Task: test the state after context closed.
98 audit
.defineTask('test-after-close', function (done
) {
100 // Render the offline context.
103 // Test suspend/resume in tested promise pattern. We don't care about the
104 // actual result of the offline rendering.
105 shouldNotThrow("p3 = offlineContext.startRendering()");
106 p3
.then(function () {
107 shouldBeEqualToString("offlineContext.state", "closed");
109 // suspend() should be rejected on a closed context.
110 offlineContext
.suspend().then(
111 handlePromise(testFailed
, "offlineContext.suspend() on a closed context not rejected"),
113 if (e
.name
=== "InvalidAccessError") {
114 testPassed("offlineContext.suspend() on a closed context rejected: " + e
);
116 testFailed("offlineContext.suspend() on a closed context rejected but expected InvalidAccessError, not: " + e
);
120 // resume() should be rejected on closed context.
121 offlineContext
.resume().then(
122 handlePromise(testFailed
, "offlineContext.resume() on a closed context not rejected"),
124 if (e
.name
=== "InvalidAccessError") {
125 testPassed("offlineContext.resume() on a closed context rejected: " + e
);
127 testFailed("offlineContext.resume() on a closed context rejected but expected InvalidAccessError, not: " + e
);
136 audit
.defineTask('finish-test', function (done
) {
148 successfullyParsed
= true;