diff --git a/CHANGELOG.md b/CHANGELOG.md index 78a6174..594668e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +### Added +- New API methods for scenario ### Fixed - Reporting of feature (suite) for parallel execution [#142](https://github.com/reportportal/agent-js-cucumber/issues/142). diff --git a/README.md b/README.md index 41edf0d..224c2e5 100644 --- a/README.md +++ b/README.md @@ -168,20 +168,23 @@ this.attach( ``` To send attachment to the launch just specify `entity: 'launch'` property. -Also `this.screenshot` and `this.launchScreenshot` methods can be used to take screenshots. +Also `this.screenshot`, `this.scenarioScreenshot` and `this.launchScreenshot` methods can be used to take screenshots. ```javascript Then(/^I should see my new task in the list$/, function(callback) { this.screenshot('This screenshot') .then(() => callback()) .catch((err) => callback(err)); + this.scenarioScreenshot('This is screenshot for scenario') + .then(() => callback()) + .catch((err) => callback(err)); this.launchScreenshot('This is screenshot for launch') .then(() => callback()) .catch((err) => callback(err)); }); ``` -`screenshot`/`launchScreenshot` function return promise fulfilled after `screenshot` is taken and image added to attachments. +`screenshot`/`scenarioScreenshot`/`launchScreenshot` function return promise fulfilled after `screenshot` is taken and image added to attachments. Handler will parse attachments and send corresponding log to the step item. ### Logs @@ -199,6 +202,19 @@ Then(/^I should see my new task in the list$/, function() { }); ``` +To report logs to the **scenario** you can use the next methods: + +```javascript +Then(/^I should see my new task in the list$/, function() { + this.scenarioInfo('This is Info Level log'); + this.scenarioDebug('This is Debug Level log'); + this.scenarioError('This is Error Level log'); + this.scenarioWarn('This is Warn Level log'); + this.scenarioTrace('This is Trace Level log'); + this.scenarioFatal('This is Fatal Level log'); +}); +``` + To report logs to the **launch** you can use the next methods: ```javascript @@ -216,7 +232,7 @@ Then(/^I should see my new task in the list$/, function() { Attributes for features and scenarios are parsed from @tags as `@key:value` pair. -To add attributes to the step items you can use the next method: +To add attributes to the **step items** you can use the next method: ```javascript Then(/^I should see my new task in the list$/, function() { @@ -224,13 +240,21 @@ Then(/^I should see my new task in the list$/, function() { }); ``` +To add attributes to the **scenario** you can use the next method: + +```javascript +Then(/^I should see my new task in the list$/, function() { + this.addScenarioAttributes([{ key: 'agent', value: 'cucumber' }]); +}); +``` + The attributes will be concatenated. ### Description Description for features and scenarios are parsed from their definition. -To add description to the items you can use the following method: +To add description to the **items** you can use the following method: ```javascript Then(/^I should see my new task in the list$/, function() { @@ -238,11 +262,19 @@ Then(/^I should see my new task in the list$/, function() { }); ``` +To add description to the **scenario** you can use the following method: + +```javascript +Then(/^I should see my new task in the list$/, function() { + this.addScenarioDescription('Scenario description.'); +}); +``` + The description will be concatenated. ### TestCaseId -To set test case id to the items you can use the following method: +To set test case id to the **items** you can use the following method: ```javascript Then(/^I should see my new task in the list$/, function() { @@ -250,6 +282,14 @@ Then(/^I should see my new task in the list$/, function() { }); ``` +To set test case id to the **scenario** you can use the following method: + +```javascript +Then(/^I should see my new task in the list$/, function() { + this.setScenarioTestCaseId('scenarioTestCaseId'); +}); +``` + ### Statuses The user can set the status of the item/launch directly depending on some conditions or behavior. @@ -268,7 +308,22 @@ Then(/^I should see my new task in the list$/, function() { }); ``` -To set status to the **item** you can use the next methods: +To set status to the **scenario** you can use the next methods: + +```javascript +Then(/^I should see my new task in the list$/, function() { + this.setScenarioStatusPassed(); + this.setScenarioStatusFailed(); + this.setScenarioStatusSkipped(); + this.setScenarioStatusStopped(); + this.setScenarioStatusInterrupted(); + this.setScenarioStatusCancelled(); + this.setScenarioStatusInfo(); + this.setScenarioStatusWarn(); +}); +``` + +To set status to the **launch** you can use the next methods: ```javascript Then(/^I should see my new task in the list$/, function() { diff --git a/modules/constants.js b/modules/constants.js index eb8fd5e..f649f34 100644 --- a/modules/constants.js +++ b/modules/constants.js @@ -40,7 +40,10 @@ const LOG_LEVELS = { WARN: 'WARN', }; -const RP_ENTITY_LAUNCH = 'launch'; +const RP_ENTITIES = { + LAUNCH: 'LAUNCH', + SCENARIO: 'SCENARIO', +}; const CUCUMBER_EVENTS = { GHERKIN_DOCUMENT: 'gherkin-document', @@ -77,10 +80,15 @@ const TEST_ITEM_TYPES = { }; const RP_EVENTS = { - TEST_CASE_ID: 'rp/testCaseId', - ATTRIBUTES: 'rp/attributes', - DESCRIPTION: 'rp/description', - STATUS: 'rp/status', + STEP_TEST_CASE_ID: 'rp/step/testCaseId', + STEP_ATTRIBUTES: 'rp/step/attributes', + STEP_DESCRIPTION: 'rp/step/description', + STEP_STATUS: 'rp/step/status', + SCENARIO_TEST_CASE_ID: 'rp/scenario/testCaseId', + SCENARIO_ATTRIBUTES: 'rp/scenario/attributes', + SCENARIO_DESCRIPTION: 'rp/scenario/description', + SCENARIO_STATUS: 'rp/scenario/status', + LAUNCH_STATUS: 'rp/launch/status', }; const TEST_STEP_FINISHED_RP_MESSAGES = { @@ -90,7 +98,7 @@ const TEST_STEP_FINISHED_RP_MESSAGES = { }; module.exports = { - RP_ENTITY_LAUNCH, + RP_ENTITIES, STATUSES, LOG_LEVELS, CUCUMBER_EVENTS, diff --git a/modules/cucumber-reportportal-formatter.js b/modules/cucumber-reportportal-formatter.js index 8918e0e..e59bee9 100644 --- a/modules/cucumber-reportportal-formatter.js +++ b/modules/cucumber-reportportal-formatter.js @@ -21,7 +21,7 @@ const utils = require('./utils'); const pjson = require('../package.json'); const { RP_EVENTS, - RP_ENTITY_LAUNCH, + RP_ENTITIES, LOG_LEVELS, STATUSES, CUCUMBER_MESSAGES, @@ -255,13 +255,13 @@ const createRPFormatterClass = (config) => scenarioCodeRefIndexValue && !isRetry ? `${currentNodeCodeRef} [${scenarioCodeRefIndexValue}]` : currentNodeCodeRef; - + const scenarioAttributes = utils.createAttributes(scenario.tags); const testData = { startTime: this.reportportal.helpers.now(), type: this.isScenarioBasedStatistics ? TEST_ITEM_TYPES.STEP : TEST_ITEM_TYPES.TEST, name: `${keyword}: ${name}`, description: scenario.description, - attributes: utils.createAttributes(scenario.tags), + attributes: scenarioAttributes, codeRef: scenarioCodeRef, retry: this.isScenarioBasedStatistics && attempt > 0, }; @@ -276,7 +276,11 @@ const createRPFormatterClass = (config) => } const parentId = ruleTempId || this.storage.getFeatureTempId(pickleFeatureUri); const { tempId } = this.reportportal.startTestItem(testData, launchTempId, parentId); - this.storage.setScenarioTempId(testCaseId, tempId); + this.storage.setScenario(testCaseId, { + tempId, + description: scenario.description, + attributes: scenarioAttributes, + }); this.storage.updateTestCase(testCaseId, { codeRef: scenarioCodeRef, }); @@ -336,22 +340,24 @@ const createRPFormatterClass = (config) => if (data) { const { testStepId, testCaseStartedId } = data; const testCaseId = this.storage.getTestCaseId(testCaseStartedId); + const scenario = this.storage.getScenario(testCaseId) || {}; const step = this.storage.getStep(testCaseId, testStepId); const dataObj = utils.getJSON(data.body); switch (data.mediaType) { - case RP_EVENTS.TEST_CASE_ID: { + case RP_EVENTS.STEP_TEST_CASE_ID: + case RP_EVENTS.STEP_STATUS: { this.storage.updateStep(testCaseId, testStepId, dataObj); break; } - case RP_EVENTS.ATTRIBUTES: { + case RP_EVENTS.STEP_ATTRIBUTES: { const savedAttributes = step.attributes || []; this.storage.updateStep(testCaseId, testStepId, { attributes: savedAttributes.concat(dataObj.attributes), }); break; } - case RP_EVENTS.DESCRIPTION: { + case RP_EVENTS.STEP_DESCRIPTION: { const savedDescription = step.description || ''; this.storage.updateStep(testCaseId, testStepId, { description: savedDescription @@ -360,31 +366,54 @@ const createRPFormatterClass = (config) => }); break; } - case RP_EVENTS.STATUS: { - if (dataObj.entity !== RP_ENTITY_LAUNCH) { - this.storage.updateStep(testCaseId, testStepId, dataObj); - } else { - this.customLaunchStatus = dataObj.status; - } + + case RP_EVENTS.SCENARIO_TEST_CASE_ID: + case RP_EVENTS.SCENARIO_STATUS: { + this.storage.updateScenario(testCaseId, dataObj); + break; + } + case RP_EVENTS.SCENARIO_ATTRIBUTES: { + const savedAttributes = scenario.attributes || []; + this.storage.updateScenario(testCaseId, { + attributes: savedAttributes.concat(dataObj.attributes), + }); + break; + } + case RP_EVENTS.SCENARIO_DESCRIPTION: { + const savedDescription = scenario.description || ''; + this.storage.updateScenario(testCaseId, { + description: savedDescription + ? `${savedDescription}
${dataObj.description}` + : dataObj.description, + }); + break; + } + + case RP_EVENTS.LAUNCH_STATUS: { + this.customLaunchStatus = dataObj.status; break; } + case 'text/plain': { const request = { time: this.reportportal.helpers.now(), }; - let tempStepId = this.storage.getStepTempId(testStepId); + let tempId = this.storage.getStepTempId(testStepId); if (dataObj) { request.level = dataObj.level; request.message = dataObj.message; - if (dataObj.entity === RP_ENTITY_LAUNCH) { - tempStepId = this.storage.getLaunchTempId(); + + if (dataObj.entity === RP_ENTITIES.LAUNCH) { + tempId = this.storage.getLaunchTempId(); + } else if (dataObj.entity === RP_ENTITIES.SCENARIO) { + tempId = this.storage.getScenarioTempId(testCaseId); } } else { request.level = LOG_LEVELS.DEBUG; request.message = data.body; } - this.reportportal.sendLog(tempStepId, request); + this.reportportal.sendLog(tempId, request); break; } default: { @@ -397,7 +426,7 @@ const createRPFormatterClass = (config) => name: fileName, }, }; - let tempStepId = this.storage.getStepTempId(testStepId); + let tempId = this.storage.getStepTempId(testStepId); if (dataObj) { if (dataObj.level) { @@ -405,8 +434,11 @@ const createRPFormatterClass = (config) => } request.message = dataObj.message; request.file.name = dataObj.message; - if (dataObj.entity === RP_ENTITY_LAUNCH) { - tempStepId = this.storage.getLaunchTempId(); + + if (dataObj.entity === RP_ENTITIES.LAUNCH) { + tempId = this.storage.getLaunchTempId(); + } else if (dataObj.entity === RP_ENTITIES.SCENARIO) { + tempId = this.storage.getScenarioTempId(testCaseId); } } const fileObj = { @@ -414,7 +446,7 @@ const createRPFormatterClass = (config) => type: data.mediaType, content: (dataObj && dataObj.data) || data.body, }; - this.reportportal.sendLog(tempStepId, request, fileObj); + this.reportportal.sendLog(tempId, request, fileObj); break; } } @@ -544,11 +576,22 @@ const createRPFormatterClass = (config) => const testCaseId = this.storage.getTestCaseId(testCaseStartedId); const testCase = this.storage.getTestCase(testCaseId); - const scenarioTempId = this.storage.getScenarioTempId(testCaseId); + const { + tempId: scenarioTempId, + status: scenarioStatus, + testCaseId: customTestCaseId, + attributes, + description, + } = this.storage.getScenario(testCaseId); this.reportportal.finishTestItem(scenarioTempId, { endTime: this.reportportal.helpers.now(), - ...(this.isScenarioBasedStatistics && { status: testCase.status || STATUSES.PASSED }), + ...(this.isScenarioBasedStatistics && { + status: scenarioStatus || testCase.status || STATUSES.PASSED, + }), + ...(this.isScenarioBasedStatistics && customTestCaseId && { testCaseId: customTestCaseId }), + ...(attributes && { attributes }), + ...(description && { description }), }); // finish RULE if it's exist and if it's last scenario @@ -575,7 +618,7 @@ const createRPFormatterClass = (config) => this.storage.removeTestCaseStartedId(testCaseStartedId); this.storage.removeSteps(testCaseId); this.storage.removeTestCase(testCaseId); - this.storage.removeScenarioTempId(testCaseStartedId); + this.storage.removeScenario(testCaseStartedId); } const { uri: pickleFeatureUri } = this.storage.getPickle(testCase.pickleId); diff --git a/modules/storage.js b/modules/storage.js index 5c96d94..de973f7 100644 --- a/modules/storage.js +++ b/modules/storage.js @@ -25,7 +25,7 @@ module.exports = class Storage { this.steps = new Map(); this.parameters = new Map(); this.astNodesData = new Map(); - this.scenarioTempId = new Map(); + this.scenario = new Map(); this.stepTempId = new Map(); this.ruleTempId = new Map(); this.ruleTempIdToTestCaseStartedId = new Map(); @@ -141,16 +141,25 @@ module.exports = class Storage { return Array.from(this.features.keys()); } - setScenarioTempId(testCaseStartedId, scenarioTempId) { - this.scenarioTempId.set(testCaseStartedId, scenarioTempId); + setScenario(testCaseStartedId, scenario) { + this.scenario.set(testCaseStartedId, scenario); + } + + updateScenario(id, newData) { + const scenario = this.scenario.get(id) || {}; + this.scenario.set(id, { ...scenario, ...newData }); + } + + getScenario(testCaseStartedId) { + return this.scenario.get(testCaseStartedId); } getScenarioTempId(testCaseStartedId) { - return this.scenarioTempId.get(testCaseStartedId); + return (this.getScenario(testCaseStartedId) || {}).tempId; } - removeScenarioTempId(testCaseStartedId) { - this.scenarioTempId.delete(testCaseStartedId); + removeScenario(testCaseStartedId) { + this.scenario.delete(testCaseStartedId); } setStepTempId(parentId, value) { diff --git a/modules/worlds/loggerWorld.js b/modules/worlds/loggerWorld.js index 8cec67f..409a36a 100644 --- a/modules/worlds/loggerWorld.js +++ b/modules/worlds/loggerWorld.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const { LOG_LEVELS, RP_ENTITY_LAUNCH } = require('../constants'); +const { LOG_LEVELS, RP_ENTITIES } = require('../constants'); class ReportPortalCucumberLoggerWorld { constructor({ attach, parameters }) { @@ -87,7 +87,7 @@ class ReportPortalCucumberLoggerWorld { JSON.stringify({ level: LOG_LEVELS.INFO, message: logMessage, - entity: RP_ENTITY_LAUNCH, + entity: RP_ENTITIES.LAUNCH, }), 'text/plain', ); @@ -98,7 +98,7 @@ class ReportPortalCucumberLoggerWorld { JSON.stringify({ level: LOG_LEVELS.DEBUG, message: logMessage, - entity: RP_ENTITY_LAUNCH, + entity: RP_ENTITIES.LAUNCH, }), 'text/plain', ); @@ -109,7 +109,7 @@ class ReportPortalCucumberLoggerWorld { JSON.stringify({ level: LOG_LEVELS.ERROR, message: logMessage, - entity: RP_ENTITY_LAUNCH, + entity: RP_ENTITIES.LAUNCH, }), 'text/plain', ); @@ -120,7 +120,7 @@ class ReportPortalCucumberLoggerWorld { JSON.stringify({ level: LOG_LEVELS.WARN, message: logMessage, - entity: RP_ENTITY_LAUNCH, + entity: RP_ENTITIES.LAUNCH, }), 'text/plain', ); @@ -131,7 +131,7 @@ class ReportPortalCucumberLoggerWorld { JSON.stringify({ level: LOG_LEVELS.TRACE, message: logMessage, - entity: RP_ENTITY_LAUNCH, + entity: RP_ENTITIES.LAUNCH, }), 'text/plain', ); @@ -142,7 +142,73 @@ class ReportPortalCucumberLoggerWorld { JSON.stringify({ level: LOG_LEVELS.FATAL, message: logMessage, - entity: RP_ENTITY_LAUNCH, + entity: RP_ENTITIES.LAUNCH, + }), + 'text/plain', + ); + } + + scenarioInfo(logMessage) { + this.attach( + JSON.stringify({ + level: LOG_LEVELS.INFO, + message: logMessage, + entity: RP_ENTITIES.SCENARIO, + }), + 'text/plain', + ); + } + + scenarioDebug(logMessage) { + this.attach( + JSON.stringify({ + level: LOG_LEVELS.DEBUG, + message: logMessage, + entity: RP_ENTITIES.SCENARIO, + }), + 'text/plain', + ); + } + + scenarioError(logMessage) { + this.attach( + JSON.stringify({ + level: LOG_LEVELS.ERROR, + message: logMessage, + entity: RP_ENTITIES.SCENARIO, + }), + 'text/plain', + ); + } + + scenarioWarn(logMessage) { + this.attach( + JSON.stringify({ + level: LOG_LEVELS.WARN, + message: logMessage, + entity: RP_ENTITIES.SCENARIO, + }), + 'text/plain', + ); + } + + scenarioTrace(logMessage) { + this.attach( + JSON.stringify({ + level: LOG_LEVELS.TRACE, + message: logMessage, + entity: RP_ENTITIES.SCENARIO, + }), + 'text/plain', + ); + } + + scenarioFatal(logMessage) { + this.attach( + JSON.stringify({ + level: LOG_LEVELS.FATAL, + message: logMessage, + entity: RP_ENTITIES.SCENARIO, }), 'text/plain', ); @@ -153,7 +219,11 @@ class ReportPortalCucumberLoggerWorld { } launchScreenshot(logMessage) { - return this.createScreenshot(logMessage, RP_ENTITY_LAUNCH); + return this.createScreenshot(logMessage, RP_ENTITIES.LAUNCH); + } + + scenarioScreenshot(logMessage) { + return this.createScreenshot(logMessage, RP_ENTITIES.SCENARIO); } createScreenshot(message, entity) { diff --git a/modules/worlds/rpWorld.js b/modules/worlds/rpWorld.js index 79852c0..594d81a 100644 --- a/modules/worlds/rpWorld.js +++ b/modules/worlds/rpWorld.js @@ -15,7 +15,7 @@ */ const LoggerWorld = require('./loggerWorld'); -const { RP_EVENTS, STATUSES, RP_ENTITY_LAUNCH } = require('../constants'); +const { RP_EVENTS, STATUSES } = require('../constants'); class ReportPortalCucumberWorld extends LoggerWorld { setTestCaseId(testCaseId) { @@ -23,7 +23,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ testCaseId, }), - RP_EVENTS.TEST_CASE_ID, + RP_EVENTS.STEP_TEST_CASE_ID, ); } @@ -32,7 +32,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ attributes, }), - RP_EVENTS.ATTRIBUTES, + RP_EVENTS.STEP_ATTRIBUTES, ); } @@ -41,7 +41,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ description, }), - RP_EVENTS.DESCRIPTION, + RP_EVENTS.STEP_DESCRIPTION, ); } @@ -50,7 +50,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.PASSED, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -59,7 +59,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.FAILED, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -68,7 +68,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.SKIPPED, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -77,7 +77,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.STOPPED, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -86,7 +86,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.INTERRUPTED, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -95,7 +95,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.CANCELLED, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -104,7 +104,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.INFO, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -113,7 +113,7 @@ class ReportPortalCucumberWorld extends LoggerWorld { JSON.stringify({ status: STATUSES.WARN, }), - RP_EVENTS.STATUS, + RP_EVENTS.STEP_STATUS, ); } @@ -121,9 +121,8 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.PASSED, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, ); } @@ -131,9 +130,8 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.FAILED, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, ); } @@ -141,9 +139,8 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.SKIPPED, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, ); } @@ -151,9 +148,8 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.STOPPED, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, ); } @@ -161,9 +157,8 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.INTERRUPTED, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, ); } @@ -171,9 +166,8 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.CANCELLED, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, ); } @@ -181,9 +175,8 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.INFO, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, ); } @@ -191,9 +184,107 @@ class ReportPortalCucumberWorld extends LoggerWorld { this.attach( JSON.stringify({ status: STATUSES.WARN, - entity: RP_ENTITY_LAUNCH, }), - RP_EVENTS.STATUS, + RP_EVENTS.LAUNCH_STATUS, + ); + } + + setScenarioTestCaseId(testCaseId) { + this.attach( + JSON.stringify({ + testCaseId, + }), + RP_EVENTS.SCENARIO_TEST_CASE_ID, + ); + } + + addScenarioAttributes(attributes) { + this.attach( + JSON.stringify({ + attributes, + }), + RP_EVENTS.SCENARIO_ATTRIBUTES, + ); + } + + addScenarioDescription(description) { + this.attach( + JSON.stringify({ + description, + }), + RP_EVENTS.SCENARIO_DESCRIPTION, + ); + } + + setScenarioStatusPassed() { + this.attach( + JSON.stringify({ + status: STATUSES.PASSED, + }), + RP_EVENTS.SCENARIO_STATUS, + ); + } + + setScenarioStatusFailed() { + this.attach( + JSON.stringify({ + status: STATUSES.FAILED, + }), + RP_EVENTS.SCENARIO_STATUS, + ); + } + + setScenarioStatusSkipped() { + this.attach( + JSON.stringify({ + status: STATUSES.SKIPPED, + }), + RP_EVENTS.SCENARIO_STATUS, + ); + } + + setScenarioStatusStopped() { + this.attach( + JSON.stringify({ + status: STATUSES.STOPPED, + }), + RP_EVENTS.SCENARIO_STATUS, + ); + } + + setScenarioStatusInterrupted() { + this.attach( + JSON.stringify({ + status: STATUSES.INTERRUPTED, + }), + RP_EVENTS.SCENARIO_STATUS, + ); + } + + setScenarioStatusCancelled() { + this.attach( + JSON.stringify({ + status: STATUSES.CANCELLED, + }), + RP_EVENTS.SCENARIO_STATUS, + ); + } + + setScenarioStatusInfo() { + this.attach( + JSON.stringify({ + status: STATUSES.INFO, + }), + RP_EVENTS.SCENARIO_STATUS, + ); + } + + setScenarioStatusWarn() { + this.attach( + JSON.stringify({ + status: STATUSES.WARN, + }), + RP_EVENTS.SCENARIO_STATUS, ); } } diff --git a/tests/cucumber-reportportal-formatter.spec.js b/tests/cucumber-reportportal-formatter.spec.js index 1274af8..b77d3ed 100644 --- a/tests/cucumber-reportportal-formatter.spec.js +++ b/tests/cucumber-reportportal-formatter.spec.js @@ -35,6 +35,7 @@ const { testCaseStartedId, feature, scenario, + scenarioId, step, launchTempId, featureTempId, @@ -44,7 +45,7 @@ const { TEST_ITEM_TYPES, CUCUMBER_MESSAGES, RP_EVENTS, - RP_ENTITY_LAUNCH, + RP_ENTITIES, TEST_STEP_FINISHED_RP_MESSAGES, LOG_LEVELS, } = require('../modules/constants'); @@ -382,7 +383,7 @@ describe('cucumber-reportportal-formatter', () => { it('should update step in storage', () => { const data = { - mediaType: RP_EVENTS.TEST_CASE_ID, + mediaType: RP_EVENTS.STEP_TEST_CASE_ID, testStepId, testCaseStartedId, body: JSON.stringify(body), @@ -395,7 +396,7 @@ describe('cucumber-reportportal-formatter', () => { it('should update step attributes in storage', () => { const data = { - mediaType: RP_EVENTS.ATTRIBUTES, + mediaType: RP_EVENTS.STEP_ATTRIBUTES, testStepId, testCaseStartedId, body: JSON.stringify(body), @@ -410,7 +411,7 @@ describe('cucumber-reportportal-formatter', () => { it('should update step description in storage', () => { const data = { - mediaType: RP_EVENTS.DESCRIPTION, + mediaType: RP_EVENTS.STEP_DESCRIPTION, testStepId, testCaseStartedId, body: JSON.stringify(body), @@ -425,7 +426,7 @@ describe('cucumber-reportportal-formatter', () => { it('should update step description in storage', () => { const data = { - mediaType: RP_EVENTS.DESCRIPTION, + mediaType: RP_EVENTS.STEP_DESCRIPTION, testStepId, testCaseStartedId, body: JSON.stringify(body), @@ -438,10 +439,50 @@ describe('cucumber-reportportal-formatter', () => { }); }); + it('should update scenario in storage', () => { + const customTestCaseId = 'test-case-id'; + const data = { + mediaType: RP_EVENTS.SCENARIO_TEST_CASE_ID, + testStepId, + testCaseStartedId, + body: JSON.stringify({ testCaseId: customTestCaseId }), + }; + + formatter.onTestStepAttachmentEvent(data); + + expect(formatter.storage.getScenario(testCaseId)).toEqual({ testCaseId: customTestCaseId }); + }); + + it('should update scenario attributes in storage', () => { + const data = { + mediaType: RP_EVENTS.SCENARIO_ATTRIBUTES, + testStepId, + testCaseStartedId, + body: JSON.stringify(body), + }; + + formatter.onTestStepAttachmentEvent(data); + + expect(formatter.storage.getScenario(testCaseId).attributes).toEqual(body.attributes); + }); + + it('should update scenario description in storage', () => { + const data = { + mediaType: RP_EVENTS.SCENARIO_DESCRIPTION, + testStepId, + testCaseStartedId, + body: JSON.stringify(body), + }; + + formatter.onTestStepAttachmentEvent(data); + + expect(formatter.storage.getScenario(testCaseId).description).toEqual(body.description); + }); + describe('Status event handling', () => { it('should update step in storage', () => { const data = { - mediaType: RP_EVENTS.STATUS, + mediaType: RP_EVENTS.STEP_STATUS, testStepId, testCaseStartedId, body: JSON.stringify(body), @@ -452,13 +493,26 @@ describe('cucumber-reportportal-formatter', () => { expect(formatter.storage.getStep(testCaseId, testStepId)).toEqual(body); }); + it('should update scenario in storage', () => { + const data = { + mediaType: RP_EVENTS.SCENARIO_STATUS, + testStepId, + testCaseStartedId, + body: JSON.stringify(body), + }; + + formatter.onTestStepAttachmentEvent(data); + + expect(formatter.storage.getScenario(testCaseId).status).toEqual(body.status); + }); + it('should set status in customLaunchStatus field', () => { const status = 'start'; const data = { - mediaType: RP_EVENTS.STATUS, + mediaType: RP_EVENTS.LAUNCH_STATUS, testStepId, testCaseStartedId, - body: JSON.stringify({ ...body, entity: RP_ENTITY_LAUNCH, status }), + body: JSON.stringify({ ...body, status }), }; formatter.onTestStepAttachmentEvent(data); @@ -488,6 +542,26 @@ describe('cucumber-reportportal-formatter', () => { }); }); + it('sendLog should be called with scenario temp id', () => { + jest.spyOn(formatter.storage, 'getScenarioTempId').mockImplementationOnce(() => scenarioId); + const spySendLog = jest.spyOn(formatter.reportportal, 'sendLog'); + + const data = { + mediaType: 'text/plain', + testStepId, + testCaseStartedId, + body: JSON.stringify({ ...body, entity: RP_ENTITIES.SCENARIO }), + }; + + formatter.onTestStepAttachmentEvent(data); + + expect(spySendLog).toHaveBeenCalledWith(scenarioId, { + time: mockedDate, + level: body.level, + message: body.message, + }); + }); + it('sendLog should be called with launch temp id', () => { jest.spyOn(formatter.storage, 'getLaunchTempId').mockImplementationOnce(() => launchTempId); const spySendLog = jest.spyOn(formatter.reportportal, 'sendLog'); @@ -496,7 +570,7 @@ describe('cucumber-reportportal-formatter', () => { mediaType: 'text/plain', testStepId, testCaseStartedId, - body: JSON.stringify({ ...body, entity: RP_ENTITY_LAUNCH }), + body: JSON.stringify({ ...body, entity: RP_ENTITIES.LAUNCH }), }; formatter.onTestStepAttachmentEvent(data); @@ -564,6 +638,37 @@ describe('cucumber-reportportal-formatter', () => { ); }); + it('sendLog should be called with scenario temp id', () => { + jest.spyOn(formatter.storage, 'getScenarioTempId').mockImplementationOnce(() => scenarioId); + const spySendLog = jest.spyOn(formatter.reportportal, 'sendLog'); + + const data = { + mediaType, + testStepId, + testCaseStartedId, + body: JSON.stringify({ ...body, entity: RP_ENTITIES.SCENARIO }), + }; + + formatter.onTestStepAttachmentEvent(data); + + expect(spySendLog).toHaveBeenCalledWith( + scenarioId, + { + time: mockedDate, + level: body.level, + message: body.message, + file: { + name: body.message, + }, + }, + { + name: fileName, + type: mediaType, + content: body.data, + }, + ); + }); + it('sendLog should be called with launch temp id', () => { jest.spyOn(formatter.storage, 'getLaunchTempId').mockImplementationOnce(() => launchTempId); const spySendLog = jest.spyOn(formatter.reportportal, 'sendLog'); @@ -572,7 +677,7 @@ describe('cucumber-reportportal-formatter', () => { mediaType, testStepId, testCaseStartedId, - body: JSON.stringify({ ...body, entity: RP_ENTITY_LAUNCH }), + body: JSON.stringify({ ...body, entity: RP_ENTITIES.LAUNCH }), }; formatter.onTestStepAttachmentEvent(data); diff --git a/tests/storage.spec.js b/tests/storage.spec.js index 67a7833..9afdb0f 100644 --- a/tests/storage.spec.js +++ b/tests/storage.spec.js @@ -147,17 +147,17 @@ describe('test Storage', () => { expect(storage.getActiveFeatureUris()).toEqual([uri]); }); - it('set/getScenarioTempId', () => { - storage.setScenarioTempId(testCaseStartedId, scenarioTempId); + it('set/getScenario', () => { + storage.setScenario(testCaseStartedId, { tempId: scenarioTempId }); - expect(storage.getScenarioTempId(testCaseStartedId)).toBe(scenarioTempId); + expect(storage.getScenario(testCaseStartedId)).toEqual({ tempId: scenarioTempId }); }); - it('set/removeScenarioTempId', () => { - storage.setScenarioTempId(testCaseStartedId, scenarioTempId); - storage.removeScenarioTempId(testCaseStartedId); + it('set/removeScenario', () => { + storage.setScenario(testCaseStartedId, { tempId: scenarioTempId }); + storage.removeScenario(testCaseStartedId); - expect(storage.getScenarioTempId(testCaseStartedId)).toBeUndefined(); + expect(storage.getScenario(testCaseStartedId)).toBeUndefined(); }); it('set/getStepTempId', () => {