/*!
 * OpenUI5
 * (c) Copyright 2009-2026 SAP SE or an SAP affiliate company.
 * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
 */

/* global QUnit */

// Load synchronously to avoid QUnit issue where tests run before QUnit is loaded
// Only load QUnit if it has not been loaded via script tag
if (!window.QUnit || !window.QUnit.test) {
	sap.ui.requireSync("sap/ui/thirdparty/qunit"); // legacy-relevant - sync fallback when caller did not load QUnit
}

// put qunit-coverage last so library files don't get measured  (we load StepDefinitions, even though we don't have to,
// so that it doesn't appear in the code coverage list, knowing that the user will need to load it)
sap.ui.define([
	"sap/base/Log",
	"sap/ui/test/gherkin/GherkinTestGenerator",
	"sap/ui/test/gherkin/StepDefinitions",
	"sap/ui/qunit/qunit-css",
	"sap/ui/qunit/qunit-junit",
	"sap/ui/qunit/qunit-coverage"
], function(Log, GherkinTestGenerator) {
	'use strict';

	/**
	 * Dynamically generates and executes QUnit tests based on a Gherkin feature file and step definitions
	 *
	 * Logs activity to QUnit, and some debug information to the console with the prefix "[GHERKIN]"
	 *
	 * @author Jonathan Benn
	 * @alias sap.ui.test.gherkin.qUnitTestHarness
	 * @namespace
	 * @since 1.40
	 * @public
	 * @static
	 */
	var qUnitTestHarness = {

		/**
		 * Dynamically generates and executes QUnit tests
		 *
		 * @param {object} args - the arguments to the function
		 * @param {string} args.featurePath - the path to the Gherkin feature file to parse, as an SAPUI5 module path. The
		 *                                    ".feature" extension is assumed and should not be included. See
		 *                                    {@link jQuery.sap.registerModulePath}
		 * @param {function} args.steps - the constructor function of type {@link sap.ui.test.gherkin.StepDefinitions}
		 * @public
		 * @throws {Error} if any parameters are invalid
		 * @function
		 * @static
		 */
		test: function(args) {

			// args is mandatory
			if (!args || typeof args !== "object") {
				throw new Error("qUnitTestHarness.test: input all arguments via a single object");
			}

			if (typeof args.featurePath !== "string" && !(args.featurePath instanceof String)) {
				throw new Error("qUnitTestHarness.test: parameter 'featurePath' must be a valid string");
			}

			if ((typeof args.steps !== "function") || !((new args.steps())._generateTestStep)) {
				throw new Error("qUnitTestHarness.test: parameter 'steps' must be a valid StepDefinitions constructor");
			}

			var oTestGenerator = new GherkinTestGenerator(args.featurePath, args.steps);
			var oFeatureTest = oTestGenerator.generate();

			QUnit.module(oFeatureTest.name, {
				beforeEach: function() {
					oTestGenerator.setUp();
				},
				afterEach: function() {
					oTestGenerator.tearDown();
				}
			});

			Log.info("[GHERKIN] Running feature: '" + oFeatureTest.name + "'");
			oFeatureTest.testScenarios.forEach(function(oTestScenario) {
				var fnTestFunction = (!oFeatureTest.skip && !oTestScenario.skip) ? QUnit.test : QUnit.skip;
				fnTestFunction(oTestScenario.name, function(assert) {
					Log.info("[GHERKIN] Running scenario: '" + oTestScenario.name + "'");
					oTestScenario.testSteps.forEach(function(oTestStep) {
						Log.info("[GHERKIN] Running step: text='" + oTestStep.text + "' regex='" + oTestStep.regex + "'");
						assert.ok(oTestStep.isMatch, oTestStep.text);
						if (oTestStep.isMatch) {
							QUnit.config.current.assertions.pop(); // don't break QUnit expect() behaviour
						}
						oTestGenerator.execute(oTestStep, assert);
					});
				});
			});
		}
	};

	return qUnitTestHarness;
}, /* bExport= */ true);
