alloy-js-test-san 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/README.rdoc +83 -0
  2. data/Rakefile +27 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/jstest +10 -0
  5. data/lib/js_test_san/runner.rb +70 -0
  6. data/lib/js_test_san/test.rb +17 -0
  7. data/lib/js_test_san/test_case.rb +103 -0
  8. data/lib/js_test_san.rb +2 -0
  9. data/test/fixtures/a_unit_test.html +27 -0
  10. data/test/fixtures/a_unit_test.js +22 -0
  11. data/test/regression/prototype/unit/ajax_test.html +29 -0
  12. data/test/regression/prototype/unit/array_test.html +28 -0
  13. data/test/regression/prototype/unit/assets/prototype.js +4900 -0
  14. data/test/regression/prototype/unit/assets/unittest.css +50 -0
  15. data/test/regression/prototype/unit/assets/unittest.js +615 -0
  16. data/test/regression/prototype/unit/assets/unittest_transport.js +1 -0
  17. data/test/regression/prototype/unit/base_test.html +27 -0
  18. data/test/regression/prototype/unit/class_test.html +27 -0
  19. data/test/regression/prototype/unit/date_test.html +27 -0
  20. data/test/regression/prototype/unit/dom_test.html +304 -0
  21. data/test/regression/prototype/unit/element_mixins_test.html +30 -0
  22. data/test/regression/prototype/unit/enumerable_test.html +35 -0
  23. data/test/regression/prototype/unit/event_test.html +31 -0
  24. data/test/regression/prototype/unit/fixtures/ajax.html +2 -0
  25. data/test/regression/prototype/unit/fixtures/ajax.js +42 -0
  26. data/test/regression/prototype/unit/fixtures/array.html +1 -0
  27. data/test/regression/prototype/unit/fixtures/class.js +83 -0
  28. data/test/regression/prototype/unit/fixtures/content.html +1 -0
  29. data/test/regression/prototype/unit/fixtures/data.json +1 -0
  30. data/test/regression/prototype/unit/fixtures/dom.css +84 -0
  31. data/test/regression/prototype/unit/fixtures/dom.html +278 -0
  32. data/test/regression/prototype/unit/fixtures/dom.js +17 -0
  33. data/test/regression/prototype/unit/fixtures/element_mixins.html +4 -0
  34. data/test/regression/prototype/unit/fixtures/element_mixins.js +2 -0
  35. data/test/regression/prototype/unit/fixtures/empty.html +0 -0
  36. data/test/regression/prototype/unit/fixtures/empty.js +1 -0
  37. data/test/regression/prototype/unit/fixtures/enumerable.html +8 -0
  38. data/test/regression/prototype/unit/fixtures/enumerable.js +23 -0
  39. data/test/regression/prototype/unit/fixtures/event.html +4 -0
  40. data/test/regression/prototype/unit/fixtures/form.html +108 -0
  41. data/test/regression/prototype/unit/fixtures/function.js +13 -0
  42. data/test/regression/prototype/unit/fixtures/hash.js +25 -0
  43. data/test/regression/prototype/unit/fixtures/hello.js +1 -0
  44. data/test/regression/prototype/unit/fixtures/logo.gif +0 -0
  45. data/test/regression/prototype/unit/fixtures/object.html +6 -0
  46. data/test/regression/prototype/unit/fixtures/object.js +7 -0
  47. data/test/regression/prototype/unit/fixtures/position.html +9 -0
  48. data/test/regression/prototype/unit/fixtures/selector.html +71 -0
  49. data/test/regression/prototype/unit/fixtures/string.js +8 -0
  50. data/test/regression/prototype/unit/fixtures/unittest.html +18 -0
  51. data/test/regression/prototype/unit/form_test.html +135 -0
  52. data/test/regression/prototype/unit/function_test.html +27 -0
  53. data/test/regression/prototype/unit/hash_test.html +27 -0
  54. data/test/regression/prototype/unit/number_test.html +27 -0
  55. data/test/regression/prototype/unit/object_test.html +32 -0
  56. data/test/regression/prototype/unit/periodical_executer_test.html +27 -0
  57. data/test/regression/prototype/unit/position_test.html +36 -0
  58. data/test/regression/prototype/unit/prototype_test.html +27 -0
  59. data/test/regression/prototype/unit/range_test.html +27 -0
  60. data/test/regression/prototype/unit/regexp_test.html +27 -0
  61. data/test/regression/prototype/unit/selector_test.html +98 -0
  62. data/test/regression/prototype/unit/string_test.html +27 -0
  63. data/test/regression/prototype/unit/tests/ajax_test.js +379 -0
  64. data/test/regression/prototype/unit/tests/array_test.js +186 -0
  65. data/test/regression/prototype/unit/tests/base_test.js +43 -0
  66. data/test/regression/prototype/unit/tests/class_test.js +136 -0
  67. data/test/regression/prototype/unit/tests/date_test.js +5 -0
  68. data/test/regression/prototype/unit/tests/dom_test.js +1493 -0
  69. data/test/regression/prototype/unit/tests/element_mixins_test.js +32 -0
  70. data/test/regression/prototype/unit/tests/enumerable_test.js +271 -0
  71. data/test/regression/prototype/unit/tests/event_test.js +235 -0
  72. data/test/regression/prototype/unit/tests/form_test.js +382 -0
  73. data/test/regression/prototype/unit/tests/function_test.js +133 -0
  74. data/test/regression/prototype/unit/tests/hash_test.js +178 -0
  75. data/test/regression/prototype/unit/tests/number_test.js +44 -0
  76. data/test/regression/prototype/unit/tests/object_test.js +180 -0
  77. data/test/regression/prototype/unit/tests/periodical_executer_test.js +15 -0
  78. data/test/regression/prototype/unit/tests/position_test.js +44 -0
  79. data/test/regression/prototype/unit/tests/prototype_test.js +43 -0
  80. data/test/regression/prototype/unit/tests/range_test.js +58 -0
  81. data/test/regression/prototype/unit/tests/regexp_test.js +42 -0
  82. data/test/regression/prototype/unit/tests/selector_test.js +408 -0
  83. data/test/regression/prototype/unit/tests/string_test.js +548 -0
  84. data/test/regression/prototype/unit/tests/unittest_test.js +148 -0
  85. data/test/regression/prototype/unit/unittest_test.html +45 -0
  86. data/test/regression/prototype/upstream +1 -0
  87. data/test/test_helper.rb +20 -0
  88. data/test/unit/runner_test.rb +165 -0
  89. data/test/unit/test_case_test.rb +167 -0
  90. data/test/unit/test_test.rb +24 -0
  91. metadata +145 -0
