summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/webcomponents/test_document_register_stack.html
blob: 34f1086549afd94aa917b07302a25087dc15fdb3 (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
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
-->
<head>
  <title>Test for document.registerElement lifecycle callback</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 id="container">
</div>
<script>

var container = document.getElementById("container");

// Test changing attributes in the created callback on an element
// created after registration.
function testChangeAttributeInCreatedCallback() {
  var createdCallbackCalled = false;
  var attributeChangedCallbackCalled = false;

  var p = Object.create(HTMLElement.prototype);
  p.createdCallback = function() {
    is(createdCallbackCalled, false, "Created callback should be called before attached callback.");
    createdCallbackCalled = true;
    is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute.");
    this.setAttribute("foo", "bar");
    is(attributeChangedCallbackCalled, false, "While element is being created, element should not be added to the current element callback queue.");
  };

  p.attributeChangedCallback = function(name, oldValue, newValue) {
    is(createdCallbackCalled, true, "attributeChanged callback should be called after the created callback because it was enqueued during created callback.");
    is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
    is(newValue, "bar", "The new value should be 'bar'");
    attributeChangedCallbackCalled = true;
    runNextTest();
  };

  document.registerElement("x-one", { prototype: p });
  document.createElement("x-one");
}

function testChangeAttributeInEnteredViewCallback() {
  var p = Object.create(HTMLElement.prototype);
  var attributeChangedCallbackCalled = false;
  var attachedCallbackCalled = false;

  p.attachedCallback = function() {
    is(attachedCallbackCalled, false, "attached callback should be called only once in this test.");
    attachedCallbackCalled = true;
    is(attributeChangedCallbackCalled, false, "Attribute changed callback should not be called before changing attribute.");
    this.setAttribute("foo", "bar");
    is(attributeChangedCallbackCalled, true, "Transition from user-agent implementation to script should result in attribute changed callback being called.");
    runNextTest();
  };

  p.attributeChangedCallback = function() {
    is(attachedCallbackCalled, true, "attached callback should have been called prior to attribute changed callback.");
    is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
    attributeChangedCallbackCalled = true;
  };

  document.registerElement("x-two", { prototype: p });
  var elem = document.createElement("x-two");

  var container = document.getElementById("container");
  container.appendChild(elem);
}

function testLeaveViewInEnteredViewCallback() {
  var p = Object.create(HTMLElement.prototype);
  var attachedCallbackCalled = false;
  var detachedCallbackCalled = false;
  var container = document.getElementById("container");

  p.attachedCallback = function() {
    is(this.parentNode, container, "Parent node should the container in which the node was appended.");
    is(attachedCallbackCalled, false, "attached callback should be called only once in this test.");
    attachedCallbackCalled = true;
    is(detachedCallbackCalled, false, "detached callback should not be called prior to removing element from document.");
    container.removeChild(this);
    is(detachedCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback.");
    runNextTest();
  };

  p.detachedCallback = function() {
    is(detachedCallbackCalled, false, "The detached callback should only be called once in this test.");
    is(attachedCallbackCalled, true, "The attached callback should be called prior to detached callback.");
    detachedCallbackCalled = true;
  };

  document.registerElement("x-three", { prototype: p });
  var elem = document.createElement("x-three");

  container.appendChild(elem);
}

function testStackedAttributeChangedCallback() {
  var p = Object.create(HTMLElement.prototype);
  var attributeChangedCallbackCount = 0;

  var attributeSequence = ["foo", "bar", "baz"];

  p.attributeChangedCallback = function(attrName, oldValue, newValue) {
    if (newValue == "baz") {
      return;
    }

    var nextAttribute = attributeSequence.shift();
    ok(true, nextAttribute);
    // Setting this attribute will call this function again, when
    // control returns to the script, the last attribute in the sequence should
    // be set on the element.
    this.setAttribute("foo", nextAttribute);
    is(this.getAttribute("foo"), "baz", "The last value in the sequence should be the value of the attribute.");

    attributeChangedCallbackCount++;
    if (attributeChangedCallbackCount == 3) {
      runNextTest();
    }
  };

  document.registerElement("x-four", { prototype: p });
  var elem = document.createElement("x-four");
  elem.setAttribute("foo", "changeme");
}

var testFunctions = [
  testChangeAttributeInCreatedCallback,
  testChangeAttributeInEnteredViewCallback,
  testLeaveViewInEnteredViewCallback,
  testStackedAttributeChangedCallback,
  SimpleTest.finish
];

function runNextTest() {
  if (testFunctions.length > 0) {
    var nextTestFunction = testFunctions.shift();
    nextTestFunction();
  }
}

SimpleTest.waitForExplicitFinish();

runNextTest();

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