nightwatchjs / nightwatch

Integrated end-to-end testing framework written in Node.js and using W3C Webdriver API. Developed at @browserstack
https://nightwatchjs.org
MIT License
11.75k stars 1.3k forks source link

unhandled rejection in select method if element is not null but tagName is #4231

Closed reallymello closed 2 days ago

reallymello commented 1 week ago

Description of the bug/issue

When I call npx nightwatch examples\tests\selectElement.js I expect the test to pass, but instead I receive

  NoSuchElementError
   Timed out while waiting for element "By(css selector, select[name=selectomatic])" 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

    Error location:
    C:\Projects\forks\nightwatch\lib\api\web-element\scoped-element.js:333
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
     331 | function createNarrowedError({error, condition, timeout}) {
     332 |   if (error.name === 'TimeoutError') {
     333 |     const err = new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`); 
     334 |     err.name = 'NoSuchElementError';
     335 |
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

  ℹ Loaded url https://www.selenium.dev/selenium/web/formPage.html in 96ms
  Error
     Response 500 POST /session/2bd9495a-54a0-4e09-9266-59a9efe49149/execute/sync (6ms)
   {
     value: {
       error: 'javascript error',
       message: 'TypeError: a is null',
       stacktrace: ''
     }
  }
  Error
     Response 500 POST /session/2bd9495a-54a0-4e09-9266-59a9efe49149/execute/sync (2ms)
   {
     value: {
       error: 'javascript error',
       message: 'TypeError: a is null',
       stacktrace: ''
     }
  }
  Error
     Response 500 POST /session/2bd9495a-54a0-4e09-9266-59a9efe49149/execute/sync (3ms)
   {
     value: {
       error: 'javascript error',
       message: 'TypeError: a is null',
       stacktrace: ''
     }
  }
    Error   Error while running .getElementValue() protocol action: TypeError: a is null

  Error
   unhandledRejection: Cannot read properties of null (reading 'toLowerCase')
TypeError: Cannot read properties of null (reading 'toLowerCase')
    at C:\Projects\forks\nightwatch\node_modules\selenium-webdriver\lib\select.js:156:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

There is no null check on tagName in select.js before it tries to access .toLowerCase() causing an unhandled rejection

image

Steps to reproduce

npx nightwatch examples\tests\selectElement.js

This is the test included in the Nightwatch repository

Sample test

const {Select} = require('selenium-webdriver');

module.exports = {
  async demoTest(browser) {
    const selectElement = browser.element('select[name=selectomatic]');

    await browser
      .url('https://www.selenium.dev/selenium/web/formPage.html')
      .perform(async function() {
        const select = new Select(selectElement);

        await select.selectByVisibleText('Four');
      })
      .assert.selected(await selectElement.findElement('option[value=four]'), 'Forth option is selected');
  }
};
clea

Command to run

npx nightwatch examples\tests\selectElement.js

Verbose Output

[Select Element] Test Suite
──────────────────────────────────────────────────────
⠋ Starting GeckoDriver on port 4444...
 Starting GeckoDriver...
(node:84532) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
⠙ Starting GeckoDriver on port 4444...
   Request POST /session  
   {
     capabilities: {
       firstMatch: [ {} ],
       alwaysMatch: {
         browserName: 'firefox',
         'moz:firefoxOptions': {
           binary: 'C:\\Users\\agent\\.cache\\selenium\\firefox\\win64\\127.0.2\\firefox.exe'
         }
       }
     }
⠦ Starting GeckoDriver on port 4444...
   Response 200 POST /session (1309ms)
   {
     value: {
       sessionId: 'f99090fa-50c8-417a-a428-dec3cff1db7e',
       capabilities: {
         acceptInsecureCerts: false,
         browserName: 'firefox',
         browserVersion: '127.0.2',
         'moz:accessibilityChecks': false,
         'moz:buildID': '20240624183754',
         'moz:geckodriverVersion': '0.34.0',
         'moz:headless': false,
         'moz:platformVersion': '10.0',
         'moz:processID': 84120,
         'moz:profile': 'C:\\Users\\agent\\AppData\\Local\\Temp\\rust_mozprofilerQfiI3',
         'moz:shutdownTimeout': 60000,
         'moz:webdriverClick': true,
         'moz:windowless': false,
         pageLoadStrategy: 'normal',
         platformName: 'windows',
         proxy: {},
         setWindowRect: true,
         strictFileInteractability: false,
         timeouts: { implicit: 0, pageLoad: 300000, script: 30000 },
         unhandledPromptBehavior: 'dismiss and notify',
         userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0'
       }
     }
ℹ Connected to GeckoDriver on port 4444 (1496ms).                                                                                                                                                                                                    
  Using: firefox (127.0.2) on WINDOWS.

 Received session with ID: f99090fa-50c8-417a-a428-dec3cff1db7e

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

  Running demoTest:
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 → Running [beforeEach]:
 → Completed [beforeEach].

 → Running command: element.find ()
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (7ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (2ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (4ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (2ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (7ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (9ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (9ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (5ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (8ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (2ms)
   { value: [] }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements  
   { using: 'css selector', value: 'select[name=selectomatic]' }
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/elements (7ms)
   { value: [] }
  NoSuchElementError
   Timed out while waiting for element "By(css selector, select[name=selectomatic])" 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

    Error location:
    C:\Projects\forks\nightwatch\lib\api\web-element\scoped-element.js:333
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
     331 | function createNarrowedError({error, condition, timeout}) {
     332 |   if (error.name === 'TimeoutError') {
     333 |     const err = new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`); 
     334 |     err.name = 'NoSuchElementError';
     335 |
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

 → Completed command: element.find () (5175ms)

 → Running command: url ('https://www.selenium.dev/selenium/web/formPage.html')
  ⠋ Loading url: https://www.selenium.dev/selenium/web/formPage.html
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/url  
  ⠹ Loading url: https://www.selenium.dev/selenium/web/formPage.html
   Response 200 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/url (182ms)
  ℹ Loaded url https://www.selenium.dev/selenium/web/formPage.html in 184ms                                                                                                                                                                          
 → Completed command: url ('https://www.selenium.dev/selenium/web/formPage.html') (184ms)

 → Running command: perform ([Function])

 → Running command: element().getElementValue ()
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/execute/sync  
   {
     script: '/* getAttribute */return (function(){return (function(){var d=this||self;function f(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};var h=Array.prototype.indexO... (6016 characters)',        
     args: [ null, 'tagName' ]
  }
  Error
     Response 500 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/execute/sync (7ms)
   {
     value: {
       error: 'javascript error',
       message: 'TypeError: a is null',
       stacktrace: ''
     }
  }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/execute/sync  (retry 1) 
   {
     script: '/* getAttribute */return (function(){return (function(){var d=this||self;function f(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};var h=Array.prototype.indexO... (221 characters)',
     args: [ null, 'tagName' ]
  }
  Error
     Response 500 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/execute/sync (5ms)
   {
     value: {
       error: 'javascript error',
       message: 'TypeError: a is null',
       stacktrace: ''
     }
  }
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/execute/sync  (retry 2) 
   {
     script: '/* getAttribute */return (function(){return (function(){var d=this||self;function f(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};var h=Array.prototype.indexO... (220 characters)',
     args: [ null, 'tagName' ]
  }
  Error
     Response 500 POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/execute/sync (9ms)
   {
     value: {
       error: 'javascript error',
       message: 'TypeError: a is null',
       stacktrace: ''
     }
  }
    Error   Error while running .getElementValue() protocol action: TypeError: a is null

 → Completed command: element().getElementValue () (2036ms)

 → Running command: element().getElementValue ()
   Request POST /session/f99090fa-50c8-417a-a428-dec3cff1db7e/execute/sync  
   {
     script: '/* getAttribute */return (function(){return (function(){var d=this||self;function f(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};var h=Array.prototype.indexO... (6016 characters)',        
     args: [ null, 'multiple' ]
  }
  Error
   unhandledRejection: Cannot read properties of null (reading 'toLowerCase')
TypeError: Cannot read properties of null (reading 'toLowerCase')
    at C:\Projects\forks\nightwatch\node_modules\selenium-webdriver\lib\select.js:156:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

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

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

Nightwatch Configuration

No response

Nightwatch.js Version

2.3.6

Node Version

20

Browser

Firefox

Operating System

Windows 11

Additional Information

image

garg3133 commented 1 week ago

This is happening because of a mistake in the example itself. In the example, we've put browser.element statement before the browser.url call, so browser.element would be placed in the Nightwatch queue before browser.url and run in the same order.

This creates a problem because it would not be able to find the required element on an empty page.

4233 should fix this.

(Also, the piece of code throwing this error is actually part of the Selenium codebase. And it was only happening because the element argument passed to the Select constructor wasn't what it expected. It expected a WebElement to be passed but we actually passed Nightwatch's own ScopedWebElement. So, the check Selenium is missing is to verify if the passed element is even an instance of WebElement or not.)