diff --git a/src/test-reader/mocha-reader/tree-builder-decorator.js b/src/test-reader/mocha-reader/tree-builder-decorator.js index 4c775ccc4..27cad49de 100644 --- a/src/test-reader/mocha-reader/tree-builder-decorator.js +++ b/src/test-reader/mocha-reader/tree-builder-decorator.js @@ -1,5 +1,6 @@ const { Suite, Test, Hook } = require("../test-object"); const crypto = require("../../utils/crypto"); +const { computeFile } = require("./utils"); class TreeBuilderDecorator { #treeBuilder; @@ -17,7 +18,9 @@ class TreeBuilderDecorator { } addSuite(mochaSuite) { - const { id: mochaId, file } = mochaSuite; + const { id: mochaId } = mochaSuite; + const file = computeFile(mochaSuite) ?? "unknown-file"; + const positionInFile = this.#suiteCounter.get(file) || 0; const id = mochaSuite.root ? mochaId : crypto.getShortMD5(file) + positionInFile; const suite = this.#mkTestObject(Suite, mochaSuite, { id }); diff --git a/src/test-reader/mocha-reader/utils.js b/src/test-reader/mocha-reader/utils.js new file mode 100644 index 000000000..eac1aadce --- /dev/null +++ b/src/test-reader/mocha-reader/utils.js @@ -0,0 +1,64 @@ +// When using "exports" mocha interface, "file" field is absent on suites, and available on tests only. +// This helper tries to resolve "file" field for suites, drilling down to child tests and using their file field. + +const findTopmostSuite = mochaSuite => { + if (mochaSuite.parent && mochaSuite.parent.root) { + return mochaSuite; + } + + if (!mochaSuite.parent) { + return null; + } + + return findTopmostSuite(mochaSuite.parent); +}; + +const getFile = mochaSuite => { + if (mochaSuite.file) { + return mochaSuite.file; + } + + if (mochaSuite.tests.length > 0 && mochaSuite.tests[0].file) { + return mochaSuite.tests[0].file; + } + + for (const childSuite of mochaSuite.suites) { + const computedFile = getFile(childSuite); + if (computedFile) { + return computedFile; + } + } + + return null; +}; + +const fillSuitesFileField = (mochaSuite, file) => { + mochaSuite.file = file; + + if (mochaSuite.suites) { + for (const childSuite of mochaSuite.suites) { + fillSuitesFileField(childSuite, file); + } + } +}; + +const computeFile = mochaSuite => { + if (mochaSuite.file) { + return mochaSuite.file; + } + + const topmostSuite = findTopmostSuite(mochaSuite); + const file = topmostSuite && getFile(topmostSuite); + + if (topmostSuite && file) { + fillSuitesFileField(topmostSuite, file); + + return file; + } + + return null; +}; + +module.exports = { + computeFile, +};