blob: 157654e8a89350c664e5dd47a92d7b8ce35f1ef8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
// TestSynchronizer Client
// Use to log assert pass/fails and notify mstest a test has completed execution
(function (window, undefined) {
var testRunId = "";
var serviceRoot = "./common/TestLogger.svc/";
var recording = null;
var recordingLength = 0;
var maxStringLength = 8192;
var maxPostLength = 2097152;
var callTestSynchronizer = function (methodName, parameterUrl) {
/** Invokes a function on the test synchronizer.
* @param {String} [partialUrl] -
* @returns {String} A response from the server, possibly null.
* If the recording variable is assigned, then the call is logged
* but nothing is invoked.
*/
var partialUrl;
if (testRunId) {
partialUrl = methodName + "?testRunId=" + testRunId + "&" + parameterUrl;
}
else {
partialUrl = methodName + "?" + parameterUrl;
}
var url = serviceRoot + partialUrl;
if (recording) {
if (url.length > maxStringLength) {
url = url.substr(0, maxStringLength);
}
recordingLength += url.length;
if (recordingLength > maxPostLength) {
submitRecording();
recording = [];
recordingLength = url.length;
}
recording.push(url);
return null;
}
var xhr;
if (window.XMLHttpRequest) {
xhr = new window.XMLHttpRequest();
} else {
xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
}
xhr.open("GET", url, false);
xhr.send();
return xhr.responseText;
};
var getLogPrefix = function (result) {
/** Returns the log prefix for a given result
* @param {Boolean} result - Whether the result is pass or fail. If null, the log line is assumed to be diagnostic
*/
return "[" + getShortDate() + "] " + (result === true ? "[PASS] " : (result === false ? "[FAIL] " : ""));
};
var getShortDate = function () {
/** Returns the current date and time formatted as "yyyy-mm-dd hh:mm:ss.nnn".*/
var padToLength = function (number, length) {
var result = number + "";
var lengthDiff = length - result.length;
for (var i = 0; i < lengthDiff; i++) {
result = "0" + result;
}
return result;
}
var date = new Date();
var day = padToLength(date.getDate(), 2);
var month = padToLength(date.getMonth() + 1, 2);
var year = date.getFullYear();
var hours = padToLength(date.getHours(), 2);
var minutes = padToLength(date.getMinutes(), 2);
var seconds = padToLength(date.getSeconds(), 2);
var milliseconds = padToLength(date.getMilliseconds(), 3);
return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + "." + milliseconds;
};
var submitRecording = function () {
var body = { urls: recording };
postToUrl("LogBatch", body);
};
var postToUrl = function (methodName, body) {
/** POSTs body to the designated methodName.
*/
var xhr;
if (window.XMLHttpRequest) {
xhr = new window.XMLHttpRequest();
} else {
xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
}
var url = serviceRoot + methodName;
xhr.open("POST", url, false);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(window.JSON.stringify(body));
if (xhr.status < 200 || xhr.status > 299) {
throw { message: "Unable to POST to url.\r\n" + xhr.responseText };
}
return xhr.responseText;
}
function LogAssert(result, message, name, expected, actual) {
var parameterUrl = "pass=" + result + "&message=" + encodeURIComponent(message) + "&name=" + encodeURIComponent(name);
if (!result) {
parameterUrl += "&actual=" + encodeURIComponent(actual) + "&expected=" + encodeURIComponent(expected);
}
callTestSynchronizer("LogAssert", parameterUrl);
}
function LogTestStart(name) {
callTestSynchronizer("LogTestStart", "name=" + encodeURIComponent(name) + "&startTime=" + encodeURIComponent(getShortDate()));
}
function LogTestDone(name, failures, total) {
callTestSynchronizer("LogTestDone", "name=" + encodeURIComponent(name) + "&failures=" + failures + "&total=" + total + "&endTime=" + encodeURIComponent(getShortDate()));
}
function TestCompleted(failures, total) {
return callTestSynchronizer("TestCompleted", "failures=" + failures + "&total=" + total);
}
var extractTestRunId = function () {
/** Extracts the testRunId value from the window query string.
* @returns {String} testRunId, possibly empty.
*/
var i, len;
var uri = window.location.search;
if (uri) {
var parameters = uri.split("&");
for (i = 0, len = parameters.length; i < len; i++) {
var index = parameters[i].indexOf("testRunId=");
if (index >= 0) {
return parameters[i].substring(index + "testRunId=".length);
}
}
}
return "";
};
var init = function (qunit) {
/** Initializes the test logger synchronizer.
* @param qunit - Unit testing to hook into.
* If there is no testRunId present, the QUnit functions are left as they are.</remarks>
*/
var logToConsole = function (context) {
if (window.console && window.console.log) {
window.console.log(context.result + ' :: ' + context.message);
}
};
testRunId = extractTestRunId();
if (!testRunId) {
qunit.log = logToConsole;
} else {
recording = [];
qunit.log = function (context) {
logToConsole(context);
var name = qunit.config.current.testName;
if (!(context.actual && context.expected)) {
context.actual = context.result;
context.expected = true;
}
LogAssert(context.result, getLogPrefix(context.result) + context.message, name, window.JSON.stringify(context.expected), window.JSON.stringify(context.actual));
};
qunit.testStart = function (context) {
LogTestStart(context.name);
};
qunit.testDone = function (context) {
LogTestDone(context.name, context.failed, context.total);
}
qunit.done = function (context) {
submitRecording();
recording = null;
var nextUrl = TestCompleted(context.failed, context.total);
nextUrl = JSON.parse(nextUrl).d;
if (nextUrl) {
window.location.href = nextUrl;
}
}
}
};
window.TestSynchronizer = {
init: init
};
})(window);