From 329d7975b3e28927884c97b955dc10511788aac0 Mon Sep 17 00:00:00 2001 From: "ahmed.badra" <42746335+badra022@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:10:33 +0200 Subject: [PATCH] Throw error and disable suite for duplicate testcases in describe instance. (#4302) Co-authored-by: Priyansh Garg --- lib/testsuite/context.js | 15 ++++++++++++++- lib/testsuite/interfaces/describe.js | 4 +++- .../skipped/duplicateTestcases.js | 11 +++++++++++ test/src/runner/testRunTestcase.js | 19 +++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 test/sampletests/withdescribe/skipped/duplicateTestcases.js diff --git a/lib/testsuite/context.js b/lib/testsuite/context.js index b32f9f9cc5..9a9b4f3f7c 100644 --- a/lib/testsuite/context.js +++ b/lib/testsuite/context.js @@ -316,7 +316,20 @@ class Context extends EventEmitter { throw new Error(`The "${testName}" test script must be a function. "${typeof testFn}" given.`); } - // TODO: warn if test name already exists + if (this.allScreenedTests.includes(testName)) { + const {Logger} = Utils; + + const err = new Error( + 'An error occurred while loading the testsuite:\n' + + `A testcase with name "${testName}" already exists. Testcases must have unique names inside the test suite, ` + + 'otherwise testcases with duplicate names might not run at all.\n\n' + + 'This testsuite has been disabled, please fix the error to run it again properly.' + ); + Logger.error(err); + + this.setAttribute('@disabled', true); + } + if (!skipTest) { this.tests.push(testName); } else { diff --git a/lib/testsuite/interfaces/describe.js b/lib/testsuite/interfaces/describe.js index 35d4d1e6bb..d0bd0a456a 100644 --- a/lib/testsuite/interfaces/describe.js +++ b/lib/testsuite/interfaces/describe.js @@ -229,8 +229,10 @@ class Describe extends Common { context.xcontext = context.describe.skip = (title, describeFn) => { this.instance.once('module-loaded', () => { - // in case tests have been declared using other interfaces (e.g. exports) + // in case tests have been declared using other interfaces (e.g. exports), + // we do not want to disable the suite. if (this.instance.tests.length === 0) { + // if no tests are added after all interfaces are loaded, disable the suite. this.instance.setAttribute('@disabled', true); } }); diff --git a/test/sampletests/withdescribe/skipped/duplicateTestcases.js b/test/sampletests/withdescribe/skipped/duplicateTestcases.js new file mode 100644 index 0000000000..c3ec351918 --- /dev/null +++ b/test/sampletests/withdescribe/skipped/duplicateTestcases.js @@ -0,0 +1,11 @@ +describe('test', function () { + test('test find', async (browser) => { + browser.globals.calls++; + browser.element.find('#weblogin'); + }); + + test('test find', async (browser) => { + browser.globals.calls++; + browser.element.find('#weblogin'); + }); +}); diff --git a/test/src/runner/testRunTestcase.js b/test/src/runner/testRunTestcase.js index bbf956d425..291385b02e 100644 --- a/test/src/runner/testRunTestcase.js +++ b/test/src/runner/testRunTestcase.js @@ -266,6 +266,25 @@ describe('testRunTestcase', function() { })); }); + it('testRunner with duplicated testcases', function() { + const testsPath = path.join(__dirname, '../../sampletests/withdescribe/skipped/duplicateTestcases.js'); + const globals = { + calls: 0, + reporter(results, cb) { + assert.strictEqual(globals.calls, 0); + assert.strictEqual(results.skipped, 2); + cb(); + }, + retryAssertionTimeout: 0 + }; + + return runTests({ + _source: [testsPath] + }, settings({ + globals + })); + }); + it('testRunner with skipped beforeEach afterEach hooks', function() { const testsPath = path.join(__dirname, '../../sampletests/withdescribe/skipped/skipBeforeAfterEach.js'); const globals = {