@@ -0,0 +1,1493 @@
1
+ var getInnerHTML = function(id) {
2
+ return $(id).innerHTML.toString().toLowerCase().gsub(/[\r\n\t]/, '');
3
+ };
4
+ var createParagraph = function(text) {
5
+ var p = document.createElement('p');
6
+ p.appendChild(document.createTextNode(text));
7
+ return p;
8
+ }
9
+
10
+ new Test.Unit.Runner({
11
+ setup: function() {
12
+ if (documentViewportProperties) return;
13
+ // Based on properties check from http://www.quirksmode.org/viewport/compatibility.html
14
+ documentViewportProperties = {
15
+ properties : [
16
+ 'self.pageXOffset', 'self.pageYOffset',
17
+ 'self.screenX', 'self.screenY',
18
+ 'self.innerHeight', 'self.innerWidth',
19
+ 'self.outerHeight', 'self.outerWidth',
20
+ 'self.screen.height', 'self.screen.width',
21
+ 'self.screen.availHeight', 'self.screen.availWidth',
22
+ 'self.screen.availTop', 'self.screen.availLeft',
23
+ 'self.screen.Top', 'self.screen.Left',
24
+ 'self.screenTop', 'self.screenLeft',
25
+ 'document.body.clientHeight', 'document.body.clientWidth',
26
+ 'document.body.scrollHeight', 'document.body.scrollWidth',
27
+ 'document.body.scrollLeft', 'document.body.scrollTop',
28
+ 'document.body.offsetHeight', 'document.body.offsetWidth',
29
+ 'document.body.offsetTop', 'document.body.offsetLeft'
30
+ ].inject([], function(properties, prop) {
31
+ if(!self.screen && prop.include('self.screen')) return;
32
+ if (!document.body && prop.include('document.body')) return;
33
+ properties.push(prop);
34
+ if (prop.include('.body') && document.documentElement)
35
+ properties.push(prop.sub('.body', '.documentElement'));
36
+ return properties;
37
+ }),
38
+
39
+ inspect : function() {
40
+ var props = [];
41
+ this.properties.each(function(prop) {
42
+ if (eval(prop)) props[prop] = eval(prop);
43
+ }, this);
44
+ return props;
45
+ }
46
+ };
47
+ },
48
+
49
+ testDollarFunction: function() {
50
+ this.assertUndefined($());
51
+
52
+ this.assertNull(document.getElementById('noWayThisIDExists'));
53
+ this.assertNull($('noWayThisIDExists'));
54
+
55
+ this.assertIdentical(document.getElementById('testdiv'), $('testdiv'));
56
+ this.assertEnumEqual([ $('testdiv'), $('container') ], $('testdiv', 'container'));
57
+ this.assertEnumEqual([ $('testdiv'), undefined, $('container') ],
58
+ $('testdiv', 'noWayThisIDExists', 'container'));
59
+ var elt = $('testdiv');
60
+ this.assertIdentical(elt, $(elt));
61
+ this.assertRespondsTo('hide', elt);
62
+ this.assertRespondsTo('childOf', elt);
63
+ },
64
+
65
+ testGetElementsByClassName: function() {
66
+ if (document.getElementsByClassName.toString().include('[native code]')) {
67
+ this.info("browser uses native getElementsByClassName; skipping tests");
68
+ return;
69
+ }
70
+
71
+
72
+ var div = $('class_names'), list = $('class_names_ul');
73
+
74
+ this.assertElementsMatch(document.getElementsByClassName('A'), 'p.A', 'ul#class_names_ul.A', 'li.A.C');
75
+
76
+
77
+ var isElementPrototypeSupported = (function(){
78
+ var el = document.createElement('div');
79
+ var result = typeof el.show != 'undefined';
80
+ el = null;
81
+ return result;
82
+ })();
83
+
84
+ if (!isElementPrototypeSupported)
85
+ this.assertUndefined(document.getElementById('unextended').show);
86
+
87
+ this.assertElementsMatch(div.getElementsByClassName('B'), 'ul#class_names_ul.A.B', 'div.B.C.D');
88
+ this.assertElementsMatch(div.getElementsByClassName('D C B'), 'div.B.C.D');
89
+ this.assertElementsMatch(div.getElementsByClassName(' D\nC\tB '), 'div.B.C.D');
90
+ this.assertElementsMatch(div.getElementsByClassName($w('D C B')));
91
+ this.assertElementsMatch(list.getElementsByClassName('A'), 'li.A.C');
92
+ this.assertElementsMatch(list.getElementsByClassName(' A '), 'li.A.C');
93
+ this.assertElementsMatch(list.getElementsByClassName('C A'), 'li.A.C');
94
+ this.assertElementsMatch(list.getElementsByClassName("C\nA "), 'li.A.C');
95
+ this.assertElementsMatch(list.getElementsByClassName('B'));
96
+ this.assertElementsMatch(list.getElementsByClassName('1'), 'li.1');
97
+ this.assertElementsMatch(list.getElementsByClassName([1]), 'li.1');
98
+ this.assertElementsMatch(list.getElementsByClassName(['1 junk']));
99
+ this.assertElementsMatch(list.getElementsByClassName(''));
100
+ this.assertElementsMatch(list.getElementsByClassName(' '));
101
+ this.assertElementsMatch(list.getElementsByClassName(['']));
102
+ this.assertElementsMatch(list.getElementsByClassName([' ', '']));
103
+ this.assertElementsMatch(list.getElementsByClassName({}));
104
+
105
+ // those lookups shouldn't have extended all nodes in document
106
+ if (!isElementPrototypeSupported)
107
+ this.assertUndefined(document.getElementById('unextended')['show']);
108
+ },
109
+
110
+ testElementInsertWithHTML: function() {
111
+ Element.insert('insertions-main', {before:'<p><em>before</em> text</p><p>more testing</p>'});
112
+ this.assert(getInnerHTML('insertions-container').startsWith('<p><em>before</em> text</p><p>more testing</p>'));
113
+ Element.insert('insertions-main', {after:'<p><em>after</em> text</p><p>more testing</p>'});
114
+ this.assert(getInnerHTML('insertions-container').endsWith('<p><em>after</em> text</p><p>more testing</p>'));
115
+ Element.insert('insertions-main', {top:'<p><em>top</em> text.</p><p>more testing</p>'});
116
+ this.assert(getInnerHTML('insertions-main').startsWith('<p><em>top</em> text.</p><p>more testing</p>'));
117
+ Element.insert('insertions-main', {bottom:'<p><em>bottom</em> text.</p><p>more testing</p>'});
118
+ this.assert(getInnerHTML('insertions-main').endsWith('<p><em>bottom</em> text.</p><p>more testing</p>'));
119
+ },
120
+
121
+ testElementInsertWithDOMNode: function() {
122
+ Element.insert('insertions-node-main', {before: createParagraph('node before')});
123
+ this.assert(getInnerHTML('insertions-node-container').startsWith('<p>node before</p>'));
124
+ Element.insert('insertions-node-main', {after: createParagraph('node after')});
125
+ this.assert(getInnerHTML('insertions-node-container').endsWith('<p>node after</p>'));
126
+ Element.insert('insertions-node-main', {top:createParagraph('node top')});
127
+ this.assert(getInnerHTML('insertions-node-main').startsWith('<p>node top</p>'));
128
+ Element.insert('insertions-node-main', {bottom:createParagraph('node bottom')});
129
+ this.assert(getInnerHTML('insertions-node-main').endsWith('<p>node bottom</p>'));
130
+ this.assertEqual($('insertions-node-main'), $('insertions-node-main').insert(document.createElement('p')));
131
+ },
132
+
133
+ testElementInsertWithToElementMethod: function() {
134
+ Element.insert('insertions-node-main', {toElement: createParagraph.curry('toElement') });
135
+ this.assert(getInnerHTML('insertions-node-main').endsWith('<p>toelement</p>'));
136
+ Element.insert('insertions-node-main', {bottom: {toElement: createParagraph.curry('bottom toElement') }});
137
+ this.assert(getInnerHTML('insertions-node-main').endsWith('<p>bottom toelement</p>'));
138
+ },
139
+
140
+ testElementInsertWithToHTMLMethod: function() {
141
+ Element.insert('insertions-node-main', {toHTML: function() { return '<p>toHTML</p>'} });
142
+ this.assert(getInnerHTML('insertions-node-main').endsWith('<p>tohtml</p>'));
143
+ Element.insert('insertions-node-main', {bottom: {toHTML: function() { return '<p>bottom toHTML</p>'} }});
144
+ this.assert(getInnerHTML('insertions-node-main').endsWith('<p>bottom tohtml</p>'));
145
+ },
146
+
147
+ testElementInsertWithNonString: function() {
148
+ Element.insert('insertions-main', {bottom:3});
149
+ this.assert(getInnerHTML('insertions-main').endsWith('3'));
150
+ },
151
+
152
+ testElementInsertInTables: function() {
153
+ Element.insert('second_row', {after:'<tr id="third_row"><td>Third Row</td></tr>'});
154
+ this.assert($('second_row').descendantOf('table'));
155
+
156
+ $('a_cell').insert({top:'hello world'});
157
+ this.assert($('a_cell').innerHTML.startsWith('hello world'));
158
+ $('a_cell').insert({after:'<td>hi planet</td>'});
159
+ this.assertEqual('hi planet', $('a_cell').next().innerHTML);
160
+ $('table_for_insertions').insert('<tr><td>a cell!</td></tr>');
161
+ this.assert($('table_for_insertions').innerHTML.gsub('\r\n', '').toLowerCase().include('<tr><td>a cell!</td></tr>'));
162
+ $('row_1').insert({after:'<tr></tr><tr></tr><tr><td>last</td></tr>'});
163
+ this.assertEqual('last', $A($('table_for_row_insertions').getElementsByTagName('tr')).last().lastChild.innerHTML);
164
+ },
165
+
166
+ testElementInsertInSelect: function() {
167
+ var selectTop = $('select_for_insert_top'), selectBottom = $('select_for_insert_bottom');
168
+ selectBottom.insert('<option value="33">option 33</option><option selected="selected">option 45</option>');
169
+ this.assertEqual('option 45', selectBottom.getValue());
170
+ selectTop.insert({top:'<option value="A">option A</option><option value="B" selected="selected">option B</option>'});
171
+ this.assertEqual(4, selectTop.options.length);
172
+ },
173
+
174
+ testElementMethodInsert: function() {
175
+ $('element-insertions-main').insert({before:'some text before'});
176
+ this.assert(getInnerHTML('element-insertions-container').startsWith('some text before'));
177
+ $('element-insertions-main').insert({after:'some text after'});
178
+ this.assert(getInnerHTML('element-insertions-container').endsWith('some text after'));
179
+ $('element-insertions-main').insert({top:'some text top'});
180
+ this.assert(getInnerHTML('element-insertions-main').startsWith('some text top'));
181
+ $('element-insertions-main').insert({bottom:'some text bottom'});
182
+ this.assert(getInnerHTML('element-insertions-main').endsWith('some text bottom'));
183
+
184
+ $('element-insertions-main').insert('some more text at the bottom');
185
+ this.assert(getInnerHTML('element-insertions-main').endsWith('some more text at the bottom'));
186
+
187
+ $('element-insertions-main').insert({TOP:'some text uppercase top'});
188
+ this.assert(getInnerHTML('element-insertions-main').startsWith('some text uppercase top'));
189
+
190
+ $('element-insertions-multiple-main').insert({
191
+ top:'1', bottom:2, before: new Element('p').update('3'), after:'4'
192
+ });
193
+ this.assert(getInnerHTML('element-insertions-multiple-main').startsWith('1'));
194
+ this.assert(getInnerHTML('element-insertions-multiple-main').endsWith('2'));
195
+ this.assert(getInnerHTML('element-insertions-multiple-container').startsWith('<p>3</p>'));
196
+ this.assert(getInnerHTML('element-insertions-multiple-container').endsWith('4'));
197
+
198
+ $('element-insertions-main').update('test');
199
+ $('element-insertions-main').insert(null);
200
+ $('element-insertions-main').insert({bottom:null});
201
+ this.assertEqual('test', getInnerHTML('element-insertions-main'));
202
+ $('element-insertions-main').insert(1337);
203
+ this.assertEqual('test1337', getInnerHTML('element-insertions-main'));
204
+ },
205
+
206
+ testNewElementInsert: function() {
207
+ var container = new Element('div'), element = new Element('div');
208
+ container.insert(element);
209
+
210
+ element.insert({ before: '<p>a paragraph</p>' });
211
+ this.assertEqual('<p>a paragraph</p><div></div>', getInnerHTML(container));
212
+ element.insert({ after: 'some text' });
213
+ this.assertEqual('<p>a paragraph</p><div></div>some text', getInnerHTML(container));
214
+
215
+ element.insert({ top: '<p>a paragraph</p>' });
216
+ this.assertEqual('<p>a paragraph</p>', getInnerHTML(element));
217
+ element.insert('some text');
218
+ this.assertEqual('<p>a paragraph</p>some text', getInnerHTML(element));
219
+ },
220
+
221
+ testInsertionBackwardsCompatibility: function() {
222
+ new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before');
223
+ this.assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing before'));
224
+ new Insertion.After('element-insertions-main', 'some backward-compatibility testing after');
225
+ this.assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing after'));
226
+ new Insertion.Top('element-insertions-main', 'some backward-compatibility testing top');
227
+ this.assert(getInnerHTML('element-insertions-main').startsWith('some backward-compatibility testing top'));
228
+ new Insertion.Bottom('element-insertions-main', 'some backward-compatibility testing bottom');
229
+ this.assert(getInnerHTML('element-insertions-main').endsWith('some backward-compatibility testing bottom'));
230
+ },
231
+
232
+ testElementWrap: function() {
233
+ var element = $('wrap'), parent = document.createElement('div');
234
+ element.wrap();
235
+ this.assert(getInnerHTML('wrap-container').startsWith('<div><p'));
236
+ element.wrap('div');
237
+ this.assert(getInnerHTML('wrap-container').startsWith('<div><div><p'));
238
+
239
+ element.wrap(parent);
240
+ this.assert(Object.isFunction(parent.setStyle));
241
+ this.assert(getInnerHTML('wrap-container').startsWith('<div><div><div><p'));
242
+
243
+ element.wrap('div', {className: 'wrapper'});
244
+ this.assert(element.up().hasClassName('wrapper'));
245
+ element.wrap({className: 'other-wrapper'});
246
+ this.assert(element.up().hasClassName('other-wrapper'));
247
+ element.wrap(new Element('div'), {className: 'yet-other-wrapper'});
248
+ this.assert(element.up().hasClassName('yet-other-wrapper'));
249
+
250
+ var orphan = new Element('p'), div = new Element('div');
251
+ orphan.wrap(div);
252
+ this.assertEqual(orphan.parentNode, div);
253
+ },
254
+
255
+ testElementWrapReturnsWrapper: function() {
256
+ var element = new Element("div");
257
+ var wrapper = element.wrap("div");
258
+ this.assertNotEqual(element, wrapper);
259
+ this.assertEqual(element.up(), wrapper);
260
+ },
261
+
262
+ testElementVisible: function(){
263
+ this.assertNotEqual('none', $('test-visible').style.display);
264
+ this.assertEqual('none', $('test-hidden').style.display);
265
+ },
266
+
267
+ testElementToggle: function(){
268
+ $('test-toggle-visible').toggle();
269
+ this.assert(!$('test-toggle-visible').visible());
270
+ $('test-toggle-visible').toggle();
271
+ this.assert($('test-toggle-visible').visible());
272
+ $('test-toggle-hidden').toggle();
273
+ this.assert($('test-toggle-hidden').visible());
274
+ $('test-toggle-hidden').toggle();
275
+ this.assert(!$('test-toggle-hidden').visible());
276
+ },
277
+
278
+ testElementShow: function(){
279
+ $('test-show-visible').show();
280
+ this.assert($('test-show-visible').visible());
281
+ $('test-show-hidden').show();
282
+ this.assert($('test-show-hidden').visible());
283
+ },
284
+
285
+ testElementHide: function(){
286
+ $('test-hide-visible').hide();
287
+ this.assert(!$('test-hide-visible').visible());
288
+ $('test-hide-hidden').hide();
289
+ this.assert(!$('test-hide-hidden').visible());
290
+ },
291
+
292
+ testElementRemove: function(){
293
+ $('removable').remove();
294
+ this.assert($('removable-container').empty());
295
+ },
296
+
297
+ testElementUpdate: function() {
298
+ $('testdiv').update('hello from div!');
299
+ this.assertEqual('hello from div!', $('testdiv').innerHTML);
300
+
301
+ Element.update('testdiv', 'another hello from div!');
302
+ this.assertEqual('another hello from div!', $('testdiv').innerHTML);
303
+
304
+ Element.update('testdiv', 123);
305
+ this.assertEqual('123', $('testdiv').innerHTML);
306
+
307
+ Element.update('testdiv');
308
+ this.assertEqual('', $('testdiv').innerHTML);
309
+
310
+ Element.update('testdiv', '&nbsp;');
311
+ this.assert(!$('testdiv').innerHTML.empty());
312
+ },
313
+
314
+ testElementUpdateWithScript: function() {
315
+ $('testdiv').update('hello from div!<script>\ntestVar="hello!";\n</'+'script>');
316
+ this.assertEqual('hello from div!',$('testdiv').innerHTML);
317
+ this.wait(100,function(){
318
+ this.assertEqual('hello!',testVar);
319
+
320
+ Element.update('testdiv','another hello from div!\n<script>testVar="another hello!"</'+'script>\nhere it goes');
321
+
322
+ // note: IE normalizes whitespace (like line breaks) to single spaces, thus the match test
323
+ this.assertMatch(/^another hello from div!\s+here it goes$/,$('testdiv').innerHTML);
324
+ this.wait(100,function(){
325
+ this.assertEqual('another hello!',testVar);
326
+
327
+ Element.update('testdiv','a\n<script>testVar="a"\ntestVar="b"</'+'script>');
328
+ this.wait(100,function(){
329
+ this.assertEqual('b', testVar);
330
+
331
+ Element.update('testdiv',
332
+ 'x<script>testVar2="a"</'+'script>\nblah\n'+
333
+ 'x<script>testVar2="b"</'+'script>');
334
+ this.wait(100,function(){
335
+ this.assertEqual('b', testVar2);
336
+ });
337
+ });
338
+ });
339
+ });
340
+ },
341
+
342
+ testElementUpdateInTableRow: function() {
343
+ $('second_row').update('<td id="i_am_a_td">test</td>');
344
+ this.assertEqual('test',$('i_am_a_td').innerHTML);
345
+
346
+ Element.update('second_row','<td id="i_am_a_td">another <span>test</span></td>');
347
+ this.assertEqual('another <span>test</span>',$('i_am_a_td').innerHTML.toLowerCase());
348
+ },
349
+
350
+ testElementUpdateInTableCell: function() {
351
+ Element.update('a_cell','another <span>test</span>');
352
+ this.assertEqual('another <span>test</span>',$('a_cell').innerHTML.toLowerCase());
353
+ },
354
+
355
+ testElementUpdateInTable: function() {
356
+ Element.update('table','<tr><td>boo!</td></tr>');
357
+ this.assertMatch(/^<tr>\s*<td>boo!<\/td><\/tr>$/,$('table').innerHTML.toLowerCase());
358
+ },
359
+
360
+ testElementUpdateInSelect: function() {
361
+ var select = $('select_for_update');
362
+ select.update('<option value="3">option 3</option><option selected="selected">option 4</option>');
363
+ this.assertEqual('option 4', select.getValue());
364
+ },
365
+
366
+ testElementUpdateWithDOMNode: function() {
367
+ $('testdiv').update(new Element('div').insert('bla'));
368
+ this.assertEqual('<div>bla</div>', getInnerHTML('testdiv'));
369
+ },
370
+
371
+ testElementUpdateWithToElementMethod: function() {
372
+ $('testdiv').update({toElement: createParagraph.curry('foo')});
373
+ this.assertEqual('<p>foo</p>', getInnerHTML('testdiv'));
374
+ },
375
+
376
+ testElementUpdateWithToHTMLMethod: function() {
377
+ $('testdiv').update({toHTML: function() { return 'hello world' }});
378
+ this.assertEqual('hello world', getInnerHTML('testdiv'));
379
+ },
380
+
381
+ testElementUpdateScriptElement: function() {
382
+ var el = new Element('script', {
383
+ type: 'text/javascript'
384
+ });
385
+ this.assertNothingRaised(function(){
386
+ el.update('(function(){})');
387
+ })
388
+ },
389
+
390
+ testElementReplace: function() {
391
+ $('testdiv-replace-1').replace('hello from div!');
392
+ this.assertEqual('hello from div!', $('testdiv-replace-container-1').innerHTML);
393
+
394
+ $('testdiv-replace-2').replace(123);
395
+ this.assertEqual('123', $('testdiv-replace-container-2').innerHTML);
396
+
397
+ $('testdiv-replace-3').replace();
398
+ this.assertEqual('', $('testdiv-replace-container-3').innerHTML);
399
+
400
+ $('testrow-replace').replace('<tr><td>hello</td></tr>');
401
+ this.assert(getInnerHTML('testrow-replace-container').include('<tr><td>hello</td></tr>'));
402
+
403
+ $('testoption-replace').replace('<option>hello</option>');
404
+ this.assert($('testoption-replace-container').innerHTML.include('hello'));
405
+
406
+ Element.replace('testinput-replace', '<p>hello world</p>');
407
+ this.assertEqual('<p>hello world</p>', getInnerHTML('testform-replace'));
408
+
409
+ Element.replace('testform-replace', '<form></form>');
410
+ this.assertEqual('<p>some text</p><form></form><p>some text</p>', getInnerHTML('testform-replace-container'));
411
+ },
412
+
413
+ testElementReplaceWithScript: function() {
414
+ $('testdiv-replace-4').replace('hello from div!<script>testVarReplace="hello!"</'+'script>');
415
+ this.assertEqual('hello from div!', $('testdiv-replace-container-4').innerHTML);
416
+ this.wait(100,function(){
417
+ this.assertEqual('hello!',testVarReplace);
418
+
419
+ $('testdiv-replace-5').replace('another hello from div!\n<script>testVarReplace="another hello!"</'+'script>\nhere it goes');
420
+
421
+ // note: IE normalizes whitespace (like line breaks) to single spaces, thus the match test
422
+ this.assertMatch(/^another hello from div!\s+here it goes$/,$('testdiv-replace-container-5').innerHTML);
423
+ this.wait(100,function(){
424
+ this.assertEqual('another hello!',testVarReplace);
425
+ });
426
+ });
427
+ },
428
+
429
+ testElementReplaceWithDOMNode: function() {
430
+ $('testdiv-replace-element').replace(createParagraph('hello'));
431
+ this.assertEqual('<p>hello</p>', getInnerHTML('testdiv-replace-container-element'));
432
+ },
433
+
434
+ testElementReplaceWithToElementMethod: function() {
435
+ $('testdiv-replace-toelement').replace({toElement: createParagraph.curry('hello')});
436
+ this.assertEqual('<p>hello</p>', getInnerHTML('testdiv-replace-container-toelement'));
437
+ },
438
+
439
+ testElementReplaceWithToHTMLMethod: function() {
440
+ $('testdiv-replace-tohtml').replace({toHTML: function() { return 'hello' }});
441
+ this.assertEqual('hello', getInnerHTML('testdiv-replace-container-tohtml'));
442
+ },
443
+
444
+ testElementSelectorMethod: function() {
445
+ ['getElementsBySelector','select'].each(function(method) {
446
+ var testSelector = $('container')[method]('p.test');
447
+ this.assertEqual(testSelector.length, 4);
448
+ this.assertEqual(testSelector[0], $('intended'));
449
+ this.assertEqual(testSelector[0], $$('#container p.test')[0]);
450
+ }, this);
451
+ },
452
+
453
+ testElementAdjacent: function() {
454
+ var elements = $('intended').adjacent('p');
455
+ this.assertEqual(elements.length, 3);
456
+ elements.each(function(element){
457
+ this.assert(element != $('intended'));
458
+ }, this);
459
+ },
460
+
461
+ testElementIdentify: function() {
462
+ var parent = $('identification');
463
+ this.assertEqual(parent.down().identify(), 'predefined_id');
464
+ this.assert(parent.down(1).identify().startsWith('anonymous_element_'));
465
+ this.assert(parent.down(2).identify().startsWith('anonymous_element_'));
466
+ this.assert(parent.down(3).identify().startsWith('anonymous_element_'));
467
+
468
+ this.assert(parent.down(3).id !== parent.down(2).id);
469
+ },
470
+
471
+ testElementClassNameMethod: function() {
472
+ var testClassNames = $('container').getElementsByClassName('test');
473
+ var testSelector = $('container').getElementsBySelector('p.test');
474
+ this.assertEqual(testClassNames[0], $('intended'));
475
+ this.assertEqual(testClassNames.length, 4);
476
+ this.assertEqual(testSelector[3], testClassNames[3]);
477
+ this.assertEqual(testClassNames.length, testSelector.length);
478
+ },
479
+
480
+ testElementAncestors: function() {
481
+ var ancestors = $('navigation_test_f').ancestors();
482
+ this.assertElementsMatch(ancestors, 'ul', 'li', 'ul#navigation_test',
483
+ 'div#nav_tests_isolator', 'body', 'html');
484
+ this.assertElementsMatch(ancestors.last().ancestors());
485
+
486
+ var dummy = $(document.createElement('DIV'));
487
+ dummy.innerHTML = '<div></div>'.times(3);
488
+ this.assert(typeof $(dummy.childNodes[0]).ancestors()[0]['setStyle'] == 'function');
489
+ },
490
+
491
+ testElementDescendants: function() {
492
+ this.assertElementsMatch($('navigation_test').descendants(),
493
+ 'li', 'em', 'li', 'em.dim', 'li', 'em', 'ul', 'li',
494
+ 'em.dim', 'li#navigation_test_f', 'em', 'li', 'em');
495
+ this.assertElementsMatch($('navigation_test_f').descendants(), 'em');
496
+
497
+ var dummy = $(document.createElement('DIV'));
498
+ dummy.innerHTML = '<div></div>'.times(3);
499
+ this.assert(typeof dummy.descendants()[0].setStyle == 'function');
500
+ },
501
+
502
+ testElementFirstDescendant: function() {
503
+ this.assertElementMatches($('navigation_test').firstDescendant(), 'li.first');
504
+ this.assertNull($('navigation_test_next_sibling').firstDescendant());
505
+ },
506
+
507
+ testElementChildElements: function() {
508
+ this.assertElementsMatch($('navigation_test').childElements(),
509
+ 'li.first', 'li', 'li#navigation_test_c', 'li.last');
510
+ this.assertNotEqual(0, $('navigation_test_next_sibling').childNodes.length);
511
+ this.assertEnumEqual([], $('navigation_test_next_sibling').childElements());
512
+
513
+ var dummy = $(document.createElement('DIV'));
514
+ dummy.innerHTML = '<div></div>'.times(3);
515
+ this.assert(typeof dummy.childElements()[0].setStyle == 'function');
516
+ },
517
+
518
+ testElementImmediateDescendants: function() {
519
+ this.assertIdentical(Element.Methods.childElements, Element.Methods.immediateDescendants);
520
+ },
521
+
522
+ testElementPreviousSiblings: function() {
523
+ this.assertElementsMatch($('navigation_test').previousSiblings(),
524
+ 'span#nav_test_prev_sibling', 'p.test', 'div', 'div#nav_test_first_sibling');
525
+ this.assertElementsMatch($('navigation_test_f').previousSiblings(), 'li');
526
+
527
+ var dummy = $(document.createElement('DIV'));
528
+ dummy.innerHTML = '<div></div>'.times(3);
529
+ this.assert(typeof $(dummy.childNodes[1]).previousSiblings()[0].setStyle == 'function');
530
+ },
531
+
532
+ testElementNextSiblings: function() {
533
+ this.assertElementsMatch($('navigation_test').nextSiblings(),
534
+ 'div#navigation_test_next_sibling', 'p');
535
+ this.assertElementsMatch($('navigation_test_f').nextSiblings());
536
+
537
+ var dummy = $(document.createElement('DIV'));
538
+ dummy.innerHTML = '<div></div>'.times(3);
539
+ this.assert(typeof $(dummy.childNodes[0]).nextSiblings()[0].setStyle == 'function');
540
+ },
541
+
542
+ testElementSiblings: function() {
543
+ this.assertElementsMatch($('navigation_test').siblings(),
544
+ 'div#nav_test_first_sibling', 'div', 'p.test',
545
+ 'span#nav_test_prev_sibling', 'div#navigation_test_next_sibling', 'p');
546
+
547
+ var dummy = $(document.createElement('DIV'));
548
+ dummy.innerHTML = '<div></div>'.times(3);
549
+ this.assert(typeof $(dummy.childNodes[0]).siblings()[0].setStyle == 'function');
550
+ },
551
+
552
+ testElementUp: function() {
553
+ var element = $('navigation_test_f');
554
+ this.assertElementMatches(element.up(), 'ul');
555
+ this.assertElementMatches(element.up(0), 'ul');
556
+ this.assertElementMatches(element.up(1), 'li');
557
+ this.assertElementMatches(element.up(2), 'ul#navigation_test');
558
+ this.assertElementsMatch(element.up('li').siblings(), 'li.first', 'li', 'li.last');
559
+ this.assertElementMatches(element.up('ul', 1), 'ul#navigation_test');
560
+ this.assertEqual(undefined, element.up('garbage'));
561
+ this.assertEqual(undefined, element.up(6));
562
+ this.assertElementMatches(element.up('.non-existant, ul'), 'ul');
563
+
564
+ var dummy = $(document.createElement('DIV'));
565
+ dummy.innerHTML = '<div></div>'.times(3);
566
+ this.assert(typeof $(dummy.childNodes[0]).up().setStyle == 'function');
567
+ },
568
+
569
+ testElementDown: function() {
570
+ var element = $('navigation_test');
571
+ this.assertElementMatches(element.down(), 'li.first');
572
+ this.assertElementMatches(element.down(0), 'li.first');
573
+ this.assertElementMatches(element.down(1), 'em');
574
+ this.assertElementMatches(element.down('li', 5), 'li.last');
575
+ this.assertElementMatches(element.down('ul').down('li', 1), 'li#navigation_test_f');
576
+ this.assertElementMatches(element.down('.non-existant, .first'), 'li.first');
577
+
578
+ var dummy = $(document.createElement('DIV'));
579
+ dummy.innerHTML = '<div></div>'.times(3);
580
+ this.assert(typeof dummy.down().setStyle == 'function');
581
+
582
+ var input = $$('input')[0];
583
+ this.assertNothingRaised(function(){ input.down('span') });
584
+ this.assertUndefined(input.down('span'));
585
+ },
586
+
587
+ testElementPrevious: function() {
588
+ var element = $('navigation_test').down('li.last');
589
+ this.assertElementMatches(element.previous(), 'li#navigation_test_c');
590
+ this.assertElementMatches(element.previous(1), 'li');
591
+ this.assertElementMatches(element.previous('.first'), 'li.first');
592
+ this.assertEqual(undefined, element.previous(3));
593
+ this.assertEqual(undefined, $('navigation_test').down().previous());
594
+ this.assertElementMatches(element.previous('.non-existant, .first'), 'li.first');
595
+
596
+ var dummy = $(document.createElement('DIV'));
597
+ dummy.innerHTML = '<div></div>'.times(3);
598
+ this.assert(typeof $(dummy.childNodes[1]).previous().setStyle == 'function');
599
+ },
600
+
601
+ testElementNext: function() {
602
+ var element = $('navigation_test').down('li.first');
603
+ this.assertElementMatches(element.next(), 'li');
604
+ this.assertElementMatches(element.next(1), 'li#navigation_test_c');
605
+ this.assertElementMatches(element.next(2), 'li.last');
606
+ this.assertElementMatches(element.next('.last'), 'li.last');
607
+ this.assertEqual(undefined, element.next(3));
608
+ this.assertEqual(undefined, element.next(2).next());
609
+ this.assertElementMatches(element.next('.non-existant, .last'), 'li.last');
610
+
611
+ var dummy = $(document.createElement('DIV'));
612
+ dummy.innerHTML = '<div></div>'.times(3);
613
+ this.assert(typeof $(dummy.childNodes[0]).next().setStyle == 'function');
614
+ },
615
+
616
+ testElementInspect: function() {
617
+ this.assertEqual('<ul id="navigation_test">', $('navigation_test').inspect());
618
+ this.assertEqual('<li class="first">', $('navigation_test').down().inspect());
619
+ this.assertEqual('<em>', $('navigation_test').down(1).inspect());
620
+ },
621
+
622
+ testElementMakeClipping: function() {
623
+ var chained = Element.extend(document.createElement('DIV'));
624
+ this.assertEqual(chained, chained.makeClipping());
625
+ this.assertEqual(chained, chained.makeClipping());
626
+ this.assertEqual(chained, chained.makeClipping().makeClipping());
627
+
628
+ this.assertEqual(chained, chained.undoClipping());
629
+ this.assertEqual(chained, chained.undoClipping());
630
+ this.assertEqual(chained, chained.undoClipping().makeClipping());
631
+
632
+ ['hidden','visible','scroll'].each( function(overflowValue) {
633
+ var element = $('element_with_'+overflowValue+'_overflow');
634
+
635
+ this.assertEqual(overflowValue, element.getStyle('overflow'));
636
+ element.makeClipping();
637
+ this.assertEqual('hidden', element.getStyle('overflow'));
638
+ element.undoClipping();
639
+ this.assertEqual(overflowValue, element.getStyle('overflow'));
640
+ }, this);
641
+ },
642
+
643
+ testElementExtend: function() {
644
+ var element = $('element_extend_test');
645
+ this.assertRespondsTo('show', element);
646
+
647
+ var XHTML_TAGS = $w(
648
+ 'a abbr acronym address applet area '+
649
+ 'b bdo big blockquote br button caption '+
650
+ 'cite code col colgroup dd del dfn div dl dt '+
651
+ 'em fieldset form h1 h2 h3 h4 h5 h6 hr '+
652
+ 'i iframe img input ins kbd label legend li '+
653
+ 'map object ol optgroup option p param pre q samp '+
654
+ 'script select small span strong style sub sup '+
655
+ 'table tbody td textarea tfoot th thead tr tt ul var');
656
+
657
+ XHTML_TAGS.each(function(tag) {
658
+ var element = document.createElement(tag);
659
+ this.assertEqual(element, Element.extend(element));
660
+ this.assertRespondsTo('show', element);
661
+ }, this);
662
+
663
+ [null,'','a','aa'].each(function(content) {
664
+ var textnode = document.createTextNode(content);
665
+ this.assertEqual(textnode, Element.extend(textnode));
666
+ this.assert(typeof textnode['show'] == 'undefined');
667
+ }, this);
668
+ },
669
+
670
+ testElementExtendReextendsDiscardedNodes: function() {
671
+ this.assertRespondsTo('show', $('discard_1'));
672
+ $('element_reextend_test').innerHTML += '<div id="discard_2"></div>';
673
+ this.assertRespondsTo('show', $('discard_1'));
674
+ },
675
+
676
+ testElementCleanWhitespace: function() {
677
+ Element.cleanWhitespace("test_whitespace");
678
+ this.assertEqual(3, $("test_whitespace").childNodes.length);
679
+
680
+ this.assertEqual(1, $("test_whitespace").firstChild.nodeType);
681
+ this.assertEqual('SPAN', $("test_whitespace").firstChild.tagName);
682
+
683
+ this.assertEqual(1, $("test_whitespace").firstChild.nextSibling.nodeType);
684
+ this.assertEqual('DIV', $("test_whitespace").firstChild.nextSibling.tagName);
685
+
686
+ this.assertEqual(1, $("test_whitespace").firstChild.nextSibling.nextSibling.nodeType);
687
+ this.assertEqual('SPAN', $("test_whitespace").firstChild.nextSibling.nextSibling.tagName);
688
+
689
+ var element = document.createElement('DIV');
690
+ element.appendChild(document.createTextNode(''));
691
+ element.appendChild(document.createTextNode(''));
692
+ this.assertEqual(2, element.childNodes.length);
693
+ Element.cleanWhitespace(element);
694
+ this.assertEqual(0, element.childNodes.length);
695
+ },
696
+
697
+ testElementEmpty: function() {
698
+ this.assert($('test-empty').empty());
699
+ this.assert($('test-empty-but-contains-whitespace').empty());
700
+ this.assert(!$('test-full').empty());
701
+ },
702
+
703
+ testDescendantOf: function() {
704
+ this.assert($('child').descendantOf('ancestor'));
705
+ this.assert($('child').descendantOf($('ancestor')));
706
+
707
+ this.assert(!$('ancestor').descendantOf($('child')));
708
+
709
+ this.assert($('great-grand-child').descendantOf('ancestor'), 'great-grand-child < ancestor');
710
+ this.assert($('grand-child').descendantOf('ancestor'), 'grand-child < ancestor');
711
+ this.assert($('great-grand-child').descendantOf('grand-child'), 'great-grand-child < grand-child');
712
+ this.assert($('grand-child').descendantOf('child'), 'grand-child < child');
713
+ this.assert($('great-grand-child').descendantOf('child'), 'great-grand-child < child');
714
+
715
+ this.assert($('sibling').descendantOf('ancestor'), 'sibling < ancestor');
716
+ this.assert($('grand-sibling').descendantOf('sibling'), 'grand-sibling < sibling');
717
+ this.assert($('grand-sibling').descendantOf('ancestor'), 'grand-sibling < ancestor');
718
+
719
+ this.assert($('grand-sibling').descendantOf(document.body), 'grand-sibling < body');
720
+
721
+ this.assert(!$('great-grand-child').descendantOf('great-grand-child'), 'great-grand-child < great-grand-child');
722
+ this.assert(!$('great-grand-child').descendantOf('sibling'), 'great-grand-child < sibling');
723
+ this.assert(!$('sibling').descendantOf('child'), 'sibling < child');
724
+ this.assert(!$('great-grand-child').descendantOf('not-in-the-family'), 'great-grand-child < not-in-the-family');
725
+ this.assert(!$('child').descendantOf('not-in-the-family'), 'child < not-in-the-family');
726
+
727
+ this.assert(!$(document.body).descendantOf('great-grand-child'));
728
+
729
+ // dynamically-created elements
730
+ $('ancestor').insert(new Element('div', { id: 'weird-uncle' }));
731
+ this.assert($('weird-uncle').descendantOf('ancestor'));
732
+
733
+ $(document.body).insert(new Element('div', { id: 'impostor' }));
734
+ this.assert(!$('impostor').descendantOf('ancestor'));
735
+
736
+ // test descendantOf document
737
+ this.assert($(document.body).descendantOf(document));
738
+ this.assert($(document.documentElement).descendantOf(document));
739
+ },
740
+
741
+ testChildOf: function() {
742
+ this.assert($('child').childOf('ancestor'));
743
+ this.assert($('child').childOf($('ancestor')));
744
+ this.assert($('great-grand-child').childOf('ancestor'));
745
+ this.assert(!$('great-grand-child').childOf('not-in-the-family'));
746
+ this.assertIdentical(Element.Methods.childOf, Element.Methods.descendantOf);
747
+ },
748
+
749
+ testElementSetStyle: function() {
750
+ Element.setStyle('style_test_3',{ 'left': '2px' });
751
+ this.assertEqual('2px', $('style_test_3').style.left);
752
+
753
+ Element.setStyle('style_test_3',{ marginTop: '1px' });
754
+ this.assertEqual('1px', $('style_test_3').style.marginTop);
755
+
756
+ $('style_test_3').setStyle({ marginTop: '2px', left: '-1px' });
757
+ this.assertEqual('-1px', $('style_test_3').style.left);
758
+ this.assertEqual('2px', $('style_test_3').style.marginTop);
759
+
760
+ this.assertEqual('none', $('style_test_3').getStyle('float'));
761
+ $('style_test_3').setStyle({ 'float': 'left' });
762
+ this.assertEqual('left', $('style_test_3').getStyle('float'));
763
+
764
+ $('style_test_3').setStyle({ cssFloat: 'none' });
765
+ this.assertEqual('none', $('style_test_3').getStyle('float'));
766
+
767
+ this.assertEqual(1, $('style_test_3').getStyle('opacity'));
768
+
769
+ $('style_test_3').setStyle({ opacity: 0.5 });
770
+ this.assertEqual(0.5, $('style_test_3').getStyle('opacity'));
771
+
772
+ $('style_test_3').setStyle({ opacity: '' });
773
+ this.assertEqual(1, $('style_test_3').getStyle('opacity'));
774
+
775
+ $('style_test_3').setStyle({ opacity: 0 });
776
+ this.assertEqual(0, $('style_test_3').getStyle('opacity'));
777
+
778
+ $('test_csstext_1').setStyle('font-size: 15px');
779
+ this.assertEqual('15px', $('test_csstext_1').getStyle('font-size'));
780
+
781
+ $('test_csstext_2').setStyle({height: '40px'});
782
+ $('test_csstext_2').setStyle('font-size: 15px');
783
+ this.assertEqual('15px', $('test_csstext_2').getStyle('font-size'));
784
+ this.assertEqual('40px', $('test_csstext_2').getStyle('height'));
785
+
786
+ $('test_csstext_3').setStyle('font-size: 15px');
787
+ this.assertEqual('15px', $('test_csstext_3').getStyle('font-size'));
788
+ this.assertEqual('1px', $('test_csstext_3').getStyle('border-top-width'));
789
+
790
+ $('test_csstext_4').setStyle('font-size: 15px');
791
+ this.assertEqual('15px', $('test_csstext_4').getStyle('font-size'));
792
+
793
+ $('test_csstext_4').setStyle('float: right; font-size: 10px');
794
+ this.assertEqual('right', $('test_csstext_4').getStyle('float'));
795
+ this.assertEqual('10px', $('test_csstext_4').getStyle('font-size'));
796
+
797
+ $('test_csstext_5').setStyle('float: left; opacity: .5; font-size: 10px');
798
+ this.assertEqual(parseFloat('0.5'), parseFloat($('test_csstext_5').getStyle('opacity')));
799
+ },
800
+
801
+ testElementSetStyleCamelized: function() {
802
+ this.assertNotEqual('30px', $('style_test_3').style.marginTop);
803
+ $('style_test_3').setStyle({ marginTop: '30px'}, true);
804
+ this.assertEqual('30px', $('style_test_3').style.marginTop);
805
+ },
806
+
807
+ testElementSetOpacity: function() {
808
+ [0,0.1,0.5,0.999].each(function(opacity){
809
+ $('style_test_3').setOpacity(opacity);
810
+
811
+ // b/c of rounding issues on IE special case
812
+ var realOpacity = $('style_test_3').getStyle('opacity');
813
+
814
+ // opera rounds off to two significant digits, so we check for a
815
+ // ballpark figure
816
+ this.assert((Number(realOpacity) - opacity) <= 0.002, 'setting opacity to ' + opacity);
817
+ }, this);
818
+
819
+ this.assertEqual(0,
820
+ $('style_test_3').setOpacity(0.0000001).getStyle('opacity'));
821
+
822
+ // for Firefox, we don't set to 1, because of flickering
823
+ this.assert(
824
+ $('style_test_3').setOpacity(0.9999999).getStyle('opacity') > 0.999
825
+ );
826
+
827
+ /*
828
+
829
+ IE <= 7 needs a `hasLayout` for opacity ("filter") to function properly
830
+ `hasLayout` is triggered by setting `zoom` style to `1`,
831
+
832
+ In IE8 setting `zoom` does not affect `hasLayout`
833
+ and IE8 does not even need `hasLayout` for opacity to work
834
+
835
+ We do a proper feature test here
836
+
837
+ */
838
+
839
+ var ZOOM_AFFECT_HAS_LAYOUT = (function(){
840
+ // IE7
841
+ var el = document.createElement('div');
842
+ el.style.zoom = 1;
843
+ var result = el.hasLayout;
844
+ el = null;
845
+ return result;
846
+ })();
847
+
848
+ if (ZOOM_AFFECT_HAS_LAYOUT) {
849
+ this.assert($('style_test_4').setOpacity(0.5).currentStyle.hasLayout);
850
+ this.assert(2, $('style_test_5').setOpacity(0.5).getStyle('zoom'));
851
+ this.assert(0.5, new Element('div').setOpacity(0.5).getOpacity());
852
+ this.assert(2, new Element('div').setOpacity(0.5).setStyle('zoom: 2;').getStyle('zoom'));
853
+ this.assert(2, new Element('div').setStyle('zoom: 2;').setOpacity(0.5).getStyle('zoom'));
854
+ }
855
+ },
856
+
857
+ testElementGetStyle: function() {
858
+ this.assertEqual("none",
859
+ $('style_test_1').getStyle('display'));
860
+
861
+ // not displayed, so "null" ("auto" is tranlated to "null")
862
+ this.assertNull(Element.getStyle('style_test_1', 'width'), 'elements that are hidden should return null on getStyle("width")');
863
+
864
+ $('style_test_1').show();
865
+
866
+ // from id rule
867
+ this.assertEqual("pointer",
868
+ Element.getStyle('style_test_1','cursor'));
869
+
870
+ this.assertEqual("block",
871
+ Element.getStyle('style_test_2','display'));
872
+
873
+ // we should always get something for width (if displayed)
874
+ // firefox and safari automatically send the correct value,
875
+ // IE is special-cased to do the same
876
+ this.assertEqual($('style_test_2').offsetWidth+'px', Element.getStyle('style_test_2','width'));
877
+
878
+ this.assertEqual("static",Element.getStyle('style_test_1','position'));
879
+ // from style
880
+ this.assertEqual("11px",
881
+ Element.getStyle('style_test_2','font-size'));
882
+ // from class
883
+ this.assertEqual("1px",
884
+ Element.getStyle('style_test_2','margin-left'));
885
+
886
+ ['not_floating_none','not_floating_style','not_floating_inline'].each(function(element) {
887
+ this.assertEqual('none', $(element).getStyle('float'));
888
+ this.assertEqual('none', $(element).getStyle('cssFloat'));
889
+ }, this);
890
+
891
+ ['floating_style','floating_inline'].each(function(element) {
892
+ this.assertEqual('left', $(element).getStyle('float'));
893
+ this.assertEqual('left', $(element).getStyle('cssFloat'));
894
+ }, this);
895
+
896
+ this.assertEqual(0.5, $('op1').getStyle('opacity'));
897
+ this.assertEqual(0.5, $('op2').getStyle('opacity'));
898
+ this.assertEqual(1.0, $('op3').getStyle('opacity'));
899
+
900
+ $('op1').setStyle({opacity: '0.3'});
901
+ $('op2').setStyle({opacity: '0.3'});
902
+ $('op3').setStyle({opacity: '0.3'});
903
+
904
+ this.assertEqual(0.3, $('op1').getStyle('opacity'));
905
+ this.assertEqual(0.3, $('op2').getStyle('opacity'));
906
+ this.assertEqual(0.3, $('op3').getStyle('opacity'));
907
+
908
+ $('op3').setStyle({opacity: 0});
909
+ this.assertEqual(0, $('op3').getStyle('opacity'));
910
+
911
+ if(navigator.appVersion.match(/MSIE/)) {
912
+ this.assertEqual('alpha(opacity=30)', $('op1').getStyle('filter'));
913
+ this.assertEqual('progid:DXImageTransform.Microsoft.Blur(strength=10)alpha(opacity=30)', $('op2').getStyle('filter'));
914
+ $('op2').setStyle({opacity:''});
915
+ this.assertEqual('progid:DXImageTransform.Microsoft.Blur(strength=10)', $('op2').getStyle('filter'));
916
+ this.assertEqual('alpha(opacity=0)', $('op3').getStyle('filter'));
917
+ this.assertEqual(0.3, $('op4-ie').getStyle('opacity'));
918
+ }
919
+ // verify that value is still found when using camelized
920
+ // strings (function previously used getPropertyValue()
921
+ // which expected non-camelized strings)
922
+ this.assertEqual("12px", $('style_test_1').getStyle('fontSize'));
923
+
924
+ // getStyle on width/height should return values according to
925
+ // the CSS box-model, which doesn't include
926
+ // margin, padding, or borders
927
+ // TODO: This test fails on IE because there seems to be no way
928
+ // to calculate this properly (clientWidth/Height returns 0)
929
+ if(!navigator.appVersion.match(/MSIE/)) {
930
+ this.assertEqual("14px", $('style_test_dimensions').getStyle('width'));
931
+ this.assertEqual("17px", $('style_test_dimensions').getStyle('height'));
932
+ }
933
+
934
+ // height/width could always be calculated if it's set to "auto" (Firefox)
935
+ this.assertNotNull($('auto_dimensions').getStyle('height'));
936
+ this.assertNotNull($('auto_dimensions').getStyle('width'));
937
+ },
938
+
939
+ testElementGetOpacity: function() {
940
+ this.assertEqual(0.45, $('op1').setOpacity(0.45).getOpacity());
941
+ },
942
+
943
+ testElementReadAttribute: function() {
944
+ this.assertEqual('test.html' , $('attributes_with_issues_1').readAttribute('href'));
945
+ this.assertEqual('L' , $('attributes_with_issues_1').readAttribute('accesskey'));
946
+ this.assertEqual('50' , $('attributes_with_issues_1').readAttribute('tabindex'));
947
+ this.assertEqual('a link' , $('attributes_with_issues_1').readAttribute('title'));
948
+
949
+ $('cloned_element_attributes_issue').readAttribute('foo')
950
+ var clone = $('cloned_element_attributes_issue').clone(true);
951
+ clone.writeAttribute('foo', 'cloned');
952
+ this.assertEqual('cloned', clone.readAttribute('foo'));
953
+ this.assertEqual('original', $('cloned_element_attributes_issue').readAttribute('foo'));
954
+
955
+ ['href', 'accesskey', 'accesskey', 'title'].each(function(attr) {
956
+ this.assertEqual('' , $('attributes_with_issues_2').readAttribute(attr));
957
+ }, this);
958
+
959
+ ['checked','disabled','readonly','multiple'].each(function(attr) {
960
+ this.assertEqual(attr, $('attributes_with_issues_'+attr).readAttribute(attr));
961
+ }, this);
962
+
963
+ this.assertEqual("alert('hello world');", $('attributes_with_issues_1').readAttribute('onclick'));
964
+ this.assertNull($('attributes_with_issues_1').readAttribute('onmouseover'));
965
+
966
+ this.assertEqual('date', $('attributes_with_issues_type').readAttribute('type'));
967
+ this.assertEqual('text', $('attributes_with_issues_readonly').readAttribute('type'));
968
+
969
+ var elements = $('custom_attributes').immediateDescendants();
970
+ this.assertEnumEqual(['1', '2'], elements.invoke('readAttribute', 'foo'));
971
+ this.assertEnumEqual(['2', null], elements.invoke('readAttribute', 'bar'));
972
+
973
+ var table = $('write_attribute_table');
974
+ this.assertEqual('4', table.readAttribute('cellspacing'));
975
+ this.assertEqual('6', table.readAttribute('cellpadding'));
976
+ },
977
+
978
+ testElementWriteAttribute: function() {
979
+ var element = Element.extend(document.body.appendChild(document.createElement('p')));
980
+ this.assertRespondsTo('writeAttribute', element);
981
+ this.assertEqual(element, element.writeAttribute('id', 'write_attribute_test'));
982
+ this.assertEqual('write_attribute_test', element.id);
983
+ this.assertEqual('http://prototypejs.org/', $('write_attribute_link').
984
+ writeAttribute({href: 'http://prototypejs.org/', title: 'Home of Prototype'}).href);
985
+ this.assertEqual('Home of Prototype', $('write_attribute_link').title);
986
+
987
+ var element2 = Element.extend(document.createElement('p'));
988
+ element2.writeAttribute('id', 'write_attribute_without_hash');
989
+ this.assertEqual('write_attribute_without_hash', element2.id);
990
+ element2.writeAttribute('animal', 'cat');
991
+ this.assertEqual('cat', element2.readAttribute('animal'));
992
+ },
993
+
994
+ testElementWriteAttributeWithBooleans: function() {
995
+ var input = $('write_attribute_input'),
996
+ select = $('write_attribute_select'),
997
+ checkbox = $('write_attribute_checkbox'),
998
+ checkedCheckbox = $('write_attribute_checked_checkbox');
999
+ this.assert( input. writeAttribute('readonly'). hasAttribute('readonly'));
1000
+ this.assert(!input. writeAttribute('readonly', false). hasAttribute('readonly'));
1001
+ this.assert( input. writeAttribute('readonly', true). hasAttribute('readonly'));
1002
+ this.assert(!input. writeAttribute('readonly', null). hasAttribute('readonly'));
1003
+ this.assert( input. writeAttribute('readonly', 'readonly').hasAttribute('readonly'));
1004
+ this.assert( select. writeAttribute('multiple'). hasAttribute('multiple'));
1005
+ this.assert( input. writeAttribute('disabled'). hasAttribute('disabled'));
1006
+ this.assert( checkbox. writeAttribute('checked'). checked);
1007
+ this.assert(!checkedCheckbox.writeAttribute('checked', false). checked);
1008
+ },
1009
+
1010
+ testElementWriteAttributeWithIssues: function() {
1011
+ var input = $('write_attribute_input').writeAttribute({maxlength: 90, tabindex: 10}),
1012
+ td = $('write_attribute_td').writeAttribute({valign: 'bottom', colspan: 2, rowspan: 2});
1013
+ this.assertEqual(90, input.readAttribute('maxlength'));
1014
+ this.assertEqual(10, input.readAttribute('tabindex'));
1015
+ this.assertEqual(2, td.readAttribute('colspan'));
1016
+ this.assertEqual(2, td.readAttribute('rowspan'));
1017
+ this.assertEqual('bottom', td.readAttribute('valign'));
1018
+
1019
+ var p = $('write_attribute_para'), label = $('write_attribute_label');
1020
+ this.assertEqual('some-class', p. writeAttribute({'class': 'some-class'}). readAttribute('class'));
1021
+ this.assertEqual('some-className', p. writeAttribute({className: 'some-className'}).readAttribute('class'));
1022
+ this.assertEqual('some-id', label.writeAttribute({'for': 'some-id'}). readAttribute('for'));
1023
+ this.assertEqual('some-other-id', label.writeAttribute({htmlFor: 'some-other-id'}). readAttribute('for'));
1024
+
1025
+ this.assert(p.writeAttribute({style: 'width: 5px;'}).readAttribute('style').toLowerCase().include('width'));
1026
+
1027
+ var table = $('write_attribute_table');
1028
+ table.writeAttribute('cellspacing', '2')
1029
+ table.writeAttribute('cellpadding', '3')
1030
+ this.assertEqual('2', table.readAttribute('cellspacing'));
1031
+ this.assertEqual('3', table.readAttribute('cellpadding'));
1032
+
1033
+ var iframe = new Element('iframe', { frameborder: 0 });
1034
+ this.assertIdentical(0, parseInt(iframe.readAttribute('frameborder')));
1035
+ },
1036
+
1037
+ testElementWriteAttributeWithCustom: function() {
1038
+ var p = $('write_attribute_para').writeAttribute({name: 'martin', location: 'stockholm', age: 26});
1039
+ this.assertEqual('martin', p.readAttribute('name'));
1040
+ this.assertEqual('stockholm', p.readAttribute('location'));
1041
+ this.assertEqual('26', p.readAttribute('age'));
1042
+ },
1043
+
1044
+ testElementHasAttribute: function() {
1045
+ var label = $('write_attribute_label');
1046
+ this.assertIdentical(true, label.hasAttribute('for'));
1047
+ this.assertIdentical(false, label.hasAttribute('htmlFor'));
1048
+ this.assertIdentical(false, label.hasAttribute('className'));
1049
+ this.assertIdentical(false, label.hasAttribute('rainbows'));
1050
+
1051
+ var input = $('write_attribute_input');
1052
+ this.assertNotIdentical(null, input.hasAttribute('readonly'));
1053
+ this.assertNotIdentical(null, input.hasAttribute('readOnly'));
1054
+ },
1055
+
1056
+ testNewElement: function() {
1057
+ this.assert(new Element('h1'));
1058
+
1059
+ var XHTML_TAGS = $w(
1060
+ 'a abbr acronym address area '+
1061
+ 'b bdo big blockquote br button caption '+
1062
+ 'cite code col colgroup dd del dfn div dl dt '+
1063
+ 'em fieldset form h1 h2 h3 h4 h5 h6 hr '+
1064
+ 'i iframe img input ins kbd label legend li '+
1065
+ 'map object ol optgroup option p param pre q samp '+
1066
+ 'script select small span strong style sub sup '+
1067
+ 'table tbody td textarea tfoot th thead tr tt ul var');
1068
+
1069
+ XHTML_TAGS.each(function(tag, index) {
1070
+ var id = tag + '_' + index, element = document.body.appendChild(new Element(tag, {id: id}));
1071
+ this.assertEqual(tag, element.tagName.toLowerCase());
1072
+ this.assertEqual(element, document.body.lastChild);
1073
+ this.assertEqual(id, element.id);
1074
+ }, this);
1075
+
1076
+
1077
+ this.assertRespondsTo('update', new Element('div'));
1078
+ Element.addMethods({
1079
+ cheeseCake: function(){
1080
+ return 'Cheese cake';
1081
+ }
1082
+ });
1083
+
1084
+ this.assertRespondsTo('cheeseCake', new Element('div'));
1085
+
1086
+ /* window.ElementOld = function(tagName, attributes) {
1087
+ if (Prototype.Browser.IE && attributes && attributes.name) {
1088
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
1089
+ delete attributes.name;
1090
+ }
1091
+ return Element.extend(document.createElement(tagName)).writeAttribute(attributes || {});
1092
+ };
1093
+
1094
+ this.benchmark(function(){
1095
+ XHTML_TAGS.each(function(tagName) { new Element(tagName) });
1096
+ }, 5);
1097
+
1098
+ this.benchmark(function(){
1099
+ XHTML_TAGS.each(function(tagName) { new ElementOld(tagName) });
1100
+ }, 5); */
1101
+
1102
+ this.assertEqual('foobar', new Element('a', {custom: 'foobar'}).readAttribute('custom'));
1103
+ var input = document.body.appendChild(new Element('input',
1104
+ {id: 'my_input_field_id', name: 'my_input_field'}));
1105
+ this.assertEqual(input, document.body.lastChild);
1106
+ this.assertEqual('my_input_field', $(document.body.lastChild).name);
1107
+ if ('outerHTML' in document.documentElement) {
1108
+ this.assertMatch(/name=["']?my_input_field["']?/, $('my_input_field_id').outerHTML);
1109
+ }
1110
+
1111
+ if (originalElement && Prototype.BrowserFeatures.ElementExtensions) {
1112
+ Element.prototype.fooBar = Prototype.emptyFunction
1113
+ this.assertRespondsTo('fooBar', new Element('div'));
1114
+ }
1115
+
1116
+ elWithClassName = new Element('div', { 'className': 'firstClassName' });
1117
+ this.assert(elWithClassName.hasClassName('firstClassName'));
1118
+
1119
+ elWithClassName = new Element('div', { 'class': 'firstClassName' });
1120
+ this.assert(elWithClassName.hasClassName('firstClassName'));
1121
+ },
1122
+
1123
+ testElementGetHeight: function() {
1124
+ this.assertIdentical(100, $('dimensions-visible').getHeight());
1125
+ this.assertIdentical(100, $('dimensions-display-none').getHeight());
1126
+ },
1127
+
1128
+ testElementGetWidth: function() {
1129
+ this.assertIdentical(200, $('dimensions-visible').getWidth());
1130
+ this.assertIdentical(200, $('dimensions-display-none').getWidth());
1131
+ },
1132
+
1133
+ testElementGetDimensions: function() {
1134
+ this.assertIdentical(100, $('dimensions-visible').getDimensions().height);
1135
+ this.assertIdentical(200, $('dimensions-visible').getDimensions().width);
1136
+ this.assertIdentical(100, $('dimensions-display-none').getDimensions().height);
1137
+ this.assertIdentical(200, $('dimensions-display-none').getDimensions().width);
1138
+
1139
+ this.assertIdentical(100, $('dimensions-visible-pos-rel').getDimensions().height);
1140
+ this.assertIdentical(200, $('dimensions-visible-pos-rel').getDimensions().width);
1141
+ this.assertIdentical(100, $('dimensions-display-none-pos-rel').getDimensions().height);
1142
+ this.assertIdentical(200, $('dimensions-display-none-pos-rel').getDimensions().width);
1143
+
1144
+ this.assertIdentical(100, $('dimensions-visible-pos-abs').getDimensions().height);
1145
+ this.assertIdentical(200, $('dimensions-visible-pos-abs').getDimensions().width);
1146
+ this.assertIdentical(100, $('dimensions-display-none-pos-abs').getDimensions().height);
1147
+ this.assertIdentical(200, $('dimensions-display-none-pos-abs').getDimensions().width);
1148
+
1149
+ // known failing issue
1150
+ // this.assert($('dimensions-nestee').getDimensions().width <= 500, 'check for proper dimensions of hidden child elements');
1151
+
1152
+ $('dimensions-td').hide();
1153
+ this.assertIdentical(100, $('dimensions-td').getDimensions().height);
1154
+ this.assertIdentical(200, $('dimensions-td').getDimensions().width);
1155
+ $('dimensions-td').show();
1156
+
1157
+ $('dimensions-tr').hide();
1158
+ this.assertIdentical(100, $('dimensions-tr').getDimensions().height);
1159
+ this.assertIdentical(200, $('dimensions-tr').getDimensions().width);
1160
+ $('dimensions-tr').show();
1161
+
1162
+ $('dimensions-table').hide();
1163
+ this.assertIdentical(100, $('dimensions-table').getDimensions().height);
1164
+ this.assertIdentical(200, $('dimensions-table').getDimensions().width);
1165
+ },
1166
+
1167
+ testDOMAttributesHavePrecedenceOverExtendedElementMethods: function() {
1168
+ this.assertNothingRaised(function() { $('dom_attribute_precedence').down('form') });
1169
+ this.assertEqual($('dom_attribute_precedence').down('input'), $('dom_attribute_precedence').down('form').update);
1170
+ },
1171
+
1172
+ testClassNames: function() {
1173
+ this.assertEnumEqual([], $('class_names').classNames());
1174
+ this.assertEnumEqual(['A'], $('class_names').down().classNames());
1175
+ this.assertEnumEqual(['A', 'B'], $('class_names_ul').classNames());
1176
+ },
1177
+
1178
+ testHasClassName: function() {
1179
+ this.assertIdentical(false, $('class_names').hasClassName('does_not_exist'));
1180
+ this.assertIdentical(true, $('class_names').down().hasClassName('A'));
1181
+ this.assertIdentical(false, $('class_names').down().hasClassName('does_not_exist'));
1182
+ this.assertIdentical(true, $('class_names_ul').hasClassName('A'));
1183
+ this.assertIdentical(true, $('class_names_ul').hasClassName('B'));
1184
+ this.assertIdentical(false, $('class_names_ul').hasClassName('does_not_exist'));
1185
+ },
1186
+
1187
+ testAddClassName: function() {
1188
+ $('class_names').addClassName('added_className');
1189
+ this.assertEnumEqual(['added_className'], $('class_names').classNames());
1190
+
1191
+ $('class_names').addClassName('added_className'); // verify that className cannot be added twice.
1192
+ this.assertEnumEqual(['added_className'], $('class_names').classNames());
1193
+
1194
+ $('class_names').addClassName('another_added_className');
1195
+ this.assertEnumEqual(['added_className', 'another_added_className'], $('class_names').classNames());
1196
+ },
1197
+
1198
+ testRemoveClassName: function() {
1199
+ $('class_names').removeClassName('added_className');
1200
+ this.assertEnumEqual(['another_added_className'], $('class_names').classNames());
1201
+
1202
+ $('class_names').removeClassName('added_className'); // verify that removing a non existent className is safe.
1203
+ this.assertEnumEqual(['another_added_className'], $('class_names').classNames());
1204
+
1205
+ $('class_names').removeClassName('another_added_className');
1206
+ this.assertEnumEqual([], $('class_names').classNames());
1207
+ },
1208
+
1209
+ testToggleClassName: function() {
1210
+ $('class_names').toggleClassName('toggled_className');
1211
+ this.assertEnumEqual(['toggled_className'], $('class_names').classNames());
1212
+
1213
+ $('class_names').toggleClassName('toggled_className');
1214
+ this.assertEnumEqual([], $('class_names').classNames());
1215
+
1216
+ $('class_names_ul').toggleClassName('toggled_className');
1217
+ this.assertEnumEqual(['A', 'B', 'toggled_className'], $('class_names_ul').classNames());
1218
+
1219
+ $('class_names_ul').toggleClassName('toggled_className');
1220
+ this.assertEnumEqual(['A', 'B'], $('class_names_ul').classNames());
1221
+ },
1222
+
1223
+ testElementScrollTo: function() {
1224
+ var elem = $('scroll_test_2');
1225
+ Element.scrollTo('scroll_test_2');
1226
+ this.assertEqual(Position.page(elem)[1], 0);
1227
+ window.scrollTo(0, 0);
1228
+
1229
+ elem.scrollTo();
1230
+ this.assertEqual(Position.page(elem)[1], 0);
1231
+ window.scrollTo(0, 0);
1232
+ },
1233
+
1234
+ testCustomElementMethods: function() {
1235
+ var elem = $('navigation_test_f');
1236
+ this.assertRespondsTo('hashBrowns', elem);
1237
+ this.assertEqual('hash browns', elem.hashBrowns());
1238
+
1239
+ this.assertRespondsTo('hashBrowns', Element);
1240
+ this.assertEqual('hash browns', Element.hashBrowns(elem));
1241
+ },
1242
+
1243
+ testSpecificCustomElementMethods: function() {
1244
+ var elem = $('navigation_test_f');
1245
+
1246
+ this.assert(Element.Methods.ByTag[elem.tagName]);
1247
+ this.assertRespondsTo('pancakes', elem);
1248
+ this.assertEqual("pancakes", elem.pancakes());
1249
+
1250
+ var elem2 = $('test-visible');
1251
+
1252
+ this.assert(Element.Methods.ByTag[elem2.tagName]);
1253
+ this.assertUndefined(elem2.pancakes);
1254
+ this.assertRespondsTo('waffles', elem2);
1255
+ this.assertEqual("waffles", elem2.waffles());
1256
+
1257
+ this.assertRespondsTo('orangeJuice', elem);
1258
+ this.assertRespondsTo('orangeJuice', elem2);
1259
+ this.assertEqual("orange juice", elem.orangeJuice());
1260
+ this.assertEqual("orange juice", elem2.orangeJuice());
1261
+
1262
+ this.assert(typeof Element.orangeJuice == 'undefined');
1263
+ this.assert(typeof Element.pancakes == 'undefined');
1264
+ this.assert(typeof Element.waffles == 'undefined');
1265
+
1266
+ },
1267
+
1268
+ testScriptFragment: function() {
1269
+ var element = document.createElement('div');
1270
+ // tests an issue with Safari 2.0 crashing when the ScriptFragment
1271
+ // regular expression is using a pipe-based approach for
1272
+ // matching any character
1273
+ ['\r','\n',' '].each(function(character){
1274
+ $(element).update("<script>"+character.times(10000)+"</scr"+"ipt>");
1275
+ this.assertEqual('', element.innerHTML);
1276
+ }, this);
1277
+ $(element).update("<script>var blah='"+'\\'.times(10000)+"'</scr"+"ipt>");
1278
+ this.assertEqual('', element.innerHTML);
1279
+ },
1280
+
1281
+ testPositionedOffset: function() {
1282
+ this.assertEnumEqual([10,10],
1283
+ $('body_absolute').positionedOffset());
1284
+ this.assertEnumEqual([10,10],
1285
+ $('absolute_absolute').positionedOffset());
1286
+ this.assertEnumEqual([10,10],
1287
+ $('absolute_relative').positionedOffset());
1288
+ this.assertEnumEqual([0,10],
1289
+ $('absolute_relative_undefined').positionedOffset());
1290
+ this.assertEnumEqual([10,10],
1291
+ $('absolute_fixed_absolute').positionedOffset());
1292
+
1293
+ var afu = $('absolute_fixed_undefined');
1294
+ this.assertEnumEqual([afu.offsetLeft, afu.offsetTop],
1295
+ afu.positionedOffset());
1296
+
1297
+ var element = new Element('div'), offset = element.positionedOffset();
1298
+ this.assertEnumEqual([0,0], offset);
1299
+ this.assertIdentical(0, offset.top);
1300
+ this.assertIdentical(0, offset.left);
1301
+ },
1302
+
1303
+ testCumulativeOffset: function() {
1304
+ var element = new Element('div'), offset = element.cumulativeOffset();
1305
+ this.assertEnumEqual([0,0], offset);
1306
+ this.assertIdentical(0, offset.top);
1307
+ this.assertIdentical(0, offset.left);
1308
+ },
1309
+
1310
+ testViewportOffset: function() {
1311
+ this.assertEnumEqual([10,10],
1312
+ $('body_absolute').viewportOffset());
1313
+ this.assertEnumEqual([20,20],
1314
+ $('absolute_absolute').viewportOffset());
1315
+ this.assertEnumEqual([20,20],
1316
+ $('absolute_relative').viewportOffset());
1317
+ this.assertEnumEqual([20,30],
1318
+ $('absolute_relative_undefined').viewportOffset());
1319
+ var element = new Element('div'), offset = element.viewportOffset();
1320
+ this.assertEnumEqual([0,0], offset);
1321
+ this.assertIdentical(0, offset.top);
1322
+ this.assertIdentical(0, offset.left);
1323
+ },
1324
+
1325
+ testOffsetParent: function() {
1326
+ this.assertEqual('body_absolute', $('absolute_absolute').getOffsetParent().id);
1327
+ this.assertEqual('body_absolute', $('absolute_relative').getOffsetParent().id);
1328
+ this.assertEqual('absolute_relative', $('inline').getOffsetParent().id);
1329
+ this.assertEqual('absolute_relative', $('absolute_relative_undefined').getOffsetParent().id);
1330
+
1331
+ this.assertEqual(document.body, new Element('div').getOffsetParent());
1332
+ },
1333
+
1334
+ testAbsolutize: function() {
1335
+ $('notInlineAbsoluted', 'inlineAbsoluted').each(function(elt) {
1336
+ if ('_originalLeft' in elt) delete elt._originalLeft;
1337
+ elt.absolutize();
1338
+ this.assertUndefined(elt._originalLeft, 'absolutize() did not detect absolute positioning');
1339
+ }, this);
1340
+ // invoking on "absolute" positioned element should return element
1341
+ var element = $('absolute_fixed_undefined').setStyle({position: 'absolute'});
1342
+ this.assertEqual(element, element.absolutize());
1343
+ },
1344
+
1345
+ testRelativize: function() {
1346
+ // invoking on "relative" positioned element should return element
1347
+ var element = $('absolute_fixed_undefined').setStyle({position: 'relative'});
1348
+ this.assertEqual(element, element.relativize());
1349
+ },
1350
+
1351
+ testViewportDimensions: function() {
1352
+ preservingBrowserDimensions(function() {
1353
+ window.resizeTo(800, 600);
1354
+ var before = document.viewport.getDimensions();
1355
+ window.resizeBy(50, 50);
1356
+ var after = document.viewport.getDimensions();
1357
+
1358
+ this.assertEqual(before.width + 50, after.width, "NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THIS TEST TO PASS");
1359
+ this.assertEqual(before.height + 50, after.height, "NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THIS TEST TO PASS");
1360
+ }.bind(this));
1361
+ },
1362
+
1363
+ testElementToViewportDimensionsDoesNotAffectDocumentProperties: function() {
1364
+ // No properties on the document should be affected when resizing
1365
+ // an absolute positioned(0,0) element to viewport dimensions
1366
+ var vd = document.viewport.getDimensions();
1367
+
1368
+ var before = documentViewportProperties.inspect();
1369
+ $('elementToViewportDimensions').setStyle({ height: vd.height + 'px', width: vd.width + 'px' }).show();
1370
+ var after = documentViewportProperties.inspect();
1371
+ $('elementToViewportDimensions').hide();
1372
+
1373
+ documentViewportProperties.properties.each(function(prop) {
1374
+ this.assertEqual(before[prop], after[prop], prop + ' was affected');
1375
+ }, this);
1376
+ },
1377
+
1378
+ testViewportScrollOffsets: function() {
1379
+ preservingBrowserDimensions(function() {
1380
+ window.scrollTo(0, 0);
1381
+ this.assertEqual(0, document.viewport.getScrollOffsets().top);
1382
+
1383
+ window.scrollTo(0, 35);
1384
+ this.assertEqual(35, document.viewport.getScrollOffsets().top);
1385
+
1386
+ window.resizeTo(200, 650);
1387
+ window.scrollTo(25, 35);
1388
+ this.assertEqual(25, document.viewport.getScrollOffsets().left, "NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THESE TESTS TO PASS");
1389
+
1390
+ window.resizeTo(850, 650);
1391
+ }.bind(this));
1392
+ },
1393
+
1394
+ testNodeConstants: function() {
1395
+ this.assert(window.Node, 'window.Node is unavailable');
1396
+
1397
+ var constants = $H({
1398
+ ELEMENT_NODE: 1,
1399
+ ATTRIBUTE_NODE: 2,
1400
+ TEXT_NODE: 3,
1401
+ CDATA_SECTION_NODE: 4,
1402
+ ENTITY_REFERENCE_NODE: 5,
1403
+ ENTITY_NODE: 6,
1404
+ PROCESSING_INSTRUCTION_NODE: 7,
1405
+ COMMENT_NODE: 8,
1406
+ DOCUMENT_NODE: 9,
1407
+ DOCUMENT_TYPE_NODE: 10,
1408
+ DOCUMENT_FRAGMENT_NODE: 11,
1409
+ NOTATION_NODE: 12
1410
+ });
1411
+
1412
+ constants.each(function(pair) {
1413
+ this.assertEqual(Node[pair.key], pair.value);
1414
+ }, this);
1415
+ },
1416
+
1417
+ testElementStorage: function() {
1418
+ var element = $('test-empty');
1419
+ element.store('foo', 'bar');
1420
+ this.assertEqual("bar", element.retrieve("foo"), "Setting and reading a property");
1421
+ var result = element.store('foo', 'thud');
1422
+ this.assertEqual("thud", element.retrieve("foo"), "Re-setting and reading property");
1423
+ this.assertIdentical(element, result, "Element#store should return element");
1424
+
1425
+ element.store('bar', 'narf');
1426
+ this.assertEnumEqual($w('foo bar'), element.getStorage().keys(), "Getting the storage hash");
1427
+ element.getStorage().unset('bar');
1428
+ this.assertEnumEqual($w('foo'), element.getStorage().keys(), "Getting the storage hash after unsetting a key");
1429
+
1430
+ element.store({ 'narf': 'narf', 'zort': 'zort' });
1431
+
1432
+ this.assertEqual("narf", element.retrieve('narf'), "Storing multiple properties at once");
1433
+ this.assertEqual("zort", element.retrieve('zort'), "Storing multiple properties at once");
1434
+
1435
+ this.assertUndefined(element.retrieve('bar'), "Undefined key should return undefined if default value is not defined");
1436
+ this.assertEqual("default", element.retrieve('bar', 'default'), "Return default value if undefined key");
1437
+ this.assertEqual("default", element.retrieve('bar'), "Makes sure default value has been set properly");
1438
+
1439
+ var clonedElement = $('test-empty').clone(false);
1440
+ this.assert(Object.isUndefined(clonedElement._prototypeUID), "Cloning a node should not confuse the storage engine");
1441
+ },
1442
+
1443
+ testElementClone: function() {
1444
+ var element = new Element('div', {
1445
+ title: 'bar'
1446
+ });
1447
+ element.className = 'foo';
1448
+
1449
+ // add child
1450
+ element.update('<span id="child">child node</span>');
1451
+
1452
+ // add observer
1453
+ element.observe('click', Prototype.emptyFunction);
1454
+
1455
+ // add observer on a child
1456
+ element.down('span').observe('dblclick', Prototype.emptyFunction);
1457
+
1458
+ var shallowClone = element.clone();
1459
+ var deepClone = element.clone(true);
1460
+
1461
+ var assertCloneTraits = (function(clone) {
1462
+ this.assert(clone); // exists
1463
+ this.assert(clone.show); // is extended
1464
+ this.assertEqual('DIV', clone.nodeName.toUpperCase()); // proper nodeName
1465
+ this.assertEqual('foo', clone.className); // proper attributes
1466
+ this.assertEqual('bar', clone.title);
1467
+ this.assert(!clone._prototypeUID); // _prototypeUID does not exist
1468
+ }).bind(this);
1469
+
1470
+ // test generic traits of both deep and shallow clones first
1471
+ assertCloneTraits(shallowClone);
1472
+ assertCloneTraits(deepClone);
1473
+
1474
+ // test deep clone traits
1475
+ this.assert(deepClone.firstChild);
1476
+ this.assertEqual('SPAN', deepClone.firstChild.nodeName.toUpperCase());
1477
+ this.assert(!deepClone.down('span')._prototypeUID);
1478
+ }
1479
+ });
1480
+
1481
+ function preservingBrowserDimensions(callback) {
1482
+ var original = document.viewport.getDimensions();
1483
+ window.resizeTo(640, 480);
1484
+ var resized = document.viewport.getDimensions();
1485
+ original.width += 640 - resized.width, original.height += 480 - resized.height;
1486
+
1487
+ try {
1488
+ window.resizeTo(original.width, original.height);
1489
+ callback();
1490
+ } finally {
1491
+ window.resizeTo(original.width, original.height);
1492
+ }
1493
+ }