diff --git a/src/testObservability.js b/src/testObservability.js index 4735312..2ef09c3 100644 --- a/src/testObservability.js +++ b/src/testObservability.js @@ -94,6 +94,7 @@ class TestObservability { this._parentSettings?.testReportingOptions || this._parentSettings?.testObservabilityOptions || {}; + const testPlanId = helper.getTestPlanId(this._bstackOptions); const accessibility = helper.isAccessibilityEnabled(this._parentSettings); const accessibilityOptions = accessibility ? this._settings.accessibilityOptions || {} : {}; this._gitMetadata = await helper.getGitMetaData(); @@ -133,6 +134,12 @@ class TestObservability { test_orchestration: this.getTestOrchestrationBuildStartData(this._parentSettings) }; + if (testPlanId) { + data["test_management"] = { + "test_plan_id": testPlanId + } + } + const config = { auth: { username: this._user, diff --git a/src/utils/helper.js b/src/utils/helper.js index 3d84078..6678ea3 100644 --- a/src/utils/helper.js +++ b/src/utils/helper.js @@ -14,6 +14,7 @@ const {RERUN_FILE, DEFAULT_WAIT_TIMEOUT_FOR_PENDING_UPLOADS, DEFAULT_WAIT_INTERV const requestQueueHandler = require('./requestQueueHandler'); const Logger = require('./logger'); const LogPatcher = require('./logPatcher'); +const TEST_MANAGEMENT_TEST_PLAN_ID_ARG = 'browserstack.testManagementOptions.testPlanId'; const BSTestOpsPatcher = new LogPatcher({}); const sessions = {}; const {execSync} = require('child_process'); @@ -74,6 +75,77 @@ exports.getObservabilityKey = (config, bstackOptions={}) => { return process.env.BROWSERSTACK_ACCESS_KEY || config?.key || bstackOptions?.accessKey; }; +const normalizeTestPlanId = (testPlanId) => { + if (typeof testPlanId !== 'string') { + return undefined; + } + + const normalizedTestPlanId = testPlanId.trim(); + + return normalizedTestPlanId.length > 0 ? normalizedTestPlanId : undefined; +}; + +const readTestPlanIdFromCliArgs = (argv = process.argv) => { + const cliFlag = `--${TEST_MANAGEMENT_TEST_PLAN_ID_ARG}`; + + for (let index = 0; index < argv.length; index += 1) { + const currentArg = argv[index]; + + if (currentArg === cliFlag) { + const nextArg = argv[index + 1]; + + if (!nextArg || nextArg.startsWith('--')) { + return undefined; + } + + return nextArg; + } + + if (currentArg.startsWith(`${cliFlag}=`)) { + return currentArg.slice(cliFlag.length + 1) || undefined; + } + } + + return undefined; +}; + +const readTestPlanIdFromConfig = (bstackOptions = {}) => { + const nestedConfigTestPlanId = normalizeTestPlanId( + bstackOptions?.testManagementOptions?.testPlanId + ); + + if (nestedConfigTestPlanId) { + return nestedConfigTestPlanId; + } + + return normalizeTestPlanId(bstackOptions?.testPlanId); +}; + +/** + * Resolve the test plan id from supported Nightwatch client-side inputs. + * + * Priority order is CLI arguments, then environment variables, and finally + * BrowserStack config capabilities. + * + * @param {Record} [bstackOptions={}] BrowserStack capability options. + * @param {string[]} [argv=process.argv] CLI arguments to inspect. + * @param {NodeJS.ProcessEnv} [env=process.env] Environment variables to inspect. + * @returns {string|undefined} The resolved test plan id, if present. + */ +exports.getTestPlanId = (bstackOptions = {}, argv = process.argv, env = process.env) => { + const cliTestPlanId = normalizeTestPlanId(readTestPlanIdFromCliArgs(argv)); + if (cliTestPlanId) { + return cliTestPlanId; + } + + const envTestPlanId = normalizeTestPlanId(env.BROWSERSTACK_TEST_PLAN_ID); + if (envTestPlanId) { + return envTestPlanId; + } + + return readTestPlanIdFromConfig(bstackOptions); +}; + exports.isAppAutomate = () => { return process.env.BROWSERSTACK_APP_AUTOMATE === 'true'; };