@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
293 lines (260 loc) • 10 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
/*global QUnit */
sap.ui.define([
'sap/ui/thirdparty/URI',
'sap/ui/test/Opa',
'sap/ui/test/Opa5',
"sap/ui/thirdparty/jquery"
], function(URI, Opa, Opa5, jQueryDOM) {
"use strict";
QUnit.begin(function (oDetails) {
Opa._usageReport.begin({uri: new URI().toString(), totalTests: oDetails.totalTests});
});
QUnit.moduleStart(function (oDetails) {
Opa._usageReport.moduleStart(oDetails);
});
QUnit.testStart(function () {
Opa._usageReport.testStart();
});
QUnit.testDone(function (oDetails) {
Opa._usageReport.testDone(oDetails);
var bQUnitTimeout = oDetails.assertions.some(function (oAssertion) {
return !oAssertion.result && oAssertion.message === "Test timed out";
});
if (bQUnitTimeout) {
Opa._stopQueue({qunitTimeout: QUnit.config.testTimeout / 1000});
}
});
QUnit.moduleDone(function (oDetails) {
Opa._usageReport.moduleDone(oDetails);
});
QUnit.done(function (oDetails) {
Opa._usageReport.done(oDetails);
});
/* When you require this file, it will also introduce global variables: opaTest, opaSkip and opaTodo.
* It will also alter some settings of QUnit.config - testTimout will be increased to 90 if you do not specify your own.
* QUnit.reorder will be set to false, because OPA tests are often depending on each other.
*/
// Export to global namespace to be backwards compatible
window.opaSkip = opaSkip;
window.opaTest = opaTest;
// QUnit.todo introduced in v2
window.opaTodo = QUnit.todo ? opaTodo : opaTest;
/**
* QUnit test adapter for OPA: add a test to be executed by QUnit
* Has the same signature as QUnit.test (QUnit version is also considered)
* Suggested usage:
* <pre><code>
* sap.ui.require(["sap/ui/test/Opa5", "sap/ui/test/opaQunit"], function (Opa5, opaTest) {
*
* Opa5.extendConfig({
* assertions: new Opa5({
* checkIfSomethingIsOk : function () {
* this.waitFor({
* success: function () {
* Opa5.assert.ok(true, "Everything is fine");
* }
* });
* }
* })
* });
*
* opaTest("Should test something", function (Given, When, Then) {
* // Implementation of the test
* Then.checkIfSomethingIsOk();
* });
*
* });
* </code></pre>
*
* @public
* @alias module:sap/ui/test/opaQunit
* @function
* @static
* @param {string} testName name of the QUnit test.
* @param {int|function} expected integer value only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
* If a function is passed instead, it is considered to be the callback parameter
* @param {function} callback the test function. Expects 3 arguments, in order:
* {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
* These arguments will be prefilled by OPA
* @param {boolean} async available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
*/
function opaTest() {
callQUnit("test", arguments, function (assert, fnDone) {
Opa._usageReport.opaEmpty();
resetOPA();
fnDone();
}, function (assert, fnDone, oOptions) {
Opa._usageReport.opaEmpty(oOptions);
// add the error message to QUnit test results
// will cause exception in case of QUnit timeout since the last test has already finished
// ("Cannot read property 'failedAssertions' of null")
assert.ok(false, oOptions.errorMessage);
resetOPA();
// let OPA finish before QUnit starts executing the next test
// call fnStart only if QUnit did not timeout
if (!oOptions.qunitTimeout) {
setTimeout(fnDone, 0);
}
});
}
/**
* QUnit test adapter for OPA: add a test to be executed by QUnit
* The test is expected to have at least one failing assertion during its run, or to timeout with either OPA or QUnit timeout
* Has the same signature as QUnit.todo (QUnit version is also considered)
*
* @public
* @function
* @static
* @param {string} testName name of the QUnit test.
* @param {int|function} expected integer value only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
* If a function is passed instead, it is considered to be the callback parameter
* @param {function} callback the test function. Expects 3 arguments, in order:
* {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
* These arguments will be prefilled by OPA
* @param {boolean} async available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
*/
function opaTodo() {
callQUnit("todo", arguments, function (assert, fnDone) {
resetOPA();
fnDone();
}, function (assert, fnDone, oOptions) {
if (oOptions.qunitTimeout) {
resetOPA();
} else {
// to pass the test, add error in case of OPA timeout
assert.ok(false, oOptions.errorMessage);
resetOPA();
// let OPA finish before QUnit starts executing the next test
// call fnStart only if QUnit did not timeout
setTimeout(fnDone, 0);
}
});
}
/**
* QUnit test adapter for OPA: add a test to be skipped by QUnit
* Has the same signature as QUnit.skip (QUnit version is also considered)
*
* @public
* @function
* @static
* @param {string} testName name of the QUnit test.
* @param {int|function} expected integer value only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
* If a function is passed instead, it is considered to be the callback parameter
* @param {function} callback the test function. Expects 3 arguments, in order:
* {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
* These arguments will be prefilled by OPA
* @param {boolean} async available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
*/
function opaSkip(testName, expected, callback, async) {
configQUnit();
var fnTestBody = function () {};
if (isQUnit2()) {
QUnit.skip(testName, fnTestBody);
} else {
QUnit.skip(testName, expected, fnTestBody, async);
}
}
// configure QUnit, modify test callback to include OPA start, and enqueue the test with QUnit
function callQUnit(sQUnitFn, aArgs, fnDone, fnFail) {
configQUnit();
// parse arguments passed to OPA adapter
var mTestBodyArgs = {
testName: aArgs[0],
expected: aArgs.length === 2 ? null : aArgs[1],
callback: aArgs.length === 2 ? aArgs[1] : aArgs[2],
async: aArgs[3]
};
if (isQUnit2() && typeof mTestBodyArgs.async !== "undefined") {
throw new Error("Qunit >=2.0 is used, which no longer supports the 'async' parameter for tests.");
}
// create and configure the callback to be executed by QUnit at test runtime
var fnTestBody = createTestBody(mTestBodyArgs, fnDone, fnFail);
// build arguments for the adapted QUnit function
var mQUnitFnArgs = [mTestBodyArgs.testName, fnTestBody, mTestBodyArgs.async];
if (!isQUnit2()) {
mQUnitFnArgs.splice(1, 0, mTestBodyArgs.expected);
}
// call adapted QUnit function
QUnit[sQUnitFn].apply(this, mQUnitFnArgs);
}
// include OPA configuration and queue execution in test callback
function createTestBody(mConfig, fnDone, fnFail) {
return function(assert) {
var fnAsync = assert.async();
Opa.config.testName = mConfig.testName;
Opa.assert = assert;
Opa5.assert = assert;
if (isQUnit2() && mConfig.expected !== null) {
assert.expect(mConfig.expected);
}
// fill in OPA queue
// preserve QUnit 'this' in order to access it from waitFor statements
mConfig.callback.call(this, Opa.config.arrangements, Opa.config.actions, Opa.config.assertions);
Opa.emptyQueue()
.done(function () {
fnDone(assert, fnAsync);
})
.fail(function (oOptions) {
fnFail(assert, fnAsync, oOptions);
});
};
}
function configQUnit() {
//Increase QUnit's timeout to 90 seconds to match default OPA timeouts
// is only done if there is no timeout or the timeout is the default of QUnit
if (!QUnit.config.testTimeout || QUnit.config.testTimeout === 30000) {
QUnit.config.testTimeout = 90000;
}
QUnit.config.reorder = false;
// better chance that screenshots will capture the current failure
QUnit.config.scrolltop = false;
}
function resetOPA() {
Opa.assert = undefined;
Opa5.assert = undefined;
}
function isQUnit2() {
return QUnit.test.length === 2;
}
QUnit.config.urlConfig.push({
id: "opaExecutionDelay",
value: {
400: "fast",
700: "medium",
1000: "slow"
},
label: "Opa speed",
tooltip: "Each waitFor will be delayed by a number of milliseconds. If it is not set Opa will execute the tests as fast as possible"
});
// synchronously hook QUnit custom async assertions from extension
Opa5._getEventProvider().attachEvent('onExtensionAfterInit',function(oEvent) {
var oParams = oEvent.getParameters();
if (oParams.extension.getAssertions) {
var oAssertions = oParams.extension.getAssertions();
jQueryDOM.each(oAssertions,function(sName,fnAssertion) {
QUnit.assert[sName] = function() {
var qunitThis = this;
// call the assertion in the app window
// assertion is async, push results when ready
var oAssertionPromise = fnAssertion.apply(oParams.appWindow, arguments)
.always(function (oResult) {
qunitThis.push(
oResult.result,
oResult.actual,
oResult.expected,
oResult.message
);
});
// schedule async assertion promise on waitFor flow so test waits till assertion is ready
Opa.config.assertions._schedulePromiseOnFlow(oAssertionPromise);
};
});
}
});
return opaTest;
});