UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

170 lines (150 loc) 6.01 kB
/*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ sap.ui.define([ "sap/base/util/deepExtend", "sap/ui/base/Object" ], function(deepExtend, BaseObject) { "use strict"; /** * Meant to be implemented/overridden by a child object. Specifically, the functions "init" and "closeApplication" * need to be overridden. * * @abstract * @class * Provides the interface between human and machine since a Gherkin feature file is human-readable * and the computer does not know how to execute its steps. * * It defines what each step in the Gherkin feature file will actually do when it is executed. * @author Rodrigo Jordao * @author Jonathan Benn * @extends sap.ui.base.Object * @alias sap.ui.test.gherkin.StepDefinitions * @since 1.40 * @public */ var StepDefinitions = BaseObject.extend("sap.ui.test.gherkin.StepDefinitions", /** @lends sap.ui.test.gherkin.StepDefinitions.prototype */ { constructor : function() { BaseObject.apply(this, arguments); /** * An array of StepDefinition objects, one of which is added to the array every time * the user calls the "register" method. Each StepDefinition object can generate one TestStep object. * * @type {StepDefinition[]} * @see #register * @see #_generateTestStep * @private */ this._aDefinitions = []; this.init(); }, /** * Registers the step definitions by calling the method "register". * * @see #register * @abstract * @public * @function * @static */ init : function() {}, /** * Closes the application and cleans up any mess made by the tests. To avoid erroneous exceptions during test * execution, make sure that it is safe to run this method even if the application was never started. * * @abstract * @public */ closeApplication: function() {}, /** * Registers a step definition. * * @param {RegExp} rRegex * The regular expression that matches the feature file step (with leading "Given", "When", * "Then", "But" or "*" removed). E.g. if the feature file has the step * "Then I should be served a coffee" it will be truncated to "I should be served a coffee" * and tested against "rRegex" to check for a match. The simple regular expression * /^I should be served a coffee$/i would match this text. The regular * expression can specify capturing groups, which will be passed as parameters to "fnFunc". * @param {function} fnFunc * the function to execute in the event that the regular expression matches. Receives * regular expression capturing groups as parameters in the same order that they are * specified in the regular expression. If a data table is specified for the step, it * will be passed as an additional final parameter. At execution time, all functions * within a particular scenario will execute within the same "this" context. * @throws {Error} if any parameters are invalid, or if method is called twice with the same value for 'rRegex' * @public */ register : function(rRegex, fnFunc) { if (!(rRegex instanceof RegExp)) { throw new Error("StepDefinitions.register: parameter 'rRegex' must be a valid RegExp object"); } if (typeof fnFunc !== "function") { throw new Error("StepDefinitions.register: parameter 'fnFunc' must be a valid Function"); } this._aDefinitions.forEach(function(oStepDef) { if (oStepDef.rRegex.source === rRegex.source) { throw new Error("StepDefinitions.register: Duplicate step definition '" + rRegex + "'"); } }); this._aDefinitions.push({ rRegex: rRegex, generateTestStep: function(oStep) { var aMatch = oStep.text.match(rRegex); if (!aMatch) { return {isMatch: false}; } var aParams = aMatch.slice(1); if (oStep.data) { aParams.push(deepExtend([], oStep.data)); } return { isMatch: true, text: oStep.text, regex: rRegex, parameters: aParams, func: fnFunc }; } }); }, /** * Searches through the registered step definitions, finds the one that matches the given feature file step and * generates a new TestStep object that combines the two. * * @param {object} oStep - a feature file step, optionally with an associated data table * @param {string} oStep.text - the feature file step's human-readable text * @returns {TestStep} a TestStep object * @see sap.ui.test.gherkin.GherkinTestGenerator * @private */ _generateTestStep : function(oStep) { var aMatchingTestSteps = []; // for each registered step definition this._aDefinitions.forEach(function(oDefinition) { // check if the inputed Feature file step matches the registered step definition var oTestStep = oDefinition.generateTestStep(oStep); if (oTestStep.isMatch) { aMatchingTestSteps.push(oTestStep); } }); // if a unique match was made if (aMatchingTestSteps.length === 1) { return aMatchingTestSteps[0]; // if an ambiguous match was made } else if (aMatchingTestSteps.length > 1) { var sListOfHumanReadableRegexes = aMatchingTestSteps .map(function(i){return "'" + i.regex + "'";}) // e.g. ['/regex1/', '/regex2/', '/regex3/'] .join(', ') // e.g. "'/regex1/', '/regex2/', '/regex3/'" .replace(/,([^,]*)$/, ' and$1'); // e.g. "'/regex1/', '/regex2/' and '/regex3/'" throw new Error( "Ambiguous step definition error: " + aMatchingTestSteps.length + " step definitions " + sListOfHumanReadableRegexes + " match the feature file step '" + oStep.text + "'"); } // else if no matches were made return { isMatch: false, text: "(NOT FOUND) " + oStep.text }; } }); return StepDefinitions; });