Bug 1492283 [wpt PR 13057] - Add SpeechSynthesisErrorEvent IDL interface, a=testonly
authorCharlie Harrison <csharrison@chromium.org>
Fri, 05 Oct 2018 14:21:07 +0000
changeset 488355 59cc5078bc4c7f75d04f78a0f068cddf1c01cef1
parent 488354 159e7ec908050a1c94442af859f4dc03cda392dd
child 488356 045dc67ac4567604c0b05d1cf285a1ebce2ff83f
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewerstestonly
bugs1492283, 13057, 885297, 1231839, 595128
milestone64.0a1
Bug 1492283 [wpt PR 13057] - Add SpeechSynthesisErrorEvent IDL interface, a=testonly Automatic update from web-platform-testsAdd SpeechSynthesisErrorEvent IDL interface See spec: https://w3c.github.io/speech-api/#speechsynthesiserrorevent and discussion on i2s on blink-dev: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/8_H3FUZm23g Previously, errors were just going through as SpeechSynthesisEvents. This CL now dispatches errors as SpeechSynthesisErrorEvents with an empty "error" method. This CL also adds constructors on both SpeechSynthesisEvent and SpeechSynthesisErrorEvent. Bug: 885297 Change-Id: I70ba998182943a50e17f2fc11eb7e163d8289e94 Reviewed-on: https://chromium-review.googlesource.com/1231839 Commit-Queue: Charlie Harrison <csharrison@chromium.org> Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org> Reviewed-by: Philip J├Ągenstedt <foolip@chromium.org> Cr-Commit-Position: refs/heads/master@{#595128} -- wpt-commits: 95b97e23ea267ac700cfa5f3a131581203f15c62 wpt-pr: 13057
testing/web-platform/tests/interfaces/speech-api.idl
testing/web-platform/tests/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html
testing/web-platform/tests/speech-api/SpeechSynthesisErrorEvent-constructor.html
testing/web-platform/tests/speech-api/SpeechSynthesisEvent-constructor.html
--- a/testing/web-platform/tests/interfaces/speech-api.idl
+++ b/testing/web-platform/tests/interfaces/speech-api.idl
@@ -132,44 +132,57 @@ interface SpeechSynthesisUtterance : Eve
     attribute EventHandler onend;
     attribute EventHandler onerror;
     attribute EventHandler onpause;
     attribute EventHandler onresume;
     attribute EventHandler onmark;
     attribute EventHandler onboundary;
 };
 
-[Exposed=Window]
+[Exposed=Window,
+  Constructor(DOMString type, SpeechSynthesisEventInit eventInitDict)]
 interface SpeechSynthesisEvent : Event {
     readonly attribute SpeechSynthesisUtterance utterance;
     readonly attribute unsigned long charIndex;
     readonly attribute float elapsedTime;
     readonly attribute DOMString name;
 };
 
+dictionary SpeechSynthesisEventInit : EventInit {
+    required SpeechSynthesisUtterance utterance;
+    unsigned long charIndex = 0;
+    float elapsedTime = 0;
+    DOMString name = "";
+};
+
 enum SpeechSynthesisErrorCode {
     "canceled",
     "interrupted",
     "audio-busy",
     "audio-hardware",
     "network",
     "synthesis-unavailable",
     "synthesis-failed",
     "language-unavailable",
     "voice-unavailable",
     "text-too-long",
     "invalid-argument",
     "not-allowed",
 };
 
-[Exposed=Window]
+[Exposed=Window,
+  Constructor(DOMString type, SpeechSynthesisErrorEventInit eventInitDict)]
 interface SpeechSynthesisErrorEvent : SpeechSynthesisEvent {
     readonly attribute SpeechSynthesisErrorCode error;
 };
 
+dictionary SpeechSynthesisErrorEventInit : SpeechSynthesisEventInit {
+    required SpeechSynthesisErrorCode error;
+};
+
 [Exposed=Window]
 interface SpeechSynthesisVoice {
     readonly attribute DOMString voiceURI;
     readonly attribute DOMString name;
     readonly attribute DOMString lang;
     readonly attribute boolean localService;
     readonly attribute boolean default;
 };
