2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * Copyright (C) 2013 Intel Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 // svg/dynamic-updates tests set enablePixelTesting=true, as we want to dump text + pixel results
28 var description, debug, successfullyParsed, errorMessage;
32 function getOrCreate(id, tagName)
34 var element = document.getElementById(id);
38 element = document.createElement(tagName);
41 var parent = document.body || document.documentElement;
42 if (id == 'description')
43 refNode = getOrCreate('console', 'div');
45 refNode = parent.firstChild;
47 parent.insertBefore(element, refNode);
51 description = function description(msg, quiet)
53 // For MSIE 6 compatibility
54 var span = document.createElement('span');
56 span.innerHTML = '<p>' + msg +
58 'On success, you will see no "<span class="fail">FAIL</span>" messages, ' +
59 'followed by "<span class="pass">TEST COMPLETE</span>".' +
62 span.innerHTML = '<p>' + msg +
64 'On success, you will see a series of "<span class="pass">PASS</span>" messages, ' +
65 'followed by "<span class="pass">TEST COMPLETE</span>".' +
68 var description = getOrCreate('description', 'p');
69 if (description.firstChild)
70 description.replaceChild(span, description.firstChild);
72 description.appendChild(span);
75 debug = function debug(msg)
77 var span = document.createElement('span');
78 getOrCreate('console', 'div').appendChild(span); // insert it first so XHTML knows the namespace
79 span.innerHTML = msg + '<br />';
84 'font-weight: bold;' +
88 'font-weight: bold;' +
92 'white-space: pre-wrap;' +
93 'font-family: monospace;' +
96 function insertStyleSheet()
98 var styleElement = document.createElement('style');
99 styleElement.textContent = css;
100 (document.head || document.documentElement).appendChild(styleElement);
105 if (!self.isOnErrorTest) {
106 self.onerror = function(message)
108 errorMessage = message;
114 function descriptionQuiet(msg) { description(msg, true); }
116 function escapeHTML(text)
118 return text.replace(/&/g, '&').replace(/</g, '<').replace(/\0/g, '\\0');
121 function testPassed(msg)
123 debug('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
126 function testFailed(msg)
128 debug('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
131 function areArraysEqual(_a, _b)
134 if (_a.length !== _b.length)
136 for (var i = 0; i < _a.length; i++)
145 function isMinusZero(n)
147 // the only way to tell 0 from -0 in JS is the fact that 1/-0 is
148 // -Infinity instead of Infinity
149 return n === 0 && 1 / n < 0;
152 function isResultCorrect(_actual, _expected)
155 return _actual === _expected && (1 / _actual) === (1 / _expected);
156 if (_actual === _expected)
158 if (typeof(_expected) == 'number' && isNaN(_expected))
159 return typeof(_actual) == 'number' && isNaN(_actual);
161 (Object.prototype.toString.call(_expected) == Object.prototype.toString.call([])))
162 return areArraysEqual(_actual, _expected);
166 function stringify(v)
168 if (v === 0 && 1 / v < 0)
173 function evalAndLog(_a, _quiet)
175 if (typeof _a != 'string')
176 debug('WARN: tryAndLog() expects a string argument');
178 // Log first in case things go horribly wrong or this causes a sync event.
186 testFailed(_a + ' threw exception ' + e);
191 function shouldBe(_a, _b, quiet)
193 if (typeof _a != 'string' || typeof _b != 'string')
194 debug('WARN: shouldBe() expects string arguments');
205 testFailed(_a + ' should be ' + _bv + '. Threw exception ' + exception);
206 else if (isResultCorrect(_av, _bv)) {
208 testPassed(_a + ' is ' + _b);
210 } else if (typeof(_av) == typeof(_bv))
211 testFailed(_a + ' should be ' + _bv + '. Was ' + stringify(_av) + '.');
213 testFailed(_a + ' should be ' + _bv + ' (of type ' + typeof _bv + '). Was ' +
214 _av + ' (of type ' + typeof _av + ').');
217 // Execute condition every 5 milliseconds until it succeed or failureTime is reached.
218 // completionHandler is executed on success, failureHandler is executed on timeout.
219 function _waitForCondition(condition, failureTime, completionHandler, failureHandler)
223 } else if (Date.now() > failureTime) {
226 setTimeout(_waitForCondition, 5, condition, failureTime, completionHandler, failureHandler);
230 function shouldBecomeEqual(_a, _b, completionHandler, timeout)
232 if (typeof _a != 'string' || typeof _b != 'string')
233 debug('WARN: shouldBecomeEqual() expects string arguments');
235 if (timeout === undefined)
238 var condition = function() {
248 testFailed(_a + ' should become ' + _bv + '. Threw exception ' + exception);
249 if (isResultCorrect(_av, _bv)) {
250 testPassed(_a + ' became ' + _b);
255 var failureTime = Date.now() + timeout;
256 var failureHandler = function() {
257 testFailed(_a + ' failed to change to ' + _b + ' in ' + (timeout / 1000) + ' seconds.');
260 _waitForCondition(condition, failureTime, completionHandler, failureHandler);
263 function shouldBecomeEqualToString(value, reference, completionHandler, timeout)
265 if (typeof value !== 'string' || typeof reference !== 'string')
266 debug('WARN: shouldBecomeEqualToString() expects string arguments');
267 var unevaledString = JSON.stringify(reference);
268 shouldBecomeEqual(value, unevaledString, completionHandler, timeout);
271 function shouldBeType(_a, _type) {
280 var _typev = eval(_type);
281 if (_av instanceof _typev) {
282 testPassed(_a + ' is an instance of ' + _type);
284 testFailed(_a + ' is not an instance of ' + _type);
288 // Variant of shouldBe()--confirms that result of eval(_to_eval) is within
289 // numeric _tolerance of numeric _target.
290 function shouldBeCloseTo(_to_eval, _target, _tolerance, quiet)
292 if (typeof _to_eval != 'string') {
293 testFailed('shouldBeCloseTo() requires string argument _to_eval. was type ' + typeof _to_eval);
296 if (typeof _target != 'number') {
297 testFailed('shouldBeCloseTo() requires numeric argument _target. was type ' + typeof _target);
300 if (typeof _tolerance != 'number') {
301 testFailed('shouldBeCloseTo() requires numeric argument _tolerance. was type ' +
308 _result = eval(_to_eval);
310 testFailed(_to_eval + ' should be within ' + _tolerance + ' of ' +
311 _target + '. Threw exception ' + e);
315 if (typeof(_result) != typeof(_target)) {
316 testFailed(_to_eval + ' should be of type ' + typeof _target +
317 ' but was of type ' + typeof _result);
318 } else if (Math.abs(_result - _target) <= _tolerance) {
320 testPassed(_to_eval + ' is within ' + _tolerance + ' of ' + _target);
323 testFailed(_to_eval + ' should be within ' + _tolerance + ' of ' + _target +
324 '. Was ' + _result + '.');
328 function shouldNotBe(_a, _b, quiet)
330 if (typeof _a != 'string' || typeof _b != 'string')
331 debug('WARN: shouldNotBe() expects string arguments');
342 testFailed(_a + ' should not be ' + _bv + '. Threw exception ' + exception);
343 else if (!isResultCorrect(_av, _bv)) {
345 testPassed(_a + ' is not ' + _b);
348 testFailed(_a + ' should not be ' + _bv + '.');
351 function shouldBecomeDifferent(_a, _b, completionHandler, timeout)
353 if (typeof _a != 'string' || typeof _b != 'string')
354 debug('WARN: shouldBecomeDifferent() expects string arguments');
355 if (timeout === undefined)
358 var condition = function() {
368 testFailed(_a + ' should became not equal to ' + _bv + '. Threw exception ' + exception);
369 if (!isResultCorrect(_av, _bv)) {
370 testPassed(_a + ' became different from ' + _b);
375 var failureTime = Date.now() + timeout;
376 var failureHandler = function() {
377 testFailed(_a + ' did not become different from ' +
378 _b + ' in ' + (timeout / 1000) + ' seconds.');
381 _waitForCondition(condition, failureTime, completionHandler, failureHandler);
384 function shouldBeTrue(_a) { shouldBe(_a, 'true'); }
385 function shouldBeTrueQuiet(_a) { shouldBe(_a, 'true', true); }
386 function shouldBeFalse(_a) { shouldBe(_a, 'false'); }
387 function shouldBeNaN(_a) { shouldBe(_a, 'NaN'); }
388 function shouldBeNull(_a) { shouldBe(_a, 'null'); }
389 function shouldBeZero(_a) { shouldBe(_a, '0'); }
391 function shouldBeEqualToString(a, b)
393 if (typeof a !== 'string' || typeof b !== 'string')
394 debug('WARN: shouldBeEqualToString() expects string arguments');
395 var unevaledString = JSON.stringify(b);
396 shouldBe(a, unevaledString);
399 function shouldBeEmptyString(_a) { shouldBeEqualToString(_a, ''); }
401 function shouldEvaluateTo(actual, expected) {
402 // A general-purpose comparator. 'actual' should be a string to be
403 // evaluated, as for shouldBe(). 'expected' may be any type and will be
404 // used without being eval'ed.
405 if (expected == null) {
406 // Do this before the object test, since null is of type 'object'.
407 shouldBeNull(actual);
408 } else if (typeof expected == 'undefined') {
409 shouldBeUndefined(actual);
410 } else if (typeof expected == 'function') {
411 // All this fuss is to avoid the string-arg warning from shouldBe().
413 actualValue = eval(actual);
415 testFailed('Evaluating ' + actual + ': Threw exception ' + e);
418 shouldBe("'" + actualValue.toString().replace(/\n/g, '') + "'",
419 "'" + expected.toString().replace(/\n/g, '') + "'");
420 } else if (typeof expected == 'object') {
421 shouldBeTrue(actual + " == '" + expected + "'");
422 } else if (typeof expected == 'string') {
423 shouldBe(actual, expected);
424 } else if (typeof expected == 'boolean') {
425 shouldBe('typeof ' + actual, "'boolean'");
427 shouldBeTrue(actual);
429 shouldBeFalse(actual);
430 } else if (typeof expected == 'number') {
431 shouldBe(actual, stringify(expected));
433 debug(expected + ' is unknown type ' + typeof expected);
434 shouldBeTrue(actual, "'" + expected.toString() + "'");
438 function shouldBeNonZero(_a)
449 testFailed(_a + ' should be non-zero. Threw exception ' + exception);
451 testPassed(_a + ' is non-zero.');
453 testFailed(_a + ' should be non-zero. Was ' + _av);
456 function shouldBeNonNull(_a)
467 testFailed(_a + ' should be non-null. Threw exception ' + exception);
468 else if (_av != null)
469 testPassed(_a + ' is non-null.');
471 testFailed(_a + ' should be non-null. Was ' + _av);
474 function shouldBeUndefined(_a)
485 testFailed(_a + ' should be undefined. Threw exception ' + exception);
486 else if (typeof _av == 'undefined')
487 testPassed(_a + ' is undefined.');
489 testFailed(_a + ' should be undefined. Was ' + _av);
492 function shouldBeDefined(_a)
503 testFailed(_a + ' should be defined. Threw exception ' + exception);
504 else if (_av !== undefined)
505 testPassed(_a + ' is defined.');
507 testFailed(_a + ' should be defined. Was ' + _av);
510 function shouldBeGreaterThanOrEqual(_a, _b) {
511 if (typeof _a != 'string' || typeof _b != 'string')
512 debug('WARN: shouldBeGreaterThanOrEqual expects string arguments');
524 testFailed(_a + ' should be >= ' + _b + '. Threw exception ' + exception);
525 else if (typeof _av == 'undefined' || _av < _bv)
526 testFailed(_a + ' should be >= ' + _b + '. Was ' + _av + ' (of type ' + typeof _av + ').');
528 testPassed(_a + ' is >= ' + _b);
531 function shouldNotThrow(_a) {
534 testPassed(_a + ' did not throw exception.');
536 testFailed(_a + ' should not throw exception. Threw exception ' + e + '.');
540 function shouldThrow(_a, _e)
555 // Handle WebAPIException and WebAPIError.
556 if (exception instanceof tizen.WebAPIException || exception instanceof tizen.WebAPIError) {
557 exception = exception.name;
561 if (typeof _e == 'undefined' || exception == _ev)
562 testPassed(_a + ' threw exception ' + exception + '.');
564 testFailed(_a + ' should throw ' + (typeof _e == 'undefined' ? 'an exception' : _ev) +
565 '. Threw exception ' + exception + '.');
566 } else if (typeof _av == 'undefined') {
567 testFailed(_a + ' should throw ' + (typeof _e == 'undefined' ? 'an exception' : _ev) +
570 testFailed(_a + ' should throw ' + (typeof _e == 'undefined' ? 'an exception' : _ev) +
571 '. Was ' + _av + '.');
575 function shouldHaveHadError(message)
579 testPassed('Got expected error');
580 else if (errorMessage.indexOf(message) !== -1)
581 testPassed("Got expected error: '" + message + "'");
583 testFailed("Unexpexted error '" + message + "'");
585 testFailed('Missing expexted error');
586 errorMessage = undefined;
589 function isSuccessfullyParsed()
591 // FIXME: Remove this and only report unexpected syntax errors.
593 successfullyParsed = true;
594 shouldBeTrue('successfullyParsed');
595 debug('<br /><span class="pass">TEST COMPLETE</span>');
598 function finishJSTest()
600 wasFinishJSTestCalled = true;
601 if (!self.wasPostTestScriptParsed)
603 isSuccessfullyParsed();