Skip to content

unhandledRejection, crashes Nightwatch when using nth when upstream element is not found #4390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
reallymello opened this issue Mar 12, 2025 · 3 comments

Comments

@reallymello
Copy link
Contributor

reallymello commented Mar 12, 2025

Description of the bug/issue

When I use the .nth(n) method to select the nth item from the result of findElements and findElements returned no found elements then I expect my test to report a normal test failure, fail my test, run teardowns gracefully, and safely exit the Nightwatch process, but instead it throws

  Error
   unhandledRejection: Error in nth(): No elements found for selector: td
Error: Error in nth(): No elements found for selector: td
    at throwError (C:\Users\agent\Desktop\nth-issue\node_modules\nightwatch\lib\api\web-element\factory.js:11:17)
    at C:\Users\agent\Desktop\nth-issue\node_modules\nightwatch\lib\api\web-element\factory.js:184:27
    at processTicksAndRejections (node:internal/process/task_queues:105:5)

and the Nightwatch process short circuits/crashes without closing the browser or session (the browser remains open)

Steps to reproduce

Write an async test case that chains .findElements and .nth where the element selector in findElements yields no matches and execute the test. See the sample test below.

Sample test

import { NightwatchTests } from 'nightwatch';

const home: NightwatchTests = {
  'Google title test': () => {
    browser.url('https://google.com/ncr').assert.titleEquals('Google');
  },

  'unhandled nth example test': async () => {
    await browser.element
      .find('#main')
      .findElements('td')
      .nth(3)
      .getText()
      .assert.equals('Closed');
  },
};

export default home;

Command to run

npx nightwatch nightwatch\nthTest.ts

Verbose Output

npx nightwatch nightwatch\nthTest.ts --verbose


