summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/webcomponents/test_document_register.html
blob: a9c194b60feb8a25cacfc5c7b8d513eb99525af2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
-->
<head>
  <title>Test for document.registerElement using custom prototype</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
<div>
<x-unresolved id="unresolved"></x-unresolved>
</div>

<script>

function testRegisterExtend(tag, extend, proto, expectException) {
  try {
    document.registerElement(tag, { prototype: proto, extends: extend });
    ok(!expectException, "Registered " + tag + " extending " + extend + " containing " + proto + " in proto chain.");
  } catch (ex) {
    ok(expectException, "Did not register " + tag + " extending " + extend + " containing " + proto + " in proto chain.");
  }
}

function testRegisterSimple(tag, proto, expectException) {
  try {
    document.registerElement(tag, { prototype: proto });
    ok(!expectException, "Registered " + tag + " containing " + proto + " in proto chain.");
  } catch (ex) {
    ok(expectException, "Did not register " + tag + " containing " + proto + " in proto chain.");
  }
}

function startTest() {
  // Test registering some simple prototypes.
  testRegisterSimple("x-html-obj-elem", Object.create(HTMLElement.prototype), false);
  testRegisterSimple("x-html-obj-p", Object.create(HTMLParagraphElement.prototype), false);

  // If prototype is an interface prototype object for any interface object,
  // registration will throw.
  testRegisterSimple("x-html-elem", HTMLElement.prototype, true);
  testRegisterSimple("x-html-select", HTMLSelectElement.prototype, true);
  testRegisterSimple("some-elem", HTMLElement.prototype, true);
  testRegisterSimple("x-html-p", HTMLParagraphElement.prototype, true);
  testRegisterSimple("x-html-span", HTMLSpanElement.prototype, true);

  // Make sure the prototype on unresolved elements is HTMLElement not HTMLUnknownElement.
  var unresolved = document.getElementById("unresolved");
  is(unresolved.__proto__, HTMLElement.prototype, "Unresolved custom elements should have HTMLElement as prototype.");

  var anotherUnresolved = document.createElement("maybe-custom-element");
  is(anotherUnresolved.__proto__, HTMLElement.prototype, "Unresolved custom elements should have HTMLElement as prototype.");

  // Registering without a prototype should automatically create one inheriting from HTMLElement.
  testRegisterSimple("x-elem-no-proto", null, false);

  var simpleProto = Object.create(HTMLElement.prototype);
  testRegisterSimple("x-elem-simple-proto", simpleProto, false);

  // Test registering some invalid prototypes.
  testRegisterSimple("x-invalid-number", 42, true);
  testRegisterSimple("x-invalid-boolean", false, true);
  testRegisterSimple("x-invalid-float", 1.0, true);
  // A prototype with a non-configurable "constructor" property must throw.
  var nonConfigProto = Object.create(HTMLElement.prototype,
    { constructor: { configurable: false, value: function() {} } });
  testRegisterSimple("x-non-config-proto", nonConfigProto, true);

  // Test invalid custom element names.
  testRegisterSimple("invalid", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("annotation-xml", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("color-profile", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("font-face", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("font-face-src", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("font-face-uri", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("font-face-format", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("font-face-name", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("missing-glyph", Object.create(HTMLElement.prototype), true);

  // Test registering elements that extend from an existing element.
  testRegisterExtend("x-extend-span", "span", Object.create(HTMLElement.prototype), false);
  testRegisterExtend("x-extend-span-caps", "SPAN", Object.create(HTMLElement.prototype), false);

  // Test registering elements that extend from a non-existing element.
  testRegisterExtend("x-extend-span-nonexist", "nonexisting", Object.create(HTMLElement.prototype), true);

  // Test registration with duplicate type.
  testRegisterSimple("x-dupe-me", Object.create(HTMLElement.prototype), false);
  testRegisterSimple("x-dupe-me", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("X-DUPE-ME", Object.create(HTMLElement.prototype), true);
  testRegisterSimple("x-dupe-me", null, true);
  testRegisterExtend("x-dupe-me", "span", Object.create(HTMLElement.prototype), true);

  // document.createElement with extended type.
  var extendedProto = Object.create(HTMLButtonElement.prototype);
  var buttonConstructor = document.registerElement("x-extended-button", { prototype: extendedProto, extends: "button" });
  var extendedButton = document.createElement("button", {is: "x-extended-button"});
  is(extendedButton.tagName, "BUTTON", "Created element should have local name of BUTTON");
  is(extendedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type.");
  is(extendedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
  is(extendedButton.type, "submit", "Created element should be a button with type of \"submit\"");

  // document.createElementNS with different namespace than definition.
  try {
    var svgButton = document.createElementNS("http://www.w3.org/2000/svg", "button", {is: "x-extended-button"});
    ok(false, "An exception should've been thrown");
  } catch(err) {
    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
  }

  // document.createElementNS with no namespace.
  try {
    var noNamespaceButton = document.createElementNS("", "button", {is: "x-extended-button"});
    ok(false, "An exception should've been thrown");
  } catch(err) {
    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
  }

  // document.createElement with non-existant extended type.
  try {
    var normalButton = document.createElement("button", {is: "x-non-existant"});
    ok(false, "An exception should've been thrown");
  } catch(err) {
    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
  }

  // document.createElement with exteneded type that does not match with local name of element.
  try {
    var normalDiv = document.createElement("div", {is: "x-extended-button"});
    ok(false, "An exception should've been thrown");
  } catch(err) {
    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
  }

  // Custom element constructor.
  var constructedButton = new buttonConstructor();
  is(constructedButton.tagName, "BUTTON", "Created element should have local name of BUTTON");
  is(constructedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type.");
  is(constructedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");

  // document.createElement with different namespace than definition for extended element.
  try {
    var htmlText = document.createElement("text", {is: "x-extended-text"});
    ok(false, "An exception should've been thrown");
  } catch(err) {
    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
  }

  // Try creating an element with a custom element name, but not in the html namespace.
  var htmlNamespaceProto = Object.create(HTMLElement.prototype);
  document.registerElement("x-in-html-namespace", { prototype: htmlNamespaceProto });
  var wrongNamespaceElem = document.createElementNS("http://www.w3.org/2000/svg", "x-in-html-namespace");
  isnot(wrongNamespaceElem.__proto__, htmlNamespaceProto, "Definition for element in html namespace should not apply to SVG elements.");
}

startTest();

</script>
</body>
</html>