chromium/third_party/blink/web_tests/webaudio/OfflineAudioContext/onstatechange.html

<!DOCTYPE html>
<html>
  <head>
    <title>
      Test statechange event
    </title>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit-util.js"></script>
    <script src="../resources/audit.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      let audit = Audit.createTaskRunner();
      let secondsToRender = 2;
      let sampleRate = 48000;

      let stateChangeCount = 0;
      let context;
      let contextState;

      function checkStateChange(e, should) {
        contextState = e.currentTarget.state;

        switch (stateChangeCount) {
          case 0:
            should(contextState, 'context.state').beEqualTo('running');
            break;
          case 1:
            should(contextState, 'context.state').beEqualTo('closed');
            break;
          default:
            should(stateChangeCount, 'Number of state changes')
                .beLessThanOrEqualTo(2)
        }
        ++stateChangeCount;
      }

      function finalCheck(should) {
        // Final check that we got the right number of state changes and the
        // correct final state.
        should(stateChangeCount, 'stateChangeCount').beEqualTo(2);
        should(context.state, 'After rendering context.state')
            .beEqualTo('closed');
      }

      audit.define(
          {label: 'test', description: 'Signaling of statechange event'},
          (task, should) => {
            // Create an offline context with a source passing through a
            // convolver.  The convolver is just to waste some time.
            context = new OfflineAudioContext(
                1, secondsToRender * sampleRate, sampleRate);
            let buffer = createImpulseBuffer(context, sampleRate);
            let source = context.createBufferSource();
            let conv = context.createConvolver();

            source.buffer = buffer;
            conv.normalize = false;
            conv.buffer = buffer;

            source.connect(conv);
            conv.connect(context.destination);

            source.start();

            context.onstatechange = (event) => checkStateChange(event, should);

            should(context.startRendering(), 'Context rendering').beResolved();

            // Don't want to set an oncomplete for the context and don't want to
            // use the promise because the order of the state change event and
            // resolving the promise is not specified.  Thus, just wait for a
            // bit and then finish the test.  We assume the offline context runs
            // faster than realtime.
            setTimeout(() => {
              finalCheck(should);
              task.done();
            }, secondsToRender * 1000);
          });

      audit.run();
    </script>
  </body>
</html>