From: chen Date: Thu, 22 Feb 2024 09:31:46 +0000 (+0800) Subject: [common][appcontrol][add webapp to support operation pick] X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F14%2F306514%2F1;p=test%2Ftct%2Fweb%2Fapi.git [common][appcontrol][add webapp to support operation pick] Change-Id: I2c2e113f3e101fa2d7c536a37e877c4bbb26c6c8 Signed-off-by: chen --- diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/AppControl_select_file.html b/common/tct-appcontrol-tizen-tests/appcontrol/AppControl_select_file.html index db328f080..982225203 100755 --- a/common/tct-appcontrol-tizen-tests/appcontrol/AppControl_select_file.html +++ b/common/tct-appcontrol-tizen-tests/appcontrol/AppControl_select_file.html @@ -1,54 +1,54 @@ - - - - -AppControl_select_file - - - - - -
- - - + + + + +AppControl_select_file + + + + + +
+ + + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_exit.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_exit.html new file mode 100755 index 000000000..6c8142e1e --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_exit.html @@ -0,0 +1,70 @@ + + + + + + + + + + +TCTAppControl + + + + + +
+
+

TCTAppControl

+

appcontrol_exit.html

+

+
+
+ + + + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_launch.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_launch.html new file mode 100755 index 000000000..35fbebd5c --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_launch.html @@ -0,0 +1,60 @@ + + + + + + + + + + + TCTAppControl + + + + + +
+
+

TCTAppControl

+

appcontrol_launch.html

+
+
+ + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_launch_explicit.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_launch_explicit.html new file mode 100755 index 000000000..870fc867a --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_launch_explicit.html @@ -0,0 +1,46 @@ + + + + + + + + + + + TCTAppControl + + + + + +
+
+

TCTAppControl

+

appcontrol_launch.html

+
+
+ + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_failure.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_failure.html new file mode 100755 index 000000000..de800de6a --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_failure.html @@ -0,0 +1,77 @@ + + + + + + + + + + + TCTAppControl + + + + + +
+
+

TCTAppControl

+

appcontrol_reply_failure.html

+

+
+
+ + + + + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_result.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_result.html new file mode 100755 index 000000000..47bda16ba --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_result.html @@ -0,0 +1,60 @@ + + + + + + + + + + + TCTAppControl + + + + + +
+
+

TCTAppControl

+

appcontrol_reply_result.html

+

+
+
+ + + + + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_result_with_data.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_result_with_data.html new file mode 100755 index 000000000..480bbead3 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_reply_result_with_data.html @@ -0,0 +1,60 @@ + + + + + + + + + + + TCTAppControl + + + + + +
+
+

TCTAppControl

+

appcontrol_reply_result_with_data.html

+

+
+
+ + + + + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_run_test.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_run_test.html new file mode 100755 index 000000000..1ac18138a --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/appcontrol_run_test.html @@ -0,0 +1,63 @@ + + + + + + + + + + + appcontrol_run_test + + + + + + + + +
+ + + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/config.xml b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/config.xml new file mode 100755 index 000000000..3b917c7c6 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/config.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TCTAppControl + + + + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/css/style.css b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/css/style.css new file mode 100755 index 000000000..5fd52e243 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/css/style.css @@ -0,0 +1,99 @@ +/* + +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + +Authors: + Junghyuk Park + + +*/ + +* { + font-family: Lucida Sans, Arial, Helvetica, sans-serif; +} + +body { + margin: 0px auto; +} + +header h1 { + font-size: 36px; + margin: 0px; +} + +header h2 { + font-size: 18px; + margin: 0px; + color: #888; + font-style: italic; +} + +nav ul { + list-style: none; + padding: 0px; + display: block; + clear: right; + background-color: #666; + padding-left: 4px; + height: 24px; +} + +nav ul li { + display: inline; + padding: 0px 20px 5px 10px; + height: 24px; + border-right: 1px solid #ccc; +} + +nav ul li a { + color: #EFD3D3; + text-decoration: none; + font-size: 13px; + font-weight: bold; +} + +nav ul li a:hover { + color: #fff; +} + +article > header h1 { + font-size: 20px; + margin-left: 14px; +} + +article > header h1 a { + color: #993333; +} + +article > header h1 img { + vertical-align:middle; +} + +article > section header h1 { + font-size: 16px; +} + +article p { + clear: both; +} + +footer p { + text-align: center; + font-size: 12px; + color: #888; + margin-top: 24px; +} diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/icon.png b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/icon.png new file mode 100755 index 000000000..c22cfa8db Binary files /dev/null and b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/icon.png differ diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/index.html b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/index.html new file mode 100755 index 000000000..89c40d411 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/index.html @@ -0,0 +1,46 @@ + + + + + + + + + + + TCTAppControl + + + + + +
+
+

TCTAppControl

+

index.html

+
+
+ + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/manifest.json b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/manifest.json new file mode 100755 index 000000000..ce32ce3b6 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/manifest.json @@ -0,0 +1,22 @@ +{ + "app": { + "launch": { + "local_path": "index.html" + } + }, + "description": "TCTAppControl", + "file_name": "manifest.json", + "icons": { + "128": "icon.png" + }, + "name": "TCTAppControl", + "permissions": [ + "tabs", + "unlimited_storage", + "notifications", + "http://*/*", + "https://*/*" + ], + "version": "2.2.1", + "webapimanager": true +} \ No newline at end of file diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/COPYING b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/COPYING new file mode 100755 index 000000000..7aa743b59 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/COPYING @@ -0,0 +1,12 @@ +All test files under this folder except COPYING, Makefile.am and blacklist.* come from +https://github.com/w3c/testharness.js (commit 81649066b179216eed02dfb58f631eb8bb6c7629) +without any modification besides the necessary adjustment on reference path to test harness + +These tests are copyright by W3C and/or the author listed in the test +file. The tests are dual-licensed under the W3C Test Suite License: +http://www.w3.org/Consortium/Legal/2008/04-testsuite-license +and the BSD 3-clause License: +http://www.w3.org/Consortium/Legal/2008/03-bsd-license +under W3C's test suite licensing policy: +http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharness.css b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharness.css new file mode 100755 index 000000000..721dce3fc --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharness.css @@ -0,0 +1,92 @@ +html { + font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans; +} + +#log .warning, +#log .warning a { + color: black; + background: yellow; +} + +#log .error, +#log .error a { + color: white; + background: red; +} + +#log pre { + border: 1px solid black; + padding: 1em; +} + +section#summary { + margin-bottom:1em; +} + +table#results { + border-collapse:collapse; + table-layout:fixed; + width:100%; +} + +table#results th:first-child, +table#results td:first-child { + width:4em; +} + +table#results th:last-child, +table#results td:last-child { + width:50%; +} + +table#results.assertions th:last-child, +table#results.assertions td:last-child { + width:35%; +} + +table#results th { + padding:0; + padding-bottom:0.5em; + border-bottom:medium solid black; +} + +table#results td { + padding:1em; + padding-bottom:0.5em; + border-bottom:thin solid black; +} + +tr.pass > td:first-child { + color:green; +} + +tr.fail > td:first-child { + color:red; +} + +tr.timeout > td:first-child { + color:red; +} + +tr.notrun > td:first-child { + color:blue; +} + +.pass > td:first-child, .fail > td:first-child, .timeout > td:first-child, .notrun > td:first-child { + font-variant:small-caps; +} + +table#results span { + display:block; +} + +table#results span.expected { + font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace; + white-space:pre; +} + +table#results span.actual { + font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace; + white-space:pre; +} + diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharness.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharness.js new file mode 100755 index 000000000..5f92be510 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharness.js @@ -0,0 +1,2237 @@ +/* +Distributed under both the W3C Test Suite License [1] and the W3C +3-clause BSD License [2]. To contribute to a W3C Test Suite, see the +policies and contribution forms [3]. + +[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license +[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license +[3] http://www.w3.org/2004/10/27-testcases +*/ + +/* + * == Introduction == + * + * This file provides a framework for writing testcases. It is intended to + * provide a convenient API for making common assertions, and to work both + * for testing synchronous and asynchronous DOM features in a way that + * promotes clear, robust, tests. + * + * == Basic Usage == + * + * To use this file, import the script and the testharnessreport script into + * the test document: + * + * + * + * Within each file one may define one or more tests. Each test is atomic + * in the sense that a single test has a single result (pass/fail/timeout). + * Within each test one may have a number of asserts. The test fails at the + * first failing assert, and the remainder of the test is (typically) not run. + * + * If the file containing the tests is a HTML file with an element of id "log" + * this will be populated with a table containing the test results after all + * the tests have run. + * + * NOTE: By default tests must be created before the load event fires. For ways + * to create tests after the load event, see "Determining when all tests + * are complete", below + * + * == Synchronous Tests == + * + * To create a synchronous test use the test() function: + * + * test(test_function, name, properties) + * + * test_function is a function that contains the code to test. For example a + * trivial passing test would be: + * + * test(function() {assert_true(true)}, "assert_true with true") + * + * The function passed in is run in the test() call. + * + * properties is an object that overrides default test properties. The + * recognised properties are: + * timeout - the test timeout in ms + * + * e.g. + * test(test_function, "Sample test", {timeout:1000}) + * + * would run test_function with a timeout of 1s. + * + * Additionally, test-specific metadata can be passed in the properties. These + * are used when the individual test has different metadata from that stored + * in the . + * The recognized metadata properties are: + * + * help - The url of the part of the specification being tested + * + * assert - A human readable description of what the test is attempting + * to prove + * + * author - Name and contact information for the author of the test in the + * format: "Name " or "Name http://contact/url" + * + * == Asynchronous Tests == + * + * Testing asynchronous features is somewhat more complex since the result of + * a test may depend on one or more events or other callbacks. The API provided + * for testing these features is indended to be rather low-level but hopefully + * applicable to many situations. + * + * To create a test, one starts by getting a Test object using async_test: + * + * async_test(name, properties) + * + * e.g. + * var t = async_test("Simple async test") + * + * Assertions can be added to the test by calling the step method of the test + * object with a function containing the test assertions: + * + * t.step(function() {assert_true(true)}); + * + * When all the steps are complete, the done() method must be called: + * + * t.done(); + * + * As a convenience, async_test can also takes a function as first argument. + * This function is called with the test object as both its `this` object and + * first argument. The above example can be rewritten as: + * + * async_test(function(t) { + * object.some_event = function() { + * t.step(function (){assert_true(true); t.done();}); + * }; + * }, "Simple async test"); + * + * which avoids cluttering the global scope with references to async + * tests instances. + * + * The properties argument is identical to that for test(). + * + * In many cases it is convenient to run a step in response to an event or a + * callback. A convenient method of doing this is through the step_func method + * which returns a function that, when called runs a test step. For example + * + * object.some_event = t.step_func(function(e) {assert_true(e.a)}); + * + * == Making assertions == + * + * Functions for making assertions start assert_ + * The best way to get a list is to look in this file for functions names + * matching that pattern. The general signature is + * + * assert_something(actual, expected, description) + * + * although not all assertions precisely match this pattern e.g. assert_true + * only takes actual and description as arguments. + * + * The description parameter is used to present more useful error messages when + * a test fails + * + * NOTE: All asserts must be located in a test() or a step of an async_test(). + * asserts outside these places won't be detected correctly by the harness + * and may cause a file to stop testing. + * + * == Setup == + * + * Sometimes tests require non-trivial setup that may fail. For this purpose + * there is a setup() function, that may be called with one or two arguments. + * The two argument version is: + * + * setup(func, properties) + * + * The one argument versions may omit either argument. + * func is a function to be run synchronously. setup() becomes a no-op once + * any tests have returned results. Properties are global properties of the test + * harness. Currently recognised properties are: + * + * timeout - The time in ms after which the harness should stop waiting for + * tests to complete (this is different to the per-test timeout + * because async tests do not start their timer until .step is called) + * + * explicit_done - Wait for an explicit call to done() before declaring all + * tests complete (see below) + * + * output_document - The document to which results should be logged. By default + * this is the current document but could be an ancestor + * document in some cases e.g. a SVG test loaded in an HTML + * wrapper + * + * explicit_timeout - disable file timeout; only stop waiting for results + * when the timeout() function is called (typically for + * use when integrating with some existing test framework + * that has its own timeout mechanism). + * + * == Determining when all tests are complete == + * + * By default the test harness will assume there are no more results to come + * when: + * 1) There are no Test objects that have been created but not completed + * 2) The load event on the document has fired + * + * This behaviour can be overridden by setting the explicit_done property to + * true in a call to setup(). If explicit_done is true, the test harness will + * not assume it is done until the global done() function is called. Once done() + * is called, the two conditions above apply like normal. + * + * == Generating tests == + * + * NOTE: this functionality may be removed + * + * There are scenarios in which is is desirable to create a large number of + * (synchronous) tests that are internally similar but vary in the parameters + * used. To make this easier, the generate_tests function allows a single + * function to be called with each set of parameters in a list: + * + * generate_tests(test_function, parameter_lists, properties) + * + * For example: + * + * generate_tests(assert_equals, [ + * ["Sum one and one", 1+1, 2], + * ["Sum one and zero", 1+0, 1] + * ]) + * + * Is equivalent to: + * + * test(function() {assert_equals(1+1, 2)}, "Sum one and one") + * test(function() {assert_equals(1+0, 1)}, "Sum one and zero") + * + * Note that the first item in each parameter list corresponds to the name of + * the test. + * + * The properties argument is identical to that for test(). This may be a + * single object (used for all generated tests) or an array. + * + * == Callback API == + * + * The framework provides callbacks corresponding to 3 events: + * + * start - happens when the first Test is created + * result - happens when a test result is recieved + * complete - happens when all results are recieved + * + * The page defining the tests may add callbacks for these events by calling + * the following methods: + * + * add_start_callback(callback) - callback called with no arguments + * add_result_callback(callback) - callback called with a test argument + * add_completion_callback(callback) - callback called with an array of tests + * and an status object + * + * tests have the following properties: + * status: A status code. This can be compared to the PASS, FAIL, TIMEOUT and + * NOTRUN properties on the test object + * message: A message indicating the reason for failure. In the future this + * will always be a string + * + * The status object gives the overall status of the harness. It has the + * following properties: + * status: Can be compared to the OK, ERROR and TIMEOUT properties + * message: An error message set when the status is ERROR + * + * == External API == + * + * In order to collect the results of multiple pages containing tests, the test + * harness will, when loaded in a nested browsing context, attempt to call + * certain functions in each ancestor and opener browsing context: + * + * start - start_callback + * result - result_callback + * complete - completion_callback + * + * These are given the same arguments as the corresponding internal callbacks + * described above. + * + * == External API through cross-document messaging == + * + * Where supported, the test harness will also send messages using + * cross-document messaging to each ancestor and opener browsing context. Since + * it uses the wildcard keyword (*), cross-origin communication is enabled and + * script on different origins can collect the results. + * + * This API follows similar conventions as those described above only slightly + * modified to accommodate message event API. Each message is sent by the harness + * is passed a single vanilla object, available as the `data` property of the + * event object. These objects are structures as follows: + * + * start - { type: "start" } + * result - { type: "result", test: Test } + * complete - { type: "complete", tests: [Test, ...], status: TestsStatus } + * + * == List of assertions == + * + * assert_true(actual, description) + * asserts that /actual/ is strictly true + * + * assert_false(actual, description) + * asserts that /actual/ is strictly false + * + * assert_equals(actual, expected, description) + * asserts that /actual/ is the same value as /expected/ + * + * assert_not_equals(actual, expected, description) + * asserts that /actual/ is a different value to /expected/. Yes, this means + * that "expected" is a misnomer + * + * assert_in_array(actual, expected, description) + * asserts that /expected/ is an Array, and /actual/ is equal to one of the + * members -- expected.indexOf(actual) != -1 + * + * assert_array_equals(actual, expected, description) + * asserts that /actual/ and /expected/ have the same length and the value of + * each indexed property in /actual/ is the strictly equal to the corresponding + * property value in /expected/ + * + * assert_approx_equals(actual, expected, epsilon, description) + * asserts that /actual/ is a number within +/- /epsilon/ of /expected/ + * + * assert_less_than(actual, expected, description) + * asserts that /actual/ is a number less than /expected/ + * + * assert_greater_than(actual, expected, description) + * asserts that /actual/ is a number greater than /expected/ + * + * assert_less_than_equal(actual, expected, description) + * asserts that /actual/ is a number less than or equal to /expected/ + * + * assert_greater_than_equal(actual, expected, description) + * asserts that /actual/ is a number greater than or equal to /expected/ + * + * assert_regexp_match(actual, expected, description) + * asserts that /actual/ matches the regexp /expected/ + * + * assert_class_string(object, class_name, description) + * asserts that the class string of /object/ as returned in + * Object.prototype.toString is equal to /class_name/. + * + * assert_own_property(object, property_name, description) + * assert that object has own property property_name + * + * assert_inherits(object, property_name, description) + * assert that object does not have an own property named property_name + * but that property_name is present in the prototype chain for object + * + * assert_idl_attribute(object, attribute_name, description) + * assert that an object that is an instance of some interface has the + * attribute attribute_name following the conditions specified by WebIDL + * + * assert_readonly(object, property_name, description) + * assert that property property_name on object is readonly + * + * assert_throws(code, func, description) + * code - the expected exception: + * o string: the thrown exception must be a DOMException with the given + * name, e.g., "TimeoutError" (for compatibility with existing + * tests, a constant is also supported, e.g., "TIMEOUT_ERR") + * o object: the thrown exception must have a property called "name" that + * matches code.name + * o null: allow any exception (in general, one of the options above + * should be used) + * func - a function that should throw + * + * assert_unreached(description) + * asserts if called. Used to ensure that some codepath is *not* taken e.g. + * an event does not fire. + * + * assert_any(assert_func, actual, expected_array, extra_arg_1, ... extra_arg_N) + * asserts that one assert_func(actual, expected_array_N, extra_arg1, ..., extra_arg_N) + * is true for some expected_array_N in expected_array. This only works for assert_func + * with signature assert_func(actual, expected, args_1, ..., args_N). Note that tests + * with multiple allowed pass conditions are bad practice unless the spec specifically + * allows multiple behaviours. Test authors should not use this method simply to hide + * UA bugs. + * + * assert_exists(object, property_name, description) + * *** deprecated *** + * asserts that object has an own property property_name + * + * assert_not_exists(object, property_name, description) + * *** deprecated *** + * assert that object does not have own property property_name + */ + +(function () +{ + var debug = false; + // default timeout is 5 seconds, test can override if needed + var settings = { + output:true, + timeout:5000, + test_timeout:2000 + }; + + var xhtml_ns = "http://www.w3.org/1999/xhtml"; + + // script_prefix is used by Output.prototype.show_results() to figure out + // where to get testharness.css from. It's enclosed in an extra closure to + // not pollute the library's namespace with variables like "src". + var script_prefix = null; + (function () + { + var scripts = document.getElementsByTagName("script"); + for (var i = 0; i < scripts.length; i++) + { + if (scripts[i].src) + { + var src = scripts[i].src; + } + else if (scripts[i].href) + { + //SVG case + var src = scripts[i].href.baseVal; + } + if (src && src.slice(src.length - "testharness.js".length) === "testharness.js") + { + script_prefix = src.slice(0, src.length - "testharness.js".length); + break; + } + } + })(); + + /* + * API functions + */ + + var name_counter = 0; + function next_default_name() + { + //Don't use document.title to work around an Opera bug in XHTML documents + var prefix = document.getElementsByTagName("title").length > 0 ? + document.getElementsByTagName("title")[0].firstChild.data : + "Untitled"; + var suffix = name_counter > 0 ? " " + name_counter : ""; + name_counter++; + return prefix + suffix; + } + + function test(func, name, properties) + { + var test_name = name ? name : next_default_name(); + properties = properties ? properties : {}; + var test_obj = new Test(test_name, properties); + test_obj.step(func); + if (test_obj.status === test_obj.NOTRUN) { + test_obj.done(); + } + } + + function async_test(func, name, properties) + { + if (typeof func !== "function") { + properties = name; + name = func; + func = null; + } + var test_name = name ? name : next_default_name(); + properties = properties ? properties : {}; + var test_obj = new Test(test_name, properties); + if (func) { + test_obj.step(func, test_obj, test_obj); + } + return test_obj; + } + + function setup(func_or_properties, maybe_properties) + { + var func = null; + var properties = {}; + if (arguments.length === 2) { + func = func_or_properties; + properties = maybe_properties; + } else if (func_or_properties instanceof Function){ + func = func_or_properties; + } else { + properties = func_or_properties; + } + tests.setup(func, properties); + output.setup(properties); + } + + function done() { + tests.end_wait(); + } + + function generate_tests(func, args, properties) { + forEach(args, function(x, i) + { + var name = x[0]; + test(function() + { + func.apply(this, x.slice(1)); + }, + name, + Array.isArray(properties) ? properties[i] : properties); + }); + } + + function on_event(object, event, callback) + { + object.addEventListener(event, callback, false); + } + + expose(test, 'test'); + expose(async_test, 'async_test'); + expose(generate_tests, 'generate_tests'); + expose(setup, 'setup'); + expose(done, 'done'); + expose(on_event, 'on_event'); + + /* + * Return a string truncated to the given length, with ... added at the end + * if it was longer. + */ + function truncate(s, len) + { + if (s.length > len) { + return s.substring(0, len - 3) + "..."; + } + return s; + } + + /* + * Convert a value to a nice, human-readable string + */ + function format_value(val) + { + if (Array.isArray(val)) + { + return "[" + val.map(format_value).join(", ") + "]"; + } + + switch (typeof val) + { + case "string": + val = val.replace("\\", "\\\\"); + for (var i = 0; i < 32; i++) + { + var replace = "\\"; + switch (i) { + case 0: replace += "0"; break; + case 1: replace += "x01"; break; + case 2: replace += "x02"; break; + case 3: replace += "x03"; break; + case 4: replace += "x04"; break; + case 5: replace += "x05"; break; + case 6: replace += "x06"; break; + case 7: replace += "x07"; break; + case 8: replace += "b"; break; + case 9: replace += "t"; break; + case 10: replace += "n"; break; + case 11: replace += "v"; break; + case 12: replace += "f"; break; + case 13: replace += "r"; break; + case 14: replace += "x0e"; break; + case 15: replace += "x0f"; break; + case 16: replace += "x10"; break; + case 17: replace += "x11"; break; + case 18: replace += "x12"; break; + case 19: replace += "x13"; break; + case 20: replace += "x14"; break; + case 21: replace += "x15"; break; + case 22: replace += "x16"; break; + case 23: replace += "x17"; break; + case 24: replace += "x18"; break; + case 25: replace += "x19"; break; + case 26: replace += "x1a"; break; + case 27: replace += "x1b"; break; + case 28: replace += "x1c"; break; + case 29: replace += "x1d"; break; + case 30: replace += "x1e"; break; + case 31: replace += "x1f"; break; + } + val = val.replace(RegExp(String.fromCharCode(i), "g"), replace); + } + return '"' + val.replace(/"/g, '\\"') + '"'; + case "boolean": + case "undefined": + return String(val); + case "number": + // In JavaScript, -0 === 0 and String(-0) == "0", so we have to + // special-case. + if (val === -0 && 1/val === -Infinity) + { + return "-0"; + } + return String(val); + case "object": + if (val === null) + { + return "null"; + } + + // Special-case Node objects, since those come up a lot in my tests. I + // ignore namespaces. I use duck-typing instead of instanceof, because + // instanceof doesn't work if the node is from another window (like an + // iframe's contentWindow): + // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295 + if ("nodeType" in val + && "nodeName" in val + && "nodeValue" in val + && "childNodes" in val) + { + switch (val.nodeType) + { + case Node.ELEMENT_NODE: + var ret = "<" + val.tagName.toLowerCase(); + for (var i = 0; i < val.attributes.length; i++) + { + ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"'; + } + ret += ">" + val.innerHTML + ""; + return "Element node " + truncate(ret, 60); + case Node.TEXT_NODE: + return 'Text node "' + truncate(val.data, 60) + '"'; + case Node.PROCESSING_INSTRUCTION_NODE: + return "ProcessingInstruction node with target " + format_value(truncate(val.target, 60)) + " and data " + format_value(truncate(val.data, 60)); + case Node.COMMENT_NODE: + return "Comment node "; + case Node.DOCUMENT_NODE: + return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); + case Node.DOCUMENT_TYPE_NODE: + return "DocumentType node"; + case Node.DOCUMENT_FRAGMENT_NODE: + return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); + default: + return "Node object of unknown type"; + } + } + + // Fall through to default + default: + return typeof val + ' "' + truncate(String(val), 60) + '"'; + } + } + expose(format_value, "format_value"); + + /* + * Assertions + */ + + function assert_true(actual, description) + { + assert(actual === true, "assert_true", description, + "expected true got ${actual}", {actual:actual}); + }; + expose(assert_true, "assert_true"); + + function assert_false(actual, description) + { + assert(actual === false, "assert_false", description, + "expected false got ${actual}", {actual:actual}); + }; + expose(assert_false, "assert_false"); + + function same_value(x, y) { + if (y !== y) + { + //NaN case + return x !== x; + } + else if (x === 0 && y === 0) { + //Distinguish +0 and -0 + return 1/x === 1/y; + } + else + { + //typical case + return x === y; + } + } + + function assert_equals(actual, expected, description) + { + /* + * Test if two primitives are equal or two objects + * are the same object + */ + if (typeof actual != typeof expected) + { + assert(false, "assert_equals", description, + "expected (" + typeof expected + ") ${expected} but got (" + typeof actual + ") ${actual}", + {expected:expected, actual:actual}); + return; + } + assert(same_value(actual, expected), "assert_equals", description, + "expected ${expected} but got ${actual}", + {expected:expected, actual:actual}); + }; + expose(assert_equals, "assert_equals"); + + function assert_not_equals(actual, expected, description) + { + /* + * Test if two primitives are unequal or two objects + * are different objects + */ + assert(!same_value(actual, expected), "assert_not_equals", description, + "got disallowed value ${actual}", + {actual:actual}); + }; + expose(assert_not_equals, "assert_not_equals"); + + function assert_in_array(actual, expected, description) + { + assert(expected.indexOf(actual) != -1, "assert_in_array", description, + "value ${actual} not in array ${expected}", + {actual:actual, expected:expected}); + } + expose(assert_in_array, "assert_in_array"); + + function assert_object_equals(actual, expected, description) + { + //This needs to be improved a great deal + function check_equal(actual, expected, stack) + { + stack.push(actual); + + var p; + for (p in actual) + { + assert(expected.hasOwnProperty(p), "assert_object_equals", description, + "unexpected property ${p}", {p:p}); + + if (typeof actual[p] === "object" && actual[p] !== null) + { + if (stack.indexOf(actual[p]) === -1) + { + check_equal(actual[p], expected[p], stack); + } + } + else + { + assert(same_value(actual[p], expected[p]), "assert_object_equals", description, + "property ${p} expected ${expected} got ${actual}", + {p:p, expected:expected, actual:actual}); + } + } + for (p in expected) + { + assert(actual.hasOwnProperty(p), + "assert_object_equals", description, + "expected property ${p} missing", {p:p}); + } + stack.pop(); + } + check_equal(actual, expected, []); + }; + expose(assert_object_equals, "assert_object_equals"); + + function assert_array_equals(actual, expected, description) + { + assert(actual.length === expected.length, + "assert_array_equals", description, + "lengths differ, expected ${expected} got ${actual}", + {expected:expected.length, actual:actual.length}); + + for (var i=0; i < actual.length; i++) + { + assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i), + "assert_array_equals", description, + "property ${i}, property expected to be $expected but was $actual", + {i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing", + actual:actual.hasOwnProperty(i) ? "present" : "missing"}); + assert(same_value(expected[i], actual[i]), + "assert_array_equals", description, + "property ${i}, expected ${expected} but got ${actual}", + {i:i, expected:expected[i], actual:actual[i]}); + } + } + expose(assert_array_equals, "assert_array_equals"); + + function assert_approx_equals(actual, expected, epsilon, description) + { + /* + * Test if two primitive numbers are equal withing +/- epsilon + */ + assert(typeof actual === "number", + "assert_approx_equals", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(Math.abs(actual - expected) <= epsilon, + "assert_approx_equals", description, + "expected ${expected} +/- ${epsilon} but got ${actual}", + {expected:expected, actual:actual, epsilon:epsilon}); + }; + expose(assert_approx_equals, "assert_approx_equals"); + + function assert_less_than(actual, expected, description) + { + /* + * Test if a primitive number is less than another + */ + assert(typeof actual === "number", + "assert_less_than", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual < expected, + "assert_less_than", description, + "expected a number less than ${expected} but got ${actual}", + {expected:expected, actual:actual}); + }; + expose(assert_less_than, "assert_less_than"); + + function assert_greater_than(actual, expected, description) + { + /* + * Test if a primitive number is greater than another + */ + assert(typeof actual === "number", + "assert_greater_than", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual > expected, + "assert_greater_than", description, + "expected a number greater than ${expected} but got ${actual}", + {expected:expected, actual:actual}); + }; + expose(assert_greater_than, "assert_greater_than"); + + function assert_less_than_equal(actual, expected, description) + { + /* + * Test if a primitive number is less than or equal to another + */ + assert(typeof actual === "number", + "assert_less_than_equal", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual <= expected, + "assert_less_than", description, + "expected a number less than or equal to ${expected} but got ${actual}", + {expected:expected, actual:actual}); + }; + expose(assert_less_than_equal, "assert_less_than_equal"); + + function assert_greater_than_equal(actual, expected, description) + { + /* + * Test if a primitive number is greater than or equal to another + */ + assert(typeof actual === "number", + "assert_greater_than_equal", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual >= expected, + "assert_greater_than_equal", description, + "expected a number greater than or equal to ${expected} but got ${actual}", + {expected:expected, actual:actual}); + }; + expose(assert_greater_than_equal, "assert_greater_than_equal"); + + function assert_regexp_match(actual, expected, description) { + /* + * Test if a string (actual) matches a regexp (expected) + */ + assert(expected.test(actual), + "assert_regexp_match", description, + "expected ${expected} but got ${actual}", + {expected:expected, actual:actual}); + } + expose(assert_regexp_match, "assert_regexp_match"); + + function assert_class_string(object, class_string, description) { + assert_equals({}.toString.call(object), "[object " + class_string + "]", + description); + } + expose(assert_class_string, "assert_class_string"); + + + function _assert_own_property(name) { + return function(object, property_name, description) + { + assert(property_name in object, + name, description, + "expected property ${p} missing", {p:property_name}); + }; + } + expose(_assert_own_property("assert_exists"), "assert_exists"); + expose(_assert_own_property("assert_own_property"), "assert_own_property"); + + function assert_not_exists(object, property_name, description) + { + assert(!object.hasOwnProperty(property_name), + "assert_not_exists", description, + "unexpected property ${p} found", {p:property_name}); + }; + expose(assert_not_exists, "assert_not_exists"); + + function _assert_inherits(name) { + return function (object, property_name, description) + { + assert(typeof object === "object", + name, description, + "provided value is not an object"); + + assert("hasOwnProperty" in object, + name, description, + "provided value is an object but has no hasOwnProperty method"); + + assert(!object.hasOwnProperty(property_name), + name, description, + "property ${p} found on object expected in prototype chain", + {p:property_name}); + + assert(property_name in object, + name, description, + "property ${p} not found in prototype chain", + {p:property_name}); + }; + } + expose(_assert_inherits("assert_inherits"), "assert_inherits"); + expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute"); + + function assert_readonly(object, property_name, description) + { + var initial_value = object[property_name]; + try { + //Note that this can have side effects in the case where + //the property has PutForwards + object[property_name] = initial_value + "a"; //XXX use some other value here? + assert(same_value(object[property_name], initial_value), + "assert_readonly", description, + "changing property ${p} succeeded", + {p:property_name}); + } + finally + { + object[property_name] = initial_value; + } + }; + expose(assert_readonly, "assert_readonly"); + + function assert_throws(code, func, description) + { + try + { + func.call(this); + assert(false, "assert_throws", description, + "${func} did not throw", {func:func}); + } + catch(e) + { + if (e instanceof AssertionError) { + throw(e); + } + if (code === null) + { + return; + } + if (typeof code === "object") + { + assert(typeof e == "object" && "name" in e && e.name == code.name, + "assert_throws", description, + "${func} threw ${actual} (${actual_name}) expected ${expected} (${expected_name})", + {func:func, actual:e, actual_name:e.name, + expected:code, + expected_name:code.name}); + return; + } + + var code_name_map = { + INDEX_SIZE_ERR: 'IndexSizeError', + HIERARCHY_REQUEST_ERR: 'HierarchyRequestError', + WRONG_DOCUMENT_ERR: 'WrongDocumentError', + INVALID_CHARACTER_ERR: 'InvalidCharacterError', + NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError', + NOT_FOUND_ERR: 'NotFoundError', + NOT_SUPPORTED_ERR: 'NotSupportedError', + INVALID_STATE_ERR: 'InvalidStateError', + SYNTAX_ERR: 'SyntaxError', + INVALID_MODIFICATION_ERR: 'InvalidModificationError', + NAMESPACE_ERR: 'NamespaceError', + INVALID_ACCESS_ERR: 'InvalidAccessError', + TYPE_MISMATCH_ERR: 'TypeMismatchError', + SECURITY_ERR: 'SecurityError', + NETWORK_ERR: 'NetworkError', + ABORT_ERR: 'AbortError', + URL_MISMATCH_ERR: 'URLMismatchError', + QUOTA_EXCEEDED_ERR: 'QuotaExceededError', + TIMEOUT_ERR: 'TimeoutError', + INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError', + DATA_CLONE_ERR: 'DataCloneError' + }; + + var name = code in code_name_map ? code_name_map[code] : code; + + var name_code_map = { + IndexSizeError: 1, + HierarchyRequestError: 3, + WrongDocumentError: 4, + InvalidCharacterError: 5, + NoModificationAllowedError: 7, + NotFoundError: 8, + NotSupportedError: 9, + InvalidStateError: 11, + SyntaxError: 12, + InvalidModificationError: 13, + NamespaceError: 14, + InvalidAccessError: 15, + TypeMismatchError: 17, + SecurityError: 18, + NetworkError: 19, + AbortError: 20, + URLMismatchError: 21, + QuotaExceededError: 22, + TimeoutError: 23, + InvalidNodeTypeError: 24, + DataCloneError: 25, + + UnknownError: 0, + ConstraintError: 0, + DataError: 0, + TransactionInactiveError: 0, + ReadOnlyError: 0, + VersionError: 0 + }; + + if (!(name in name_code_map)) + { + throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()'); + } + + var required_props = { code: name_code_map[name] }; + + if (required_props.code === 0 + || ("name" in e && e.name !== e.name.toUpperCase() && e.name !== "DOMException")) + { + // New style exception: also test the name property. + required_props.name = name; + } + + //We'd like to test that e instanceof the appropriate interface, + //but we can't, because we don't know what window it was created + //in. It might be an instanceof the appropriate interface on some + //unknown other window. TODO: Work around this somehow? + + assert(typeof e == "object", + "assert_throws", description, + "${func} threw ${e} with type ${type}, not an object", + {func:func, e:e, type:typeof e}); + + for (var prop in required_props) + { + assert(typeof e == "object" && prop in e && e[prop] == required_props[prop], + "assert_throws", description, + "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}", + {func:func, e:e, prop:prop, actual:e[prop], expected:required_props[prop]}); + } + } + } + expose(assert_throws, "assert_throws"); + + function assert_unreached(description) { + assert(false, "assert_unreached", description, + "Reached unreachable code"); + } + expose(assert_unreached, "assert_unreached"); + + function assert_any(assert_func, actual, expected_array) + { + var args = [].slice.call(arguments, 3) + var errors = [] + var passed = false; + forEach(expected_array, + function(expected) + { + try { + assert_func.apply(this, [actual, expected].concat(args)) + passed = true; + } catch(e) { + errors.push(e.message); + } + }); + if (!passed) { + throw new AssertionError(errors.join("\n\n")); + } + } + expose(assert_any, "assert_any"); + + function Test(name, properties) + { + this.name = name; + this.status = this.NOTRUN; + this.timeout_id = null; + this.is_done = false; + + this.properties = properties; + this.timeout_length = properties.timeout ? properties.timeout : settings.test_timeout; + + this.message = null; + + var this_obj = this; + this.steps = []; + + tests.push(this); + } + + Test.statuses = { + PASS:0, + FAIL:1, + TIMEOUT:2, + NOTRUN:3 + }; + + Test.prototype = merge({}, Test.statuses); + + Test.prototype.structured_clone = function() + { + if(!this._structured_clone) + { + var msg = this.message; + msg = msg ? String(msg) : msg; + this._structured_clone = merge({ + name:String(this.name), + status:this.status, + message:msg + }, Test.statuses); + } + return this._structured_clone; + }; + + Test.prototype.step = function(func, this_obj) + { + //In case the test has already failed + if (this.status !== this.NOTRUN) + { + return; + } + + tests.started = true; + + if (this.timeout_id === null) { + this.set_timeout(); + } + + this.steps.push(func); + + if (arguments.length === 1) + { + this_obj = this; + } + + try + { + return func.apply(this_obj, Array.prototype.slice.call(arguments, 2)); + } + catch(e) + { + //This can happen if something called synchronously invoked another + //step + if (this.status !== this.NOTRUN) + { + return; + } + this.status = this.FAIL; + this.message = (typeof e === "object" && e !== null) ? e.message : e; + if (typeof e.stack != "undefined" && typeof e.message == "string") { + //Try to make it more informative for some exceptions, at least + //in Gecko and WebKit. This results in a stack dump instead of + //just errors like "Cannot read property 'parentNode' of null" + //or "root is null". Makes it a lot longer, of course. + this.message += "(stack: " + e.stack + ")"; + } + this.done(); + if (debug && e.constructor !== AssertionError) { + throw e; + } + } + }; + + Test.prototype.step_func = function(func, this_obj) + { + var test_this = this; + + if (arguments.length === 1) + { + this_obj = test_this; + } + + return function() + { + test_this.step.apply(test_this, [func, this_obj].concat( + Array.prototype.slice.call(arguments))); + }; + }; + + Test.prototype.step_func_done = function(func, this_obj) + { + var test_this = this; + + if (arguments.length === 1) + { + this_obj = test_this; + } + + return function() + { + test_this.step.apply(test_this, [func, this_obj].concat( + Array.prototype.slice.call(arguments))); + test_this.done(); + }; + }; + + Test.prototype.set_timeout = function() + { + var this_obj = this; + this.timeout_id = setTimeout(function() + { + this_obj.timeout(); + }, this.timeout_length); + }; + + Test.prototype.timeout = function() + { + this.status = this.TIMEOUT; + this.timeout_id = null; + this.message = "Test timed out"; + this.done(); + }; + + Test.prototype.done = function() + { + if (this.is_done) { + return; + } + clearTimeout(this.timeout_id); + if (this.status === this.NOTRUN) + { + this.status = this.PASS; + } + this.is_done = true; + tests.result(this); + }; + + + /* + * Harness + */ + + function TestsStatus() + { + this.status = null; + this.message = null; + } + + TestsStatus.statuses = { + OK:0, + ERROR:1, + TIMEOUT:2 + }; + + TestsStatus.prototype = merge({}, TestsStatus.statuses); + + TestsStatus.prototype.structured_clone = function() + { + if(!this._structured_clone) + { + var msg = this.message; + msg = msg ? String(msg) : msg; + this._structured_clone = merge({ + status:this.status, + message:msg + }, TestsStatus.statuses); + } + return this._structured_clone; + }; + + function Tests() + { + this.tests = []; + this.num_pending = 0; + + this.phases = { + INITIAL:0, + SETUP:1, + HAVE_TESTS:2, + HAVE_RESULTS:3, + COMPLETE:4 + }; + this.phase = this.phases.INITIAL; + + this.properties = {}; + + //All tests can't be done until the load event fires + this.all_loaded = false; + this.wait_for_finish = false; + this.processing_callbacks = false; + + this.timeout_length = settings.timeout; + this.timeout_id = null; + + this.start_callbacks = []; + this.test_done_callbacks = []; + this.all_done_callbacks = []; + + this.status = new TestsStatus(); + + var this_obj = this; + + on_event(window, "load", + function() + { + this_obj.all_loaded = true; + if (this_obj.all_done()) + { + this_obj.complete(); + } + }); + + this.set_timeout(); + } + + Tests.prototype.setup = function(func, properties) + { + if (this.phase >= this.phases.HAVE_RESULTS) + { + return; + } + if (this.phase < this.phases.SETUP) + { + this.phase = this.phases.SETUP; + } + + for (var p in properties) + { + if (properties.hasOwnProperty(p)) + { + this.properties[p] = properties[p]; + } + } + + if (properties.timeout) + { + this.timeout_length = properties.timeout; + } + if (properties.explicit_done) + { + this.wait_for_finish = true; + } + if (properties.explicit_timeout) { + this.timeout_length = null; + } + + if (func) + { + try + { + func(); + } catch(e) + { + this.status.status = this.status.ERROR; + this.status.message = e; + }; + } + this.set_timeout(); + }; + + Tests.prototype.set_timeout = function() + { + var this_obj = this; + clearTimeout(this.timeout_id); + if (this.timeout_length !== null) + { + this.timeout_id = setTimeout(function() { + this_obj.timeout(); + }, this.timeout_length); + } + }; + + Tests.prototype.timeout = function() { + this.status.status = this.status.TIMEOUT; + this.complete(); + }; + + Tests.prototype.end_wait = function() + { + this.wait_for_finish = false; + if (this.all_done()) { + this.complete(); + } + }; + + Tests.prototype.push = function(test) + { + if (this.phase < this.phases.HAVE_TESTS) { + this.start(); + } + this.num_pending++; + this.tests.push(test); + }; + + Tests.prototype.all_done = function() { + return (this.all_loaded && this.num_pending === 0 && + !this.wait_for_finish && !this.processing_callbacks); + }; + + Tests.prototype.start = function() { + this.phase = this.phases.HAVE_TESTS; + this.notify_start(); + }; + + Tests.prototype.notify_start = function() { + var this_obj = this; + forEach (this.start_callbacks, + function(callback) + { + callback(this_obj.properties); + }); + forEach_windows( + function(w, is_same_origin) + { + if(is_same_origin && w.start_callback) + { + try + { + w.start_callback(this_obj.properties); + } + catch(e) + { + if (debug) + { + throw(e); + } + } + } + if (supports_post_message(w) && w !== self) + { + w.postMessage({ + type: "start", + properties: this_obj.properties + }, "*"); + } + }); + }; + + Tests.prototype.result = function(test) + { + if (this.phase > this.phases.HAVE_RESULTS) + { + return; + } + this.phase = this.phases.HAVE_RESULTS; + this.num_pending--; + this.notify_result(test); + }; + + Tests.prototype.notify_result = function(test) { + var this_obj = this; + this.processing_callbacks = true; + forEach(this.test_done_callbacks, + function(callback) + { + callback(test, this_obj); + }); + + forEach_windows( + function(w, is_same_origin) + { + if(is_same_origin && w.result_callback) + { + try + { + w.result_callback(test); + } + catch(e) + { + if(debug) { + throw e; + } + } + } + if (supports_post_message(w) && w !== self) + { + w.postMessage({ + type: "result", + test: test.structured_clone() + }, "*"); + } + }); + this.processing_callbacks = false; + if (this_obj.all_done()) + { + this_obj.complete(); + } + }; + + Tests.prototype.complete = function() { + if (this.phase === this.phases.COMPLETE) { + return; + } + this.phase = this.phases.COMPLETE; + var this_obj = this; + this.tests.forEach( + function(x) + { + if(x.status === x.NOTRUN) + { + this_obj.notify_result(x); + } + } + ); + this.notify_complete(); + }; + + Tests.prototype.notify_complete = function() + { + clearTimeout(this.timeout_id); + var this_obj = this; + var tests = map(this_obj.tests, + function(test) + { + return test.structured_clone(); + }); + if (this.status.status === null) + { + this.status.status = this.status.OK; + } + + forEach (this.all_done_callbacks, + function(callback) + { + callback(this_obj.tests, this_obj.status); + }); + + forEach_windows( + function(w, is_same_origin) + { + if(is_same_origin && w.completion_callback) + { + try + { + w.completion_callback(this_obj.tests, this_obj.status); + } + catch(e) + { + if (debug) + { + throw e; + } + } + } + if (supports_post_message(w) && w !== self) + { + w.postMessage({ + type: "complete", + tests: tests, + status: this_obj.status.structured_clone() + }, "*"); + } + }); + }; + + var tests = new Tests(); + + function timeout() { + if (tests.timeout_length === null) + { + tests.timeout(); + } + } + expose(timeout, 'timeout'); + + function add_start_callback(callback) { + tests.start_callbacks.push(callback); + } + + function add_result_callback(callback) + { + tests.test_done_callbacks.push(callback); + } + + function add_completion_callback(callback) + { + tests.all_done_callbacks.push(callback); + } + + expose(add_start_callback, 'add_start_callback'); + expose(add_result_callback, 'add_result_callback'); + expose(add_completion_callback, 'add_completion_callback'); + + /* + * Output listener + */ + + function Output() { + this.output_document = document; + this.output_node = null; + this.done_count = 0; + this.enabled = settings.output; + this.phase = this.INITIAL; + } + + Output.prototype.INITIAL = 0; + Output.prototype.STARTED = 1; + Output.prototype.HAVE_RESULTS = 2; + Output.prototype.COMPLETE = 3; + + Output.prototype.setup = function(properties) { + if (this.phase > this.INITIAL) { + return; + } + + //If output is disabled in testharnessreport.js the test shouldn't be + //able to override that + this.enabled = this.enabled && (properties.hasOwnProperty("output") ? + properties.output : settings.output); + }; + + Output.prototype.init = function(properties) + { + if (this.phase >= this.STARTED) { + return; + } + if (properties.output_document) { + this.output_document = properties.output_document; + } else { + this.output_document = document; + } + this.phase = this.STARTED; + }; + + Output.prototype.resolve_log = function() + { + var output_document; + if (typeof this.output_document === "function") + { + output_document = this.output_document.apply(undefined); + } else + { + output_document = this.output_document; + } + if (!output_document) + { + return; + } + var node = output_document.getElementById("log"); + if (node) + { + this.output_document = output_document; + this.output_node = node; + } + }; + + Output.prototype.show_status = function(test) + { + if (this.phase < this.STARTED) + { + this.init(); + } + if (!this.enabled) + { + return; + } + if (this.phase < this.HAVE_RESULTS) + { + this.resolve_log(); + this.phase = this.HAVE_RESULTS; + } + this.done_count++; + if (this.output_node) + { + if (this.done_count < 100 + || (this.done_count < 1000 && this.done_count % 100 == 0) + || this.done_count % 1000 == 0) { + this.output_node.textContent = "Running, " + + this.done_count + " complete, " + + tests.num_pending + " remain"; + } + } + }; + + Output.prototype.show_results = function (tests, harness_status) + { + if (this.phase >= this.COMPLETE) { + return; + } + if (!this.enabled) + { + return; + } + if (!this.output_node) { + this.resolve_log(); + } + this.phase = this.COMPLETE; + + var log = this.output_node; + if (!log) + { + return; + } + var output_document = this.output_document; + + while (log.lastChild) + { + log.removeChild(log.lastChild); + } + + if (script_prefix != null) { + var stylesheet = output_document.createElementNS(xhtml_ns, "link"); + stylesheet.setAttribute("rel", "stylesheet"); + stylesheet.setAttribute("href", script_prefix + "testharness.css"); + var heads = output_document.getElementsByTagName("head"); + if (heads.length) { + heads[0].appendChild(stylesheet); + } + } + + var status_text = {}; + status_text[Test.prototype.PASS] = "Pass"; + status_text[Test.prototype.FAIL] = "Fail"; + status_text[Test.prototype.TIMEOUT] = "Timeout"; + status_text[Test.prototype.NOTRUN] = "Not Run"; + + var status_number = {}; + forEach(tests, function(test) { + var status = status_text[test.status]; + if (status_number.hasOwnProperty(status)) + { + status_number[status] += 1; + } else { + status_number[status] = 1; + } + }); + + function status_class(status) + { + return status.replace(/\s/g, '').toLowerCase(); + } + + var summary_template = ["section", {"id":"summary"}, + ["h2", {}, "Summary"], + ["p", {}, "Found ${num_tests} tests"], + function(vars) { + var rv = [["div", {}]]; + var i=0; + while (status_text.hasOwnProperty(i)) { + if (status_number.hasOwnProperty(status_text[i])) { + var status = status_text[i]; + rv[0].push(["div", {"class":status_class(status)}, + ["label", {}, + ["input", {type:"checkbox", checked:"checked"}], + status_number[status] + " " + status]]); + } + i++; + } + return rv; + }]; + + log.appendChild(render(summary_template, {num_tests:tests.length}, output_document)); + + forEach(output_document.querySelectorAll("section#summary label"), + function(element) + { + on_event(element, "click", + function(e) + { + if (output_document.getElementById("results") === null) + { + e.preventDefault(); + return; + } + var result_class = element.parentNode.getAttribute("class"); + var style_element = output_document.querySelector("style#hide-" + result_class); + var input_element = element.querySelector("input"); + if (!style_element && !input_element.checked) { + style_element = output_document.createElementNS(xhtml_ns, "style"); + style_element.id = "hide-" + result_class; + style_element.textContent = "table#results > tbody > tr."+result_class+"{display:none}"; + output_document.body.appendChild(style_element); + } else if (style_element && input_element.checked) { + style_element.parentNode.removeChild(style_element); + } + }); + }); + + // This use of innerHTML plus manual escaping is not recommended in + // general, but is necessary here for performance. Using textContent + // on each individual adds tens of seconds of execution time for + // large test suites (tens of thousands of tests). + function escape_html(s) + { + return s.replace(/\&/g, "&") + .replace(/" + + "ResultTest Name" + + (assertions ? "Assertion" : "") + + "Message" + + ""; + for (var i = 0; i < tests.length; i++) { + html += '' + + escape_html(status_text[tests[i].status]) + + "" + + escape_html(tests[i].name) + + "" + + (assertions ? escape_html(get_assertion(tests[i])) + "" : "") + + escape_html(tests[i].message ? tests[i].message : " ") + + ""; + } + html += ""; + try { + log.lastChild.innerHTML = html; + } catch (e) { + log.appendChild(document.createElementNS(xhtml_ns, "p")) + .textContent = "Setting innerHTML for the log threw an exception."; + log.appendChild(document.createElementNS(xhtml_ns, "pre")) + .textContent = html; + } + }; + + var output = new Output(); + add_start_callback(function (properties) {output.init(properties);}); + add_result_callback(function (test) {output.show_status(tests);}); + add_completion_callback(function (tests, harness_status) {output.show_results(tests, harness_status);}); + + /* + * Template code + * + * A template is just a javascript structure. An element is represented as: + * + * [tag_name, {attr_name:attr_value}, child1, child2] + * + * the children can either be strings (which act like text nodes), other templates or + * functions (see below) + * + * A text node is represented as + * + * ["{text}", value] + * + * String values have a simple substitution syntax; ${foo} represents a variable foo. + * + * It is possible to embed logic in templates by using a function in a place where a + * node would usually go. The function must either return part of a template or null. + * + * In cases where a set of nodes are required as output rather than a single node + * with children it is possible to just use a list + * [node1, node2, node3] + * + * Usage: + * + * render(template, substitutions) - take a template and an object mapping + * variable names to parameters and return either a DOM node or a list of DOM nodes + * + * substitute(template, substitutions) - take a template and variable mapping object, + * make the variable substitutions and return the substituted template + * + */ + + function is_single_node(template) + { + return typeof template[0] === "string"; + } + + function substitute(template, substitutions) + { + if (typeof template === "function") { + var replacement = template(substitutions); + if (replacement) + { + var rv = substitute(replacement, substitutions); + return rv; + } + else + { + return null; + } + } + else if (is_single_node(template)) + { + return substitute_single(template, substitutions); + } + else + { + return filter(map(template, function(x) { + return substitute(x, substitutions); + }), function(x) {return x !== null;}); + } + } + + function substitute_single(template, substitutions) + { + var substitution_re = /\${([^ }]*)}/g; + + function do_substitution(input) { + var components = input.split(substitution_re); + var rv = []; + for (var i=0; i= 0) + ret = false; + + return ret; +} + +// vim: set expandtab shiftwidth=4 tabstop=4: diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharnessreport.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharnessreport.js new file mode 100755 index 000000000..8305f7bac --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/resources/testharnessreport.js @@ -0,0 +1,380 @@ +/* + * This file is intended for vendors to implement + * code needed to integrate testharness.js tests with their own test systems. + * + * The default implementation extracts metadata from the tests and validates + * it against the cached version that should be present in the test source + * file. If the cache is not found or is out of sync, source code suitable for + * caching the metadata is optionally generated. + * + * The cached metadata is present for extraction by test processing tools that + * are unable to execute javascript. + * + * Metadata is attached to tests via the properties parameter in the test + * constructor. See testharness.js for details. + * + * Typically test system integration will attach callbacks when each test has + * run, using add_result_callback(callback(test)), or when the whole test file + * has completed, using + * add_completion_callback(callback(tests, harness_status)). + * + * For more documentation about the callback functions and the + * parameters they are called with see testharness.js + */ + + + +var metadata_generator = { + + currentMetadata: {}, + cachedMetadata: false, + metadataProperties: ['help', 'assert', 'author'], + + error: function(message) { + var messageElement = document.createElement('p'); + messageElement.setAttribute('class', 'error'); + this.appendText(messageElement, message); + + var summary = document.getElementById('summary'); + if (summary) { + summary.parentNode.insertBefore(messageElement, summary); + } + else { + document.body.appendChild(messageElement); + } + }, + + /** + * Ensure property value has contact information + */ + validateContact: function(test, propertyName) { + var result = true; + var value = test.properties[propertyName]; + var values = Array.isArray(value) ? value : [value]; + for (var index = 0; index < values.length; index++) { + value = values[index]; + var re = /(\S+)(\s*)<(.*)>(.*)/; + if (! re.test(value)) { + re = /(\S+)(\s+)(http[s]?:\/\/)(.*)/ + if (! re.test(value)) { + this.error('Metadata property "' + propertyName + + '" for test: "' + test.name + + '" must have name and contact information ' + + '("name " or "name http(s)://")'); + result = false; + } + } + } + return result; + }, + + /** + * Extract metadata from test object + */ + extractFromTest: function(test) { + var testMetadata = {}; + // filter out metadata from other properties in test + for (var metaIndex = 0; metaIndex < this.metadataProperties.length; + metaIndex++) { + var meta = this.metadataProperties[metaIndex]; + if (test.properties.hasOwnProperty(meta)) { + if ('author' == meta) { + this.validateContact(test, meta); + } + testMetadata[meta] = test.properties[meta]; + } + } + return testMetadata; + }, + + /** + * Compare cached metadata to extracted metadata + */ + validateCache: function() { + for (var testName in this.currentMetadata) { + if (! this.cachedMetadata.hasOwnProperty(testName)) { + return false; + } + var testMetadata = this.currentMetadata[testName]; + var cachedTestMetadata = this.cachedMetadata[testName]; + delete this.cachedMetadata[testName]; + + for (var metaIndex = 0; metaIndex < this.metadataProperties.length; + metaIndex++) { + var meta = this.metadataProperties[metaIndex]; + if (cachedTestMetadata.hasOwnProperty(meta) && + testMetadata.hasOwnProperty(meta)) { + if (Array.isArray(cachedTestMetadata[meta])) { + if (! Array.isArray(testMetadata[meta])) { + return false; + } + if (cachedTestMetadata[meta].length == + testMetadata[meta].length) { + for (var index = 0; + index < cachedTestMetadata[meta].length; + index++) { + if (cachedTestMetadata[meta][index] != + testMetadata[meta][index]) { + return false; + } + } + } + else { + return false; + } + } + else { + if (Array.isArray(testMetadata[meta])) { + return false; + } + if (cachedTestMetadata[meta] != testMetadata[meta]) { + return false; + } + } + } + else if (cachedTestMetadata.hasOwnProperty(meta) || + testMetadata.hasOwnProperty(meta)) { + return false; + } + } + } + for (var testName in this.cachedMetadata) { + return false; + } + return true; + }, + + appendText: function(elemement, text) { + elemement.appendChild(document.createTextNode(text)); + }, + + jsonifyArray: function(arrayValue, indent) { + var output = '['; + + if (1 == arrayValue.length) { + output += JSON.stringify(arrayValue[0]); + } + else { + for (var index = 0; index < arrayValue.length; index++) { + if (0 < index) { + output += ',\n ' + indent; + } + output += JSON.stringify(arrayValue[index]); + } + } + output += ']'; + return output; + }, + + jsonifyObject: function(objectValue, indent) { + var output = '{'; + + var count = 0; + for (var property in objectValue) { + ++count; + if (Array.isArray(objectValue[property]) || + ('object' == typeof(value))) { + ++count; + } + } + if (1 == count) { + for (var property in objectValue) { + output += ' "' + property + '": ' + + JSON.stringify(objectValue[property]) + + ' '; + } + } + else { + var first = true; + for (var property in objectValue) { + if (! first) { + output += ','; + } + first = false; + output += '\n ' + indent + '"' + property + '": '; + var value = objectValue[property]; + if (Array.isArray(value)) { + output += this.jsonifyArray(value, indent + + ' '.substr(0, 5 + property.length)); + } + else if ('object' == typeof(value)) { + output += this.jsonifyObject(value, indent + ' '); + } + else { + output += JSON.stringify(value); + } + } + if (1 < output.length) { + output += '\n' + indent; + } + } + output += '}'; + return output; + }, + + /** + * Generate javascript source code for captured metadata + * Metadata is in pretty-printed JSON format + */ + generateSource: function() { + var source = + '\n'; + return source; + }, + + /** + * Add element containing metadata source code + */ + addSourceElement: function(event) { + var sourceWrapper = document.createElement('div'); + sourceWrapper.setAttribute('id', 'metadata_source'); + + var instructions = document.createElement('p'); + if (this.cachedMetadata) { + this.appendText(instructions, + 'Replace the existing \n'); + } + if (head_src.search(/\/testharnessreport.js\W/) === -1) { + document.write('\n'); + } +})(); + +var _registered_types = {}; + +function _resolve_registered_type(type) { + while (type in _registered_types) { + type = _registered_types[type]; + } + return type; +} + +/** + * Method checks extra argument for none argument method. + * The only check is that method will not throw an exception. + * Example usage: + * checkExtraArgument(tizen.notification, "removeAll"); + * + * @param object object + * @param methodName string - name of the method + */ +function checkExtraArgument(object, methodName) { + var extraArgument = [ + null, + undefined, + "Tizen", + 1, + false, + ["one", "two"], + {argument: 1}, + function () {} + ], i; + + for (i = 0; i < extraArgument.length; i++) { + object[methodName](extraArgument[i]); + } +} + +/** + * Method to validate conversion. + * Example usage: + * conversionTable = getTypeConversionExceptions("functionObject", true); + * for(i = 0; i < conversionTable.length; i++) { + * errorCallback = conversionTable[i][0]; + * exceptionName = conversionTable[i][1]; + * + * assert_throws({name : exceptionName}, + * function () { + * tizen.systemsetting.setProperty("HOME_SCREEN", + * propertyValue, successCallback, errorCallback); + * }, exceptionName + " should be thrown - given incorrect errorCallback."); + * } + * + * @param conversionType + * @param isOptional + * @returns table of tables which contain value (index 0) and exceptionName (index 1) + * + */ +function getTypeConversionExceptions(conversionType, isOptional) { + var exceptionName = "TypeMismatchError", + conversionTable; + switch (conversionType) { + case "enum": + conversionTable = [ + [undefined, exceptionName], + [null, exceptionName], + [0, exceptionName], + [true, exceptionName], + ["dummyInvalidEnumValue", exceptionName], + [{ }, exceptionName] + ]; + break; + case "double": + conversionTable = [ + [undefined, exceptionName], + [NaN, exceptionName], + [Number.POSITIVE_INFINITY, exceptionName], + [Number.NEGATIVE_INFINITY, exceptionName], + ["TIZEN", exceptionName], + [{ name : "TIZEN" }, exceptionName], + [function () { }, exceptionName] + ]; + break; + case "object": + conversionTable = [ + [true, exceptionName], + [false, exceptionName], + [NaN, exceptionName], + [0, exceptionName], + ["", exceptionName], + ["TIZEN", exceptionName], + [undefined, exceptionName] + ]; + if (!isOptional) { + conversionTable.push([null, exceptionName]); + } + break; + case "functionObject": + conversionTable = [ + [true, exceptionName], + [false, exceptionName], + [NaN, exceptionName], + [0, exceptionName], + ["", exceptionName], + ["TIZEN", exceptionName], + [[], exceptionName], + [{ }, exceptionName], + [undefined, exceptionName] + ]; + if (!isOptional) { + conversionTable.push([null, exceptionName]); + } + break; + case "array": + conversionTable = [ + [true, exceptionName], + [false, exceptionName], + [NaN, exceptionName], + [0, exceptionName], + ["", exceptionName], + ["TIZEN", exceptionName], + [{ }, exceptionName], + [function () { }, exceptionName], + [undefined, exceptionName] + ]; + if (!isOptional) { + conversionTable.push([null, exceptionName]); + } + break; + case "dictionary": + conversionTable = [ + [true, exceptionName], + [false, exceptionName], + [NaN, exceptionName], + [0, exceptionName], + ["", exceptionName], + ["TIZEN", exceptionName], + [undefined, exceptionName] + ]; + if (!isOptional) { + conversionTable.push([null, exceptionName]); + } + break; + default: + assert_unreached("Fix your test. Wrong conversionType '" + conversionType + "'."); + }; + + return conversionTable; +} + + +function assert_type(obj, type, description) { + var org_type = type, prop_name, prop_type, prop_value; + + type = _resolve_registered_type(type); + + if (typeof (type) === 'string') { + type = type.toLowerCase(); + switch (type) { + case 'object': + case 'string': + case 'number': + case 'function': + case 'boolean': + case 'undefined': + case 'xml': + assert_equals(typeof (obj), type, description); + break; + case 'null': + assert_true(obj === null, description); + break; + case 'array': + assert_true(Array.isArray(obj), description); + break; + case 'date': + assert_true(obj instanceof Date, description); + break; + case 'byte': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_BYTE, description + " - value too low."); + assert_less_than_equal(obj, MAX_BYTE, description + " - value too high."); + assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer."); + break; + case 'octet': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_OCTET, description + " - value too low."); + assert_less_than_equal(obj, MAX_OCTET, description + " - value too high."); + assert_equals(obj % 1, 0, description + " - value is not an integer."); + break; + case 'short': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_SHORT, description + " - value too low."); + assert_less_than_equal(obj, MAX_SHORT, description + " - value too high."); + assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer."); + break; + case 'unsigned short': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_UNSIGNED_SHORT, description + " - value too low."); + assert_less_than_equal(obj, MAX_UNSIGNED_SHORT, description + " - value too high."); + assert_equals(obj % 1, 0, description + " - value is not an integer."); + break; + case 'long': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_LONG, description + " - value too low."); + assert_less_than_equal(obj, MAX_LONG, description + " - value too high."); + assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer."); + break; + case 'unsigned long': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_UNSIGNED_LONG, description + " - value too low."); + assert_less_than_equal(obj, MAX_UNSIGNED_LONG, description + " - value too high."); + assert_equals(obj % 1, 0, description + " - value is not an integer."); + break; + case 'long long': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_LONG_LONG, description + " - value too low."); + assert_less_than_equal(obj, MAX_LONG_LONG, description + " - value too high."); + assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer."); + break; + case 'unsigned long long': + assert_equals(typeof (obj), 'number', description); + assert_greater_than_equal(obj, MIN_UNSIGNED_LONG_LONG, description + " - value too low."); + assert_less_than_equal(obj, MAX_UNSIGNED_LONG_LONG, description + " - value too high."); + assert_equals(obj % 1, 0, description + " - value is not an integer."); + break; + case 'double': + assert_equals(typeof (obj), 'number', description); + break; + default: + assert_unreached('Fix your test. Wrong type \'' + org_type + '\''); + } + } else if (typeof (type) === 'function') { + assert_true(obj instanceof type, description); + } else if (typeof (type) === 'object') { + for (prop_name in type) { + prop_type = type[prop_name]; + if (prop_type === 'function') { + assert_inherits(obj, prop_name); + assert_equals(typeof obj[prop_name], prop_type, 'Object should have method ' + prop_name); + } else { + assert_own_property(obj, prop_name); + } + } + } else { + assert_unreached('Fix your test. Wrong type ' + org_type); + } +} + +function register_type(alias, type_spec) { + _registered_types[alias] = type_spec; +} + +/** + * Method to check if attribute is const. + * Example usage: + * check_const(tizen.bluetooth.deviceMinor, 'TOY_DOLL', 0x03, 'number', 0x29B); + * + * @param obj object to test which has const attribute + * @param attributeName attribute name. + * @param expectedValue expected value of provided attribute name + * @param expectedType expected type of provided attribute name + * @param valueToAssign value to assign in order to check if attribute value can be modified + */ +function check_const(obj, attributeName, expectedValue, expectedType, valueToAssign) { + var tmp; + if (expectedValue === valueToAssign) { + assert_unreached("Fix your test. The same values given for " + attributeName + + " in 'value' and 'valueToSet' arguments."); + } + if (typeof (attributeName) === "string") { + assert_true(attributeName in obj, "Name " + attributeName + " doesn't exist in provided object."); + assert_equals(obj[attributeName], expectedValue, "Value of " + attributeName + " is diffrent."); + if (typeof (expectedType) !== "undefined") { + if (expectedValue === null) { + assert_type(obj[attributeName], "object", "Type of " + attributeName + " is different."); + } else { + assert_type(obj[attributeName], expectedType, "Type of " + attributeName + " is different."); + } + } else { + assert_unreached("Fix your test. Wrong type " + expectedType); + } + tmp = obj[attributeName]; + obj[attributeName] = valueToAssign; + assert_equals(obj[attributeName], tmp, attributeName + " can be modified."); + } else { + assert_unreached("Fix your test. Wrong type of name " + typeof (attributeName)); + } +} + +/** + * Method to check if attribute is readonly. + * Example usage: + * check_readonly(statusNotification, "postedTime", null, 'object', new Date()); + * + * @param obj object to test which has readonly attribute + * @param attributeName attribute name. + * @param expectedValue expected value of provided attribute name + * @param expectedType expected type of provided attribute name + * @param valueToAssign value to assign in order to check if attribute value can be modified + */ +function check_readonly(obj, attributeName, expectedValue, expectedType, valueToAssign) { + check_const(obj, attributeName, expectedValue, expectedType, valueToAssign); +} + +/** + * Method to check if attribute can be set to null. + * Example usage: + * check_not_nullable(syncInfo, "mode"); + * + * @param obj object to test which has not nullable attribute + * @param attributeName attribute name. + */ +function check_not_nullable(obj, attributeName) +{ var old_value = obj[attributeName]; + obj[attributeName] = null; + assert_not_equals(obj[attributeName], null, "Attribute " + attributeName + " can be set to null."); + obj[attributeName] = old_value; +} + +/** + * Method to check NoInterfaceObject + * Example usage: + * check_no_interface_object("BluetoothAdapter") + * + * @param interfaceName interface name + */ +function check_no_interface_object(interfaceName) { + assert_throws({name: "TypeError"}, function () { + tizen[interfaceName](); + },"Wrong call as a function"); + assert_throws({name: "TypeError"}, function () { + new tizen[interfaceName](); + },"Wrong call as a new function"); + assert_throws({name: "TypeError"}, function () { + ({}) instanceof tizen[interfaceName]; + },"instanceof exception"); + assert_equals(tizen[interfaceName], undefined, interfaceName + " is not undefined."); +} + + +/** + * Method to check Constructors + * Example usage: + * check_constructor("BluetoothAdapter") + * + * @param constructorName constructor name + */ + +function check_constructor(constructorName) { + assert_true(constructorName in tizen, "No " + constructorName + " in tizen."); + assert_false({} instanceof tizen[constructorName],"Custom object is not instance of " + constructorName); + assert_throws({ + name: "TypeError" + }, function () { + tizen[constructorName](); + }, "Constructor called as function."); +} + +/** + * Method to check if given method can be overridden in a given object - (TEMPORARY REMOVED). + * That method also checks if given method exists in a given object. + * Example usage: + * check_method_exists(tizen.notification, "get"); + * + * @param obj object with method + * @param methodName name of the method to check. + */ +function check_method_exists(obj, methodName) { + assert_type(obj[methodName], 'function', "Method does not exist."); +} + +/** + * Method to check extensibility of given object. + * Method checks if new attribute and method can be added. + * Example usage: + * check_extensibility(tizen.notification); + * + * @param obj object to check + */ +function check_extensibility(obj) { + var dummyAttribute = "dummyAttributeValue", dummyMethodResult = "dummyMethodResultValue"; + obj.newDummyMethod = function() { + return dummyMethodResult; + } + assert_equals(obj.newDummyMethod(), dummyMethodResult, "Incorrect result from added method."); + + obj.newDummyAttribute = dummyAttribute; + assert_equals(obj.newDummyAttribute, dummyAttribute, "Incorrect result from added attribute."); +} + +/** + * Method to check if attribute can be modify. + * Example usage: + * check_attr(downloadRequest, "fileName", default_val, "string", "file_name.html"); + * + * @param obj object to test which has not readonly attribute + * @param attributeName attribute name. + * @param expectedValue expected value of provided attribute name + * @param expectedType expected type of provided attribute name + * @param valueToAssign value to assign in order to check if attribute value can be modified + */ +function check_attribute(obj, attributeName, expectedValue, expectedType, valueToAssign) { + if (expectedValue === valueToAssign) { + assert_unreached("Fix your test. The same values given for " + attributeName + + " in 'value' and 'valueToSet' arguments."); + } + if (typeof (attributeName) === "string") { + assert_true(attributeName in obj, "Name " + attributeName + " doesn't exist in provided object."); + assert_equals(obj[attributeName], expectedValue, "Value of " + attributeName + " is diffrent."); + if (typeof (expectedType) !== "undefined") { + if (expectedValue === null) { + assert_type(obj[attributeName], "object", "Type of " + attributeName + " is different."); + } else { + assert_type(obj[attributeName], expectedType, "Type of " + attributeName + " is different."); + } + } else { + assert_unreached("Fix your test. Wrong type " + expectedType); + } + obj[attributeName] = valueToAssign; + assert_equals(obj[attributeName], valueToAssign, attributeName + " can be modified."); + } else { + assert_unreached("Fix your test. Wrong type of name " + typeof (attributeName)); + } +} + +/** + * Method to check if whole array can be overwritten with an invalid value. + * Sample usage: + * check_invalid_array_assignments(message, "to", false); + * + * @param obj object which has the array as its property + * @param array name of the array to check + * @param isNullable indicates if the array can be null + */ +function check_invalid_array_assignments(obj, array, isNullable) { + var args = [undefined, true, false, NaN, 0, "TIZEN", {}, function () {}], + val = obj[array], i; + + if (!isNullable) { + obj[array] = null; + assert_not_equals(obj[array], null, "Non-nullable array was set to null"); + assert_type(obj[array], "array", "Non-nullable array type changed after assigning null"); + assert_equals(obj[array].toString(), val.toString(), "Non-nullable array contents changed after assigning null"); + } + + for (i = 0 ; i < args.length ; i++) { + obj[array] = args[i]; + assert_type(obj[array], "array", "Array type changed after assigning an invalid value"); + assert_equals(obj[array].toString(), val.toString(), "Array contents changed after assigning an invalid value"); + } +} + +/** + * Method to check if an object can be overwritten with an invalid value. + * Sample usage: + * check_invalid_object_assignments(message, "body", false); + * + * @param parentObj object which has the 'obj' object as its property + * @param obj name of the object to check + * @param isNullable indicates if the object can be null + */ +function check_invalid_obj_assignments(parentObj, obj, isNullable) { + var args = [undefined, true, false, NaN, 0, "TIZEN", function () {}], + val = parentObj[obj], i; + + if (!isNullable) { + parentObj[obj] = null; + assert_equals(parentObj[obj], val, "Non-nullable obj was modified after assigning null"); + } + + for (i = 0 ; i < args.length ; i++) { + parentObj[obj] = args[i]; + assert_equals(parentObj[obj], val, "The object was set to " + args[i]); + } +} + +/** + * Method to validate conversion for listeners. + * Example usage: + * incorrectListeners = getListenerConversionExceptions(["oninstalled", "onupdated", "onuninstalled"]); + * for(i = 0; i < incorrectListeners.length; i++) { + * packageInformationEventCallback = incorrectListeners[i][0]; + * exceptionName = incorrectListeners[i][1]; + * assert_throws({name : exceptionName}, + * function () { + * tizen.package.setPackageInfoEventListener(packageInformationEventCallback); + * }, exceptionName + " should be thrown - given incorrect successCallback."); + * } + * + * + * @param callbackNames Array with names + * @returns {Array} table of tables which contain incorrect listener (index 0) and exceptionName (index 1) + * + */ +function getListenerConversionExceptions(callbackNames) { + var result = [], conversionTable, i, j, listenerName; + conversionTable = getTypeConversionExceptions("functionObject", false); + + for (i = 0; i < callbackNames.length; i++) { + for (j = 0; j < conversionTable.length; j++) { + listenerName = {}; + listenerName[callbackNames[i]] = conversionTable[j][0]; + result.push([listenerName, conversionTable[j][1]]); + } + } + + return result; +} diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_getRequestedAppControl.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_getRequestedAppControl.js new file mode 100755 index 000000000..eabd4e16c --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_getRequestedAppControl.js @@ -0,0 +1,54 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + Junghyuk Park + +*/ + +test(function () { + var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(), + appControl; + + assert_true("appControl" in reqAppControl, "RequestedApplicationControl should have appControl attribute"); + + appControl = reqAppControl.appControl; + assert_type(appControl, "object", "incorrect type of appControl"); + assert_true("operation" in appControl, "ApplicationControl should have operation attribute"); + assert_true("uri" in appControl, "ApplicationControl should have uri attribute"); + assert_true("mime" in appControl, "ApplicationControl should have mime attribute"); + assert_true("category" in appControl, "ApplicationControl should have category attribute"); + assert_true("data" in appControl, "ApplicationControl should have data attribute"); + + reqAppControl.appControl = { + operation: "dummy", + uri: "dummy", + mime: "dummy", + category: "dummy", + data: [] + }; + + assert_equals(reqAppControl.appControl.operation, appControl.operation, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.uri, appControl.uri, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.mime, appControl.mime, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.category, appControl.category, "appControl is not readonly"); + if(appControl.data) { + assert_equals(reqAppControl.appControl.data.length, appControl.data.length, "appControl is not readonly"); + } else { + assert_equals(reqAppControl.appControl.data, appControl.data, "appControl is not readonly"); + } + +}, "Application_getRequestedAppControl"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_getRequestedAppControl_extra_argument.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_getRequestedAppControl_extra_argument.js new file mode 100755 index 000000000..c3c0c430e --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_getRequestedAppControl_extra_argument.js @@ -0,0 +1,57 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + Junghyuk Park + +*/ + +test(function () { + var i, argumentsList = [null, undefined, "string", 1, false, ["one", "two"], {arg: 1}, function () {}], + reqAppControl, appControl; + + for (i = 0; i < argumentsList.length; i++) { + reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(argumentsList[i]), + assert_true("appControl" in reqAppControl, "RequestedApplicationControl should have appControl attribute"); + + appControl = reqAppControl.appControl; + assert_type(appControl, "object", "incorrect type of appControl"); + assert_true("operation" in appControl, "ApplicationControl should have operation attribute"); + assert_true("uri" in appControl, "ApplicationControl should have uri attribute"); + assert_true("mime" in appControl, "ApplicationControl should have mime attribute"); + assert_true("category" in appControl, "ApplicationControl should have category attribute"); + assert_true("data" in appControl, "ApplicationControl should have data attribute"); + + reqAppControl.appControl = new tizen.ApplicationControl( + "operation", + "uri", + "mime", + "category", + [ new tizen.ApplicationControlData("key", [ "value" ]) ] + ); + + assert_equals(reqAppControl.appControl.operation, appControl.operation, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.uri, appControl.uri, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.mime, appControl.mime, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.category, appControl.category, "appControl is not readonly"); + if(appControl.data) { + assert_equals(reqAppControl.appControl.data.length, appControl.data.length, "appControl is not readonly"); + } else { + assert_equals(reqAppControl.appControl.data, appControl.data, "appControl is not readonly"); + } + } + +}, "Application_getRequestedAppControl_extra_argument"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_hide.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_hide.js new file mode 100755 index 000000000..b4de28751 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_hide.js @@ -0,0 +1,28 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + Mariusz Polasinski + +*/ + +test(function () { + var retVal, currentApplication = tizen.application.getCurrentApplication(); + + retVal = currentApplication.hide(); + assert_equals(retVal, undefined, "wrong returned value"); + +}, "Application_hide"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_hide_extra_argument.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_hide_extra_argument.js new file mode 100755 index 000000000..b4c041575 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/Application_hide_extra_argument.js @@ -0,0 +1,26 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + +*/ + +test(function () { + var currentApplication = tizen.application.getCurrentApplication(); + + checkExtraArgument(currentApplication, "hide"); + +}, "Application_hide_extra_argument"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_appControl_attribute.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_appControl_attribute.js new file mode 100755 index 000000000..10adb3bfd --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_appControl_attribute.js @@ -0,0 +1,53 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + +*/ + +test(function () { + var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(), + appControl; + + assert_true("appControl" in reqAppControl, "RequestedApplicationControl should have appControl attribute"); + + appControl = reqAppControl.appControl; + assert_type(appControl, "object", "incorrect type of appControl"); + assert_true("operation" in appControl, "ApplicationControl should have operation attribute"); + assert_true("uri" in appControl, "ApplicationControl should have uri attribute"); + assert_true("mime" in appControl, "ApplicationControl should have mime attribute"); + assert_true("category" in appControl, "ApplicationControl should have category attribute"); + assert_true("data" in appControl, "ApplicationControl should have data attribute"); + + reqAppControl.appControl = { + operation: "dummy", + uri: "dummy", + mime: "dummy", + category: "dummy", + data: [] + }; + + assert_equals(reqAppControl.appControl.operation, appControl.operation, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.uri, appControl.uri, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.mime, appControl.mime, "appControl is not readonly"); + assert_equals(reqAppControl.appControl.category, appControl.category, "appControl is not readonly"); + if(appControl.data) { + assert_equals(reqAppControl.appControl.data.length, appControl.data.length, "appControl is not readonly"); + } else { + assert_equals(reqAppControl.appControl.data, appControl.data, "appControl is not readonly"); + } + +}, "RequestedApplicationControl_appControl_attribute"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_callerAppId_attribute.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_callerAppId_attribute.js new file mode 100755 index 000000000..0bab55488 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_callerAppId_attribute.js @@ -0,0 +1,27 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + +*/ + +test(function () { + var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(); + + assert_true("callerAppId" in reqAppControl, "RequestedApplicationControl should have callerAppId attribute"); + check_readonly(reqAppControl, "callerAppId", reqAppControl.callerAppId, "string", "dummy"); + +}, "RequestedApplicationControl_callerAppId_attribute"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_extend.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_extend.js new file mode 100755 index 000000000..f6406274b --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_extend.js @@ -0,0 +1,24 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + +*/ + +test(function () { + var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(); + check_extensibility(reqAppControl); +}, "RequestedApplicationControl_extend"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyFailure_exist.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyFailure_exist.js new file mode 100755 index 000000000..891e06683 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyFailure_exist.js @@ -0,0 +1,24 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + +*/ + +test(function () { + var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(); + check_method_exists(reqAppControl, "replyFailure"); +}, "RequestedApplicationControl_replyFailure_exist"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyResult_data_TypeMismatch.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyResult_data_TypeMismatch.js new file mode 100755 index 000000000..c0fa2f495 --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyResult_data_TypeMismatch.js @@ -0,0 +1,36 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + +*/ + +test(function () { + var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(), + conversionTable, exceptionName, i, data; + + conversionTable = getTypeConversionExceptions("array", true); + + for(i = 0; i < conversionTable.length; i++) { + data = conversionTable[i][0]; + exceptionName = conversionTable[i][1]; + + assert_throws({name: exceptionName}, + function () { + reqAppControl.replyResult(data); + }, exceptionName + " should be thrown."); + } +}, "RequestedApplicationControl_replyResult_data_TypeMismatch"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyResult_exist.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyResult_exist.js new file mode 100755 index 000000000..76de5d4fc --- /dev/null +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/TCTAppControl/tests/RequestedApplicationControl_replyResult_exist.js @@ -0,0 +1,28 @@ +/* +Copyright (c) 2013 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Krzysztof Lachacz + +*/ + +test(function () { + var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(); + + assert_true("replyResult" in reqAppControl, "reqAppControl should have replyResult method"); + assert_type(reqAppControl.replyResult, "function", "incorrect type of replyResult"); + + check_method_exists(reqAppControl, "replyResult"); +}, "RequestedApplicationControl_replyResult_exist"); diff --git a/common/tct-appcontrol-tizen-tests/appcontrol/support/appcontrol_common.js b/common/tct-appcontrol-tizen-tests/appcontrol/support/appcontrol_common.js index 5823e58a6..86a531a6b 100755 --- a/common/tct-appcontrol-tizen-tests/appcontrol/support/appcontrol_common.js +++ b/common/tct-appcontrol-tizen-tests/appcontrol/support/appcontrol_common.js @@ -1,62 +1,62 @@ -/* -Copyright (c) 2014 Samsung Electronics Co., Ltd. - -Licensed under the Apache License, Version 2.0 (the License); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Authors: - Piotr Szydelko - Mohammad Ashekur Rahman - -*/ - -var TEST_DIR = ""; -var TEST_URL_HTTP = "http://www.tizen.org"; -var TEST_URL_HTTPS = "https://www.tizen.org"; - -var TEST_FILE_IMAGE_BMP = ""; -var TEST_FILE_IMAGE_JPEG = ""; -var TEST_FILE_IMAGE_GIF = ""; -var TEST_FILE_IMAGE_PNG = ""; -var TEST_FILE_SOUND_AAC = ""; -var TEST_FILE_SOUND_AMR = ""; -var TEST_FILE_SOUND_MP3 = ""; -var TEST_FILE_SOUND_WAV = ""; -var TEST_FILE_VIDEO_MP4 = ""; -var TEST_FILE_VIDEO_3GPP = ""; - -function checkAppControls(this_test, appControls) { - var onSuccess, onError, currentAppControl, appControlDesc; - - onSuccess = this_test.step_func(function(informationArray, appControl) { - assert_true(Array.isArray(informationArray), "informationArray should be Array"); - assert_not_equals(informationArray.length, 0, "Number of application found for: " + appControlDesc); - - // check next from the list or report success if list is empty - if(appControls.length === 0) { - return this_test.done(); - } else { - checkAppControls(this_test, appControls); - } - }); - - onError = this_test.step_func(function(error) { - assert_unreached("onError: " + error.message); - }); - - currentAppControl = appControls.shift(); - appControlDesc = '(' + currentAppControl.operation + " " + currentAppControl.uri + " " + currentAppControl.mime + ')'; - - tizen.application.findAppControl(currentAppControl, onSuccess, onError); -} -document.write(''); -document.write(''); +/* +Copyright (c) 2014 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the License); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Authors: + Piotr Szydelko + Mohammad Ashekur Rahman + +*/ + +var TEST_DIR = ""; +var TEST_URL_HTTP = "http://www.tizen.org"; +var TEST_URL_HTTPS = "https://www.tizen.org"; + +var TEST_FILE_IMAGE_BMP = ""; +var TEST_FILE_IMAGE_JPEG = ""; +var TEST_FILE_IMAGE_GIF = ""; +var TEST_FILE_IMAGE_PNG = ""; +var TEST_FILE_SOUND_AAC = ""; +var TEST_FILE_SOUND_AMR = ""; +var TEST_FILE_SOUND_MP3 = ""; +var TEST_FILE_SOUND_WAV = ""; +var TEST_FILE_VIDEO_MP4 = ""; +var TEST_FILE_VIDEO_3GPP = ""; + +function checkAppControls(this_test, appControls) { + var onSuccess, onError, currentAppControl, appControlDesc; + + onSuccess = this_test.step_func(function(informationArray, appControl) { + assert_true(Array.isArray(informationArray), "informationArray should be Array"); + assert_not_equals(informationArray.length, 0, "Number of application found for: " + appControlDesc); + + // check next from the list or report success if list is empty + if(appControls.length === 0) { + return this_test.done(); + } else { + checkAppControls(this_test, appControls); + } + }); + + onError = this_test.step_func(function(error) { + assert_unreached("onError: " + error.message); + }); + + currentAppControl = appControls.shift(); + appControlDesc = '(' + currentAppControl.operation + " " + currentAppControl.uri + " " + currentAppControl.mime + ')'; + + tizen.application.findAppControl(currentAppControl, onSuccess, onError); +} +document.write(''); +document.write(''); diff --git a/common/tct-appcontrol-tizen-tests/inst.wgt.py b/common/tct-appcontrol-tizen-tests/inst.wgt.py index b72850d63..9b91907fb 100755 --- a/common/tct-appcontrol-tizen-tests/inst.wgt.py +++ b/common/tct-appcontrol-tizen-tests/inst.wgt.py @@ -10,7 +10,6 @@ import string from optparse import OptionParser, make_option import configparser - SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PKG_NAME = os.path.basename(SCRIPT_DIR) PARAMETERS = None diff --git a/common/tct-appcontrol-tizen-tests/suite.json b/common/tct-appcontrol-tizen-tests/suite.json index 945e536b3..07d433181 100755 --- a/common/tct-appcontrol-tizen-tests/suite.json +++ b/common/tct-appcontrol-tizen-tests/suite.json @@ -1,55 +1,75 @@ -{ - "pkg-blacklist": [ - "config.xml", - "pack.py", - "testcase.xsl", - "testresult.xsl", - "tests.css", - "icon.png", - "manifest.json", - "suite.json", - "inst.*" - ], - "pkg-list": { - "wgt": { - "blacklist": [ - "appcontrol", - "COPYING", - "LICENSE.*", - "NOTICE", - "resources", - "tests.full.xml", - "webrunner" - ], - "copylist": { - "inst.wgt.py": "inst.py", - "tests.xml": "tests.xml" - }, - "pkg-app": { - "blacklist": [], - "sign-flag": "true", - "sign-flag": "true" - } - }, - "xpk": { - "blacklist": [ - "appcontrol", - "COPYING", - "LICENSE.*", - "NOTICE", - "resources", - "tests.full.xml", - "webrunner" - ], - "copylist": { - "inst.xpk.py": "inst.py", - "tests.xml": "tests.xml" - }, - "pkg-app": { - "blacklist": [], - "sign-flag": "true" - } - } - }, - "pkg-name": "tct-appcontrol-tizen-tests" +{ + "pkg-blacklist": [ + "config.xml", + "pack.py", + "testcase.xsl", + "testresult.xsl", + "tests.css", + "icon.png", + "manifest.json", + "suite.json", + "inst.*" + ], + "pkg-list": { + "wgt": { + "blacklist": [ + "appcontrol", + "COPYING", + "LICENSE.*", + "NOTICE", + "resources", + "tests.full.xml", + "webrunner" + ], + "copylist": { + "inst.wgt.py": "inst.py", + "tests.xml": "tests.xml" + }, + "subapp-list": { + "appcontrol/support/TCTAppControl": { + "app-name": "TCTAppControl", + "blacklist": [ + "manifest.json" + ], + "install-path": "apps", + "sign-flag": "true" + } + }, + "pkg-app": { + "blacklist": [], + "sign-flag": "true", + "sign-flag": "true" + } + }, + "xpk": { + "blacklist": [ + "appcontrol", + "COPYING", + "LICENSE.*", + "NOTICE", + "resources", + "tests.full.xml", + "webrunner" + ], + "subapp-list": { + "appcontrol/support/TCTAppControl": { + "app-name": "TCTAppControl", + "blacklist": [ + "manifest.json" + ], + "install-path": "apps", + "sign-flag": "true" + } + }, + "copylist": { + "inst.xpk.py": "inst.py", + "tests.xml": "tests.xml" + }, + "pkg-app": { + "blacklist": [], + "sign-flag": "true" + } + } + }, + "pkg-name": "tct-appcontrol-tizen-tests" } \ No newline at end of file