ac0c2374d0dda0841d97f8d40b6376cbabc730cc
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / LayoutTests / w3c / web-platform-tests / shadow-dom / testcommon.js
1 // Copyright 2012 Google Inc. All Rights Reserved.
2
3 /*
4 Distributed under both the W3C Test Suite License [1] and the W3C
5 3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
6 policies and contribution forms [3].
7
8 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
9 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
10 [3] http://www.w3.org/2004/10/27-testcases
11 */
12
13 "use strict";
14
15 var HTML5_ELEMENT_NAMES = [
16     'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio',
17     'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button',
18     'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'command',
19     'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt',
20     'em', 'embed',
21     'fieldset', 'figcaption', 'figure', 'footer', 'form',
22     'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr',
23     'html',
24     'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen',
25     'label', 'legend', 'li', 'link',
26     'map', 'mark', 'menu', 'meta', 'meter',
27     'nav', 'noscript',
28     'object', 'ol', 'optgroup', 'option', 'output',
29     'p', 'param', 'pre', 'progress',
30     'q',
31     'rp', 'rt', 'ruby',
32     's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span',
33     'strong', 'style', 'sub',
34     'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time',
35     'title', 'tr', 'track',
36     'u', 'ul',
37     'var', 'video',
38     'wbr'
39 ];
40
41 // http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#form-associated-element
42 var HTML5_FORM_ASSOCIATED_ELEMENTS = ['button', 'fieldset', 'input', 'keygen', 'label',
43                                       'object', 'output', 'select', 'textarea'];
44
45 // Whether to work around vendor prefixes.
46 var USE_VENDOR_SPECIFIC_WORKAROUND = true;
47
48 function activateVendorSpecificWorkaround() {
49     if (Element.prototype.webkitCreateShadowRoot &&
50         !Element.prototype.createShadowRoot) {
51         Element.prototype.createShadowRoot =
52             Element.prototype.webkitCreateShadowRoot;
53
54         Object.defineProperty(Element.prototype, 'pseudo', {
55             get: function () { return this.webkitPseudo; },
56             set: function (value) { return this.webkitPseudo = value; }
57         });
58
59         Object.defineProperty(Element.prototype, 'shadowRoot', {
60             get: function () { return this.webkitShadowRoot; }
61         });
62     }
63 }
64
65 if (USE_VENDOR_SPECIFIC_WORKAROUND)
66     activateVendorSpecificWorkaround();
67
68 // ----------------------------------------------------------------------------
69 // Deprecated: The code below is preserved only for the existing tests that are
70 // using it. Now vendor prefixes are handled in a way that does not require
71 // manual intervention. New tests should just use unprefixed APIs and you
72 // are all set.
73 //
74 // These functions will eventually be removed when no tests use them.
75
76 function ShadowDomNotSupportedError() {
77     this.message = "Shadow DOM is not supported";
78 }
79
80 function createSR(element) {
81         if (element.createShadowRoot) {
82                 return element.createShadowRoot(); 
83         }
84         if (element.webkitCreateShadowRoot) {
85                 return element.webkitCreateShadowRoot();
86         }
87         throw new ShadowDomNotSupportedError();
88 }
89
90 // To allow using of both prefixed and non-prefixed API we do
91 // the following hook
92 function addPrefixed(element) {
93         if (element && !element.pseudo) {
94                 Object.defineProperty(element, 'pseudo', {
95                           get: function () { return element.webkitPseudo; },
96                           set: function (value) { return element.webkitPseudo = value; }
97                 });
98         }
99 }
100
101 function addDocumentPrefixed(d) {
102         if (d) {
103                 if (d.body) {
104                     addPrefixed(d.body);
105                 }
106                 if (d.head) {
107                     addPrefixed(d.head);                        
108                 }
109                 if (d.documentElement) {
110                         addPrefixed(d.documentElement);
111                 }
112                 d.oldCreate = d.createElement;
113                 d.createElement = function(tagName) {
114                         var el = d.oldCreate(tagName);
115                         addPrefixed(el);
116                         return el;
117                 };              
118         }       
119 }
120
121
122 function rethrowInternalErrors(e) {
123     if (e instanceof ShadowDomNotSupportedError) {
124         throw e;
125     }
126
127 }
128
129 function newDocument() {
130     var d = document.implementation.createDocument(
131         'http://www.w3.org/1999/xhtml', 'html');
132     //FIXME remove the call below when non-prefixed API is used
133     addDocumentPrefixed(d);
134     return d;        
135 }
136
137 function newHTMLDocument() {
138         var d = document.implementation.createHTMLDocument('Test Document');
139     //FIXME remove the call below when non-prefixed API is used
140     addDocumentPrefixed(d);
141     return d;
142 }
143
144 function newIFrame(ctx, src) {
145     if (typeof(ctx) == 'undefined' || typeof (ctx.iframes) != 'object') {
146         assert_unreached('Illegal context object in newIFrame');
147     }
148
149     var iframe = document.createElement('iframe');
150     if (!ctx.debug) {
151         iframe.style.display = 'none';
152     }
153     if (typeof(src) != 'undefined') {
154         iframe.src = src;
155     }
156     document.body.appendChild(iframe);
157     ctx.iframes.push(iframe);
158
159     assert_true(typeof(iframe.contentWindow) != 'undefined'
160         && typeof(iframe.contentWindow.document) != 'undefined'
161         && iframe.contentWindow.document != document, 'Failed to create new rendered document'
162     );
163     return iframe;
164 }
165 function newRenderedHTMLDocument(ctx) {
166     var frame = newIFrame(ctx);
167     var d = frame.contentWindow.document;
168     //FIXME remove the call below when non-prefixed API is used
169     addDocumentPrefixed(d);
170     return d;    
171 }
172
173 // End deprecated.
174 // ----------------------------------------------------------------------------
175
176 function newContext() {
177     return {iframes:[]};
178 }
179
180 function cleanContext(ctx) {
181     if (!ctx.debug) {
182         ctx.iframes.forEach(function (e) {
183             e.parentNode.removeChild(e);
184         });
185     }
186 }
187
188 function unit(f) {
189     return function () {
190         var ctx = newContext();
191         try {
192             f(ctx);
193         } finally {
194             cleanContext(ctx);
195         }
196     }
197 }
198
199 function step_unit(f, ctx, t) {
200     return function () {
201         var done = false;
202         try {
203             f();
204             done = true;
205         } finally {
206             if (done) {
207                 t.done();
208             }
209             cleanContext(ctx);
210         }
211     }
212 }
213
214 function assert_nodelist_contents_equal_noorder(actual, expected, message) {
215     assert_equals(actual.length, expected.length, message);
216     var used = [];
217     for (var i = 0; i < expected.length; i++) {
218         used.push(false);
219     }
220     for (i = 0; i < expected.length; i++) {
221         var found = false;
222         for (var j = 0; j < actual.length; j++) {
223             if (used[j] == false && expected[i] == actual[j]) {
224                 used[j] = true;
225                 found = true;
226                 break;
227             }
228         }
229         if (!found) {
230             assert_unreached(message + ". Fail reason:  element not found: " + expected[i]);
231         }
232     }
233 }
234
235
236 //Example taken from http://www.w3.org/TR/shadow-dom/#event-retargeting-example
237 function createTestMediaPlayer(d) {
238     d.body.innerHTML = '' +
239         '<div id="player">' +
240                 '<input type="checkbox" id="outside-control">' +
241                 '<div id="player-shadow-root">' +
242             '</div>' +
243         '</div>';
244
245         var playerShadowRoot = createSR(d.querySelector('#player-shadow-root'));
246         playerShadowRoot.innerHTML = '' +
247                 '<div id="controls">' +
248                         '<button class="play-button">PLAY</button>' +
249                         '<input type="range" id="timeline">' +
250                                 '<div id="timeline-shadow-root">' +
251                                 '</div>' +
252                         '</input>' +
253                     '<div class="volume-slider-container" id="volume-slider-container">' +
254                         '<input type="range" class="volume-slider" id="volume-slider">' +
255                             '<div id="volume-shadow-root">' +
256                             '</div>' +
257                         '</input>' +
258                     '</div>' +
259                 '</div>';
260
261         var timeLineShadowRoot = createSR(playerShadowRoot.querySelector('#timeline-shadow-root'));
262         timeLineShadowRoot.innerHTML =  '<div class="slider-thumb" id="timeline-slider-thumb"></div>';
263
264         var volumeShadowRoot = createSR(playerShadowRoot.querySelector('#volume-shadow-root'));
265         volumeShadowRoot.innerHTML = '<div class="slider-thumb" id="volume-slider-thumb"></div>';
266
267         return {
268                 'playerShadowRoot': playerShadowRoot,
269                 'timeLineShadowRoot': timeLineShadowRoot,
270                 'volumeShadowRoot': volumeShadowRoot
271                 };
272 }
273
274 //FIXME This call of initKeyboardEvent works for WebKit-only.
275 //See https://bugs.webkit.org/show_bug.cgi?id=16735
276 // and https://bugs.webkit.org/show_bug.cgi?id=13368. Add check for browser here
277 function fireKeyboardEvent(doc, element, key) {
278     var event = doc.createEvent('KeyboardEvent');
279     event.initKeyboardEvent("keydown", true, true, doc.defaultView, key, 0, false, false, false, false);
280     element.dispatchEvent(event);
281 }