--- a/testing/web-platform/tests/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html
+++ b/testing/web-platform/tests/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html
@@ -3,14 +3,14 @@
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
 // TODO(csharrison): Make this test not tentative once
 // https://github.com/w3c/speech-api/issues/35 is resolved.
 async_test(t => {
   const utter = new SpeechSynthesisUtterance('1');
   utter.onerror = t.step_func_done((e) => {
-    assert_equals(e.name, "not-allowed");
+    assert_equals(e.error, "not-allowed");
   });
   utter.onend = t.step_func_done(() => assert_unreached());
   speechSynthesis.speak(utter);
 }, 'speechSynthesis.speak requires user activation');
 </script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/speech-api/SpeechSynthesisErrorEvent-constructor.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+/*
+[Exposed=Window,
+ Constructor(DOMString type, SpeechSynthesisErrorEventInit eventInitDict)]
+interface SpeechSynthesisErrorEvent : SpeechSynthesisErrorEvent {
+    readonly attribute SpeechSynthesisErrorCode error;
+};
+*/
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisErrorEvent();
+  });
+}, "SpeechSynthesisErrorEvent with no arguments throws TypeError");
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisErrorEvent("type");
+  });
+}, "SpeechSynthesisErrorEvent with no eventInitDict throws TypeError");
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisErrorEvent("type", {});
+  });
+}, `SpeechSynthesisErrorEvent with empty eventInitDict throws TypeError (requires
+    utterance and error)`);
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisErrorEvent("type", {error:"not-allowed"});
+  });
+}, `SpeechSynthesisErrorEvent with eventInitDict without utterance throws
+    TypeError`);
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisErrorEvent("type", {utterance: new SpeechSynthesisUtterance()});
+  });
+}, `SpeechSynthesisErrorEvent with eventInitDict without error throws
+    TypeError`);
+
+test(() => {
+  const utterance = new SpeechSynthesisUtterance("foo");
+  const event = new SpeechSynthesisErrorEvent("type", {utterance: utterance, error:"not-allowed"});
+  assert_equals(event.utterance, utterance);
+  assert_equals(event.error, "not-allowed");
+  assert_equals(event.charIndex, 0);
+  assert_equals(event.elapsedTime, 0);
+  assert_equals(event.name, "");
+}, "SpeechSynthesisErrorEvent with eventInitDict having utterance and error");
+
+test(() => {
+  const utterance = new SpeechSynthesisUtterance("foo");
+  const event = new SpeechSynthesisErrorEvent("type", {
+    utterance: utterance,
+    charIndex: 5,
+    elapsedTime: 100,
+    name: "foo",
+    error: "synthesis-failed"
+  });
+  assert_equals(event.bubbles, false);
+  assert_equals(event.cancelable, false);
+  assert_equals(event.type, "type");
+  assert_equals(event.utterance, utterance);
+  assert_equals(event.charIndex, 5);
+  assert_equals(event.elapsedTime, 100);
+  assert_equals(event.name, "foo");
+  assert_equals(event.error, "synthesis-failed");
+}, "SpeechSynthesisErrorEvent with custom eventInitDict");
+
+test(() => {
+  function createEventFunc(error) {
+    return () => {
+      new SpeechSynthesisErrorEvent("type", {
+        utterance: new SpeechSynthesisUtterance(),
+        error: error
+      });
+    };
+  };
+  assert_throws(new TypeError(), createEventFunc(""));
+  assert_throws(new TypeError(), createEventFunc("foo"));
+  assert_throws(new TypeError(), createEventFunc("bar"));
+}, "SpeechSynthesisErrorEvent with wrong error enum");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/speech-api/SpeechSynthesisEvent-constructor.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+/*
+[Exposed=Window,
+ Constructor(DOMString type, SpeechSynthesisEventInit eventInitDict)]
+interface SpeechSynthesisEvent : Event {
+    readonly attribute SpeechSynthesisUtterance utterance;
+    readonly attribute unsigned long charIndex;
+    readonly attribute float elapsedTime;
+    readonly attribute DOMString name;
+};
+*/
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisEvent();
+  });
+}, "SpeechSynthesisEvent with no arguments throws TypeError");
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisEvent("type");
+  });
+}, "SpeechSynthesisEvent with no eventInitDict throws TypeError");
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisEvent("type", {});
+  });
+}, `SpeechSynthesisEvent with empty eventInitDict throws TypeError (requires
+    utterance)`);
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new SpeechSynthesisEvent("type", {charIndex: 10, elapsedTime: 50, name:"foo"});
+  });
+}, `SpeechSynthesisEvent with eventInitDict not having utterance throws
+    TypeError`);
+
+test(() => {
+  const utterance = new SpeechSynthesisUtterance("foo");
+  const event = new SpeechSynthesisEvent("type", {utterance: utterance});
+  assert_equals(event.utterance, utterance);
+  assert_equals(event.charIndex, 0);
+  assert_equals(event.elapsedTime, 0);
+  assert_equals(event.name, "");
+}, "SpeechSynthesisEvent with eventInitDict having an utterance");
+
+test(() => {
+  const utterance = new SpeechSynthesisUtterance("foo");
+  const event = new SpeechSynthesisEvent("type", {
+    utterance: utterance,
+    charIndex: 5,
+    elapsedTime: 100,
+    name: "foo"
+  });
+  assert_equals(event.bubbles, false);
+  assert_equals(event.cancelable, false);
+  assert_equals(event.type, "type");
+  assert_equals(event.utterance, utterance);
+  assert_equals(event.charIndex, 5);
+  assert_equals(event.elapsedTime, 100);
+  assert_equals(event.name, "foo");
+}, "SpeechSynthesisEvent with custom eventInitDict");
+</script>