summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html
blob: 3007fafc546d78b9115f36d2d27e0a43d1c3ab61 (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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<!DOCTYPE html>
<html>
<head>
<title>Shadow DOM Test: Upper-boundary encapsulation: document's DOM tree accessors</title>
<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
<meta name="assert" content="Upper-boundary encapsulation: The shadow nodes and named shadow elements are not accessible using shadow host's document DOM tree accessors.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../../../html/resources/common.js"></script>
</head>
<body>
<div id="log"></div>
<script>
// A document's "DOM tree accessors" include:
//   (document.)head, title, body, images, embeds, plugins, links, forms,
//   scripts, getElementsByName(), cssElementMap, and currentScript
//
// Of these, it is unclear how document.cssElementMap can be tested.
// Except for it, there is a test corresponding to each accessor.
//
// Additionally, there are obsolete accessors
// <http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#other-elements,-attributes-and-apis>:
//   (document.)anchors, applets, and all.
//
// and some accessors defined in the DOM specification (formerly known as
// "DOM Core") <http://dom.spec.whatwg.org/#interface-document>:
//   (document.)documentElement, getElementsByTagName(),
//   getElementsByTagNameNS(), getElementsByClassName(), and getElementById().
//
// As it seems reasonable to have tests for these accessors, this file also
// includes tests for them, except for document.documentElement which is
// unclear whether we can test; the distribution process of Shadow DOM does not
// alter the host element, so the document element (e.g. <html>) cannot be
// replaced with an element in a shadow tree.

// ----------------------------------------------------------------------------
// Constants and utility functions

// Place the same HTML content into both the host document and the shadow root.
// To differentiate these two, a class name is assigned to every element by
// populateTestContentToHostDocument() and populateTestContentToShadowRoot().
var HTML_CONTENT = [
    '<head>',
    '<title></title>',
    '<link rel="help" href="#">',
    '</head>',
    '<body>',
    '<p></p>',
    '<a name="test-name"></a>',
    '<a href="#"></a>',
    '<area href="#">',
    '<img src="#" alt="">',
    '<embed></embed>',
    '<form></form>',
    '<script><' + '/script>',
    '</body>'
].join('\n');

function addClassNameToAllElements(document, root, className) {
    var nodeIterator = document.createNodeIterator(
        root, NodeFilter.SHOW_ELEMENT, null);
    var node;
    while (node = nodeIterator.nextNode())
        node.className = className;
}

function populateTestContentToHostDocument(document) {
    document.documentElement.innerHTML = HTML_CONTENT;
    addClassNameToAllElements(document, document.documentElement, 'host');
}

function populateTestContentToShadowRoot(shadowRoot) {
    shadowRoot.innerHTML = HTML_CONTENT;
    addClassNameToAllElements(shadowRoot.ownerDocument, shadowRoot, 'shadow');
}

function createDocumentForTesting() {
    var doc = document.implementation.createHTMLDocument('');
    populateTestContentToHostDocument(doc);
    var shadowRoot = doc.body.attachShadow({mode: 'open'});
    populateTestContentToShadowRoot(shadowRoot);
    return doc;
}

// Make sure the given HTMLCollection contains at least one elements and
// all elements have the class named "host". This function works well with
// HTMLCollection, HTMLAllCollection, and NodeList consisting of elements.
function assert_collection(collection) {
    assert_true(collection.length > 0);
    Array.prototype.forEach.call(collection, function (element) {
        assert_equals(element.className, 'host');
    });
}

// ----------------------------------------------------------------------------
// Tests for DOM tree accessors defined in HTML specification

test(function () {
    var doc = createDocumentForTesting();
    assert_equals(doc.head.className, 'host');
    assert_equals(doc.body.className, 'host');
},
    '<head> and <body> in a shadow tree should not be accessible from ' +
    'owner document\'s "head" and "body" properties, respectively.'
);

test(function () {
    var doc = document.implementation.createHTMLDocument('');
    populateTestContentToHostDocument(doc);

    // Note: this test is originally written to replace document.documentElement
    // with shadow contents, but among Shadow DOM V1 allowed elements body is the
    // most approximate to it, though some test may make lesser sense.
    var shadowRoot = doc.body.attachShadow({mode: 'open'});
    populateTestContentToShadowRoot(shadowRoot);

    // Replace the content of <title> to distinguish elements in a host
    // document and a shadow tree.
    doc.getElementsByTagName('title')[0].textContent = 'Title of host document';
    shadowRoot.querySelector('title').textContent =
        'Title of shadow tree';

    assert_equals(doc.title, 'Title of host document');
},
    'The content of title element in a shadow tree should not be accessible ' +
    'from owner document\'s "title" attribute.'
);

function testHTMLCollection(accessor) {
    var doc = createDocumentForTesting();
    assert_collection(doc[accessor]);
}

generate_tests(
    testHTMLCollection,
    ['images', 'embeds', 'plugins', 'links', 'forms', 'scripts'].map(
        function (accessor) {
            return [
                'Elements in a shadow tree should not be accessible from ' +
                'owner document\'s "' + accessor + '" attribute.',
                accessor
            ];
        }));

test(function () {
    var doc = createDocumentForTesting();
    assert_collection(doc.getElementsByName('test-name'));
},
    'Elements in a shadow tree should not be accessible from owner ' +
    'document\'s getElementsByName() method.'
);

// ----------------------------------------------------------------------------
// Tests for obsolete accessors

generate_tests(
    testHTMLCollection,
    ['anchors', 'all'].map(
        function (accessor) {
            return [
                'Elements in a shadow tree should not be accessible from ' +
                'owner document\'s "' + accessor + '" attribute.',
                accessor
            ];
        }));

// ----------------------------------------------------------------------------
// Tests for accessors defined in DOM specification

test(function () {
    var doc = createDocumentForTesting();
    assert_collection(doc.getElementsByTagName('p'));
},
    'Elements in a shadow tree should not be accessible from owner ' +
    'document\'s getElementsByTagName() method.'
);

test(function () {
    // Create a XML document.
    var namespace = 'http://www.w3.org/1999/xhtml';
    var doc = document.implementation.createDocument(namespace, 'html');
    doc.documentElement.appendChild(doc.createElementNS(namespace, 'head'));
    var body = doc.createElementNS(namespace, 'body');
    var pHost = doc.createElementNS(namespace, 'p');
    pHost.className = "host";
    body.appendChild(pHost);
    doc.documentElement.appendChild(body);

    var shadowRoot = body.attachShadow({mode: 'open'});
    var pShadow = doc.createElementNS(namespace, 'p');
    pShadow.className = "shadow";
    shadowRoot.appendChild(pShadow);

    assert_collection(doc.getElementsByTagNameNS(namespace, 'p'));
},
    'Elements in a shadow tree should not be accessible from owner ' +
    'document\'s getElementsByTagNameNS() method.'
);

test(function () {
    var doc = document.implementation.createHTMLDocument('');
    populateTestContentToHostDocument(doc);
    var shadowRoot = doc.body.attachShadow({mode: 'open'});
    populateTestContentToShadowRoot(shadowRoot);

    shadowRoot.querySelectorAll('p')[0].id = 'test-id';
    assert_equals(doc.getElementById('test-id'), null);
},
    'Elements in a shadow tree should not be accessible from owner ' +
    'document\'s getElementById() method.'
);
</script>
</body>
</html>