[Nightwatch\nth Test] Test Suite
────────────────────────────────────────────────────────────────
⠋ Starting ChromeDriver on port 9515...
⠙ Starting ChromeDriver on port 9515...
   Request POST /session  
   {
     capabilities: {
       firstMatch: [ {} ],
       alwaysMatch: {
         browserName: 'chrome',
         'goog:chromeOptions': {
           binary: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'
         }
       }
     }
⠹ Starting ChromeDriver on port 9515...

⠦ Starting ChromeDriver on port 9515...
   Response 200 POST /session (455ms)
   {
     value: {
       capabilities: {
         acceptInsecureCerts: false,
         browserName: 'chrome',
         browserVersion: '134.0.6998.89',
         chrome: {
           chromedriverVersion: '134.0.6998.88 (7e3d5c978c6d3a6eda25692cfac7f893a2b20dd0-refs/branch-heads/6998@{#1898})',
           userDataDir: 'C:\\Users\\agent\\AppData\\Local\\Temp\\scoped_dir95404_421647162'
         },
         'fedcm:accounts': true,
         'goog:chromeOptions': { debuggerAddress: 'localhost:55526' },
         networkConnectionEnabled: false,
         pageLoadStrategy: 'normal',
         platformName: 'windows',
         proxy: {},
         setWindowRect: true,
         strictFileInteractability: false,
         timeouts: { implicit: 0, pageLoad: 300000, script: 30000 },
         unhandledPromptBehavior: 'dismiss and notify',
         'webauthn:extension:credBlob': true,
         'webauthn:extension:largeBlob': true,
         'webauthn:extension:minPinLength': true,
         'webauthn:extension:prf': true,
         'webauthn:virtualAuthenticators': true
       },
       sessionId: '566b7af0435f468b510727e21ea64b3e'
     }
ℹ Connected to ChromeDriver on port 9515 (702ms).                                                                                                                                                                                                                                        
  Using: chrome (134.0.6998.89) on WINDOWS.

 Received session with ID: 566b7af0435f468b510727e21ea64b3e

 → Running [before]:
 → Completed [before].



  Running Google title test:
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 → Running [beforeEach]:
 → Completed [beforeEach].
 
 → Running command: url ('https://google.com/ncr')
  ⠋ Loading url: https://google.com/ncr
   Request POST /session/566b7af0435f468b510727e21ea64b3e/url  
  ⠏ Loading url: https://google.com/ncr
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/url (875ms)
  ℹ Loaded url https://google.com/ncr in 877ms                                                                                                                                                                                                                                           
 → Completed command: url ('https://google.com/ncr') (877ms)

 → Running command: assert.titleEquals ('Google')
 
 → Running command: title ([Function])
   Request GET /session/566b7af0435f468b510727e21ea64b3e/title  

   Response 200 GET /session/566b7af0435f468b510727e21ea64b3e/title (3ms)
   { value: 'Google' }
  √ Testing if the page title equals 'Google' (20ms)
 → Completed command: title ([Function]) (4ms)
 → Completed command: assert.titleEquals ('Google') (31ms)
 → Running [afterEach]:
 → Completed [afterEach].

  ✨ PASSED. 1 assertions. (916ms)



  Running unhandled nth example test:
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 → Running [beforeEach]:
 → Completed [beforeEach].
 
 → Running command: element.find ({ By(css selector, #main) })
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (6ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (4ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (4ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (3ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (12ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (9ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (5ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (10ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (5ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (3ms)
   { value: [] }
   Request POST /session/566b7af0435f468b510727e21ea64b3e/elements  
   { using: 'css selector', value: '#main' }
   Response 200 POST /session/566b7af0435f468b510727e21ea64b3e/elements (13ms)
   { value: [] }
  NoSuchElementError
   Timed out while waiting for element "By(css selector, #main)" to be present for 5000 milliseconds.

    Try fixing by :
    1. Please inspect the html before the step
    2. Verify if an element with the mentioned selector is present in the DOM tree
 → Completed command: element.find ({ By(css selector, #main) }) (5199ms)

 → Running command: element.findAll ({ td })
  ✖ TypeError
   Cannot read properties of null (reading 'findElements')
    Stack Trace :
    at ScopedElements.findElements (C:\Users\agent\Desktop\nth-issue\node_modules\nightwatch\lib\api\web-element\scoped-elements.js:63:44)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async commandFn (C:\Users\agent\Desktop\nth-issue\node_modules\nightwatch\lib\api\web-element\scoped-elements.js:88:16)

 → Completed command: element.findAll ({ td }) (2ms)
  Error
   unhandledRejection: Error in nth(): No elements found for selector: td
Error: Error in nth(): No elements found for selector: td
    at throwError (C:\Users\agent\Desktop\nth-issue\node_modules\nightwatch\lib\api\web-element\factory.js:11:17)
    at C:\Users\agent\Desktop\nth-issue\node_modules\nightwatch\lib\api\web-element\factory.js:184:27
    at processTicksAndRejections (node:internal/process/task_queues:105:5)

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  ️TEST FAILURE (7.367s):
   - 1 error during execution;
   - 0 tests failed;
   - 0/NA tests passed

Nightwatch Configuration

// Refer to the online docs for more details:
// https://nightwatchjs.org/gettingstarted/configuration/
//

//  _   _  _         _      _                     _          _
// | \ | |(_)       | |    | |                   | |        | |
// |  \| | _   __ _ | |__  | |_ __      __  __ _ | |_   ___ | |__
// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \
// | |\  || || (_| || | | || |_  \ V  V / | (_| || |_ | (__ | | | |
// \_| \_/|_| \__, ||_| |_| \__|  \_/\_/   \__,_| \__| \___||_| |_|
//             __/ |
//            |___/

module.exports = {
  // An array of folders (excluding subfolders) where your tests are located;
  // if this is not specified, the test source must be passed as the second argument to the test runner.
  src_folders: ['test','nightwatch'],

  // See https://nightwatchjs.org/guide/concepts/page-object-model.html
  page_objects_path: [],

  // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html
  custom_commands_path: [],

  // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html
  custom_assertions_path: [],

  // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html
  plugins: [],
  
  // See https://nightwatchjs.org/guide/concepts/test-globals.html
  globals_path: '',
  
  webdriver: {},

  test_workers: {
    enabled: true
  },

  test_settings: {
    default: {
      disable_error_log: false,
      launch_url: 'http://localhost',

      screenshots: {
        enabled: false,
        path: 'screens',
        on_failure: true
      },

      desiredCapabilities: {
        browserName: 'chrome'
      },
      
      webdriver: {
        start_process: true,
        server_path: ''
      },
      
    },
    
    chrome: {
      desiredCapabilities: {
        browserName: 'chrome',
        'goog:chromeOptions': {
          // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/
          args: [
            //'--no-sandbox',
            //'--ignore-certificate-errors',
            //'--allow-insecure-localhost',
            //'--headless=new'
          ]
        }
      },

      webdriver: {
        start_process: true,
        server_path: '',
        cli_args: [
          // --verbose
        ]
      }
    },
    
  },
  
};

Nightwatch.js Version

3.12.0

Node Version

22.13.1

Browser

Chrome 134

Operating System

Windows 11

Additional Information

nth-issue.zip

@kishorprajapati1212
Copy link

The issue was caused by an incorrect ID. The #main ID does not exist on Google's page, so the test was unable to locate the correct element, leading to errors. I tested a different case instead, as the Google test was causing more issues on my setup.

import { NightwatchTests } from 'nightwatch';

const home: NightwatchTests = {
  'Wikipedia nth element test': async () => {
    await browser.url('https://en.wikipedia.org/wiki/Nightwatch_(software)').assert.titleEquals('Nightwatch (software) - Wikipedia');

    const nthItem = await browser.element
    .find('#vector-main-menu-dropdown')
    .findElements('li')
    .nth(3)
    .getId(); //get id because it not get the text

    console.log('items of the css:', nthItem);

    await browser.assert.notEqual(nthItem, 'close');
  },
};

export default home;

Image

@reallymello
Copy link
Contributor Author

reallymello commented Mar 15, 2025

Sorry if I wasn't clear, yes, I purposefully designed the test to look for elements that don't exist because the issue I am reporting needs for that sort of failure to occur...e.g. the test was purposefully designed with that mistake/error to replicate the issue. The issue is, instead of Nightwatch reporting the missing element and logging a test failure it seems to crash out early and leave the browser and session closed which causes issues for the test suite run--especially in BrowserStack which encounters an eventual test timeout vs reporting back with a pass or fail.

Organically, what happened in our real scenario was a test using a similar scenario was working fine for some time, but the page changed in a later build, causing the element to not be present and it started throwing this unhandled exception vs logging a normal test failure.

I need someone from the dev team to look into what its happening and see why Nightwatch isn't handling it properly.

@kishorprajapati1212
Copy link

I found the main issue in nightwatch/lib/api/web-element/scoped-element.js When findElements doesn’t find any elements, it throws an error but doesn’t actually stop the test. This means the test keeps running instead of failing right away.

To fix this, I updated the code to properly mark the test as failed, clean up, and exit safely:

if (webElements.length === 0) {
      const err = new Error(`Cannot find element with "${selector}" selector in ${timeout} milliseconds.`);

        this.reporter.registerTestError(err);
        this.reporter.fail(errMsg); // Explicitly mark as failed if Nightwatch supports it

        await this.tearDown(); // Ensure cleanup runs before exiting
        process.exit(1); // Exit safely
    }

I hope this would help in bug fixing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants