mirror of
https://github.com/servo/servo.git
synced 2025-09-03 11:38:22 +01:00
Update web-platform-tests to revision a46616a5b18e83587ddbbed756c7b96cbb4b015d
This commit is contained in:
parent
3f07cfec7c
commit
578498ba24
4001 changed files with 159517 additions and 30260 deletions
947
tests/wpt/web-platform-tests/wai-aria/scripts/ATTAcomm.js
Normal file
947
tests/wpt/web-platform-tests/wai-aria/scripts/ATTAcomm.js
Normal file
|
@ -0,0 +1,947 @@
|
|||
/* globals Promise, window, done, assert_true, on_event, promise_test */
|
||||
|
||||
/**
|
||||
* Creates an ATTAcomm object. If the parameters are supplied
|
||||
* it sets up event listeners to send the test data to an ATTA if one
|
||||
* is available. If the ATTA does not respond, it will assume the test
|
||||
* is being done manually and the results are being entered in the
|
||||
* parent test window.
|
||||
*
|
||||
* @constructor
|
||||
* @param {object} params
|
||||
* @param {string} [params.test] - object containing JSON test definition
|
||||
* @param {string} [params.testFile] - URI of a file with JSON test definition
|
||||
* @param {string} params.ATTAuri - URI to use to exercise the window
|
||||
* @event DOMContentLoaded Calls go once DOM is fully loaded
|
||||
* @returns {object} Reference to the new object
|
||||
*
|
||||
*/
|
||||
|
||||
function ATTAcomm(params) {
|
||||
'use strict';
|
||||
|
||||
this.Params = null; // parameters passed in
|
||||
this.Promise = null; // master Promise that resolves when intialization is complete
|
||||
this.Properties = null; // testharness_properties from the opening window
|
||||
this.Tests = null; // test object being processed
|
||||
this.testName = ""; // name of test being run
|
||||
this.log = ""; // a buffer to capture log information for debugging
|
||||
this.startReponse = {}; // startTest response will go in here for debugging
|
||||
|
||||
this.loading = true;
|
||||
|
||||
this.timeout = 5000;
|
||||
|
||||
var pending = [] ;
|
||||
|
||||
// set up in case DOM finishes loading early
|
||||
pending.push(new Promise(function(resolve) {
|
||||
on_event(document, "DOMContentLoaded", function() {
|
||||
resolve(true);
|
||||
}.bind(this));
|
||||
}.bind(this)));
|
||||
|
||||
// if we are under runner, then there are props in the parent window
|
||||
//
|
||||
// if "output" is set in that, then pause at the end of running so the output
|
||||
// can be analyzed. @@@TODO@@@
|
||||
if (window && window.opener && window.opener.testharness_properties) {
|
||||
this.Properties = window.opener.testharness_properties;
|
||||
}
|
||||
|
||||
this.Params = params;
|
||||
|
||||
if (this.Params.hasOwnProperty("ATTAuri")) {
|
||||
this.ATTAuri = this.Params.ATTAuri;
|
||||
} else {
|
||||
this.ATTAuri = "http://localhost:4119";
|
||||
}
|
||||
|
||||
if (this.Params.hasOwnProperty("title")) {
|
||||
this.testName = this.Params.title;
|
||||
}
|
||||
|
||||
// start by loading the test (it might be inline, but
|
||||
// loadTest deals with that
|
||||
pending.push(this.loadTest(params)
|
||||
.then(function(tests) {
|
||||
// if the test is NOT an object, turn it into one
|
||||
if (typeof tests === 'string') {
|
||||
tests = JSON.parse(tests) ;
|
||||
}
|
||||
|
||||
this.Tests = tests;
|
||||
|
||||
}.bind(this)));
|
||||
|
||||
this.Promise = new Promise(function(resolve, reject) {
|
||||
// once the DOM and the test is loaded... set us up
|
||||
Promise.all(pending)
|
||||
.then(function() {
|
||||
// Everything is loaded
|
||||
this.loading = false ;
|
||||
// run the automated tests (or setup for manual testing)
|
||||
this.go();
|
||||
resolve(this);
|
||||
}.bind(this))
|
||||
.catch(function(err) {
|
||||
// loading the components failed somehow - report the errors and mark the test failed
|
||||
test( function() {
|
||||
assert_true(false, "Loading of test components failed: " +JSON.stringify(err)) ;
|
||||
}, "Loading test components");
|
||||
this.dumpLog();
|
||||
done() ;
|
||||
reject("Loading of test components failed: "+JSON.stringify(err));
|
||||
return ;
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
ATTAcomm.prototype = {
|
||||
|
||||
/**
|
||||
* go sets up the connection to the ATTA
|
||||
*
|
||||
* If that succeeds and the tests in this test file have methods for
|
||||
* the API supported by the ATTA, then it automatically runs those tests.
|
||||
*
|
||||
* Otherwise it sets up for manualt testing.
|
||||
*/
|
||||
go: function() {
|
||||
'use strict';
|
||||
// everything is ready. Let's talk to the ATTA
|
||||
this.startTest().then(function(res) {
|
||||
|
||||
// start was successful - iterate over steps
|
||||
var API = res.body.API;
|
||||
|
||||
var subtestsForAPI = false;
|
||||
|
||||
// check main and potentially nested lists of tests for
|
||||
// tests with this API. If any step is missing this API
|
||||
// mapping, then we need to be manual
|
||||
this.Tests.forEach(function(subtest) {
|
||||
if (subtest.hasOwnProperty("test") &&
|
||||
subtest.test.hasOwnProperty(API)) {
|
||||
// there is at least one subtest for this API so
|
||||
// this is a test that needs to be looked at by an atta
|
||||
subtestsForAPI = true;
|
||||
} else if (Array.isArray(subtest)) {
|
||||
subtest.forEach(function(st) {
|
||||
if (st.hasOwnProperty("test") &&
|
||||
st.test.hasOwnProperty(API)) {
|
||||
subtestsForAPI = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (subtestsForAPI) {
|
||||
this.runTests(API, this.Tests)
|
||||
.then(function() {
|
||||
// the tests all ran; close it out
|
||||
this.endTest().then(function() {
|
||||
this.dumpLog();
|
||||
done();
|
||||
}.bind(this));
|
||||
}.bind(this))
|
||||
.catch(function(err) {
|
||||
this.endTest().then(function() {
|
||||
this.dumpLog();
|
||||
done();
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
} else {
|
||||
// we don't know this API for this test
|
||||
// but we ARE talking to an ATTA; skip this test
|
||||
this.dumpLog();
|
||||
if (window.opener && window.opener.completion_callback) {
|
||||
window.opener.completion_callback([], { status: 3, message: "No steps for AT API " + API } );
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
// this.setupManualTest("Unknown AT API: " + API);
|
||||
}
|
||||
}.bind(this))
|
||||
.catch(function(res) {
|
||||
// startTest failed so just sit and wait for a manual test to occur
|
||||
if (res.timeout || res.status === 102) {
|
||||
this.setupManualTest("No response from ATTA at " + this.ATTAuri);
|
||||
} else if (res.status === 200 ) {
|
||||
this.setupManualTest(res.message);
|
||||
} else if (res.statusText === "No response from ATTA") {
|
||||
this.setupManualTest("");
|
||||
} else {
|
||||
this.setupManualTest("Error from ATTA: " + res.status + ": " + res.statusText);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
runTests: function(API, collection) {
|
||||
// this method returns a promise
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
// accumulate promises; complete when done
|
||||
var pending = [];
|
||||
var testCount = 0;
|
||||
|
||||
this.sendEvents(API, collection)
|
||||
.then(function(eventStatus) {
|
||||
|
||||
/* Loop strategy...
|
||||
*
|
||||
* If the the step is a 'test' then push it into the pending queue as a promise
|
||||
*
|
||||
* If the step is anything else, then if there is anything in pending, wait on it
|
||||
* Once it resolves, clear the queue and then execute the other step.
|
||||
*
|
||||
*/
|
||||
collection.forEach(function(subtest) {
|
||||
// what "type" of step in the sequence is this?
|
||||
var theType = "test" ;
|
||||
if (Array.isArray(subtest)) {
|
||||
// it is a group
|
||||
Promise.all(pending).then(function() {
|
||||
pending = [];
|
||||
// recursively run the tests
|
||||
pending.push(this.runTests(API, subtest));
|
||||
}.bind(this));
|
||||
} else if (subtest.hasOwnProperty("type")) {
|
||||
theType = subtest.type;
|
||||
}
|
||||
testCount++;
|
||||
if (theType === "test") {
|
||||
// this is a set of assertions that should be evaluated
|
||||
pending.push(this.runTest(testCount, API, subtest));
|
||||
} else if (theType === "script") {
|
||||
Promise.all(pending).then(function() {
|
||||
pending = [];
|
||||
// execute the script
|
||||
this.runScript(testCount, subtest);
|
||||
}.bind(this));
|
||||
} else if (theType === "attribute") {
|
||||
Promise.all(pending).then(function() {
|
||||
pending = [];
|
||||
// raise the event
|
||||
this.handleAttribute(testCount, subtest);
|
||||
}.bind(this));
|
||||
// } else {
|
||||
} else if (theType === "event") {
|
||||
Promise.all(pending).then(function() {
|
||||
pending = [];
|
||||
// raise the event
|
||||
this.raiseEvent(testCount, subtest);
|
||||
}.bind(this));
|
||||
// } else {
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
Promise.all(pending)
|
||||
.then(function() {
|
||||
// this collection all ran
|
||||
if (eventStatus !== "NOEVENTS") {
|
||||
// there were some events at the beginning
|
||||
this.sendStopListen().then(function() {
|
||||
resolve(true);
|
||||
});
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
setupManualTest: function(message) {
|
||||
// if we determine the test should run manually, then expose all of the conditions that are
|
||||
// in the TEST data structure so that a human can to the inspection and calculate the result
|
||||
//
|
||||
'use strict';
|
||||
|
||||
var ref = document.getElementById("manualMode");
|
||||
if (ref) {
|
||||
// we have a manualMode block. Populate it
|
||||
var content = "<h2>Manual Mode Enabled</h2><p>"+message+"</p>";
|
||||
if (this.Tests.hasOwnProperty("description")) {
|
||||
content += "<p>" + this.Tests.description + "</p>";
|
||||
}
|
||||
var theTable = "<table id='steps'><tr><th>Step</th><th>Type</th><th>Element ID</th><th>Assertions</th></tr>";
|
||||
this.Tests.forEach(function(subtest) {
|
||||
var type = "test";
|
||||
if (subtest.hasOwnProperty("type")) {
|
||||
type = subtest.type;
|
||||
}
|
||||
var id = "" ;
|
||||
if (subtest.hasOwnProperty("element")) {
|
||||
id = subtest.element;
|
||||
}
|
||||
theTable += "<tr><td class='step'>" + subtest.title +"</td>";
|
||||
theTable += "<td class='type'>" + type + "</td>";
|
||||
theTable += "<td class='element'>" + id +"</td>";
|
||||
|
||||
// now what do we put over here? depends on the type
|
||||
if (type === "test") {
|
||||
// it is a test; dump the assertions
|
||||
theTable += "<td>" + this.buildAssertionTable(subtest.test) + "</td>";
|
||||
} else if (type === "attribute" ) {
|
||||
if (subtest.hasOwnProperty("attribute") && subtest.hasOwnProperty("value") && subtest.hasOwnProperty("element")) {
|
||||
if (subtest.value === "none") {
|
||||
theTable += "<td>Remove attribute <code>" + subtest.attribute + "</code> from the element with ID <code>" + subtest.element + "</code></td>";
|
||||
} else {
|
||||
theTable += "<td>Set attribute <code>" + subtest.attribute + "</code> on the element with ID <code>" + subtest.element + "</code> to the value <code>" + subtest.value + "</code></td>";
|
||||
}
|
||||
}
|
||||
} else if (type === "event" ) {
|
||||
// it is some events
|
||||
if (subtest.hasOwnProperty("event") && subtest.hasOwnProperty("element")) {
|
||||
theTable += "<td>Send event <code>" + subtest.event + "</code> to the element with ID <code>" + subtest.element + "</code></td>";
|
||||
}
|
||||
} else if (type === "script" ) {
|
||||
// it is a script fragment
|
||||
theTable += "<td>Script: " + subtest.script + "</td>";
|
||||
} else {
|
||||
theTable += "<td>Unknown type: " + type + "</td>";
|
||||
}
|
||||
theTable += "</tr>";
|
||||
|
||||
|
||||
}.bind(this));
|
||||
|
||||
theTable += "</table>";
|
||||
ref.innerHTML = content + theTable ;
|
||||
}
|
||||
},
|
||||
|
||||
buildAssertionTable: function(asserts) {
|
||||
"use strict";
|
||||
var output = "<table class='api'><tr><th>API Name</th><th colspan='4'>Assertions</th></tr>";
|
||||
var APIs = [] ;
|
||||
for (var k in asserts) {
|
||||
if (asserts.hasOwnProperty(k)) {
|
||||
APIs.push(k);
|
||||
}
|
||||
}
|
||||
|
||||
APIs.sort().forEach(function(theAPI) {
|
||||
var rows = asserts[theAPI] ;
|
||||
var height = rows.length;
|
||||
output += "<tr><td rowspan='" + height + "' class='apiName'>"+theAPI+"</td>";
|
||||
var lastRow = rows.length - 1;
|
||||
rows.forEach(function(theRow, index) {
|
||||
var span = 4 - theRow.length;
|
||||
var colspan = span ? " colspan='"+span+"'" : "";
|
||||
theRow.forEach(function(item) {
|
||||
output += "<td" + colspan + ">" + item + "</td>";
|
||||
});
|
||||
output += "</tr>";
|
||||
if (index < lastRow) {
|
||||
output += "<tr>";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
output += "</table>";
|
||||
return output;
|
||||
},
|
||||
|
||||
// eventList - find the events for an API
|
||||
//
|
||||
// @param {string} API
|
||||
// @param {array} collection - a collection of tests
|
||||
// @returns {array} list of event names
|
||||
|
||||
eventList: function(API, collection) {
|
||||
var eventHash = {};
|
||||
|
||||
if (!API || API === "") {
|
||||
return [];
|
||||
}
|
||||
|
||||
collection.forEach(function(subtest) {
|
||||
if (subtest.hasOwnProperty("test") &&
|
||||
subtest.test.hasOwnProperty(API)) {
|
||||
// this is a subtest for this API; look at the events
|
||||
subtest.test[API].forEach(function(assert) {
|
||||
// look for event names
|
||||
if (assert[0] === "event" && assert[1] === "type" && assert[2] === "is") {
|
||||
eventHash[assert[3]] = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return Object.keys(eventHash);
|
||||
},
|
||||
|
||||
// handleAttribute - set or clear an attribute
|
||||
/**
|
||||
* @param {integer} testNum - The subtest number
|
||||
* @param {object} subtest - attribute information to set
|
||||
*/
|
||||
handleAttribute: function(testNum, subtest) {
|
||||
"use strict";
|
||||
if (subtest) {
|
||||
if (subtest.hasOwnProperty("attribute") && subtest.hasOwnProperty("element") && subtest.hasOwnProperty("value")) {
|
||||
// update an attribute
|
||||
try {
|
||||
var node = document.getElementById(subtest.element);
|
||||
if (node) {
|
||||
if (subtest.value === "none") {
|
||||
// remove this attribute
|
||||
node.removeAttribute(subtest.attribute);
|
||||
} else if (subtest.value === '""') {
|
||||
node.setAttribute(subtest.attribute, "");
|
||||
} else if (subtest.value.match(/^"/) ) {
|
||||
var v = subtest.value;
|
||||
v = v.replace(/^"/, '');
|
||||
v = v.replace(/"$/, '');
|
||||
node.setAttribute(subtest.attribute, v);
|
||||
} else {
|
||||
node.setAttribute(subtest.attribute, subtest.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
test(function() {
|
||||
assert_true(false, "Subtest attribute failed to update: " +e);
|
||||
}, "Attribute subtest " + testNum);
|
||||
}
|
||||
} else {
|
||||
test(function() {
|
||||
var err = "";
|
||||
if (!subtest.hasOwnProperty("attribute")) {
|
||||
err += "Attribute subtest has no attribute property; ";
|
||||
} else if (!subtest.hasOwnProperty("value")) {
|
||||
err += "Attribute subtest has no value property; ";
|
||||
} else if (!subtest.hasOwnProperty("element")) {
|
||||
err += "Attribute subtest has no element property; ";
|
||||
}
|
||||
assert_true(false, err);
|
||||
}, "Attribute subtest " + testNum );
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
|
||||
|
||||
// raiseEvent - throw an event at an item
|
||||
/**
|
||||
* @param {integer} testNum - The subtest number
|
||||
* @param {object} subtest - event information to throw
|
||||
*/
|
||||
raiseEvent: function(testNum, subtest) {
|
||||
"use strict";
|
||||
var evt;
|
||||
if (subtest) {
|
||||
var kp = function(target, key) {
|
||||
evt = document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent ("keypress", true, true, window,
|
||||
0, 0, 0, 0, 0, "e".charCodeAt(0));
|
||||
target.dispatchEvent(evt);
|
||||
};
|
||||
if (subtest.hasOwnProperty("event") && subtest.hasOwnProperty("element")) {
|
||||
// throw an event
|
||||
try {
|
||||
var node = document.getElementById(subtest.element);
|
||||
if (node) {
|
||||
if (subtest.event === "focus") {
|
||||
node.focus();
|
||||
} else if (subtest.event === "select") {
|
||||
node.click();
|
||||
} else if (subtest.event.startsWith('key:')) {
|
||||
var key = subtest.event.replace('key:', '');
|
||||
evt = new KeyboardEvent("keypress", { "key": key});
|
||||
node.dispatchEvent(evt);
|
||||
} else {
|
||||
evt = new Event(subtest.element);
|
||||
node.dispatchEvent(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
test(function() {
|
||||
assert_true(false, "Subtest event failed to dispatch: " +e);
|
||||
}, "Event subtest " + testNum);
|
||||
}
|
||||
} else {
|
||||
test(function() {
|
||||
var err = "";
|
||||
if (!subtest.hasOwnProperty("event")) {
|
||||
err += "Event subtest has no event property; ";
|
||||
} else if (!subtest.hasOwnProperty("element")) {
|
||||
err += "Event subtest has no element property; ";
|
||||
}
|
||||
assert_true(false, err);
|
||||
}, "Event subtest " + testNum );
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
// runScript - run a script in the context of the window
|
||||
/**
|
||||
* @param {integer} testNum - The subtest number
|
||||
* @param {object} subtest - script and related information
|
||||
*/
|
||||
runScript: function(testNum, subtest) {
|
||||
"use strict";
|
||||
if (subtest) {
|
||||
if (subtest.hasOwnProperty("script") && typeof subtest.script === "string") {
|
||||
try {
|
||||
/* jshint evil:true */
|
||||
eval(subtest.script);
|
||||
}
|
||||
catch (e) {
|
||||
test(function() {
|
||||
assert_true(false, "Subtest script " + subtest.script + " failed to evaluate: " +e);
|
||||
}, "Event subtest " + testNum);
|
||||
}
|
||||
} else {
|
||||
test(function() {
|
||||
assert_true(false, "Event subtest has no script property");
|
||||
}, "Event subtest " + testNum );
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
// runTest - process subtest
|
||||
/**
|
||||
* @param {integer} testNum - The subtest number
|
||||
* @param {string} API - name of the API being tested
|
||||
* @param {object} subtest - a subtest to run; contains 'title', 'element', and
|
||||
* 'test array'
|
||||
* @returns {Promise} - a Promise that resolves when the test completes
|
||||
*/
|
||||
runTest: function(testNum, API, subtest) {
|
||||
'use strict';
|
||||
|
||||
var data = {
|
||||
"title" : subtest.title,
|
||||
"id" : subtest.element,
|
||||
"data": this.normalize(subtest.test[API])
|
||||
};
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
var ANNO = this;
|
||||
if (subtest.test[API]) {
|
||||
// we actually have a test to run
|
||||
promise_test(function() {
|
||||
// force a resolve of the promise regardless
|
||||
this.add_cleanup(function() { resolve(true); });
|
||||
return ANNO.sendTest(data)
|
||||
.then(function(res) {
|
||||
if (typeof res.body === "object" && res.body.hasOwnProperty("status")) {
|
||||
// we got some sort of response
|
||||
if (res.body.status === "OK") {
|
||||
// the test ran - yay!
|
||||
var messages = "";
|
||||
var thisResult = null;
|
||||
var theLog = "";
|
||||
var assertionCount = 0;
|
||||
res.body.results.forEach( function (a) {
|
||||
if (typeof a === "object") {
|
||||
// we have a result for this assertion
|
||||
// first, what is the assertion?
|
||||
var aRef = data.data[assertionCount];
|
||||
var assertionText = '"' + aRef.join(" ") +'"';
|
||||
|
||||
if (a.hasOwnProperty("log") && a.log !== null && a.log !== '' ) {
|
||||
// there is log data - save it
|
||||
theLog += "\n--- Assertion " + assertionCount + " ---";
|
||||
theLog += "\nAssertion: " + assertionText + "\nLog data: "+a.log ;
|
||||
}
|
||||
|
||||
// is there a message?
|
||||
var theMessage = "";
|
||||
if (a.hasOwnProperty("message")) {
|
||||
theMessage = a.message;
|
||||
}
|
||||
if (!a.hasOwnProperty("result")) {
|
||||
messages += "ATTA did not report a result " + theMessage + "; ";
|
||||
} else if (a.result === "ERROR") {
|
||||
messages += "ATTA reported ERROR with message: " + theMessage + "; ";
|
||||
} else if (a.result === "FAIL") {
|
||||
thisResult = false;
|
||||
messages += assertionText + " failed " + theMessage + "; ";
|
||||
} else if (a.result === "PASS" && thisResult === null) {
|
||||
// if we got a pass and there was no other result thus far
|
||||
// then we are passing
|
||||
thisResult = true;
|
||||
}
|
||||
}
|
||||
assertionCount++;
|
||||
});
|
||||
if (theLog !== "") {
|
||||
ANNO.saveLog("runTest", theLog, subtest);
|
||||
}
|
||||
if (thisResult !== null) {
|
||||
assert_true(thisResult, messages);
|
||||
} else {
|
||||
assert_true(false, "ERROR: No results reported from ATTA; " + messages);
|
||||
}
|
||||
} else if (res.body.status === "ERROR") {
|
||||
assert_true(false, "ATTA returned ERROR with message: " + res.body.statusText);
|
||||
} else {
|
||||
assert_true(false, "ATTA returned unknown status " + res.body.status + " with message: " + res.body.statusText);
|
||||
}
|
||||
} else {
|
||||
// the return wasn't an object!
|
||||
assert_true(false, "ATTA failed to return a result object: returned: "+JSON.stringify(res));
|
||||
}
|
||||
});
|
||||
}, subtest.name );
|
||||
} else {
|
||||
// there are no test steps for this API. fake a subtest result
|
||||
promise_test(function() {
|
||||
// force a resolve of the promise regardless
|
||||
this.add_cleanup(function() { resolve(true); });
|
||||
return new Promise(function(innerResolve) {
|
||||
innerResolve(true);
|
||||
})
|
||||
.then(function(res) {
|
||||
var theLog = "\nSUBTEST NOTRUN: No assertions for API " + API + "\n";
|
||||
if (theLog !== "") {
|
||||
ANNO.saveLog("runTest", theLog, subtest);
|
||||
}
|
||||
assert_false(true, "NOTRUN: No assertion for API " + API);
|
||||
});
|
||||
}, subtest.name );
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// loadTest - load a test from an external JSON file
|
||||
//
|
||||
// returns a promise that resolves with the contents of the
|
||||
// test
|
||||
|
||||
loadTest: function(params) {
|
||||
'use strict';
|
||||
|
||||
if (params.hasOwnProperty('stepFile')) {
|
||||
// the test is referred to by a file name
|
||||
return this._fetch("GET", params.stepFile);
|
||||
} // else
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (params.hasOwnProperty('steps')) {
|
||||
resolve(params.steps);
|
||||
} else {
|
||||
reject("Must supply a 'steps' or 'stepFile' parameter");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/* dumpLog - put log information into the log div on the page if it exists
|
||||
*/
|
||||
|
||||
dumpLog: function() {
|
||||
'use strict';
|
||||
if (this.log !== "") {
|
||||
var ref = document.getElementById("ATTAmessages");
|
||||
if (ref) {
|
||||
// we have a manualMode block. Populate it
|
||||
var content = "<h2>Logging information recorded</h2>";
|
||||
if (this.startResponse && this.startResponse.hasOwnProperty("API")) {
|
||||
content += "<h3>ATTA Information</h3>";
|
||||
content += "<pre>"+JSON.stringify(this.startResponse, null, " ")+"</pre>";
|
||||
}
|
||||
content += "<textarea rows='50' style='width:100%'>"+this.log+"</textarea>";
|
||||
ref.innerHTML = content ;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* saveLog - capture logging information so that it can be displayed on the page after testing is complete
|
||||
*
|
||||
* @param {string} caller name
|
||||
* @param {string} log message
|
||||
* @param {object} subtest
|
||||
*/
|
||||
|
||||
saveLog: function(caller, message, subtest) {
|
||||
'use strict';
|
||||
|
||||
if (typeof message === "string" && message !== "") {
|
||||
this.log += "============================================================\n";
|
||||
this.log += "Message from " + caller + "\n";
|
||||
if (subtest && typeof subtest === "object") {
|
||||
var API = this.startResponse.API;
|
||||
this.log += "\n SUBTEST TITLE: " + subtest.title;
|
||||
this.log += "\n SUBTEST ELEMENT: " + subtest.element;
|
||||
this.log += "\n SUBTEST DATA: " + JSON.stringify(subtest.test[API]);
|
||||
this.log += "\n\n";
|
||||
}
|
||||
this.log += message;
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
// startTest - send the test start message
|
||||
//
|
||||
// @returns {Promise} resolves if the start is successful, or rejects with
|
||||
|
||||
startTest: function() {
|
||||
'use strict';
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
var params = {
|
||||
test: this.testName || window.title,
|
||||
url: document.location.href
|
||||
};
|
||||
|
||||
this._fetch("POST", this.ATTAuri + "/start", null, params)
|
||||
.then(function(res) {
|
||||
if (res.body.hasOwnProperty("status")) {
|
||||
if (res.body.status === "READY") {
|
||||
this.startResponse = res.body;
|
||||
if (res.body.hasOwnProperty("log")) {
|
||||
// there is some logging data - capture it
|
||||
this.saveLog("startTest", res.body.log);
|
||||
}
|
||||
// the system is ready for us - is it really?
|
||||
if (res.body.hasOwnProperty("API")) {
|
||||
resolve(res);
|
||||
} else {
|
||||
res.message = "No API in response from ATTA";
|
||||
reject(res);
|
||||
}
|
||||
} else {
|
||||
// the system reported something else - fail out with the statusText as a result
|
||||
res.message = "ATTA reported an error: " + res.body.statusText;
|
||||
reject(res);
|
||||
}
|
||||
} else {
|
||||
res.message = "ATTA did not report a status";
|
||||
reject(res);
|
||||
}
|
||||
}.bind(this))
|
||||
.catch(function(res) {
|
||||
reject(res);
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// sendEvents - send the list of events the ATTA needs to listen for
|
||||
//
|
||||
// @param {string} API
|
||||
// @param {array} collection - a list of tests
|
||||
// @returns {Promise} resolves if the message is successful, or rejects with
|
||||
|
||||
sendEvents: function(API, collection) {
|
||||
'use strict';
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
var eList = this.eventList(API, collection) ;
|
||||
if (eList && eList.length) {
|
||||
var params = {
|
||||
events: eList
|
||||
};
|
||||
|
||||
this._fetch("POST", this.ATTAuri + "/startlisten", null, params)
|
||||
.then(function(res) {
|
||||
if (res.body.hasOwnProperty("status")) {
|
||||
if (res.body.status === "READY") {
|
||||
if (res.body.hasOwnProperty("log")) {
|
||||
// there is some logging data - capture it
|
||||
this.saveLog("sendEvents", res.body.log);
|
||||
}
|
||||
resolve(res.body.status);
|
||||
} else {
|
||||
// the system reported something else - fail out with the statusText as a result
|
||||
res.message = "ATTA reported an error: " + res.body.statusText;
|
||||
reject(res);
|
||||
}
|
||||
} else {
|
||||
res.message = "ATTA did not report a status";
|
||||
reject(res);
|
||||
}
|
||||
}.bind(this))
|
||||
.catch(function(res) {
|
||||
reject(res);
|
||||
});
|
||||
} else {
|
||||
// there are no events
|
||||
resolve("NOEVENTS");
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
sendStopListen: function() {
|
||||
'use strict';
|
||||
|
||||
return this._fetch("POST", this.ATTAuri + "/stoplisten", null, null);
|
||||
},
|
||||
|
||||
// sendTest - send test data to an ATTA and wait for a response
|
||||
//
|
||||
// returns a promise that resolves with the results of the test
|
||||
|
||||
sendTest: function(testData) {
|
||||
'use strict';
|
||||
|
||||
if (typeof testData !== "string") {
|
||||
testData = JSON.stringify(testData);
|
||||
}
|
||||
var ret = this._fetch("POST", this.ATTAuri + "/test", null, testData, true);
|
||||
ret.then(function(res) {
|
||||
if (res.body.hasOwnProperty("log")) {
|
||||
// there is some logging data - capture it
|
||||
this.saveLog("sendTest", res.body.log);
|
||||
}
|
||||
}.bind(this));
|
||||
return ret;
|
||||
},
|
||||
|
||||
endTest: function() {
|
||||
'use strict';
|
||||
|
||||
return this._fetch("GET", this.ATTAuri + "/end");
|
||||
},
|
||||
|
||||
/* normalize - ensure subtest data conforms to ATTA spec
|
||||
*/
|
||||
|
||||
normalize: function( data ) {
|
||||
'use strict';
|
||||
|
||||
var ret = [] ;
|
||||
|
||||
if (data) {
|
||||
data.forEach(function(assert) {
|
||||
var normal = [] ;
|
||||
// ensure if there is a value list it is compressed
|
||||
if (Array.isArray(assert)) {
|
||||
// we have an array
|
||||
normal[0] = assert[0];
|
||||
normal[1] = assert[1];
|
||||
normal[2] = assert[2];
|
||||
if ("string" === typeof assert[3] && assert[3].match(/^\[.*\]$/)) {
|
||||
// it is a string and matches the valuelist pattern
|
||||
normal[3] = assert[3].replace(/, +/, ',');
|
||||
} else {
|
||||
normal[3] = assert[3];
|
||||
}
|
||||
ret.push(normal);
|
||||
} else {
|
||||
ret.push(assert);
|
||||
}
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
// _fetch - return a promise after sending data
|
||||
//
|
||||
// Resolves with the returned information in a structure
|
||||
// including:
|
||||
//
|
||||
// xhr - a raw xhr object
|
||||
// headers - an array of headers sent in the request
|
||||
// status - the status code
|
||||
// statusText - the text of the return status
|
||||
// text - raw returned data
|
||||
// body - an object parsed from the returned content
|
||||
//
|
||||
|
||||
_fetch: function (method, url, headers, content, parse) {
|
||||
'use strict';
|
||||
if (method === null || method === undefined) {
|
||||
method = "GET";
|
||||
}
|
||||
if (parse === null || parse === undefined) {
|
||||
parse = true;
|
||||
}
|
||||
if (headers === null || headers === undefined) {
|
||||
headers = [];
|
||||
}
|
||||
|
||||
|
||||
// note that this Promise always resolves - there is no reject
|
||||
// condition
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
// this gets returned when the request completes
|
||||
var resp = {
|
||||
xhr: xhr,
|
||||
headers: null,
|
||||
status: 0,
|
||||
statusText: "",
|
||||
body: null,
|
||||
text: ""
|
||||
};
|
||||
|
||||
xhr.open(method, url);
|
||||
|
||||
// headers?
|
||||
headers.forEach(function(ref) {
|
||||
xhr.setRequestHeader(ref[0], ref[1]);
|
||||
});
|
||||
|
||||
//if (this.timeout) {
|
||||
// xhr.timeout = this.timeout;
|
||||
//}
|
||||
|
||||
xhr.ontimeout = function() {
|
||||
resp.timeout = this.timeout;
|
||||
resolve(resp);
|
||||
};
|
||||
|
||||
xhr.onerror = function() {
|
||||
if (this.status) {
|
||||
resp.status = this.status;
|
||||
resp.statusText = xhr.statusText;
|
||||
} else if (this.status === 0) {
|
||||
resp.status = 0;
|
||||
resp.statusText = "No response from ATTA";
|
||||
}
|
||||
reject(resp);
|
||||
};
|
||||
|
||||
xhr.onload = function () {
|
||||
resp.status = this.status;
|
||||
if (this.status >= 200 && this.status < 300) {
|
||||
var d = xhr.response;
|
||||
// return the raw text of the response
|
||||
resp.text = d;
|
||||
// we have it; what is it?
|
||||
if (parse) {
|
||||
try {
|
||||
d = JSON.parse(d);
|
||||
resp.body = d;
|
||||
}
|
||||
catch(err) {
|
||||
resp.body = null;
|
||||
}
|
||||
}
|
||||
resolve(resp);
|
||||
} else {
|
||||
reject({
|
||||
status: this.status,
|
||||
statusText: xhr.statusText
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (content !== null && content !== undefined) {
|
||||
if ("object" === typeof(content)) {
|
||||
xhr.send(JSON.stringify(content));
|
||||
} else if ("function" === typeof(content)) {
|
||||
xhr.send(content());
|
||||
} else if ("string" === typeof(content)) {
|
||||
xhr.send(content);
|
||||
}
|
||||
} else {
|
||||
xhr.send();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
// vim: set ts=2 sw=2:
|
Loading…
Add table
Add a link
Reference in a new issue