Conformance Tests from lists.w3.org/Archives/Public/public-speech-api/2012Dec/0001.html
authorGlen Shires <gshires@google.com>
Fri, 20 Feb 2015 08:58:23 -0800
changeset 75 6117f5bea58d
parent 74 09b82979be01
child 76 4f41ea1126bb
Conformance Tests from lists.w3.org/Archives/Public/public-speech-api/2012Dec/0001.html
conformance/abort.html
conformance/nospeech.html
conformance/onresult.html
conformance/stop.html
conformance/webspeech.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conformance/abort.html	Fri Feb 20 08:58:23 2015 -0800
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>SpeechRecognition.abort</title>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharness.js">
+    </script>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharnessreport.js">
+    </script>
+    <script type="text/javascript" src="webspeech.js"></script>
+  </head>
+  <body>
+    <h1>Conformance test for Web Speech API SpeechRecognition.abort</h1>
+    <p><b>Version</b>: Test is based on W3C
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/9a0075d25326/speechapi.html">
+        Web Speech API Specification</a> 19 October 2012 and
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi-errata.html">
+        Errata</a> through December 7, 2012.
+      <br>
+      <b>Prerequisites</b>: The machine that the test is executed on must have
+        a microphone.
+      <br>
+      <b>Prefix</b>: Uses webkitSpeechRecognition object. To test conformance
+        with actual spec, should instead use SpeechRecognition object.
+      <br>
+      <b>License</b>: Distributed under both the
+      <a href="http://www.w3.org/Consortium/Legal/2008/04-testsuite-license">
+        W3C Test Suite License</a> and the
+      <a href="http://www.w3.org/Consortium/Legal/2008/03-bsd-license">
+        W3C 3-clause BSD License</a>. To contribute to a W3C Test Suite, see the
+      <a href="http://www.w3.org/2004/10/27-testcases">
+        policies and contribution forms</a>.
+    </p>
+    <hr>
+    <p><b>Instructions:</b> Do NOT speak. Run test in silence.
+      This test may fail if too much noise.</p>
+    <div id="log"></div>
+    <div id="notes"></div>
+    <script type="text/javascript">
+var audioTest = new CycleTest('onaudio');
+reco.onaudiostart = audioTest.startEvent();
+reco.onaudioend = audioTest.endEvent();
+
+reco.onsoundstart = neverFireEvent('onsoundstart');
+reco.onsoundend = neverFireEvent('onsoundend');
+reco.onspeechstart = neverFireEvent('onspeechstart');
+reco.onspeechend = neverFireEvent('onsspeechend');
+reco.onresult = neverFireEvent('onresult');
+reco.onnomatch = neverFireEvent('onnomatch');
+
+var errorTest = new CountTest('onerror aborted', 1, 1);
+reco.onerror = errorTest.test().step_func(function(event) {
+  errorTest.count(1);
+  assert_equals(typeof(event.message), 'string', 'typeof(event.message)');
+  notes.innerHTML += 'onerror message is "' + event.message + '"' + '<br>';
+  assert_equals(event.error, 'aborted', 'onerror event.error');
+});
+
+reco.start();
+
+function beginTest() {
+  setTimeout(function() { reco.abort(); }, DELAY);
+}
+    </script>
+  </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conformance/nospeech.html	Fri Feb 20 08:58:23 2015 -0800
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>SpeechRecognition.onerror no-speech</title>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharness.js">
+    </script>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharnessreport.js">
+    </script>
+    <script type="text/javascript">
+      var TIMEOUT_OVERRIDE = 10000;  // In milliseconds.
+    </script>
+    <script type="text/javascript" src='webspeech.js'></script>
+  </head>
+  <body>
+    <h1>Conformance test for Web Speech API SpeechRecognition.onerror
+      no-speech</h1>
+    <p><b>Version</b>: Test is based on W3C
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/9a0075d25326/speechapi.html">
+        Web Speech API Specification</a> 19 October 2012 and
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi-errata.html">
+        Errata</a> through December 7, 2012.
+      <br>
+      <b>Prerequisites</b>: The machine that the test is executed on must have
+        a microphone.
+      <br>
+      <b>Prefix</b>: Uses webkitSpeechRecognition object. To test conformance
+        with actual spec, should instead use SpeechRecognition object.
+      <br>
+      <b>License</b>: Distributed under both the
+      <a href="http://www.w3.org/Consortium/Legal/2008/04-testsuite-license">
+        W3C Test Suite License</a> and the
+      <a href="http://www.w3.org/Consortium/Legal/2008/03-bsd-license">
+        W3C 3-clause BSD License</a>. To contribute to a W3C Test Suite, see the
+      <a href="http://www.w3.org/2004/10/27-testcases">
+        policies and contribution forms</a>.
+    </p>
+    <hr>
+    <p><b>Instructions:</b> Do NOT speak. Run test in silence.
+      This test may fail if too much noise.</p>
+    <div id="log"></div>
+    <div id="notes"></div>
+    <script type="text/javascript">
+var audioTest = new CycleTest('onaudio');
+reco.onaudiostart = audioTest.startEvent();
+reco.onaudioend = audioTest.endEvent();
+
+reco.onsoundstart = neverFireEvent('onsoundstart');
+reco.onsoundend = neverFireEvent('onsoundend');
+reco.onspeechstart = neverFireEvent('onspeechstart');
+reco.onspeechend = neverFireEvent('onsspeechend');
+reco.onresult = neverFireEvent('onresult');
+reco.onnomatch = neverFireEvent('onnomatch');
+
+var errorTest = new CountTest('onerror no-speech', 1, 1);
+reco.onerror = errorTest.test().step_func(function(event) {
+  errorTest.count(1);
+  assert_equals(typeof(event.message), 'string', 'typeof(event.message)');
+  notes.innerHTML += 'onerror message is "' + event.message + '"' + '<br>';
+  assert_equals(event.error, 'no-speech', 'onerror event.error');
+});
+
+reco.start();
+    </script>
+  </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conformance/onresult.html	Fri Feb 20 08:58:23 2015 -0800
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>SpeechRecognition.onresult</title>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharness.js">
+    </script>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharnessreport.js">
+    </script>
+    <script type="text/javascript">
+      var TIMEOUT_OVERRIDE = 60000;  // In milliseconds.
+    </script>
+    <script type="text/javascript" src="webspeech.js"></script>
+  </head>
+  <body>
+    <h1>Conformance test for Web Speech API SpeechRecognition.onresult</h1>
+    <p><b>Version</b>: Test is based on W3C
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/9a0075d25326/speechapi.html">
+        Web Speech API Specification</a> 19 October 2012 and
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi-errata.html">
+        Errata</a> through December 7, 2012.
+      <br>
+      <b>Prerequisites</b>: The machine that the test is executed on must have
+        a microphone.
+      <br>
+      <b>Prefix</b>: Uses webkitSpeechRecognition object. To test conformance
+        with actual spec, should instead use SpeechRecognition object.
+      <br>
+      <b>License</b>: Distributed under both the
+      <a href="http://www.w3.org/Consortium/Legal/2008/04-testsuite-license">
+        W3C Test Suite License</a> and the
+      <a href="http://www.w3.org/Consortium/Legal/2008/03-bsd-license">
+        W3C 3-clause BSD License</a>. To contribute to a W3C Test Suite, see the
+      <a href="http://www.w3.org/2004/10/27-testcases">
+        policies and contribution forms</a>.
+    </p>
+    <hr>
+    <b>Instructions:</b>
+    <p>Reload and re-run this test at least 4 times to cover all 4 combinations
+      of these checkboxes:
+    <input type="checkbox" id="continuous">continuous
+    <input type="checkbox" id="interim">interimResults
+    <button id="button" onclick="startButton()">Click and Speak</button>
+    <br>
+    You may also wish to test with various combinations of these:
+    maxAlternatives:
+    <input type="text" value="3" size="2" id="maxAlternatives">,
+    language:
+    <input type="text" value="en-us" size="7" id="language">
+    </p>
+    <div id="results"></div>
+    <div id="log"></div>
+    <div id="notes"></div>
+    <script type="text/javascript">
+var audioTest = new CycleTest('onaudio');
+reco.onaudiostart = audioTest.startEvent();
+reco.onaudioend = audioTest.endEvent();
+
+var soundTest = new CycleTest('onsound');
+reco.onsoundstart = soundTest.startEvent();
+reco.onsoundend = soundTest.endEvent();
+
+var speechTest = new CycleTest('onspeech');
+reco.onspeechstart = speechTest.startEvent();
+reco.onspeechend = speechTest.endEvent();
+
+reco.onerror = neverFireEvent('onerror');
+reco.onnomatch = neverFireEvent('onnomatch');
+
+var lastIsFinal = -1;  // Highest results index that has been marked isFinal.
+var lastInterimCount = 0;  // Number of results that are not marked isFinal.
+var resultTest = new CountTest('onresult', 1, 9999);
+
+resultTest.whenDone = function() {
+  assert_equals(lastInterimCount, 0, 'Number of interim results pending');
+};
+
+function appendAlternatives(array, results) {
+  for (var i = 0; i < reco.maxAlternatives; i++) {
+    if (i < results.length) {
+      array[i] += results[i].transcript;
+    } else {
+      array[i] += '<no alternative>';
+      assert_true(i > 0, 'Must return at least one alternative.');
+    }
+  }
+}
+
+reco.onresult = resultTest.test().step_func(function(event) {
+  resultTest.count(1);
+  var final = new Array();
+  var interim = new Array();
+  for (var i = 0; i < reco.maxAlternatives; i++) {
+    final[i] = '';
+    interim[i] = '';
+  }
+  assert_true(event.resultIndex > lastIsFinal, 'resultIndex must not ' +
+      'indicate a change in a result that was previously marked isFinal.');
+  assert_true(event.resultIndex <= event.results.length,
+      'resultIndex must not be greater than results.length.');
+  for (var i = 0; i < event.results.length; ++i) {
+    assert_true(event.results[i].length <= reco.maxAlternatives,
+        'Number of alternatives must not exceed maxAlternatives.');
+    if (event.results[i].isFinal) {
+      appendAlternatives(final, event.results[i]);
+      assert_true(reco.continuous || i < 1,
+          'When SpeechRecognition.continuous is false, no more than one ' +
+          'SpeechRecognitionResult.isFinal true should be returned.');
+      if (i > lastIsFinal) {
+        lastIsFinal = i;
+      }
+    } else {
+      appendAlternatives(interim, event.results[i]);
+      assert_true(i > lastIsFinal, 'A SpeechRecognitionResult was previously ' +
+          'marked isFinal, but now is not marked isFinal.');
+    }
+  lastInterimCount = event.results.length - lastIsFinal - 1;
+  assert_true(reco.interimResults || lastInterimCount == 0,
+      'Should not return interim results when reco.interimResults is false.');
+  }
+  for (var i = 0; i < reco.maxAlternatives; i++) {
+    document.getElementById('final_span_' + i).innerHTML = final[i];
+    document.getElementById('interim_span_' + i).innerHTML = interim[i];
+  }
+});
+
+function configureRecognition() {
+  var continuousBox = document.getElementById('continuous');
+  var interimBox = document.getElementById('interim');
+  var maxAlternativesInput = document.getElementById('maxAlternatives');
+  var langInput = document.getElementById('language');
+  reco.continuous = continuousBox.checked;
+  reco.interimResults = interimBox.checked;
+  reco.maxAlternatives = maxAlternativesInput.value;
+  reco.lang = langInput.value;
+  continuousBox.disabled = true;
+  interimBox.disabled = true;
+  maxAlternativesInput.disabled = true;
+  langInput.disabled = true;
+  test(function() {
+    assert_equals(reco.continuous, continuousBox.checked,
+                  'SpeechRecognition.continuous');
+    assert_equals(reco.interimResults, interim.checked,
+                  'SpeechRecognition.interimResults');
+    assert_equals(reco.maxAlternatives, parseInt(maxAlternativesInput.value),
+                  'SpeechRecognition.maxAlternatives');
+    assert_equals(reco.lang, langInput.value,
+                  'SpeechRecognition.lang');
+  }, 'SpeechRecognition settings');
+}
+
+var clicks = 0;
+function startButton() {
+  var button = document.getElementById('button');
+  if (++clicks == 1) {
+    configureRecognition();
+    if (reco.continuous) {
+      button.innerHTML = 'Click when done speaking';
+    } else {
+      button.hidden = true;
+    }
+    var results_html = '';
+    for (var i = 0; i < reco.maxAlternatives; i++) {
+      results_html += '<div style="border:1px dotted gray; padding:10px; ' +
+          'font-weight:bold">' +
+          '<span id="final_span_' + i + '"></span>' +
+          '<span id="interim_span_' + i + '" style="color:blue"></span>' +
+          '</div>';
+    }
+    results.innerHTML = results_html;
+    reco.start();
+  } else {
+    button.hidden = true;
+    reco.stop();
+  }
+}
+    </script>
+  </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conformance/stop.html	Fri Feb 20 08:58:23 2015 -0800
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>SpeechRecognition.stop</title>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharness.js">
+    </script>
+    <script type="text/javascript" src="https://w3c-test.org/resources/testharnessreport.js">
+    </script>
+    <script type="text/javascript" src="webspeech.js"></script>
+  </head>
+  <body>
+    <h1>Conformance test for Web Speech API SpeechRecognition.stop</h1>
+    <p><b>Version</b>: Test is based on W3C
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/9a0075d25326/speechapi.html">
+        Web Speech API Specification</a> 19 October 2012 and
+      <a href="http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi-errata.html">
+        Errata</a> through December 7, 2012.
+      <br>
+      <b>Prerequisites</b>: The machine that the test is executed on must have
+        a microphone.
+      <br>
+      <b>Prefix</b>: Uses webkitSpeechRecognition object. To test conformance
+        with actual spec, should instead use SpeechRecognition object.
+      <br>
+      <b>License</b>: Distributed under both the
+      <a href="http://www.w3.org/Consortium/Legal/2008/04-testsuite-license">
+        W3C Test Suite License</a> and the
+      <a href="http://www.w3.org/Consortium/Legal/2008/03-bsd-license">
+        W3C 3-clause BSD License</a>. To contribute to a W3C Test Suite, see the
+      <a href="http://www.w3.org/2004/10/27-testcases">
+        policies and contribution forms</a>.
+    </p>
+    <hr>
+    <p><b>Instructions:</b> Do NOT speak. Run test in silence.
+      This test may fail if too much noise.</p>
+    <div id="log"></div>
+    <div id="notes"></div>
+    <script type="text/javascript">
+var audioTest = new CycleTest('onaudio');
+reco.onaudiostart = audioTest.startEvent();
+reco.onaudioend = audioTest.endEvent();
+
+reco.onsoundstart = neverFireEvent('onsoundstart');
+reco.onsoundend = neverFireEvent('onsoundend');
+reco.onspeechstart = neverFireEvent('onspeechstart');
+reco.onspeechend = neverFireEvent('onsspeechend');
+reco.onresult = neverFireEvent('onresult');
+reco.onerror = neverFireEvent('onerror');
+
+var nomatchTest = new CountTest('onnomatch', 0, 1);
+reco.onnomatch = nomatchTest.test().step_func(function(event) {
+  nomatchTest.count(1);
+});
+
+reco.start();
+
+function beginTest() {
+  setTimeout(function() { reco.stop(); }, DELAY);
+}
+    </script>
+  </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conformance/webspeech.js	Fri Feb 20 08:58:23 2015 -0800
@@ -0,0 +1,119 @@
+var DELAY = 500;  // In milliseconds.
+var TIMEOUT = 2000;  // In milliseconds.  Used for most tests.
+if (typeof(TIMEOUT_OVERRIDE) != 'undefined') {
+  TIMEOUT = TIMEOUT_OVERRIDE;
+}
+GLOBAL_TIMEOUT = TIMEOUT + 2000;  // In milliseconds.
+setup({timeout: GLOBAL_TIMEOUT});
+var onstarted = false;
+var neverFireTest = async_test('Events that should not fire',
+                               {timeout: TIMEOUT});
+var onstartTest = async_test('onstart', {timeout: TIMEOUT});
+var reco = new webkitSpeechRecognition();
+test(function() {
+  assert_equals(reco.grammars.length, 0, 'SpeechRecognition.grammars.length');
+  assert_equals(reco.lang, '', 'SpeechRecognition.lang');
+  assert_false(reco.continuous, 'SpeechRecognition.continuous');
+  assert_false(reco.interimResults, 'SpeechRecognition.interimResults');
+  assert_equals(reco.maxAlternatives, 1, 'SpeechRecognition.maxAlternatives');
+}, 'SpeechRecognition defaults');
+
+reco.onstart = onstartTest.step_func(function(event) {
+  assert_false(onstarted, 'onstart should only fire once.');
+  onstarted = true;
+  onstartTest.done();
+  beginTest();
+});
+
+reco.onend = function() {
+  neverFireTest.done();
+  for (var i = 0; i < doneOnEndTestList.length; i++) {
+    doneOnEndTestList[i].done();
+  }
+};
+
+function neverFireEvent(name) {
+  return neverFireTest.step_func(function(event) {
+    assert_unreached(name + ' should not fire.');
+  });
+}
+
+var doneOnEndTestList = [];  // List of all test objects to call done at onend.
+
+// Tally calls to count() and test against min/max when test ends.
+// A max value of 0 indicates no maximum.
+function CountTest(name, min, max) {
+  doneOnEndTestList.push(this);
+  this.name = name;
+  this.min = min;
+  this.max = max;
+  this.sum = 0;
+  this.asyncTest = async_test(name, {timeout: TIMEOUT});
+
+  this.count = function(increment) { this.sum += increment; };
+
+  this.test = function() { return this.asyncTest; };
+
+  this.done = function() {
+    var cTest = this;
+    this.asyncTest.step(function() {
+      notes.innerHTML += cTest.name + ' occurred ' + cTest.sum + ' times.<br>';
+      if (cTest.min == cTest.max) {
+        assert_true(cTest.sum == cTest.min, cTest.name + ' occurred ' +
+          cTest.sum + ' times and should have occurred ' +
+          cTest.min + ' times.');
+      } else {
+        assert_true(cTest.sum >= cTest.min, cTest.name + ' occurred ' +
+            cTest.sum + ' times and should have occurred at least ' +
+            cTest.min + ' times.');
+        assert_true(cTest.max == 0 || cTest.sum <= cTest.max, cTest.name +
+            ' occurred ' + cTest.sum +
+            ' times and should have occurred at most ' + cTest.max + ' times.');
+      }
+      if (cTest.whenDone) {
+        cTest.whenDone();
+      }
+    });
+    this.asyncTest.done();
+  };
+}
+
+// Test for proper cycling of startEvent followed by endEvent.
+function CycleTest(name) {
+  doneOnEndTestList.push(this);
+  this.name = name;
+  this.count = 0;  // Counts number of start / end cycles.
+  this.started = false; // Tracks whether last event was a start or end event.
+  this.test = async_test(name + ' start/stop', {timeout: TIMEOUT});
+
+  this.startEvent = function() {
+    var cycle = this;
+    return this.test.step_func(function(event) {
+      assert_true(onstarted, cycle.name + 'start fired before onstart.');
+      assert_false(cycle.started, cycle.name + 'start fired twice without ' +
+                   cycle.name + 'stop.');
+      cycle.started = true;
+    });
+  };
+
+  this.endEvent = function() {
+    var cycle = this;
+    return this.test.step_func(function(event) {
+      assert_true(cycle.started, cycle.name + 'end fired before ' +
+                  cycle.name + 'start.');
+      cycle.started = false;
+      cycle.count += 1;
+    });
+  };
+
+  this.done = function() {
+    var cycle = this;
+    this.test.step(function() {
+      assert_false(cycle.started, cycle.name + 'start fired but not ' +
+                   cycle.name + 'end.');
+      assert_true(cycle.count > 0, cycle.name + 'start never fired.');
+      notes.innerHTML += cycle.name + ' cycled ' + cycle.count + ' times.<br>';
+    });
+    this.test.done();
+  };
+}