From 4755bc7378de8768b4aa3e825cd4a82b2b07c6c9 Mon Sep 17 00:00:00 2001 From: Shelex Date: Mon, 15 Nov 2021 17:27:52 +0200 Subject: [PATCH 1/2] feat: decouple reporter internal entities --- .../AllureInterface.js | 9 +- reporter/allure-cypress/AllureReporter.js | 430 +++++++ reporter/allure-cypress/CucumberHandler.js | 152 +++ reporter/allure-cypress/CypressChain.js | 57 + reporter/allure-cypress/CypressHandler.js | 508 ++++++++ reporter/index.js | 12 +- reporter/mocha-allure/AllureReporter.js | 1116 ----------------- yarn.lock | 388 +++--- 8 files changed, 1301 insertions(+), 1371 deletions(-) rename reporter/{mocha-allure => allure-cypress}/AllureInterface.js (93%) create mode 100644 reporter/allure-cypress/AllureReporter.js create mode 100644 reporter/allure-cypress/CucumberHandler.js create mode 100644 reporter/allure-cypress/CypressChain.js create mode 100644 reporter/allure-cypress/CypressHandler.js delete mode 100644 reporter/mocha-allure/AllureReporter.js diff --git a/reporter/mocha-allure/AllureInterface.js b/reporter/allure-cypress/AllureInterface.js similarity index 93% rename from reporter/mocha-allure/AllureInterface.js rename to reporter/allure-cypress/AllureInterface.js index e293b4f..b5b5151 100644 --- a/reporter/mocha-allure/AllureInterface.js +++ b/reporter/allure-cypress/AllureInterface.js @@ -1,8 +1,3 @@ -/** - * A lot of credit to Sergey Korol who made - * Allure-mocha reporter: "https://github.com/allure-framework/allure-js/tree/master/packages/allure-mocha" - */ - const { Allure, Status, @@ -63,9 +58,7 @@ Allure.prototype.step = function (name, isParent = true) { Allure.prototype.stepStart = function (name) { // define last chainer that still not finished and has allure step - const chainer = this.reporter.commands - .reverse() - .find((c) => !c.finished && c.step && c.step.info.name); + const chainer = this.reporter.cy.chain.getLatestWithStep(); // define fallback allure executable const previousExecutable = this.currentExecutable; diff --git a/reporter/allure-cypress/AllureReporter.js b/reporter/allure-cypress/AllureReporter.js new file mode 100644 index 0000000..9087fcf --- /dev/null +++ b/reporter/allure-cypress/AllureReporter.js @@ -0,0 +1,430 @@ +const { + LabelName, + Stage, + Status +} = require('@shelex/allure-js-commons-browser'); +const crypto = require('crypto-js'); +const AllureInterface = require('./AllureInterface'); +const { languageLabel } = require('../languageLabel'); +const logger = require('../debug'); +const CypressHandler = require('./CypressHandler'); +const CucumberHandler = require('./CucumberHandler'); + +module.exports = class AllureReporter { + constructor(runtime, options) { + this.suites = []; + this.steps = []; + this.files = []; + this.labelStorage = []; + this.runningTest = null; + this.previousTestName = null; + this.runtime = runtime; + this.currentHook = null; + this.parentStep = null; + this.cy = new CypressHandler(this); + this.gherkin = new CucumberHandler(this); + this.logCypress = options.logCypress || false; + this.logGherkinSteps = options.logGherkinSteps || false; + this.attachRequests = options.attachRequests || false; + } + + /** + * @returns {AllureInterface} + */ + getInterface() { + return new AllureInterface(this, this.runtime); + } + + get currentExecutable() { + return ( + this.currentStep || + this.parentStep || + this.currentHook || + this.currentTest || + this.currentSuite + ); + } + + get currentSuite() { + if (this.suites.length === 0) { + return null; + } + return this.suites[this.suites.length - 1]; + } + + get currentSuiteIsGlobal() { + return ( + this.currentSuite && + this.currentSuite.testResultContainer.name === 'Global' + ); + } + + get currentStep() { + if (this.steps.length > 0) { + return this.steps[this.steps.length - 1]; + } + return null; + } + + get currentTest() { + return this.runningTest; + } + + set currentTest(test) { + if (this.runningTest) { + this.previousTestName = this.runningTest.info.name; + } + this.runningTest = test; + // in case labels were defined outside of test + // we could attach them from storage + if (this.runningTest) { + this.runningTest.info.labels.push(...this.labelStorage); + } + } + + get testNameForAttachment() { + const cyTest = cy.state().test; + return ( + (cyTest && cyTest.title) || + (this.currentTest && this.currentTest.info.name) || + this.previousTestName + ); + } + + originalNameOf(hook) { + return hook.hookName || hook.originalTitle || hook.title; + } + + startSuite(suiteName) { + if (this.currentSuite) { + if (this.currentSuiteIsGlobal) { + /** + * cypress creates suite for spec file + * where global hooks and other nested suites are held + * in order to have global hooks available + * this global suite can just be renamed + * to the first user's suite + */ + this.currentSuite.testResultContainer.name = suiteName; + return; + } else { + /** + * but if previous suite is not global + * it should be finished, and new one created + */ + logger.allure(`finish previous suite %O`, this.currentSuite); + this.endSuite(true); + } + } + const scope = this.currentSuite || this.runtime; + const suite = scope.startGroup(suiteName || 'Global'); + logger.allure(`start suite %O`, suite); + this.pushSuite(suite); + } + + endSuite(isGlobal = false) { + if (this.currentSuite && isGlobal) { + this.cy.handleRemainingCommands(Status.PASSED); + logger.allure(`finished cypress commands`); + this.finishRemainingSteps(Status.PASSED); + logger.allure(`finished steps`); + this.currentStep !== null && this.currentStep.endStep(); + this.currentTest && + this.currentTest.testResult.stage !== Stage.FINISHED && + this.endTest(); + this.currentSuite.endGroup(); + this.popSuite(); + logger.allure(`finished suite`); + } + // restrict label storage to single suite scope + this.labelStorage = []; + } + + startCase(test, config) { + logger.allure(`starting case %s %O`, test.title, test); + if (this.currentSuite === null) { + logger.allure(`no active suite available`); + throw new Error('No active suite'); + } + + /** + * skipped test sometimes initially receives pending event + * where test will be created + * and then comes start test event followed by end test + * so start for skipped test should be omitted + * when current test is already skipped with same name + */ + if ( + this.currentTest && + this.currentTest.info.status === 'skipped' && + this.currentTest.info.name === test.title + ) { + logger.allure(`skipped test already exists`); + return; + } + + this.cy.chain.clear(); + this.currentTest = this.currentSuite.startTest(test.title); + this.currentTest.fullName = test.title; + this.currentTest.historyId = crypto + .MD5(test.fullTitle()) + .toString(crypto.enc.Hex); + this.currentTest.stage = Stage.RUNNING; + + if ( + config && + config.clearFilesForPreviousAttempt() && + test._currentRetry > 0 + ) { + logger.allure(`clearing screenshots from previous retries`); + // remove screenshots from previous attempt + this.files = this.files.filter( + (file) => file.testName !== test.title + ); + } + + if (config && config.addAnalyticLabels()) { + logger.allure(`adding analytic labels`); + this.currentTest.addLabel(LabelName.FRAMEWORK, 'Cypress'); + const language = languageLabel(test); + language && this.currentTest.addLabel(LabelName.LANGUAGE, language); + } + + if (test.parent) { + const titlePath = test.parent.titlePath(); + // should add suite label for test if it has parent + if (titlePath.length === 1) { + this.currentTest.addLabel(LabelName.SUITE, titlePath.pop()); + } else { + const [parentSuite, suite, ...subSuites] = titlePath; + if (parentSuite) { + this.currentTest.addLabel( + LabelName.PARENT_SUITE, + parentSuite + ); + } + if (suite) { + this.currentTest.addLabel(LabelName.SUITE, suite); + } + if (subSuites.length > 0) { + this.currentTest.addLabel( + LabelName.SUB_SUITE, + subSuites.join(' > ') + ); + } + } + } + } + + passTestCase(test) { + if (this.currentTest === null) { + logger.allure(`not found allure test, created new`); + this.startCase(test); + } + this.updateTest(Status.PASSED); + logger.allure(`set passed for test: %s %O`, test.title, test); + } + + pendingTestCase(test) { + this.startCase(test); + this.updateTest(Status.SKIPPED, { message: 'Test ignored' }); + logger.allure( + `created new test and set to pending: %s %O`, + test.title, + test + ); + } + + failTestCase(test, error) { + logger.allure( + `received test failed event: %s, %O, %O`, + test.title, + test, + error + ); + if (this.currentTest === null) { + logger.allure(`not found test, created new`); + this.startCase(test); + } + + this.updateTest(Status.FAILED, { + message: error.message, + trace: error.stack + }); + /** + * in case error comes from hook + */ + if (test.type === 'hook') { + logger.allure(`test error origin is hook`); + this.endHook(test, true); + /** + * in case of before all cypress creates new test + * which not produce any mocha events + * as result should be finished manually + */ + + if ( + test.hookName && + ['before all', 'before each'].includes(test.hookName) + ) { + logger.allure( + `finishing test as no events received for failed test in before all hook` + ); + + if (!test.parent && !test.parent.tests) { + return this.endTest(); + } + + // mark remaining tests as broken due to before all hook failure + test.parent.tests.forEach((test, index) => { + logger.allure( + `found cancelled test due to before all hook: %O`, + test + ); + index === 0 + ? (this.currentTest.info.name = test.title) + : this.startCase(test); + this.updateTest(Status.BROKEN, { + message: error.message, + trace: error.stack + }); + this.endTest(); + }); + } + } + } + + writeAttachment(content, type) { + return this.runtime.writeAttachment(content, type); + } + + pushStep(step) { + this.steps.push(step); + } + + popStep() { + return this.steps.pop(); + } + + finishRemainingSteps(status = Status.PASSED) { + this.steps.forEach((step) => { + step.info.stage = Stage.FINISHED; + if (step.info.steps.length) { + step.info.status = step.info.steps.some( + (step) => step.status === Status.FAILED + ) + ? Status.FAILED + : Status.PASSED; + } else { + step.info.status = status; + } + step.endStep(); + }); + this.steps = []; + if (this.parentStep) { + this.parentStep.info.stage = Stage.FINISHED; + this.parentStep.info.status = status; + this.parentStep.endStep(); + } + } + + startHook(hook) { + logger.allure(`starting hook %s`, hook.title); + if (!this.currentSuite || isEmpty(hook)) { + logger.allure(`no suite or hook is empty function`); + return; + } + /** + * When hook is global - it is attached to suite + * and will be displayed as precondition + * `each` hooks will be available as test steps + */ + if (this.originalNameOf(hook).includes('all')) { + const parent = this.currentSuite; + const allureHook = this.originalNameOf(hook).includes('before') + ? parent.addBefore() + : parent.addAfter(); + this.currentHook = allureHook; + } else { + if (!this.logCypress) { + return; + } + const customHookName = hook.title.replace( + /\"(before|after) each\" hook:? */g, + '' + ); + + const step = this.currentTest.startStep( + customHookName || hook.title + ); + this.currentHook = step; + } + } + + endHook(hook, failed = false) { + logger.allure(`finishing hook %s`, hook.title); + if (!this.currentSuite || !this.currentHook || isEmpty(hook)) { + logger.allure(`no suite or no hook or hook is empty function`); + return; + } + // should define results property for all or each hook + const currentHookInfo = this.originalNameOf(hook).includes('all') + ? this.currentHook.info + : this.currentHook.stepResult; + + if (hook.err) { + currentHookInfo.status = Status.FAILED; + currentHookInfo.stage = Stage.FINISHED; + currentHookInfo.statusDetails = { + message: hook.err.message, + trace: hook.err.stack + }; + } else { + currentHookInfo.status = Status.PASSED; + currentHookInfo.stage = Stage.FINISHED; + } + + // in case hook is a step we should complete it + if (this.originalNameOf(hook).includes('each')) { + this.currentHook && this.currentHook.endStep(); + } + !failed && (this.currentHook = null); + } + + pushSuite(suite) { + this.suites.push(suite); + } + + popSuite() { + this.suites.pop(); + } + + updateTest(status, details) { + if (this.currentTest === null) { + throw new Error('finishing test while no test is running'); + } + (this.logCypress || this.logGherkinSteps) && + this.cy.handleRemainingCommands(status); + this.finishRemainingSteps(status); + this.parentStep = null; + + logger.allure( + `updating test %O to have status:%s and details: %O`, + this.currentTest, + status, + details + ); + + details && (this.currentTest.statusDetails = details); + this.currentTest.status = status; + this.currentTest.stage = Stage.FINISHED; + this.currentTest.testResult.stop = Date.now(); + } + + endTest() { + logger.allure(`finishing current test`); + this.currentTest && this.currentTest.endTest(); + } +}; + +const isEmpty = (hook) => hook && hook.body === 'function () {}'; diff --git a/reporter/allure-cypress/CucumberHandler.js b/reporter/allure-cypress/CucumberHandler.js new file mode 100644 index 0000000..abcb11a --- /dev/null +++ b/reporter/allure-cypress/CucumberHandler.js @@ -0,0 +1,152 @@ +const logger = require('../debug'); +const { tagToLabel, tagToLink, exampleNumber } = require('../gherkinToLabel'); + +module.exports = class CucumberHandler { + constructor(reporter) { + this.reporter = reporter; + this.examplesStorage = []; + } + + checkLinksInExamplesTable() { + if (globalThis && globalThis.testState) { + const { testState } = globalThis; + + if (testState.currentScenario.keyword === 'Scenario Outline') { + logger.allure(`populating gherkin links from examples table`); + const scenario = testState.currentScenario; + + !this.examplesStorage.length && + this.examplesStorage.push(...scenario.examples); + + const example = + this.examplesStorage.length && this.examplesStorage.pop(); + + if (example) { + const findCellIndex = (type) => + example.tableHeader.cells.findIndex( + (cell) => cell.value === type + ); + + const tmsCellIndex = findCellIndex('tms'); + const issueCellIndex = findCellIndex('issue'); + + const exampleRowNumber = parseInt( + exampleNumber.exec(scenario.name).pop() + ); + + if (!exampleRowNumber) { + return; + } + + const exampleRowIndex = exampleRowNumber - 1; + + const findTableCellValue = (headerIndex) => + example.tableBody[exampleRowIndex].cells[headerIndex] + .value; + + const addScenarioTag = (type, value) => { + const current = + globalThis.testState.runScenarios[scenario.name]; + + globalThis.testState.runScenarios[scenario.name].tags = + [ + ...current.tags, + { + type: 'Tag', + name: `@${type}("${value}")` + } + ]; + }; + + if (tmsCellIndex !== -1) { + const tmsId = findTableCellValue(tmsCellIndex); + logger.allure(`found tms link: %s`, tmsId); + addScenarioTag('tms', tmsId); + } + + if (issueCellIndex !== -1) { + const issueId = findTableCellValue(issueCellIndex); + logger.allure(`found issue link: %s`, issueId); + addScenarioTag('issue', issueId); + } + } + } + } + } + + // accept cucumber tags from cypress-cucumber-preprocessor as commands + checkTags() { + if (globalThis && globalThis.testState) { + logger.allure(`parsing gherkin tags`); + const { testState } = globalThis; + const { currentTest } = this.reporter; + + // set bdd feature by default + currentTest.addLabel('feature', testState.feature.name); + + /** + * tags set on test level has higher priority + * to not be overwritten by feature tags + */ + ['feature', 'currentScenario'].forEach(function (type) { + logger.allure(`tags for %s`, type); + testState[type] && + testState[type].tags + // check for labels + .filter(function ({ name }) { + const match = tagToLabel.exec(name); + if (match) { + const [, command, value] = match; + // feature and suite should be overwritten to avoid duplicates + if (['feature', 'suite'].includes(command)) { + const index = + currentTest.info.labels.findIndex( + (label) => label.name === command + ); + currentTest.info.labels[index] = { + name: command, + value: value + }; + } else { + currentTest.addLabel(command, value); + } + } + return !match; + }) + // check for links + .filter(function ({ name }) { + const match = tagToLink.exec(name); + if (match) { + const [, command, name, matchUrl] = match; + + const url = matchUrl || name; + + const prefixBy = { + issue: Cypress.env('issuePrefix'), + tms: Cypress.env('tmsPrefix'), + link: null + }; + const urlPrefix = prefixBy[command]; + + const pattern = + urlPrefix && urlPrefix.includes('*') + ? urlPrefix + : `${urlPrefix}*`; + currentTest.addLink( + urlPrefix && pattern + ? pattern.replace(/\*/g, url) + : url, + name, + command + ); + } + return !match; + }) + // add other tags + .forEach(function ({ name }) { + currentTest.addLabel('tag', name.replace('@', '')); + }); + }); + } + } +}; diff --git a/reporter/allure-cypress/CypressChain.js b/reporter/allure-cypress/CypressChain.js new file mode 100644 index 0000000..ba4f0c3 --- /dev/null +++ b/reporter/allure-cypress/CypressChain.js @@ -0,0 +1,57 @@ +module.exports = class Chain { + constructor() { + this.chain = []; + this.currentChainer = null; + } + + add(chainable) { + const command = { + id: chainable.chainerId, + name: chainable.name, + type: chainable.type, + parent: this.currentChainer && this.currentChainer.chainerId, + children: [], + passed: true, // will be set false in case failed or failed child command + finished: false, + step: null, + commandLog: null + }; + this.chain.push(command); + return command; + } + + getParent(chainerId) { + return this.chain.find( + (command) => + command.id === chainerId && !command.finished && command.step + ); + } + + addChild(commandId, parentId) { + const parent = this.getParent(parentId); + // set new child from start as command queue works as LIFO (last in - first out) approach + parent && parent.children.unshift(commandId); + } + + getCommand(command, withStep = false) { + return this.chain.find( + (chainable) => + chainable.id === command.chainerId && + chainable.name === command.name && + Boolean(chainable.step) === withStep && + !chainable.finished + ); + } + + getCommandsWithSteps() { + return this.chain.filter((c) => !c.finished && c.step).reverse(); + } + + getLatestWithStep() { + return this.getCommandsWithSteps().find((c) => c.step.info.name); + } + + clear() { + this.chain = []; + } +}; diff --git a/reporter/allure-cypress/CypressHandler.js b/reporter/allure-cypress/CypressHandler.js new file mode 100644 index 0000000..62fd4ff --- /dev/null +++ b/reporter/allure-cypress/CypressHandler.js @@ -0,0 +1,508 @@ +const logger = require('../debug'); +const stubbedAllure = require('../stubbedAllure'); +const callbacks = ['then', 'spread', 'each', 'within']; +const { Stage, Status } = require('@shelex/allure-js-commons-browser'); +const Chain = require('./CypressChain'); + +module.exports = class CypressHandler { + constructor(reporter) { + this.reporter = reporter; + this.chain = new Chain(); + } + + shouldBeLogged(command) { + return commandIsGherkinStep(command) + ? this.reporter.logGherkinSteps + : this.reporter.logCypress; + } + + findAllureExecutableFor(command) { + if (command.parent) { + const parent = this.chain.getParent(command.parent); + + if (!parent) { + return this.reporter.currentExecutable; + } + + // such commands contain argument + // which is basically a function that will be executed + if (callbacks.includes(parent.name)) { + return this.findAllureExecutableFor(parent); + } + + // in case latest step in newer then parent - attach to user defined step + return this.reporter.currentStep && + this.reporter.currentStep.info.start > parent.step.info.start + ? this.reporter.currentStep + : parent.step; + } + return this.reporter.currentExecutable; + } + + enqueued(command) { + logger.cy(`enqueued: %s %O`, command.name, command); + // rules for skipping commands: + const skippingRules = { + // assertions, as they don't receive command:start and command:end events and are hardly trackable + isAssertion: command.type === 'assertion', + + // allure custom command used for interacting with allure api (cy.allure()) + isAllureCustomCommand: command.name === 'allure', + + // commands, which are child commands of cy.allure command + isAllureCustomChildCommand: + Object.getOwnPropertyNames( + stubbedAllure.reporter.getInterface() + ).includes(command.name) && command.type === 'child', + + // commands, where second argument has {log: false} + isNotLogged: + command.args && + command.args.length && + command.args.some( + (arg) => + arg && + typeof arg.log !== 'undefined' && + arg.log === false + ) + }; + + const shouldBeSkipped = Object.keys(skippingRules).some( + (rule) => skippingRules[rule] + ); + + if (shouldBeSkipped) { + logger.cy(`command should be skipped`); + return; + } + + // prepare chainer command object with specific information to process it with events + const chainable = this.chain.add(command); + + logger.cy(`tracking command: %O`, chainable); + + // in case command in enqueued while there was active chainer - treat it as parent + // so this command should be added as child to track if we should finish parent command step + if (chainable.parent) { + this.chain.addChild(command.id, chainable.parent); + logger.cy(`added as child of command: %O`, parent); + } + } + + started(command) { + logger.cy(`started: %s %O`, command.name, command); + // check if we have enqueued command + const chainable = this.chain.getCommand(command); + + if (!chainable) { + logger.cy(`command not available`); + return; + } + + logger.cy(`tracked info about command: %O`, command); + + chainable.commandLog = command; + + // add dummy allure step implementation for "then" commands to avoid adding them to report + // as they mostly expose other plugin internals and other functions not related to test + // on other hand, if they produce info for command log - step will be created when command end + if (callbacks.includes(chainable.name)) { + chainable.step = { + info: {}, + stepResult: {}, + endStep() {} + }; + } else { + const executable = this.findAllureExecutableFor(chainable); + + const displayArg = (arg) => { + logger.cy(`checking argument %O and provide to step`, arg); + if (typeof arg === 'function') { + return '[function]'; + } + if (typeof arg === 'object') { + if ( + arg && + arg.constructor && + arg.constructor.toString && + typeof arg.constructor.toString === 'function' && + ((arg.constructor.toString().includes('HTML') && + arg.constructor.toString().includes('Element')) || + arg.constructor + .toString() + .includes('The jQuery object')) + ) { + return '[Object]'; + } + + return JSON.stringify(arg, getCircularReplacer(), 2); + } + + return arg; + }; + + const commandArgs = + command.args.length && + command.args.map((arg) => `"${displayArg(arg)}"`).join('; '); + + const step = + this.shouldBeLogged(command) && + executable.startStep( + `${chainable.name}${commandArgs ? ` (${commandArgs})` : ''}` + ); + + if (step) { + logger.cy(`started allure step %s %O`, step.info.name, step); + + chainable.step = step; + } + } + this.chain.currentChainer = command; + } + + finished(chainable, failed = false) { + logger.cy(`finished: %s %O`, chainable.name, chainable); + // check if we have enqueued command + const command = this.chain.getCommand(chainable, true); + + if (!command) { + logger.cy(`command not available`); + return; + } + + logger.cy(`tracked info about command: %O`, command); + this.chain.currentChainer = null; + + // in case no children enqueued - finish this step + if (!command.children.length || failed) { + logger.cy(`no children enqueued left, finishing step`); + // check if command has some entries for command log + if (command.commandLog.logs.length) { + logger.cy( + `found command log entries %O`, + command.commandLog.logs + ); + // set first command log (which refers to current command) as last + // and process other child logs first (asserts are processed such way) + + command.commandLog.logs.push(command.commandLog.logs.shift()); + + command.commandLog.logs.forEach((entry, index) => { + let log; + + // try...catch for handling case when Cypress.log has error in consoleProps function + try { + log = entry.toJSON(); + } catch (e) { + logger.cy( + `could not call toJSON for command log entry #%d, %O`, + index, + entry + ); + return; + } + logger.cy(`checking entry #%d, %O`, index, log); + + // for main log (which we set last) we should finish command step + if (index === command.commandLog.logs.length - 1) { + logger.cy(`last entry, finishing step`); + // in case "then" command has some logging - create step for that + if (callbacks.includes(command.name)) { + const executable = + this.findAllureExecutableFor(command); + + if ( + !this.reporter.logGherkinSteps && + commandIsGherkinStep(chainable) + ) { + return; + } + + const step = this.startStep(executable, log); + logger.cy(`creating step for then's %O`, step); + + command.step = step; + + if (log.name === 'step') { + logger.cy( + `found gherkin step, finishing all current steps` + ); + this.reporter.finishRemainingSteps( + command.passed + ? Status.PASSED + : Status.FAILED + ); + this.reporter.steps.push(step); + this.reporter.parentStep = step; + } + } + + const commandPassed = this.finishStep( + command.step, + log, + command.passed + ); + + !commandPassed && (command.passed = false); + } else { + // handle case when other logs refer to chained assertions + // so steps should be created + const executable = this.findAllureExecutableFor({ + id: log.id, + parent: command.parent + }); + + const step = this.startStep(executable, log); + logger.cy( + `attaching command log entries as allure steps %O`, + step + ); + + const commandPassed = this.finishStep(step, log); + + !commandPassed && (command.passed = false); + } + }); + } else { + logger.cy( + `no command log entries, finish step %O`, + command.step + ); + this.finishStep( + command.step, + { + state: command.passed ? Status.PASSED : Status.FAILED + }, + command.passed + ); + } + command.finished = true; + !command.passed && (failed = true); + // notify parent that one of child commands is finished + // and pass status + this.informParent(command, failed); + } + } + + informParent(child, failed = false) { + if (child.parent) { + const parent = this.chain.getParent(child.parent); + + // better to skip case when no parent found + if (!parent) { + return; + } + + logger.cy(`command has parent, %O`, parent); + + const childIndex = parent.children.indexOf(child.id); + + // if found child - remove it from parent + if (childIndex > -1) { + logger.cy(`removing child from parent %O`, parent); + parent.children.splice(childIndex, 1); + // update status of parent in case any of children failed + if (!child.passed || failed) { + parent.passed = false; + } + } + + // finish parent step when no children left or when test is failed + if (!parent.children.length || failed) { + logger.cy( + `finish parent step as no other children left %O`, + parent + ); + !parent.passed && (failed = true); + this.finished(parent.commandLog, failed); + } + } + } + + handleRemainingCommands(status = Status.FAILED) { + // process all not finished steps from chainer left + // usually is executed on fail + this.chain.getCommandsWithSteps().forEach((command) => { + !command.finished && + this.finished(command.commandLog, status === Status.FAILED); + }); + this.chain.currentChainer = null; + } + + finishStep(step, log, commandStatus) { + this.attachRequestsMaybe(step, log); + + const shouldOverrideName = !['request', 'step'].includes(log.name); + + if ( + step && + step.info && + step.info.name && + log.name && + log.message && + shouldOverrideName + ) { + step.info.name = `${log.name} ${log.message}`; + logger.cy(`changing step name to "%s" %O`, step.info.name, step); + } + + const passed = + log && log.err + ? false + : commandStatus || log.state !== Status.FAILED; + + step.info.stage = Stage.FINISHED; + + step.info.status = passed ? Status.PASSED : Status.FAILED; + + log.name !== 'step' && step.endStep(); + return passed; + } + + startStep(executable, log) { + logger.cy(`creating step for command log entry %O`, log); + // define step name based on cypress log name or messages + const messages = { + xhr: () => + `${ + (log.consoleProps.Stubbed === 'Yes' ? 'STUBBED ' : '') + + log.consoleProps.Method + } ${log.consoleProps.URL}`, + step: () => `${log.displayName}${log.message.replace(/\*/g, '')}`, + stub: () => + `${log.name} [ function: ${log.functionName} ] ${ + log.alias ? `as ${log.alias}` : '' + }`, + route: () => `${log.name} ${log.method} ${log.url}`, + default: () => + log.message ? `${log.message} ${log.name}` : `${log.name}` + }; + + // handle cases with stubs name containing increments (stub-1, stub-2, etc.) + const lookupName = log.name.startsWith('stub') ? 'stub' : log.name; + + const message = messages[lookupName] || messages.default; + + // in case log name is "step" - assumed that it comes from cucumber preprocessor + // in case it is cucumber step - executable should be current test + if (log.name === 'step') { + executable = this.reporter.currentTest; + } + + const newStep = executable.startStep(message()); + + // parse docString for gherkin steps + if ( + log.name === 'step' && + log.consoleProps && + log.consoleProps.step && + log.consoleProps.step.argument && + log.consoleProps.step.argument.content + ) { + newStep.addParameter( + log.consoleProps.step.argument.type, + log.consoleProps.step.argument.content + ); + } + + // add expected and actual for asserts + if (log.name === 'assert') { + const displayValue = (value) => + typeof value === 'object' + ? JSON.stringify(value, getCircularReplacer(), 2) + : value; + + logger.cy( + '[allure:cy] adding actual and expected as a parameter %O', + log + ); + + log.actual && + newStep.addParameter('actual', displayValue(log.actual)); + log.expected && + newStep.addParameter('expected', displayValue(log.expected)); + } + + return newStep; + } + + attachRequestsMaybe(step, log) { + if ( + // check for requests + log.name === 'request' || + // or for then commands which have requests being logged in command log + (log.name === 'then' && + log.consoleProps && + log.consoleProps.Request) + ) { + if (log.renderProps && log.renderProps.message) { + step.info.name = log.renderProps.message; + } + + if (this.reporter.attachRequests && log.consoleProps) { + const request = + log.consoleProps.Request || + Cypress._.last(log.consoleProps.Requests); + const response = log.consoleProps.Yielded; + + const attach = (step, name, content) => { + if (!content) { + return; + } + + let jsonContent; + + try { + jsonContent = + typeof content === 'string' + ? JSON.parse(content) + : content; + } catch (e) { + // content is not json + } + + const fileType = jsonContent + ? 'application/json' + : 'text/plain'; + const fileName = this.reporter.writeAttachment( + jsonContent + ? JSON.stringify(jsonContent, null, 2) + : content, + fileType + ); + step.addAttachment(name, fileType, fileName); + }; + + if (request) { + attach(step, 'requestHeaders', request['Request Headers']); + attach(step, 'request', request['Request Body']); + } + if (response) { + attach(step, 'responseHeaders', response.headers); + attach(step, 'response', response.body); + } + } + } + } +}; + +const commandIsGherkinStep = (command) => + command.args && + command.args.length === 1 && + command.args[0] && + typeof command.args[0] === 'function' && + command.args[0].toString && + command.args[0].toString().includes('state.onStartStep'); + +const getCircularReplacer = () => { + const seen = new WeakSet(); + return (key, value) => { + if (typeof value === 'object' && value !== null) { + if (seen.has(value)) { + return; + } + seen.add(value); + } + return value; + }; +}; diff --git a/reporter/index.js b/reporter/index.js index fe4e28a..b7ad035 100644 --- a/reporter/index.js +++ b/reporter/index.js @@ -18,7 +18,7 @@ const { InMemoryAllureWriter, ContentType } = require('@shelex/allure-js-commons-browser'); -const AllureReporter = require('./mocha-allure/AllureReporter'); +const AllureReporter = require('./allure-cypress/AllureReporter'); const stubbedAllure = require('./stubbedAllure'); const logger = require('./debug'); @@ -136,8 +136,8 @@ class CypressAllureReporter { logger.mocha(`EVENT_TEST_END: %s %O`, test.title, test); attachVideo(this.reporter, test, 'finished'); - this.reporter.populateGherkinLinksFromExampleTable(); - this.reporter.handleCucumberTags(); + this.reporter.gherkin.checkLinksInExamplesTable(); + this.reporter.gherkin.checkTags(); this.reporter.endTest(); }) .on(EVENT_HOOK_BEGIN, (hook) => { @@ -152,21 +152,21 @@ class CypressAllureReporter { Cypress.on('command:enqueued', (command) => { if (shouldListenToCyCommandEvents()) { logger.cy(`command:enqueued %O`, command); - this.reporter.cyCommandEnqueue(command); + this.reporter.cy.enqueued(command); } }); Cypress.on('command:start', (command) => { if (shouldListenToCyCommandEvents()) { logger.cy(`command:start %O`, command); - this.reporter.cyCommandStart(command.attributes); + this.reporter.cy.started(command.attributes); } }); Cypress.on('command:end', (command) => { if (shouldListenToCyCommandEvents()) { logger.cy(`command:end %O`, command); - this.reporter.cyCommandEnd(command.attributes); + this.reporter.cy.finished(command.attributes); } }); } diff --git a/reporter/mocha-allure/AllureReporter.js b/reporter/mocha-allure/AllureReporter.js deleted file mode 100644 index 2333d90..0000000 --- a/reporter/mocha-allure/AllureReporter.js +++ /dev/null @@ -1,1116 +0,0 @@ -/** - * A lot of credit to Sergey Korol who made - * Allure-mocha reporter: "https://github.com/allure-framework/allure-js/tree/master/packages/allure-mocha" - */ - -const { - LabelName, - Stage, - Status -} = require('@shelex/allure-js-commons-browser'); -const crypto = require('crypto-js'); -const AllureInterface = require('./AllureInterface'); -const { tagToLabel, tagToLink, exampleNumber } = require('../gherkinToLabel'); -const { languageLabel } = require('../languageLabel'); -const stubbedAllure = require('../stubbedAllure'); -const logger = require('../debug'); -const callbacks = ['then', 'spread', 'each', 'within']; - -module.exports = class AllureReporter { - constructor(runtime, options) { - this.suites = []; - this.steps = []; - this.commands = []; - this.files = []; - this.labelStorage = []; - this.gherkinExamplesStorage = []; - this.currentChainer = null; - this.runningTest = null; - this.previousTestName = null; - this.runtime = runtime; - this.currentHook = null; - this.parentStep = null; - this.logCypress = options.logCypress || false; - this.logGherkinSteps = options.logGherkinSteps || false; - this.attachRequests = options.attachRequests || false; - } - - /** - * @returns {Allure} - */ - getInterface() { - return new AllureInterface(this, this.runtime); - } - - get currentExecutable() { - return ( - this.currentStep || - this.parentStep || - this.currentHook || - this.currentTest || - this.currentSuite - ); - } - - get currentSuite() { - if (this.suites.length === 0) { - return null; - } - return this.suites[this.suites.length - 1]; - } - - get currentSuiteIsGlobal() { - return ( - this.currentSuite && - this.currentSuite.testResultContainer.name === 'Global' - ); - } - - get currentStep() { - if (this.steps.length > 0) { - return this.steps[this.steps.length - 1]; - } - return null; - } - - get currentTest() { - return this.runningTest; - } - - set currentTest(test) { - if (this.runningTest) { - this.previousTestName = this.runningTest.info.name; - } - this.runningTest = test; - // in case labels were defined outside of test - // we could attach them from storage - if (this.runningTest) { - this.runningTest.info.labels.push(...this.labelStorage); - } - } - - get testNameForAttachment() { - const cyTest = cy.state().test; - return ( - (cyTest && cyTest.title) || - (this.currentTest && this.currentTest.info.name) || - this.previousTestName - ); - } - - originalNameOf(hook) { - return hook.hookName || hook.originalTitle || hook.title; - } - - startSuite(suiteName) { - if (this.currentSuite) { - if (this.currentSuiteIsGlobal) { - /** - * cypress creates suite for spec file - * where global hooks and other nested suites are held - * in order to have global hooks available - * this global suite can just be renamed - * to the first user's suite - */ - this.currentSuite.testResultContainer.name = suiteName; - return; - } else { - /** - * but if previous suite is not global - * it should be finished, and new one created - */ - logger.allure(`finish previous suite %O`, this.currentSuite); - this.endSuite(true); - } - } - const scope = this.currentSuite || this.runtime; - const suite = scope.startGroup(suiteName || 'Global'); - logger.allure(`start suite %O`, suite); - this.pushSuite(suite); - } - - endSuite(isGlobal = false) { - if (this.currentSuite && isGlobal) { - this.cyCommandsFinish(Status.PASSED); - logger.allure(`finished cypress commands`); - this.finishAllSteps(Status.PASSED); - logger.allure(`finished steps`); - this.currentStep !== null && this.currentStep.endStep(); - this.currentTest && - this.currentTest.testResult.stage !== Stage.FINISHED && - this.endTest(); - this.currentSuite.endGroup(); - this.popSuite(); - logger.allure(`finished suite`); - } - // restrict label storage to single suite scope - this.labelStorage = []; - } - - startCase(test, config) { - logger.allure(`starting case %s %O`, test.title, test); - if (this.currentSuite === null) { - logger.allure(`no active suite available`); - throw new Error('No active suite'); - } - - /** - * skipped test sometimes initially receives pending event - * where test will be created - * and then comes start test event followed by end test - * so start for skipped test should be omitted - * when current test is already skipped with same name - */ - if ( - this.currentTest && - this.currentTest.info.status === 'skipped' && - this.currentTest.info.name === test.title - ) { - logger.allure(`skipped test already exists`); - return; - } - - this.commands = []; - this.currentTest = this.currentSuite.startTest(test.title); - this.currentTest.fullName = test.title; - this.currentTest.historyId = crypto - .MD5(test.fullTitle()) - .toString(crypto.enc.Hex); - this.currentTest.stage = Stage.RUNNING; - - if ( - config && - config.clearFilesForPreviousAttempt() && - test._currentRetry > 0 - ) { - logger.allure(`clearing screenshots from previous retries`); - // remove screenshots from previous attempt - this.files = this.files.filter( - (file) => file.testName !== test.title - ); - } - - if (config && config.addAnalyticLabels()) { - logger.allure(`adding analytic labels`); - this.currentTest.addLabel(LabelName.FRAMEWORK, 'Cypress'); - const language = languageLabel(test); - language && this.currentTest.addLabel(LabelName.LANGUAGE, language); - } - - if (test.parent) { - const titlePath = test.parent.titlePath(); - // should add suite label for test if it has parent - if (titlePath.length === 1) { - this.currentTest.addLabel(LabelName.SUITE, titlePath.pop()); - } else { - const [parentSuite, suite, ...subSuites] = titlePath; - if (parentSuite) { - this.currentTest.addLabel( - LabelName.PARENT_SUITE, - parentSuite - ); - } - if (suite) { - this.currentTest.addLabel(LabelName.SUITE, suite); - } - if (subSuites.length > 0) { - this.currentTest.addLabel( - LabelName.SUB_SUITE, - subSuites.join(' > ') - ); - } - } - } - } - - populateGherkinLinksFromExampleTable() { - if (globalThis && globalThis.testState) { - const { testState } = globalThis; - - if (testState.currentScenario.keyword === 'Scenario Outline') { - logger.allure(`populating gherkin links from examples table`); - const scenario = testState.currentScenario; - - !this.gherkinExamplesStorage.length && - this.gherkinExamplesStorage.push(...scenario.examples); - - const example = - this.gherkinExamplesStorage.length && - this.gherkinExamplesStorage.pop(); - - if (example) { - const findCellIndex = (type) => - example.tableHeader.cells.findIndex( - (cell) => cell.value === type - ); - - const tmsCellIndex = findCellIndex('tms'); - const issueCellIndex = findCellIndex('issue'); - - const exampleRowNumber = parseInt( - exampleNumber.exec(scenario.name).pop() - ); - - if (!exampleRowNumber) { - return; - } - - const exampleRowIndex = exampleRowNumber - 1; - - const findTableCellValue = (headerIndex) => - example.tableBody[exampleRowIndex].cells[headerIndex] - .value; - - const addScenarioTag = (type, value) => { - const current = - globalThis.testState.runScenarios[scenario.name]; - - globalThis.testState.runScenarios[scenario.name].tags = - [ - ...current.tags, - { - type: 'Tag', - name: `@${type}("${value}")` - } - ]; - }; - - if (tmsCellIndex !== -1) { - const tmsId = findTableCellValue(tmsCellIndex); - logger.allure(`found tms link: %s`, issueId); - addScenarioTag('tms', tmsId); - } - - if (issueCellIndex !== -1) { - const issueId = findTableCellValue(issueCellIndex); - logger.allure(`found issue link: %s`, issueId); - addScenarioTag('issue', issueId); - } - } - } - } - } - - // accept cucumber tags from cypress-cucumber-preprocessor as commands - handleCucumberTags() { - if (globalThis && globalThis.testState) { - logger.allure(`parsing gherkin tags`); - const { testState } = globalThis; - const { currentTest } = this; - - // set bdd feature by default - currentTest.addLabel('feature', testState.feature.name); - - /** - * tags set on test level has higher priority - * to not be overwritten by feature tags - */ - ['feature', 'currentScenario'].forEach(function (type) { - logger.allure(`tags for %s`, type); - testState[type] && - testState[type].tags - // check for labels - .filter(function ({ name }) { - const match = tagToLabel.exec(name); - if (match) { - const [, command, value] = match; - // feature and suite should be overwritten to avoid duplicates - if (['feature', 'suite'].includes(command)) { - const index = - currentTest.info.labels.findIndex( - (label) => label.name === command - ); - currentTest.info.labels[index] = { - name: command, - value: value - }; - } else { - currentTest.addLabel(command, value); - } - } - return !match; - }) - // check for links - .filter(function ({ name }) { - const match = tagToLink.exec(name); - if (match) { - const [, command, name, matchUrl] = match; - - const url = matchUrl || name; - - const prefixBy = { - issue: Cypress.env('issuePrefix'), - tms: Cypress.env('tmsPrefix'), - link: null - }; - const urlPrefix = prefixBy[command]; - - const pattern = - urlPrefix && urlPrefix.includes('*') - ? urlPrefix - : `${urlPrefix}*`; - currentTest.addLink( - urlPrefix && pattern - ? pattern.replace(/\*/g, url) - : url, - name, - command - ); - } - return !match; - }) - // add other tags - .forEach(function ({ name }) { - currentTest.addLabel('tag', name.replace('@', '')); - }); - }); - } - } - - passTestCase(test) { - if (this.currentTest === null) { - logger.allure(`not found allure test, created new`); - this.startCase(test); - } - this.updateTest(Status.PASSED); - logger.allure(`set passed for test: %s %O`, test.title, test); - } - - pendingTestCase(test) { - this.startCase(test); - this.updateTest(Status.SKIPPED, { message: 'Test ignored' }); - logger.allure( - `created new test and set to pending: %s %O`, - test.title, - test - ); - } - - failTestCase(test, error) { - logger.allure( - `received test failed event: %s, %O, %O`, - test.title, - test, - error - ); - if (this.currentTest === null) { - logger.allure(`not found test, created new`); - this.startCase(test); - } - - this.updateTest(Status.FAILED, { - message: error.message, - trace: error.stack - }); - /** - * in case error comes from hook - */ - if (test.type === 'hook') { - logger.allure(`test error origin is hook`); - this.endHook(test, true); - /** - * in case of before all cypress creates new test - * which not produce any mocha events - * as result should be finished manually - */ - - if ( - test.hookName && - ['before all', 'before each'].includes(test.hookName) - ) { - logger.allure( - `finishing test as no events received for failed test in before all hook` - ); - - // mark failed tests as broken due to before all hook failure - if (test.parent && test.parent.tests) { - test.parent.tests.forEach((test, index) => { - logger.allure( - `found cancelled test due to before all hook: %O`, - test - ); - if (index === 0) { - this.currentTest.info.name = test.title; - } else { - this.startCase(test); - } - this.updateTest(Status.BROKEN, { - message: error.message, - trace: error.stack - }); - this.endTest(); - }); - } else { - this.endTest(); - } - } - } - } - - writeAttachment(content, type) { - return this.runtime.writeAttachment(content, type); - } - - pushStep(step) { - this.steps.push(step); - } - - popStep() { - return this.steps.pop(); - } - - finishAllSteps(status = Status.PASSED) { - this.steps.forEach((step) => { - step.info.stage = Stage.FINISHED; - if (step.info.steps.length) { - step.info.status = step.info.steps.some( - (step) => step.status === Status.FAILED - ) - ? Status.FAILED - : Status.PASSED; - } else { - step.info.status = status; - } - step.endStep(); - }); - this.steps = []; - if (this.parentStep) { - this.parentStep.info.stage = Stage.FINISHED; - this.parentStep.info.status = status; - this.parentStep.endStep(); - } - } - - startHook(hook) { - logger.allure(`starting hook %s`, hook.title); - if (!this.currentSuite || isEmpty(hook)) { - logger.allure(`no suite or hook is empty function`); - return; - } - /** - * When hook is global - it is attached to suite - * and will be displayed as precondition - * `each` hooks will be available as test steps - */ - if (this.originalNameOf(hook).includes('all')) { - const parent = this.currentSuite; - const allureHook = this.originalNameOf(hook).includes('before') - ? parent.addBefore() - : parent.addAfter(); - this.currentHook = allureHook; - } else { - if (!this.logCypress) { - return; - } - const customHookName = hook.title.replace( - /\"(before|after) each\" hook:? */g, - '' - ); - - const step = this.currentTest.startStep( - customHookName || hook.title - ); - this.currentHook = step; - } - } - - endHook(hook, failed = false) { - logger.allure(`finishing hook %s`, hook.title); - if (!this.currentSuite || !this.currentHook || isEmpty(hook)) { - logger.allure(`no suite or no hook or hook is empty function`); - return; - } - // should define results property for all or each hook - const currentHookInfo = this.originalNameOf(hook).includes('all') - ? this.currentHook.info - : this.currentHook.stepResult; - - if (hook.err) { - currentHookInfo.status = Status.FAILED; - currentHookInfo.stage = Stage.FINISHED; - currentHookInfo.statusDetails = { - message: hook.err.message, - trace: hook.err.stack - }; - } else { - currentHookInfo.status = Status.PASSED; - currentHookInfo.stage = Stage.FINISHED; - } - - // in case hook is a step we should complete it - if (this.originalNameOf(hook).includes('each')) { - this.currentHook && this.currentHook.endStep(); - } - !failed && (this.currentHook = null); - } - - pushSuite(suite) { - this.suites.push(suite); - } - - popSuite() { - this.suites.pop(); - } - - updateTest(status, details) { - if (this.currentTest === null) { - throw new Error('finishing test while no test is running'); - } - (this.logCypress || this.logGherkinSteps) && - this.cyCommandsFinish(status); - this.finishAllSteps(status); - this.parentStep = null; - - logger.allure( - `updating test %O to have status:%s and details: %O`, - this.currentTest, - status, - details - ); - - details && (this.currentTest.statusDetails = details); - this.currentTest.status = status; - this.currentTest.stage = Stage.FINISHED; - this.currentTest.testResult.stop = Date.now(); - } - - endTest() { - logger.allure(`finishing current test`); - this.currentTest && this.currentTest.endTest(); - } - - cyCommandShouldBeLogged(attributes) { - // handle case when nothing should be logged - if (!this.logCypress && !this.logGherkinSteps) { - logger.cy(`logging cy commands is disabled`); - return false; - } - - // handle case when should log gherkin steps but not cy commands - if ( - this.logGherkinSteps && - !this.logCypress && - !attributeIsGherkinStep(attributes) - ) { - logger.cy(`is not a gherkin step`); - return false; - } - return true; - } - - cyCommandExecutable(command) { - if (command.parent) { - const parent = this.commands.find( - (c) => c.id === command.parent && c.step && !c.finished - ); - - if (!parent) { - return this.currentExecutable; - } - - // such commands contain argument - // which is basically a function that will be executed - if (callbacks.includes(parent.name)) { - return this.cyCommandExecutable(parent); - } - - // in case latest step in newer then parent - attach to user defined step - return this.currentStep && - this.currentStep.info.start > parent.step.info.start - ? this.currentStep - : parent.step; - } - return this.currentExecutable; - } - - cyCommandEnqueue(attributes) { - logger.cy(`cyCommandEnqueue: %s %O`, attributes.name, attributes); - // skipped are: - // assertions, as they don't receive command:start and command:end events and are hardly trackable - // allure custom command used for interacting with allure api - // commands, where second argument has {log: false} - // commands, which are child commands of cy.allure command - const commandShouldBeSkipped = (attributes) => { - return ( - attributes.type === 'assertion' || - attributes.name === 'allure' || - (Object.getOwnPropertyNames( - stubbedAllure.reporter.getInterface() - ).includes(attributes.name) && - attributes.type === 'child') || - (attributes.args && - attributes.args.length && - attributes.args.find((arg) => arg && arg.log === false)) - ); - }; - - if (commandShouldBeSkipped(attributes)) { - logger.cy(`command should be skipped`); - return; - } - - // prepare chainer command object with specific information to process it with events - const command = { - id: attributes.chainerId, - name: attributes.name, - type: attributes.type, - parent: this.currentChainer && this.currentChainer.chainerId, - children: [], - passed: true, // will be set false in case failed or failed child command - finished: false, - step: null, - commandLog: null - }; - - this.commands.push(command); - logger.cy(`tracking command: %O`, command); - - // in case command in enqueued while there was active chainer - treat it as parent - // so this command should be added as child to track if we should finish parent command step - if (command.parent) { - const parent = this.commands.find( - (c) => c.id === command.parent && !c.finished && c.step - ); - // set new child from start as command queue works as LIFO (last in - first out) approach - parent && parent.children.unshift(command.id); - logger.cy(`added as child of command: %O`, parent); - } - } - - cyCommandStart(attributes) { - logger.cy(`cyCommandStart: %s %O`, attributes.name, attributes); - // check if we have enqueued command - const command = this.commands.find( - (command) => - command.id === attributes.chainerId && - command.name === attributes.name && - !command.step && - !command.finished - ); - - if (!command) { - logger.cy(`command not available`); - return; - } - - logger.cy(`tracked info about command: %O`, command); - - command.commandLog = attributes; - - // add dummy allure step implementation for "then" commands to avoid adding them to report - // as they mostly expose other plugin internals and other functions not related to test - // on other hand, if they produce info for command log - step will be created when command end - if (callbacks.includes(command.name)) { - command.step = { - info: {}, - stepResult: {}, - endStep() {} - }; - } else { - const executable = this.cyCommandExecutable(command); - - const displayArg = (arg) => { - logger.cy(`checking argument %O and provide to step`, arg); - if (typeof arg === 'function') { - return '[function]'; - } - if (typeof arg === 'object') { - if ( - arg && - arg.constructor && - arg.constructor.toString && - typeof arg.constructor.toString === 'function' && - ((arg.constructor.toString().includes('HTML') && - arg.constructor.toString().includes('Element')) || - arg.constructor - .toString() - .includes('The jQuery object')) - ) { - return '[Object]'; - } - - return JSON.stringify(arg, getCircularReplacer(), 2); - } - - return arg; - }; - - const commandArgs = - attributes.args.length && - attributes.args.map((arg) => `"${displayArg(arg)}"`).join('; '); - - const step = - this.cyCommandShouldBeLogged(attributes) && - executable.startStep( - `${command.name}${commandArgs ? ` (${commandArgs})` : ''}` - ); - - if (step) { - logger.cy(`started allure step %s %O`, step.info.name, step); - - command.step = step; - } - } - this.currentChainer = attributes; - } - - cyCommandEnd(attributes, failed = false) { - logger.cy(`cyCommandEnd: %s %O`, attributes.name, attributes); - // check if we have enqueued command - const command = this.commands.find( - (command) => - command.id === attributes.chainerId && - command.name === attributes.name && - command.step && - !command.finished - ); - - if (!command) { - logger.cy(`command not available`); - return; - } - - logger.cy(`tracked info about command: %O`, command); - this.currentChainer = null; - - // in case no children enqueued - finish this step - if (!command.children.length || failed) { - logger.cy(`no children enqueued left, finishing step`); - // check if command has some entries for command log - if (command.commandLog.logs.length) { - logger.cy( - `found command log entries %O`, - command.commandLog.logs - ); - // set first command log (which refers to current command) as last - // and process other child logs first (asserts are processed such way) - - command.commandLog.logs.push(command.commandLog.logs.shift()); - - command.commandLog.logs.forEach((entry, index) => { - let log; - - // try...catch for handling case when Cypress.log has error in consoleProps function - try { - log = entry.toJSON(); - } catch (e) { - logger.cy( - `could not call toJSON for command log entry #%d, %O`, - index, - entry - ); - return; - } - logger.cy(`checking entry #%d, %O`, index, log); - - // for main log (which we set last) we should finish command step - if (index === command.commandLog.logs.length - 1) { - logger.cy(`last entry, finishing step`); - // in case "then" command has some logging - create step for that - if (callbacks.includes(command.name)) { - const executable = - this.cyCommandExecutable(command); - - if ( - !this.logGherkinSteps && - attributeIsGherkinStep(attributes) - ) { - return; - } - - const step = this.cyStartStepForLog( - executable, - log - ); - logger.cy(`creating step for then's %O`, step); - - command.step = step; - - if (log.name === 'step') { - logger.cy( - `found gherkin step, finishing all current steps` - ); - this.finishAllSteps( - command.passed - ? Status.PASSED - : Status.FAILED - ); - this.steps.push(step); - this.parentStep = step; - } - } - - const commandPassed = this.cyCommandEndStep( - command.step, - log, - command.passed - ); - - !commandPassed && (command.passed = false); - } else { - // handle case when other logs refer to chained assertions - // so steps should be created - const executable = this.cyCommandExecutable({ - id: log.id, - parent: command.parent - }); - - const step = this.cyStartStepForLog(executable, log); - logger.cy( - `attaching command log entries as allure steps %O`, - step - ); - - const commandPassed = this.cyCommandEndStep(step, log); - - !commandPassed && (command.passed = false); - } - }); - } else { - logger.cy( - `no command log entries, finish step %O`, - command.step - ); - this.cyCommandEndStep( - command.step, - { - state: command.passed ? Status.PASSED : Status.FAILED - }, - command.passed - ); - } - command.finished = true; - !command.passed && (failed = true); - // notify parent that one of child commands is finished - // and pass status - this.cyRemoveChildFromParent(command, failed); - } - } - - cyRemoveChildFromParent(child, failed = false) { - if (child.parent) { - const parent = this.commands.find( - (c) => c.id === child.parent && c.step && !c.finished - ); - - // better to skip case when no parent found - if (!parent) { - return; - } - - logger.cy(`command has parent, %O`, parent); - - const childIndex = parent.children.indexOf(child.id); - - // if found child - remove it from parent - if (childIndex > -1) { - logger.cy(`removing child from parent %O`, parent); - parent.children.splice(childIndex, 1); - // update status of parent in case any of children failed - if (!child.passed || failed) { - parent.passed = false; - } - } - - // finish parent step when no children left or when test is failed - if (!parent.children.length || failed) { - logger.cy( - `finish parent step as no other children left %O`, - parent - ); - !parent.passed && (failed = true); - this.cyCommandEnd(parent.commandLog, failed); - } - } - } - - cyCommandsFinish(state = Status.FAILED) { - // process all not finished steps from chainer left - // usually is executed on fail - this.commands - .filter((c) => !c.finished && c.step) - .reverse() - .forEach((command) => { - !command.finished && - this.cyCommandEnd( - command.commandLog, - state === Status.FAILED - ); - }); - this.currentChainer = null; - } - - cyCommandEndStep(step, log, commandStatus) { - if ( - // check for requests - log.name === 'request' || - // or for then commands which have requests being logged in command log - (log.name === 'then' && - log.consoleProps && - log.consoleProps.Request) - ) { - if (log.renderProps && log.renderProps.message) { - step.info.name = log.renderProps.message; - } - - if (this.attachRequests && log.consoleProps) { - const request = - log.consoleProps.Request || - Cypress._.last(log.consoleProps.Requests); - const response = log.consoleProps.Yielded; - - const attach = (step, name, content) => { - if (!content) { - return; - } - - let jsonContent; - - try { - jsonContent = - typeof content === 'string' - ? JSON.parse(content) - : content; - } catch (e) { - // content is not json - } - - const fileType = jsonContent - ? 'application/json' - : 'text/plain'; - const fileName = this.writeAttachment( - jsonContent - ? JSON.stringify(jsonContent, null, 2) - : content, - fileType - ); - step.addAttachment(name, fileType, fileName); - }; - - if (request) { - attach(step, 'requestHeaders', request['Request Headers']); - attach(step, 'request', request['Request Body']); - } - if (response) { - attach(step, 'responseHeaders', response.headers); - attach(step, 'response', response.body); - } - } - } - - const logNameNoOverride = ['request', 'step']; - if ( - step && - step.info && - step.info.name && - log.name && - log.message && - !logNameNoOverride.includes(log.name) - ) { - step.info.name = `${log.name} ${log.message}`; - logger.cy(`changing step name to "%s" %O`, step.info.name, step); - } - - const passed = - log && log.err - ? false - : commandStatus || log.state !== Status.FAILED; - - step.info.stage = Stage.FINISHED; - - step.info.status = passed ? Status.PASSED : Status.FAILED; - - log.name !== 'step' && step.endStep(); - return passed; - } - - cyStartStepForLog(executable, log) { - logger.cy(`creating step for command log entry %O`, log); - // define step name based on cypress log name or messages - const messages = { - xhr: () => - `${ - (log.consoleProps.Stubbed === 'Yes' ? 'STUBBED ' : '') + - log.consoleProps.Method - } ${log.consoleProps.URL}`, - step: () => `${log.displayName}${log.message.replace(/\*/g, '')}`, - stub: () => - `${log.name} [ function: ${log.functionName} ] ${ - log.alias ? `as ${log.alias}` : '' - }`, - route: () => `${log.name} ${log.method} ${log.url}`, - default: () => - log.message ? `${log.message} ${log.name}` : `${log.name}` - }; - - // handle cases with stubs name containing increments (stub-1, stub-2, etc.) - const lookupName = log.name.startsWith('stub') ? 'stub' : log.name; - - const message = messages[lookupName] || messages.default; - - // in case log name is "step" - assumed that it comes from cucumber preprocessor - // in case it is cucumber step - executable should be current test - if (log.name === 'step') { - executable = this.currentTest; - } - - const newStep = executable.startStep(message()); - - // parse docString for gherkin steps - if ( - log.name === 'step' && - log.consoleProps && - log.consoleProps.step && - log.consoleProps.step.argument && - log.consoleProps.step.argument.content - ) { - newStep.addParameter( - log.consoleProps.step.argument.type, - log.consoleProps.step.argument.content - ); - } - - // add expected and actual for asserts - if (log.name === 'assert') { - const displayValue = (value) => - typeof value === 'object' - ? JSON.stringify(value, getCircularReplacer(), 2) - : value; - - logger.cy( - '[allure:cy] adding actual and expected as a parameter %O', - log - ); - - log.actual && - newStep.addParameter('actual', displayValue(log.actual)); - log.expected && - newStep.addParameter('expected', displayValue(log.expected)); - } - - return newStep; - } -}; - -const attributeIsGherkinStep = (attribute) => - attribute.args && - attribute.args.length === 1 && - attribute.args[0] && - typeof attribute.args[0] === 'function' && - attribute.args[0].toString && - attribute.args[0].toString().includes('state.onStartStep'); - -const isEmpty = (hook) => hook && hook.body === 'function () {}'; - -const getCircularReplacer = () => { - const seen = new WeakSet(); - return (key, value) => { - if (typeof value === 'object' && value !== null) { - if (seen.has(value)) { - return; - } - seen.add(value); - } - return value; - }; -}; diff --git a/yarn.lock b/yarn.lock index 3c9cf07..e66ec61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -838,7 +838,7 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== -"@isaacs/string-locale-compare@*", "@isaacs/string-locale-compare@^1.0.1": +"@isaacs/string-locale-compare@^1.0.1", "@isaacs/string-locale-compare@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ== @@ -864,20 +864,20 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@npmcli/arborist@*", "@npmcli/arborist@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-4.0.0.tgz#cdee5800c4d9a5351ede8544008cf6690e066c46" - integrity sha512-UtgFRDJGgnFNONW9hjyq0ft6fQPK8nLuYyFFXlhaEKVl7+/rhtUG0t7TWwu8CBXn7KjxhbHZgIlZBKIE+v1C6g== +"@npmcli/arborist@^2.3.0", "@npmcli/arborist@^2.5.0", "@npmcli/arborist@^2.9.0": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-2.10.0.tgz#424c2d73a7ae59c960b0cc7f74fed043e4316c2c" + integrity sha512-CLnD+zXG9oijEEzViimz8fbOoFVb7hoypiaf7p6giJhvYtrxLAyY3cZAMPIFQvsG731+02eMDp3LqVBNo7BaZA== dependencies: "@isaacs/string-locale-compare" "^1.0.1" "@npmcli/installed-package-contents" "^1.0.7" "@npmcli/map-workspaces" "^1.0.2" - "@npmcli/metavuln-calculator" "^2.0.0" + "@npmcli/metavuln-calculator" "^1.1.0" "@npmcli/move-file" "^1.1.0" "@npmcli/name-from-folder" "^1.0.1" "@npmcli/node-gyp" "^1.0.1" "@npmcli/package-json" "^1.0.1" - "@npmcli/run-script" "^2.0.0" + "@npmcli/run-script" "^1.8.2" bin-links "^2.2.1" cacache "^15.0.3" common-ancestor-path "^1.0.1" @@ -889,7 +889,7 @@ npm-package-arg "^8.1.5" npm-pick-manifest "^6.1.0" npm-registry-fetch "^11.0.0" - pacote "^12.0.0" + pacote "^11.3.5" parse-conflict-json "^1.1.1" proc-log "^1.0.0" promise-all-reject-late "^1.0.0" @@ -902,12 +902,17 @@ treeverse "^1.0.4" walk-up-path "^1.0.0" -"@npmcli/ci-detect@*", "@npmcli/ci-detect@^1.3.0": +"@npmcli/ci-detect@^1.2.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@npmcli/ci-detect/-/ci-detect-1.4.0.tgz#18478bbaa900c37bfbd8a2006a6262c62e8b0fe1" + integrity sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q== + +"@npmcli/ci-detect@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@npmcli/ci-detect/-/ci-detect-1.3.0.tgz#6c1d2c625fb6ef1b9dea85ad0a5afcbef85ef22a" integrity sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q== -"@npmcli/config@*": +"@npmcli/config@^2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-2.3.0.tgz#364fbe942037e562a832a113206e14ccb651f7bc" integrity sha512-yjiC1xv7KTmUTqfRwN2ZL7BHV160ctGF0fLXmKkkMXj40UOvBe45Apwvt5JsFRtXSoHkUYy1ouzscziuWNzklg== @@ -955,7 +960,7 @@ npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" -"@npmcli/map-workspaces@*", "@npmcli/map-workspaces@^1.0.2": +"@npmcli/map-workspaces@^1.0.2", "@npmcli/map-workspaces@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-1.0.4.tgz#915708b55afa25e20bc2c14a766c124c2c5d4cab" integrity sha512-wVR8QxhyXsFcD/cORtJwGQodeeaDf0OxcHie8ema4VgFeqwYkFsDPnSrIRSytX8xR6nKPAH89WnwTcaU608b/Q== @@ -965,14 +970,13 @@ minimatch "^3.0.4" read-package-json-fast "^2.0.1" -"@npmcli/metavuln-calculator@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-2.0.0.tgz#70937b8b5a5cad5c588c8a7b38c4a8bd6f62c84c" - integrity sha512-VVW+JhWCKRwCTE+0xvD6p3uV4WpqocNYYtzyvenqL/u1Q3Xx6fGTJ+6UoIoii07fbuEO9U3IIyuGY0CYHDv1sg== +"@npmcli/metavuln-calculator@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-1.1.1.tgz#2f95ff3c6d88b366dd70de1c3f304267c631b458" + integrity sha512-9xe+ZZ1iGVaUovBVFI9h3qW+UuECUzhvZPxK9RaEA2mjU26o5D0JloGYWwLYvQELJNmBdQB6rrpuN8jni6LwzQ== dependencies: cacache "^15.0.5" - json-parse-even-better-errors "^2.3.1" - pacote "^12.0.0" + pacote "^11.1.11" semver "^7.3.2" "@npmcli/move-file@^1.0.1", "@npmcli/move-file@^1.1.0": @@ -993,7 +997,7 @@ resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz#a912e637418ffc5f2db375e93b85837691a43a33" integrity sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA== -"@npmcli/package-json@*", "@npmcli/package-json@^1.0.1": +"@npmcli/package-json@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-1.0.1.tgz#1ed42f00febe5293c3502fd0ef785647355f6e89" integrity sha512-y6jnu76E9C23osz8gEMBayZmaZ69vFOIk8vR1FJL/wbEJ54+9aVG9rLTjQKSXfgYZEr50nw1txBBFfBZZe+bYg== @@ -1007,17 +1011,7 @@ dependencies: infer-owner "^1.0.4" -"@npmcli/run-script@*", "@npmcli/run-script@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-2.0.0.tgz#9949c0cab415b17aaac279646db4f027d6f1e743" - integrity sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig== - dependencies: - "@npmcli/node-gyp" "^1.0.2" - "@npmcli/promise-spawn" "^1.3.2" - node-gyp "^8.2.0" - read-package-json-fast "^2.0.1" - -"@npmcli/run-script@^1.8.2": +"@npmcli/run-script@^1.8.2", "@npmcli/run-script@^1.8.3", "@npmcli/run-script@^1.8.4", "@npmcli/run-script@^1.8.6": version "1.8.6" resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-1.8.6.tgz#18314802a6660b0d4baa4c3afe7f1ad39d8c28b7" integrity sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g== @@ -1275,7 +1269,7 @@ JSONStream@^1.0.3, JSONStream@^1.0.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -abbrev@*, abbrev@1: +abbrev@1, abbrev@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== @@ -1394,12 +1388,12 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.3.0: dependencies: color-convert "^2.0.1" -ansicolors@*, ansicolors@~0.3.2: +ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= -ansistyles@*: +ansistyles@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk= @@ -1432,7 +1426,7 @@ arch@^2.2.0: resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== -archy@*: +archy@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= @@ -2003,7 +1997,7 @@ builtins@^1.0.3: resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= -cacache@*, cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0: +cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0, cacache@^15.3.0: version "15.3.0" resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== @@ -2109,14 +2103,6 @@ chai@^4.1.2: pathval "^1.1.1" type-detect "^4.0.5" -chalk@*, chalk@^4.0.0, chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -2137,6 +2123,14 @@ chalk@^2.0.0, chalk@^2.3.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -2166,7 +2160,7 @@ chokidar@^2.0.4, chokidar@^2.1.1: optionalDependencies: fsevents "^1.2.7" -chownr@*, chownr@^2.0.0: +chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== @@ -2206,13 +2200,13 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-columns@*: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-4.0.0.tgz#9fe4d65975238d55218c41bd2ed296a7fa555646" - integrity sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ== +cli-columns@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-3.1.2.tgz#6732d972979efc2ae444a1f08e08fa139c96a18e" + integrity sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4= dependencies: - string-width "^4.2.3" - strip-ansi "^6.0.1" + string-width "^2.0.0" + strip-ansi "^3.0.1" cli-cursor@^1.0.2: version "1.0.2" @@ -2228,7 +2222,7 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-table3@*, cli-table3@^0.6.0, cli-table3@~0.6.0: +cli-table3@^0.6.0, cli-table3@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee" integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== @@ -2344,7 +2338,7 @@ colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -columnify@*: +columnify@~1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= @@ -3428,7 +3422,7 @@ fast-safe-stringify@^2.0.7: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== -fastest-levenshtein@*: +fastest-levenshtein@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== @@ -3741,7 +3735,7 @@ glob-parent@^5.1.2: dependencies: is-glob "^4.0.1" -glob@*, glob@^7.0.0, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.0, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -3784,7 +3778,7 @@ globby@^11.0.0, globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" -graceful-fs@*, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.8: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== @@ -3915,18 +3909,18 @@ hook-std@^2.0.0: resolved "https://registry.yarnpkg.com/hook-std/-/hook-std-2.0.0.tgz#ff9aafdebb6a989a354f729bb6445cf4a3a7077c" integrity sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g== -hosted-git-info@*, hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.0, hosted-git-info@^4.0.1, hosted-git-info@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== dependencies: lru-cache "^6.0.0" -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - htmlescape@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" @@ -4004,13 +3998,6 @@ ignore-walk@^3.0.3: dependencies: minimatch "^3.0.4" -ignore-walk@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-4.0.1.tgz#fc840e8346cf88a3a9380c5b17933cd8f4d39fa3" - integrity sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw== - dependencies: - minimatch "^3.0.4" - ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -4079,7 +4066,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@*, ini@2.0.0, ini@^2.0.0: +ini@2.0.0, ini@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== @@ -4089,7 +4076,7 @@ ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -init-package-json@*: +init-package-json@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-2.0.5.tgz#78b85f3c36014db42d8f32117252504f68022646" integrity sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA== @@ -4188,7 +4175,7 @@ is-ci@^3.0.0: dependencies: ci-info "^3.1.1" -is-cidr@*: +is-cidr@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-4.0.2.tgz#94c7585e4c6c77ceabf920f8cde51b8c0fda8814" integrity sha512-z4a1ENUajDbEl/Q6/pVBpTR1nBjjEE1X7qb7bmWYanNnPoKAvUCPFKeXV6Fe4mgTkWKBqiHIcwsI3SndiO5FeA== @@ -4467,7 +4454,7 @@ json-parse-better-errors@^1.0.1: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-parse-even-better-errors@*, json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -4614,7 +4601,7 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -libnpmaccess@*: +libnpmaccess@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-4.0.3.tgz#dfb0e5b0a53c315a2610d300e46b4ddeb66e7eec" integrity sha512-sPeTSNImksm8O2b6/pf3ikv4N567ERYEpeKRPSmqlNt1dTZbvgpJIzg5vAhXHpw2ISBsELFRelk0jEahj1c6nQ== @@ -4624,7 +4611,7 @@ libnpmaccess@*: npm-package-arg "^8.1.2" npm-registry-fetch "^11.0.0" -libnpmdiff@*: +libnpmdiff@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/libnpmdiff/-/libnpmdiff-2.0.4.tgz#bb1687992b1a97a8ea4a32f58ad7c7f92de53b74" integrity sha512-q3zWePOJLHwsLEUjZw3Kyu/MJMYfl4tWCg78Vl6QGSfm4aXBUSVzMzjJ6jGiyarsT4d+1NH4B1gxfs62/+y9iQ== @@ -4638,31 +4625,31 @@ libnpmdiff@*: pacote "^11.3.0" tar "^6.1.0" -libnpmexec@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/libnpmexec/-/libnpmexec-3.0.1.tgz#bc2fddf1b7bd2c1b2c43b4b726ec4cf11920ad0a" - integrity sha512-VUZTpkKBRPv3Z9DIjbsiHhEQXmQ+OwSQ/yLCY9i6CFE8UIczWyE6wVxP5sJ5NSGtSTUs6I98WewQOL45OKMyxA== +libnpmexec@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/libnpmexec/-/libnpmexec-2.0.1.tgz#729ae3e15a3ba225964ccf248117a75d311eeb73" + integrity sha512-4SqBB7eJvJWmUKNF42Q5qTOn20DRjEE4TgvEh2yneKlAiRlwlhuS9MNR45juWwmoURJlf2K43bozlVt7OZiIOw== dependencies: - "@npmcli/arborist" "^4.0.0" + "@npmcli/arborist" "^2.3.0" "@npmcli/ci-detect" "^1.3.0" - "@npmcli/run-script" "^2.0.0" + "@npmcli/run-script" "^1.8.4" chalk "^4.1.0" mkdirp-infer-owner "^2.0.0" npm-package-arg "^8.1.2" - pacote "^12.0.0" + pacote "^11.3.1" proc-log "^1.0.0" read "^1.0.7" read-package-json-fast "^2.0.2" walk-up-path "^1.0.0" -libnpmfund@*: - version "2.0.1" - resolved "https://registry.yarnpkg.com/libnpmfund/-/libnpmfund-2.0.1.tgz#3c7e2be61e8c79e22c4918dde91ef57f64faf064" - integrity sha512-OhDbjB3gqdRyuQ56AhUtO49HZ7cZHSM7yCnhQa1lsNpmAmGPnjCImfx8SoWaAkUM7Ov8jngMR5JHKAr1ddjHTQ== +libnpmfund@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/libnpmfund/-/libnpmfund-1.1.0.tgz#ee91313905b3194b900530efa339bc3f9fc4e5c4" + integrity sha512-Kfmh3pLS5/RGKG5WXEig8mjahPVOxkik6lsbH4iX0si1xxNi6eeUh/+nF1MD+2cgalsQif3O5qyr6mNz2ryJrQ== dependencies: - "@npmcli/arborist" "^4.0.0" + "@npmcli/arborist" "^2.5.0" -libnpmhook@*: +libnpmhook@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-6.0.3.tgz#1d7f0d7e6a7932fbf7ce0881fdb0ed8bf8748a30" integrity sha512-3fmkZJibIybzmAvxJ65PeV3NzRc0m4xmYt6scui5msocThbEp4sKFT80FhgrCERYDjlUuFahU6zFNbJDHbQ++g== @@ -4670,7 +4657,7 @@ libnpmhook@*: aproba "^2.0.0" npm-registry-fetch "^11.0.0" -libnpmorg@*: +libnpmorg@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-2.0.3.tgz#4e605d4113dfa16792d75343824a0625c76703bc" integrity sha512-JSGl3HFeiRFUZOUlGdiNcUZOsUqkSYrg6KMzvPZ1WVZ478i47OnKSS0vkPmX45Pai5mTKuwIqBMcGWG7O8HfdA== @@ -4678,16 +4665,16 @@ libnpmorg@*: aproba "^2.0.0" npm-registry-fetch "^11.0.0" -libnpmpack@*: - version "3.0.0" - resolved "https://registry.yarnpkg.com/libnpmpack/-/libnpmpack-3.0.0.tgz#b1cdf182106bc0d25910e79bb5c9b6c23cd71670" - integrity sha512-W6lt4blkR9YXu/qOrFknfnKBajz/1GvAc5q1XcWTGuBJn2DYKDWHtA7x1fuMQdn7hKDBOPlZ/Aqll+ZvAnrM6g== +libnpmpack@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/libnpmpack/-/libnpmpack-2.0.1.tgz#d3eac25cc8612f4e7cdeed4730eee339ba51c643" + integrity sha512-He4/jxOwlaQ7YG7sIC1+yNeXeUDQt8RLBvpI68R3RzPMZPa4/VpxhlDo8GtBOBDYoU8eq6v1wKL38sq58u4ibQ== dependencies: - "@npmcli/run-script" "^2.0.0" + "@npmcli/run-script" "^1.8.3" npm-package-arg "^8.1.0" - pacote "^12.0.0" + pacote "^11.2.6" -libnpmpublish@*: +libnpmpublish@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-4.0.2.tgz#be77e8bf5956131bcb45e3caa6b96a842dec0794" integrity sha512-+AD7A2zbVeGRCFI2aO//oUmapCwy7GHqPXFJh3qpToSRNU+tXKJ2YFUgjt04LPPAf2dlEH95s6EhIHM1J7bmOw== @@ -4698,14 +4685,14 @@ libnpmpublish@*: semver "^7.1.3" ssri "^8.0.1" -libnpmsearch@*: +libnpmsearch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-3.1.2.tgz#aee81b9e4768750d842b627a3051abc89fdc15f3" integrity sha512-BaQHBjMNnsPYk3Bl6AiOeVuFgp72jviShNBw5aHaHNKWqZxNi38iVNoXbo6bG/Ccc/m1To8s0GtMdtn6xZ1HAw== dependencies: npm-registry-fetch "^11.0.0" -libnpmteam@*: +libnpmteam@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-2.0.4.tgz#9dbe2e18ae3cb97551ec07d2a2daf9944f3edc4c" integrity sha512-FPrVJWv820FZFXaflAEVTLRWZrerCvfe7ZHSMzJ/62EBlho2KFlYKjyNEsPW3JiV7TLSXi3vo8u0gMwIkXSMTw== @@ -4713,13 +4700,13 @@ libnpmteam@*: aproba "^2.0.0" npm-registry-fetch "^11.0.0" -libnpmversion@*: - version "2.0.1" - resolved "https://registry.yarnpkg.com/libnpmversion/-/libnpmversion-2.0.1.tgz#20b1425d88cd99c66806a54b458d2d654066b550" - integrity sha512-uFGtNTe/m0GOIBQCE4ryIsgGNJdeShW+qvYtKNLCCuiG7JY3YEslL/maFFZbaO4wlQa/oj1t0Bm9TyjahvtgQQ== +libnpmversion@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/libnpmversion/-/libnpmversion-1.2.1.tgz#689aa7fe0159939b3cbbf323741d34976f4289e9" + integrity sha512-AA7x5CFgBFN+L4/JWobnY5t4OAHjQuPbAwUYJ7/NtHuyLut5meb+ne/aj0n7PWNiTGCJcRw/W6Zd2LoLT7EZuQ== dependencies: "@npmcli/git" "^2.0.7" - "@npmcli/run-script" "^2.0.0" + "@npmcli/run-script" "^1.8.4" json-parse-even-better-errors "^2.3.1" semver "^7.3.5" stringify-package "^1.0.1" @@ -4864,7 +4851,7 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-fetch-happen@*, make-fetch-happen@^9.0.1: +make-fetch-happen@^9.0.1, make-fetch-happen@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== @@ -4886,27 +4873,6 @@ make-fetch-happen@*, make-fetch-happen@^9.0.1: socks-proxy-agent "^6.0.0" ssri "^8.0.0" -make-fetch-happen@^8.0.14: - version "8.0.14" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz#aaba73ae0ab5586ad8eaa68bd83332669393e222" - integrity sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ== - dependencies: - agentkeepalive "^4.1.3" - cacache "^15.0.5" - http-cache-semantics "^4.1.0" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^6.0.0" - minipass "^3.1.3" - minipass-collect "^1.0.2" - minipass-fetch "^1.3.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - promise-retry "^2.0.1" - socks-proxy-agent "^5.0.0" - ssri "^8.0.0" - map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -5108,7 +5074,7 @@ minipass-json-stream@^1.0.1: jsonparse "^1.3.1" minipass "^3.0.0" -minipass-pipeline@*, minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: +minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== @@ -5122,7 +5088,7 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@*, minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: version "3.1.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732" integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw== @@ -5150,7 +5116,7 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp-infer-owner@*, mkdirp-infer-owner@^2.0.0: +mkdirp-infer-owner@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz#55d3b368e7d89065c38f32fd38e638f0ab61d316" integrity sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw== @@ -5159,11 +5125,6 @@ mkdirp-infer-owner@*, mkdirp-infer-owner@^2.0.0: infer-owner "^1.0.4" mkdirp "^1.0.3" -mkdirp@*, mkdirp@^1.0.3, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - mkdirp@^0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -5171,6 +5132,11 @@ mkdirp@^0.5.0: dependencies: minimist "^1.2.5" +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -5197,11 +5163,6 @@ module-deps@^6.0.0, module-deps@^6.2.3: through2 "^2.0.0" xtend "^4.0.0" -ms@*, ms@^2.0.0, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -5212,6 +5173,11 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.0.0, ms@^2.1.1, ms@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -5294,23 +5260,7 @@ node-fetch@^2.6.1: dependencies: whatwg-url "^5.0.0" -node-gyp@*, node-gyp@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.2.0.tgz#ef509ccdf5cef3b4d93df0690b90aa55ff8c7977" - integrity sha512-KG8SdcoAnw2d6augGwl1kOayALUrXW/P2uOAm2J2+nmW/HjZo7y+8TDg7LejxbekOOSv3kzhq+NSUYkIDAX8eA== - dependencies: - env-paths "^2.2.0" - glob "^7.1.4" - graceful-fs "^4.2.6" - make-fetch-happen "^8.0.14" - nopt "^5.0.0" - npmlog "^4.1.2" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.2" - which "^2.0.2" - -node-gyp@^7.1.0: +node-gyp@^7.1.0, node-gyp@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== @@ -5331,7 +5281,7 @@ node-releases@^1.1.77: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== -nopt@*, nopt@^5.0.0: +nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== @@ -5375,7 +5325,7 @@ normalize-url@^6.0.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -npm-audit-report@*: +npm-audit-report@^2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-2.1.5.tgz#a5b8850abe2e8452fce976c8960dd432981737b5" integrity sha512-YB8qOoEmBhUH1UJgh1xFAv7Jg1d+xoNhsDYiFQlEFThEBui0W1vIz2ZK6FVg4WZjwEdl7uBQlm1jy3MUfyHeEw== @@ -5389,7 +5339,7 @@ npm-bundled@^1.1.1: dependencies: npm-normalize-package-bin "^1.0.1" -npm-install-checks@*, npm-install-checks@^4.0.0: +npm-install-checks@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-4.0.0.tgz#a37facc763a2fde0497ef2c6d0ac7c3fbe00d7b4" integrity sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w== @@ -5401,7 +5351,7 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== -npm-package-arg@*, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-package-arg@^8.1.1, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: +npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-package-arg@^8.1.1, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: version "8.1.5" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44" integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== @@ -5420,17 +5370,7 @@ npm-packlist@^2.1.4: npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" -npm-packlist@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-3.0.0.tgz#0370df5cfc2fcc8f79b8f42b37798dd9ee32c2a9" - integrity sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ== - dependencies: - glob "^7.1.6" - ignore-walk "^4.0.1" - npm-bundled "^1.1.1" - npm-normalize-package-bin "^1.0.1" - -npm-pick-manifest@*, npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.0, npm-pick-manifest@^6.1.1: +npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.0, npm-pick-manifest@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz#7b5484ca2c908565f43b7f27644f36bb816f5148" integrity sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA== @@ -5440,14 +5380,14 @@ npm-pick-manifest@*, npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.0, npm-pic npm-package-arg "^8.1.2" semver "^7.3.4" -npm-profile@*: +npm-profile@^5.0.3: version "5.0.4" resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-5.0.4.tgz#73e5bd1d808edc2c382d7139049cc367ac43161b" integrity sha512-OKtU7yoAEBOnc8zJ+/uo5E4ugPp09sopo+6y1njPp+W99P8DvQon3BJYmpvyK2Bf1+3YV5LN1bvgXRoZ1LUJBA== dependencies: npm-registry-fetch "^11.0.0" -npm-registry-fetch@*, npm-registry-fetch@^11.0.0: +npm-registry-fetch@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76" integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA== @@ -5466,7 +5406,7 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npm-user-validate@*: +npm-user-validate@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.1.tgz#31428fc5475fe8416023f178c0ab47935ad8c561" integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw== @@ -5547,16 +5487,6 @@ npm@^7.0.0: which "^2.0.2" write-file-atomic "^3.0.3" -npmlog@*: - version "5.0.1" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" - integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== - dependencies: - are-we-there-yet "^2.0.0" - console-control-strings "^1.1.0" - gauge "^3.0.0" - set-blocking "^2.0.0" - npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -5567,6 +5497,16 @@ npmlog@^4.1.2: gauge "~2.7.3" set-blocking "~2.0.0" +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -5639,7 +5579,7 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -opener@*: +opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== @@ -5753,32 +5693,7 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pacote@*, pacote@^12.0.0: - version "12.0.2" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-12.0.2.tgz#14ae30a81fe62ec4fc18c071150e6763e932527c" - integrity sha512-Ar3mhjcxhMzk+OVZ8pbnXdb0l8+pimvlsqBGRNkble2NVgyqOGE3yrCGi/lAYq7E7NRDMz89R1Wx5HIMCGgeYg== - dependencies: - "@npmcli/git" "^2.1.0" - "@npmcli/installed-package-contents" "^1.0.6" - "@npmcli/promise-spawn" "^1.2.0" - "@npmcli/run-script" "^2.0.0" - cacache "^15.0.5" - chownr "^2.0.0" - fs-minipass "^2.1.0" - infer-owner "^1.0.4" - minipass "^3.1.3" - mkdirp "^1.0.3" - npm-package-arg "^8.0.1" - npm-packlist "^3.0.0" - npm-pick-manifest "^6.0.0" - npm-registry-fetch "^11.0.0" - promise-retry "^2.0.1" - read-package-json-fast "^2.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.1.0" - -pacote@^11.3.0: +pacote@^11.1.11, pacote@^11.2.6, pacote@^11.3.0, pacote@^11.3.1, pacote@^11.3.5: version "11.3.5" resolved "https://registry.yarnpkg.com/pacote/-/pacote-11.3.5.tgz#73cf1fc3772b533f575e39efa96c50be8c3dc9d2" integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== @@ -5840,7 +5755,7 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-conflict-json@*, parse-conflict-json@^1.1.1: +parse-conflict-json@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-1.1.1.tgz#54ec175bde0f2d70abf6be79e0e042290b86701b" integrity sha512-4gySviBiW5TRl7XHvp1agcS7SOe0KZOjC//71dzZVWJrY9hCrgtvl5v3SyIxCZ4fZF47TxD9nfzmxcx76xmbUw== @@ -6093,7 +6008,7 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qrcode-terminal@*: +qrcode-terminal@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== @@ -6165,7 +6080,7 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -read-package-json-fast@*, read-package-json-fast@^2.0.1, read-package-json-fast@^2.0.2: +read-package-json-fast@^2.0.1, read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" integrity sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ== @@ -6173,7 +6088,7 @@ read-package-json-fast@*, read-package-json-fast@^2.0.1, read-package-json-fast@ json-parse-even-better-errors "^2.3.0" npm-normalize-package-bin "^1.0.1" -read-package-json@*, read-package-json@^4.1.1: +read-package-json@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.1.tgz#153be72fce801578c1c86b8ef2b21188df1b9eea" integrity sha512-P82sbZJ3ldDrWCOSKxJT0r/CXMWR0OR3KRh55SgKo3p91GSIEEC32v3lSHAvO/UcH3/IoL7uqhOFBduAnwdldw== @@ -6202,7 +6117,7 @@ read-pkg@^5.0.0, read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -read@*, read@1, read@^1.0.7, read@~1.0.1: +read@1, read@^1.0.7, read@~1.0.1, read@~1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= @@ -6231,7 +6146,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readdir-scoped-modules@*, readdir-scoped-modules@^1.1.0: +readdir-scoped-modules@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== @@ -6465,7 +6380,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@*, rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -6567,13 +6482,6 @@ semver-regex@^3.1.2: resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.3.tgz#b2bcc6f97f63269f286994e297e229b6245d0dc3" integrity sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ== -semver@*, semver@^7.1.1, semver@^7.1.2, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -6589,6 +6497,13 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.1.1, semver@^7.1.2, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + serialize-error@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" @@ -6726,15 +6641,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -socks-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz#032fb583048a29ebffec2e6a73fca0761f48177e" - integrity sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ== - dependencies: - agent-base "^6.0.2" - debug "4" - socks "^2.3.3" - socks-proxy-agent@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz#869cf2d7bd10fea96c7ad3111e81726855e285c3" @@ -6744,7 +6650,7 @@ socks-proxy-agent@^6.0.0: debug "^4.3.1" socks "^2.6.1" -socks@^2.3.3, socks@^2.6.1: +socks@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA== @@ -6862,7 +6768,7 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -ssri@*, ssri@^8.0.0, ssri@^8.0.1: +ssri@^8.0.0, ssri@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== @@ -6970,7 +6876,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.1 || ^2.0.0", "string-width@^1.0.2 || 2": +"string-width@^1.0.1 || ^2.0.0", "string-width@^1.0.2 || 2", string-width@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -7114,7 +7020,7 @@ table@^6.0.9: string-width "^4.2.3" strip-ansi "^6.0.1" -tar@*, tar@^6.0.2, tar@^6.1.0, tar@^6.1.2: +tar@^6.0.2, tar@^6.1.0, tar@^6.1.11: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -7147,7 +7053,7 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-table@*, text-table@^0.2.0: +text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= @@ -7198,7 +7104,7 @@ timers-browserify@^1.0.1: dependencies: process "~0.11.0" -tiny-relative-date@*: +tiny-relative-date@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== @@ -7278,7 +7184,7 @@ traverse@~0.6.6: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= -treeverse@*, treeverse@^1.0.4: +treeverse@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-1.0.4.tgz#a6b0ebf98a1bca6846ddc7ecbc900df08cb9cd5f" integrity sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g== @@ -7569,7 +7475,7 @@ validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@*, validate-npm-package-name@^3.0.0: +validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= @@ -7628,7 +7534,7 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which@*, which@^2.0.1, which@^2.0.2: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== @@ -7675,7 +7581,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@*, write-file-atomic@^3.0.3: +write-file-atomic@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== From ccb1b4119db9c4185b5b31b62573f38cc7492c45 Mon Sep 17 00:00:00 2001 From: Shelex Date: Sun, 21 Nov 2021 13:28:04 +0200 Subject: [PATCH 2/2] fix: cy command object arguments logging, address #102 --- reporter/allure-cypress/CypressHandler.js | 25 +++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/reporter/allure-cypress/CypressHandler.js b/reporter/allure-cypress/CypressHandler.js index 62fd4ff..cc90af3 100644 --- a/reporter/allure-cypress/CypressHandler.js +++ b/reporter/allure-cypress/CypressHandler.js @@ -121,21 +121,28 @@ module.exports = class CypressHandler { return '[function]'; } if (typeof arg === 'object') { + // for jquery objects log selector only + if (arg.selector) { + return arg.selector; + } + + // for html elements check name and class + if (arg.localName) { + return `${arg.localName}${ + arg.className ? `.${arg.className}` : '' + }`; + } + + // log just native types - object, array, etc if ( - arg && arg.constructor && - arg.constructor.toString && typeof arg.constructor.toString === 'function' && - ((arg.constructor.toString().includes('HTML') && - arg.constructor.toString().includes('Element')) || - arg.constructor - .toString() - .includes('The jQuery object')) + arg.constructor.toString().endsWith('{ [native code] }') ) { - return '[Object]'; + return JSON.stringify(arg, getCircularReplacer(), 2); } - return JSON.stringify(arg, getCircularReplacer(), 2); + return '[Object]'; } return arg;