Conformance Tests from lists.w3.org/Archives/Public/public-speech-api/2012Dec/0001.html
--- /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();
+ };
+}