Repository: nightwatchjs/nightwatch
Pull request #4187 (2024-04-11 11:49:40)

Update Page Object tests to make sure invalid Page Objects elements are handled
Thanks in advance for your contribution. Please follow the below steps in submitting a pull request, as it will help us with reviewing it quicker.

- [x] Before marking your PR for review, please test and verify your changes by making appropriate modifications to any of the Nightwatch example tests (present in `examples/tests` directory of the project) and running them. `ecosia.js` and `duckDuckGo.js` are good examples to work with.
- [x] Create a new branch from master (e.g. `features/my-new-feature` or `issue/123-my-bugfix`);
- [ ] If you're fixing a bug also create an issue if one doesn't exist yet;
- [ ] If it's a new feature explain why do you think it's necessary. Please check with the maintainers beforehand to make sure it is something that we will accept. Usually we only accept new features if we feel that they will benefit the entire community;
- [ ] Please avoid sending PRs which contain drastic or low level changes. If you are certain that the changes are needed, please discuss them beforehand and indicate what the impact will be;
- [ ] If your change is based on existing functionality please consider refactoring first. Pull requests that duplicate code will most likely be ignored;
- [ ] Do not include changes that are not related to the issue at hand;
- [ ] Follow the same coding style with regards to spaces, semicolons, variable naming etc.;
- [x] Always add unit tests - PRs without tests are most of the times ignored.


github-actions[bot]: 
## Status
* ❌ No modified files found in the **types** directory.
Please make sure to include types for any changes you have made. Thank you!.

Patch:
diff --git a/lib/api/_loaders/element-api.js b/lib/api/_loaders/element-api.js
index 6b431444..e42294fb 100644
--- a/lib/api/_loaders/element-api.js
+++ b/lib/api/_loaders/element-api.js
@@ -5,9 +5,10 @@ const {By} = require('selenium-webdriver');
 
 class ScopedElementAPILoader {
   static get availableElementCommands() {
+    // commands directly available on `browser.element`
     return [
       ['findElement', 'find', 'get'],
-      ['findAll'],
+      ['findAll', 'findElements', 'getAll'],
       ['findByText'],
       ['findAllByText'],
       ['findByRole'],
diff --git a/lib/api/client-commands/axeInject.js b/lib/api/client-commands/axeInject.js
index 7d3c1d97..f7ba0544 100644
--- a/lib/api/client-commands/axeInject.js
+++ b/lib/api/client-commands/axeInject.js
@@ -1,5 +1,6 @@
 /**
  * Injects the [axe-core](https://github.com/dequelabs/axe-core) js library into the current page (using the `.executeScript()` command).
+ *
  * To be paired with `.axeRun()` to evaluate the axe-core accessibility rules.
  *
  * @example
diff --git a/lib/api/client-commands/axeRun.js b/lib/api/client-commands/axeRun.js
index 4b2b5519..e1129ba9 100644
--- a/lib/api/client-commands/axeRun.js
+++ b/lib/api/client-commands/axeRun.js
@@ -16,7 +16,7 @@
  *
  * @method axeRun
  * @syntax browser.axeRun('body')
- * @param {*} [context] Defines the scope of the analysis, will cascade to child elements. See [axe-core docs](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#context-parameter) for more details.
+ * @param {any} [context] Defines the scope of the analysis, will cascade to child elements. See [axe-core docs](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#context-parameter) for more details.
  * @param {object} [options] Object containing rules configuration to use when performing the analysis. See [axe-core docs](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#options-parameter) for more details.
  * @param {function} [callback] Optional callback function which is called with the results.
  * @api protocol.accessibility
diff --git a/lib/api/client-commands/debug.js b/lib/api/client-commands/debug.js
index 53a3e868..e5632223 100644
--- a/lib/api/client-commands/debug.js
+++ b/lib/api/client-commands/debug.js
@@ -1,15 +1,16 @@
-const util = require('util');
 const EventEmitter = require('events');
 const NightwatchRepl = require('../../testsuite/repl');
 const Debuggability = require('../../utils/debuggability.js');
 
 /**
  * This command halts the test execution and provides users with a REPL interface where they can type
- * any of the available Nightwatch commands and the command will be executed in the running browser
+ * any of the available Nightwatch commands or assertions and it will be executed in the running browser
  * in real-time.
  *
- * This can be used to debug why a certain command in not working as expected, find the correct
- * locators for your assertions or just play around with the available Nightwatch commands.
+ * This can be used to debug why a certain command in not working as expected or a certain assertion is
+ * failing by trying out the commands and assertions in different ways (trying an assertion with different
+ * locators until the correct one if found), or just play around with the available Nightwatch commands
+ * and assertions.
  *
  * @example
  * // async function is required while using the debug
@@ -26,52 +27,51 @@ const Debuggability = require('../../utils/debuggability.js');
  * };
  *
  * @method debug
- * @param {object} config Config options for the REPL interface.
+ * @param {object} [config] Config options for the REPL interface.
  * @param {function} [callback] Optional callback function to be called when the command finishes.
  * @api protocol.utilities
  */
+class Debug extends EventEmitter {
+  static get avoidPrematureParentNodeResolution() {
+    return true;
+  }
 
-function Debug() {
-  EventEmitter.call(this);
-}
-
-util.inherits(Debug, EventEmitter);
-
-Debug.prototype.command = function(config, cb) {
-  const repl = new NightwatchRepl(config);
+  command(config, callback) {
+    const repl = new NightwatchRepl(config);
 
-  // eslint-disable-next-line
-  console.log(NightwatchRepl.introMessage());
+    // eslint-disable-next-line
+    console.log(NightwatchRepl.introMessage());
 
-  // Create context for vm
-  const context = {
-    browser: this.api,
-    app: this.api
-  };
-  if (config?.selector) {
-    this.api.executeScript('console.log("Element ' + config.selector + ':", document.querySelector("' + config.selector + '"))');
-  }
-  // Before starting REPL server, Set debugMode to true
-  Debuggability.debugMode = true;
-  // Set isES6AsyncTestcase to true in debugmode
-  const isES6AsyncTestcase = this.client.isES6AsyncTestcase;
-  this.client.isES6AsyncTestcase = true;
-  repl.startServer(context);
+    // Create context for vm
+    const context = {
+      browser: this.api,
+      app: this.api
+    };
+    if (config?.selector) {
+      this.api.executeScript('console.log("Element ' + config.selector + ':", document.querySelector("' + config.selector + '"))');
+    }
+    // Before starting REPL server, Set debugMode to true
+    Debuggability.debugMode = true;
+    // Set isES6AsyncTestcase to true in debugmode
+    const isES6AsyncTestcase = this.client.isES6AsyncTestcase;
+    this.client.isES6AsyncTestcase = true;
+    repl.startServer(context);
 
-  repl.onExit(() => {
-    // On exit, Set debugMode to false
-    Debuggability.debugMode = false;
-    this.client.isES6AsyncTestcase = isES6AsyncTestcase;
+    repl.onExit(() => {
+      // On exit, Set debugMode to false
+      Debuggability.debugMode = false;
+      this.client.isES6AsyncTestcase = isES6AsyncTestcase;
 
-    // if we have a callback, call it right before the complete event
-    if (cb) {
-      cb.call(this.client.api);
-    }
+      // if we have a callback, call it right before the complete event
+      if (callback) {
+        callback.call(this.client.api);
+      }
 
-    this.emit('complete');
-  });
+      this.emit('complete');
+    });
 
-  return this;
-};
+    return this;
+  }
+}
 
 module.exports = Debug;
diff --git a/lib/api/client-commands/pause.js b/lib/api/client-commands/pause.js
index 695d8a4a..080025de 100644
--- a/lib/api/client-commands/pause.js
+++ b/lib/api/client-commands/pause.js
@@ -1,7 +1,5 @@
-const util = require('util');
 const EventEmitter = require('events');
 const readline = require('readline');
-const tty = require('tty');
 const Debuggability = require('../../utils/debuggability.js');
 
 /**
@@ -31,65 +29,63 @@ const Debuggability = require('../../utils/debuggability.js');
  * @param {function} [callback] Optional callback function to be called when the command finishes.
  * @api protocol.utilities
  */
+class Pause extends EventEmitter {
 
-function Pause() {
-  EventEmitter.call(this);
-}
-
-util.inherits(Pause, EventEmitter);
-
-Pause.prototype.command = function(ms, cb) {
-  // If we don't pass the milliseconds, the client will
-  // be suspended indefinitely, until the user presses some
-  // key in the terminal to resume it.
-  if (ms === undefined) {
-    // eslint-disable-next-line
-    console.log(`Paused...
-  Press <space> or F10 to step over to the next test command and pause again.
-  Press Ctrl+C to exit.
-  Press any other key to RESUME.`);
-
-    readline.emitKeypressEvents(process.stdin);
-    process.stdin.resume();
-    if (process.stdin.isTTY) {
-      process.stdin.setRawMode(true);
-    }
-    process.stdin.once('keypress', (str, key) => {
-      if (key.ctrl && key.name === 'c') {
-        this.api.end(function() {
-          process.exit(0);
-        });
-      } else if (key.name === 'space' || key.name === 'f10') {
-        Debuggability.stepOverAndPause = true;
-      }
+  command(ms, callback) {
+    // If we don't pass the milliseconds, the client will
+    // be suspended indefinitely, until the user presses some
+    // key in the terminal to resume it.
+    if (ms === undefined) {
+      // eslint-disable-next-line
+      console.log(`Paused...
+    Press <space> or F10 to step over to the next test command and pause again.
+    Press Ctrl+C to exit.
+    Press any other key to RESUME.`);
 
+      readline.emitKeypressEvents(process.stdin);
+      process.stdin.resume();
       if (process.stdin.isTTY) {
-        process.stdin.setRawMode(false);
+        process.stdin.setRawMode(true);
       }
-      process.stdin.pause();
+      process.stdin.once('keypress', (str, key) => {
+        if (key.ctrl && key.name === 'c') {
+          this.api.end(function() {
+            process.exit(0);
+          });
+        } else if (key.name === 'space' || key.name === 'f10') {
+          Debuggability.stepOverAndPause = true;
+        } else if (key.name === 'd') {
+          this.api.debug();
+        }
 
-      // Remove the logged paused... information above
-      readline.moveCursor(process.stdout, 0, -4);
-      readline.clearScreenDown(process.stdout);
+        if (process.stdin.isTTY) {
+          process.stdin.setRawMode(false);
+        }
+        process.stdin.pause();
 
-      if (cb) {
-        cb.call(this.client.api);
-      }
+        // Remove the logged paused... information above
+        readline.moveCursor(process.stdout, 0, -4);
+        readline.clearScreenDown(process.stdout);
 
-      this.emit('complete');
-    });
-  } else {
-    setTimeout(() => {
-      // if we have a callback, call it right before the complete event
-      if (cb) {
-        cb.call(this.client.api);
-      }
+        if (callback) {
+          callback.call(this.client.api);
+        }
 
-      this.emit('complete');
-    }, ms);
-  }
+        this.emit('complete');
+      });
+    } else {
+      setTimeout(() => {
+        // if we have a callback, call it right before the complete event
+        if (callback) {
+          callback.call(this.client.api);
+        }
+
+        this.emit('complete');
+      }, ms);
+    }
 
-  return this;
-};
+    return this;
+  }
+}
 
 module.exports = Pause;
diff --git a/lib/api/web-element/commands/find.js b/lib/api/web-element/commands/find.js
index ae682815..584317ae 100644
--- a/lib/api/web-element/commands/find.js
+++ b/lib/api/web-element/commands/find.js
@@ -30,6 +30,8 @@
  * @syntax browser.element.find(selector)
  * @param {String|Object} selector
  * @returns {ScopedWebElement}
+ * @alias get
+ * @alias findElement
  */
 module.exports.command = function(selector) {
   return this.createScopedElement(selector, this);
diff --git a/lib/api/web-element/commands/findAll.js b/lib/api/web-element/commands/findAll.js
index f85df013..de261052 100644
--- a/lib/api/web-element/commands/findAll.js
+++ b/lib/api/web-element/commands/findAll.js
@@ -24,6 +24,8 @@
  * @syntax browser.element.findAll(syntax)
  * @param {Selector} selector
  * @returns {Array.<ScopeWebElement>}
+ * @alias getAll
+ * @alias findElements
  */
 module.exports.command = function(selector) {
   return this.createScopedElements(selector, {parentElement: this, commandName: 'findAll'});
diff --git a/lib/api/web-element/scoped-element.js b/lib/api/web-element/scoped-element.js
index 1aaee5f8..341778be 100644
--- a/lib/api/web-element/scoped-element.js
+++ b/lib/api/web-element/scoped-element.js
@@ -23,8 +23,13 @@ class ScopedWebElement {
       'findAllByPlaceholderText': ['getAllByPlaceholderText'],
       'findAllByAltText': ['getAllByAltText'],
       'getRect': ['getSize', 'getLocation', 'rect'],
-      'getProperty': ['property'],
-      'getCssProperty': ['css'],
+      'getAttribute': ['attr', 'attribute'],
+      'getProperty': ['property', 'prop'],
+      'getText': ['text'],
+      'getTagName': ['tagName'],
+      'getAccessibleName': ['accessibleName'],
+      'getCssProperty': ['css', 'getCssValue'],
+      'getAriaRole': ['ariaRole'],
       'isVisible': ['isDisplayed']
     };
   }
@@ -324,9 +329,14 @@ class ScopedWebElement {
 }
 
 function createNarrowedError({error, condition, timeout}) {
-  return error.name === 'TimeoutError'
-    ? new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`)
-    : error;
+  if (error.name === 'TimeoutError') {
+    const err = new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`);
+    err.name = 'NoSuchElementError';
+
+    return err;
+  }
+
+  return error;
 }
 
 module.exports = ScopedWebElement;
diff --git a/lib/transport/errors/index.js b/lib/transport/errors/index.js
index 90308435..5f5e2ccd 100644
--- a/lib/transport/errors/index.js
+++ b/lib/transport/errors/index.js
@@ -155,11 +155,13 @@ module.exports = {
     if (err && (err.name in SeleniumNightwatchErrorCodeMap)) {
       const statusCode = SeleniumNightwatchErrorCodeMap[err.name];
 
-      return {
-        ...err,
-        ...Errors[statusCode],
-        id: statusCode
-      };
+      for (const [key, value] of Object.entries(Errors[statusCode])) {
+        err[key] ||= value;
+      }
+
+      err.id = statusCode;
+
+      return err;
     } else if (err && err.name && (err.stack || err.stackTrace)){
       return err;
     }
diff --git a/lib/transport/selenium-webdriver/method-mappings.js b/lib/transport/selenium-webdriver/method-mappings.js
index bb915573..0f10c8f7 100644
--- a/lib/transport/selenium-webdriver/method-mappings.js
+++ b/lib/transport/selenium-webdriver/method-mappings.js
@@ -587,6 +587,16 @@ module.exports = class MethodMappings {
           const element = this.getWebElement(webElementOrId);
           await element.clear();
 
+          try {
+            const value = await element.getProperty('value');
+            if (isString(value) && value.length > 0) {
+              const backArr = Array(value.length).fill(Key.BACK_SPACE);
+              await element.sendKeys(...backArr);
+            }
+          } catch {
+            // silent catch
+          }
+
           return null;
         },
 
@@ -607,7 +617,7 @@ module.exports = class MethodMappings {
 
           // clear Element value
           try {
-            await element.clear();
+            await this.methods.session.clearElementValue.call(this, webElementOrId);
           } catch (err) {
             if (err.name !== 'InvalidElementStateError') {
               throw err;
diff --git a/lib/transport/selenium-webdriver/options.js b/lib/transport/selenium-webdriver/options.js
index e17f1ef3..da198b55 100644
--- a/lib/transport/selenium-webdriver/options.js
+++ b/lib/transport/selenium-webdriver/options.js
@@ -37,8 +37,10 @@ module.exports = class SeleniumCapabilities {
     this.desiredCapabilities = this.settings.capabilities || this.settings.desiredCapabilities;
 
     // flatten alwaysMatch param from desired Capabilities
-    Object.assign(this.desiredCapabilities, this.desiredCapabilities?.alwaysMatch);
-    delete this.desiredCapabilities['alwaysMatch'];
+    if (this.desiredCapabilities.alwaysMatch) {
+      Object.assign(this.desiredCapabilities, this.desiredCapabilities.alwaysMatch);
+      delete this.desiredCapabilities['alwaysMatch'];
+    }
 
     if (typeof this.desiredCapabilities == 'function') {
       this.desiredCapabilities = this.desiredCapabilities.call(this.settings);
diff --git a/lib/utils/mobile.js b/lib/utils/mobile.js
index b019fa2f..9d2a6621 100644
--- a/lib/utils/mobile.js
+++ b/lib/utils/mobile.js
@@ -172,7 +172,7 @@ class RealIosDeviceIdError extends Error {
       `Pass ${Logger.colors.green('deviceId')} in the command (for e.g : ${Logger.colors.cyan('--deviceId 00008030-00024C2C3453402E')})`,
       `Or pass ${Logger.colors.green('safari:deviceUDID')} capability in config`,
       `To verify the deviceId run, ${Logger.colors.cyan('system_profiler SPUSBDataType | sed -n \'/iPhone/,/Serial/p\' | grep \'Serial Number:\' | awk -F \': \' \'{print $2}')}`,
-      `For more help, run: ${Logger.colors.cyan('npx run @nightwatch/mobile-helper ios')}\n`
+      `For more help, run: ${Logger.colors.cyan('npx @nightwatch/mobile-helper ios')}\n`
     ];
     this.stack = false;
   }
@@ -275,7 +275,7 @@ class IosSessionNotCreatedError extends Error {
       // 'The session timed out while connecting to a Safari instance.'
       help = [
         'Re-run the test command',
-        `If it doesn't work, try running: ${Logger.colors.cyan('npx run @nightwatch/mobile-helper ios')}`
+        `If it doesn't work, try running: ${Logger.colors.cyan('npx @nightwatch/mobile-helper ios')}`
       ];
     } else if (this.message.includes('not find any session hosts') || this.message.includes('Some devices were found')) {
       // Could not find any session hosts that match the requested capabilities
@@ -284,21 +284,21 @@ class IosSessionNotCreatedError extends Error {
         help = [
           `Run command to get device list: ${Logger.colors.cyan('xcrun simctl list devices')}`,
           `Update the ${Logger.colors.cyan('safari:platformVersion')} and/or ${Logger.colors.cyan('safari:platforName')} in Nightwatch configuration accordingly`,
-          `If it doesn't work, try running: ${Logger.colors.cyan('npx run @nightwatch/mobile-helper ios')}`
+          `If it doesn't work, try running: ${Logger.colors.cyan('npx @nightwatch/mobile-helper ios')}`
         ];
       } else {
         help = [
           `Make sure you have passed correct ${Logger.colors.green('deviceId')} in the command (for e.g : ${Logger.colors.cyan('--deviceId 00008030-00024C2C3453402E')})`,
           `Or pass ${Logger.colors.green('safari:deviceUDID')} capability in config`,
           `To verify the deviceId run, ${Logger.colors.cyan('system_profiler SPUSBDataType | sed -n \'/iPhone/,/Serial/p\' | grep \'Serial Number:\' | awk -F \': \' \'{print $2}')}`,
-          `For more help, run: ${Logger.colors.cyan('npx run @nightwatch/mobile-helper ios')}\n`
+          `For more help, run: ${Logger.colors.cyan('npx @nightwatch/mobile-helper ios')}\n`
         ];
       }
     } else if (this.desiredCapabilities['safari:deviceUDID']) {
       help = [
         `Verify the UDID of the device set in Nightwatch configuration (look for ${Logger.colors.cyan('safari:deviceUDID')} capability) or pass the correct UDID using ${Logger.colors.cyan('--deviceId')} flag in the test command.`,
         'Re-run the test command',
-        `If it doesn't work, try running: ${Logger.colors.cyan('npx run @nightwatch/mobile-helper ios')}`
+        `If it doesn't work, try running: ${Logger.colors.cyan('npx @nightwatch/mobile-helper ios')}`
       ];
 
       if (isRealIos(this.desiredCapabilities)) {
diff --git a/types/web-element.d.ts b/types/web-element.d.ts
index d8fc0c71..a5e2c778 100644
--- a/types/web-element.d.ts
+++ b/types/web-element.d.ts
@@ -15,6 +15,7 @@ export interface ScopedElement extends Element, PromiseLike<WebElement> {
 
   find(selector: ScopedElementSelector): ScopedElement;
   get(selector: ScopedElementSelector): ScopedElement;
+  findElement(selector: ScopedElementSelector): ScopedElement;
 
   findByText(
     text: string,
@@ -45,30 +46,31 @@ export interface ScopedElement extends Element, PromiseLike<WebElement> {
       readonly expanded?: boolean;
     }
   ): ScopedElement;
-  
+
   findByPlaceholderText(
     text: string,
     options?: Omit<ScopedSelectorObject, 'selector'> & {
       readonly exact?: boolean;
     }
   ): ScopedElement;
-  
+
   findByLabelText(
     text: string,
     options?: Omit<ScopedSelectorObject, 'selector'> & {
       readonly exact?: boolean;
     }
   ): ScopedElement;
-  
+
   findByAltText(
     text: string,
     options?: Omit<ScopedSelectorObject, 'selector'> & {
       readonly exact?: boolean;
     }
   ): ScopedElement;
-  
+
   findAll(selector: ScopedSelector | Promise<ScopedSelector>): Elements;
   getAll(selector: ScopedSelector | Promise<ScopedSelector>): Elements;
+  findElements(selector: ScopedSelector | Promise<ScopedSelector>): Elements;
 
   findAllByText(
     text: string,
@@ -146,8 +148,10 @@ export interface ScopedElement extends Element, PromiseLike<WebElement> {
   getLocation(): ElementValue<ScopedElementRect>;
 
   getTagName(): ElementValue<string>;
+  tagName(): ElementValue<string>;
 
   getText(): ElementValue<string>;
+  text(): ElementValue<string>;
 
   click(): Promise<WebElement>;
 
@@ -158,10 +162,14 @@ export interface ScopedElement extends Element, PromiseLike<WebElement> {
   submit(): Promise<WebElement>;
 
   getProperty(name: string): ElementValue<string | null>;
+  prop(name: string): ElementValue<string | null>;
+  property(name: string): ElementValue<string | null>;
 
   setProperty(name: string, value: unknown): Promise<WebElement>;
 
   getAttribute(name: string): ElementValue<string | null>;
+  attr(name: string): ElementValue<string | null>;
+  attribute(name: string): ElementValue<string | null>;
 
   setAttribute(name: string, value: string | null): Promise<WebElement>;
 
@@ -176,10 +184,14 @@ export interface ScopedElement extends Element, PromiseLike<WebElement> {
   upload(file: string): Promise<WebElement>;
 
   getAccessibleName(): ElementValue<string>;
+  accessibleName(): ElementValue<string>;
 
   getAriaRole(): ElementValue<string>;
+  ariaRole(): ElementValue<string>;
 
   getCssProperty(name: string): ElementValue<string>;
+  css(name: string): ElementValue<string>;
+  getCssValue(name: string): ElementValue<string>;
 
   getValue(): ElementValue<string | null>;
 
@@ -347,8 +359,8 @@ export type DragAndDropDestination = {
 export interface ElementFunction
   extends Pick<
     ScopedElement,
-    'find' | 'findByText' | 'findByRole' | 'findByPlaceholderText' | 'findByLabelText' | 'findByAltText' |
-    'findAll' | 'findAllByText' | 'findAllByRole' | 'findAllByPlaceholderText' | 'findAllByAltText'
+    'find' | 'get' | 'findElement' | 'findByText' | 'findByRole' | 'findByPlaceholderText' | 'findByLabelText' | 'findByAltText' |
+    'findAll' | 'getAll' | 'findElements' | 'findAllByText' | 'findAllByRole' | 'findAllByPlaceholderText' | 'findAllByAltText'
   > {
   (selector: ScopedElementSelector): ScopedElement;
   (


Test patch:
diff --git a/test/src/api/commands/element/testClearValue.js b/test/src/api/commands/element/testClearValue.js
index 3f4498f6..9d22938e 100644
--- a/test/src/api/commands/element/testClearValue.js
+++ b/test/src/api/commands/element/testClearValue.js
@@ -1,6 +1,7 @@
 const assert = require('assert');
 const MockServer  = require('../../../../lib/mockserver.js');
 const Nightwatch = require('../../../../lib/nightwatch.js');
+const {Key} = require('selenium-webdriver');
 
 describe('clearValue', function() {
 
@@ -118,6 +119,114 @@ describe('clearValue', function() {
     });
   });
 
+  it('client.clearValue() with webdriver protocol - fallback sending backspace keys', function (done) {
+    Nightwatch.initClient({
+      selenium: {
+        version2: false,
+        start_process: false,
+        host: null
+      },
+      output: false,
+      silent: false,
+      webdriver: {
+        host: 'localhost',
+        start_process: false
+      }
+    }).then((client) => {
+      let sendKeysMockCalled = false;
+      let callbackResultValue;
+  
+      MockServer
+        .addMock({
+          url: '/session/13521-10219-202/element/0/clear',
+          response: {value: null}
+        }, true)
+        .addMock({
+          url: '/session/13521-10219-202/element/0/property/value',
+          method: 'GET',
+          response: {value: 'sample'}
+        }, true)
+        .addMock({
+          url: '/session/13521-10219-202/element/0/value',
+          method: 'POST',
+          response: {value: null},
+          onRequest(_, requestData) {
+            assert.strictEqual(requestData.text, Array(6).fill(Key.BACK_SPACE).join(''));
+            sendKeysMockCalled = true;
+          }
+        }, true);
+
+      client.api.clearValue('css selector', '#signupSection', function (result) {
+        callbackResultValue = result.value;
+      });
+  
+      client.start(function (err) {
+        try {
+          assert.strictEqual(err, undefined);
+          assert.strictEqual(callbackResultValue, null);
+          // ensure fallback is working (backspaces are sent to element)
+          assert.strictEqual(sendKeysMockCalled, true);
+          done();
+        } catch (e) {
+          done(e);
+        }
+      });
+    });
+  });
+
+  it('client.clearValue() with webdriver protocol - fallback sending nothing when element cleared correctly', function (done) {
+    Nightwatch.initClient({
+      selenium: {
+        version2: false,
+        start_process: false,
+        host: null
+      },
+      output: false,
+      silent: false,
+      webdriver: {
+        host: 'localhost',
+        start_process: false
+      }
+    }).then((client) => {
+      let sendKeysMockCalled = false;
+      let callbackResultValue;
+  
+      MockServer
+        .addMock({
+          url: '/session/13521-10219-202/element/0/clear',
+          response: {value: null}
+        }, true)
+        .addMock({
+          url: '/session/13521-10219-202/element/0/property/value',
+          method: 'GET',
+          response: {value: ''}
+        }, true)
+        .addMock({
+          url: '/session/13521-10219-202/element/0/value',
+          method: 'POST',
+          response: {value: null},
+          onRequest() {
+            sendKeysMockCalled = true;
+          }
+        }, true);
+
+      client.api.clearValue('css selector', '#signupSection', function (result) {
+        callbackResultValue = result.value;
+      });
+  
+      client.start(function (err) {
+        try {
+          assert.strictEqual(err, undefined);
+          assert.strictEqual(callbackResultValue, null);
+          assert.strictEqual(sendKeysMockCalled, false);
+          done();
+        } catch (e) {
+          done(e);
+        }
+      });
+    });
+  });
+
   it('client.clearValue() with webdriver protocol - element not found', function(done) {
     Nightwatch.initClient({
       selenium: {
@@ -163,4 +272,4 @@ describe('clearValue', function() {
       client.start(done);
     });
   });
-});
+});
\ No newline at end of file
diff --git a/test/src/api/commands/web-element/testClear.js b/test/src/api/commands/web-element/testClear.js
index 01c5399a..8fda24f2 100644
--- a/test/src/api/commands/web-element/testClear.js
+++ b/test/src/api/commands/web-element/testClear.js
@@ -1,5 +1,5 @@
 const assert = require('assert');
-const {WebElement} = require('selenium-webdriver');
+const {WebElement, Key} = require('selenium-webdriver');
 const MockServer  = require('../../../../lib/mockserver.js');
 const CommandGlobals = require('../../../../lib/globals/commands-w3c.js');
 const common = require('../../../../common.js');
@@ -73,4 +73,73 @@ describe('element().clear() command', function () {
     assert.strictEqual(result instanceof WebElement, true);
     assert.strictEqual(await result.getId(), '0');
   });
+
+  it('test .element().clear() with fallback sending keys', async function() {
+    let sendKeysMockCalled = false;
+
+    MockServer
+      .addMock({
+        url: '/session/13521-10219-202/element/0/clear',
+        method: 'POST',
+        response: JSON.stringify({
+          value: null
+        })
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/0/property/value',
+        method: 'GET',
+        response: {value: 'sample'}
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/0/value',
+        method: 'POST',
+        response: {value: null},
+        onRequest(_, requestData) {
+          assert.strictEqual(requestData.text, Array(6).fill(Key.BACK_SPACE).join(''));
+          sendKeysMockCalled = true;
+        }
+      }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').clear();
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, true);
+    assert.strictEqual(await result.getId(), '0');
+
+    assert.strictEqual(sendKeysMockCalled, true);
+  });
+
+  it('test .element().clear() with fallback not sending keys when clear working correctly', async function() {
+    let sendKeysMockCalled = false;
+
+    MockServer
+      .addMock({
+        url: '/session/13521-10219-202/element/0/clear',
+        method: 'POST',
+        response: JSON.stringify({
+          value: null
+        })
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/0/property/value',
+        method: 'GET',
+        response: {value: ''}
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/0/value',
+        method: 'POST',
+        response: {value: null},
+        onRequest() {
+          sendKeysMockCalled = true;
+        }
+      }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').clear();
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, true);
+    assert.strictEqual(await result.getId(), '0');
+
+    assert.strictEqual(sendKeysMockCalled, false);
+  });
 });
diff --git a/test/src/api/commands/web-element/testFind.js b/test/src/api/commands/web-element/testFind.js
index 721b5001..ff6a739f 100644
--- a/test/src/api/commands/web-element/testFind.js
+++ b/test/src/api/commands/web-element/testFind.js
@@ -76,4 +76,24 @@ describe('element().find() commands', function () {
     assert.strictEqual(signupWebElement instanceof WebElement, true);
     assert.strictEqual(await signupWebElement.getId(), '0');
   });
+
+  it('test .element.get()', async function() {
+    const signupElement = this.client.api.element.get('#signupSection');
+    assert.strictEqual(signupElement instanceof Element, true);
+    assert.strictEqual(await signupElement.getId(), '0');
+
+    const signupWebElement = await signupElement;
+    assert.strictEqual(signupWebElement instanceof WebElement, true);
+    assert.strictEqual(await signupWebElement.getId(), '0');
+  });
+
+  it('test .element.findElement()', async function() {
+    const signupElement = this.client.api.element.findElement('#signupSection');
+    assert.strictEqual(signupElement instanceof Element, true);
+    assert.strictEqual(await signupElement.getId(), '0');
+
+    const signupWebElement = await signupElement;
+    assert.strictEqual(signupWebElement instanceof WebElement, true);
+    assert.strictEqual(await signupWebElement.getId(), '0');
+  });
 });
diff --git a/test/src/api/commands/web-element/testFindAll.js b/test/src/api/commands/web-element/testFindAll.js
index 89878b42..24d5ec9c 100644
--- a/test/src/api/commands/web-element/testFindAll.js
+++ b/test/src/api/commands/web-element/testFindAll.js
@@ -115,6 +115,40 @@ describe('element().findAll() commands', function () {
     assert.strictEqual(await btnWEbElements[0].getId(), '5cc459b8-36a8-3042-8b4a-258883ea642b');
   });
 
+  it('test .element.getAll()', async function() {
+    const webLoginElements = this.client.api.element.getAll('#weblogin');
+    assert.strictEqual(webLoginElements instanceof Element, false);
+    assert.strictEqual(typeof webLoginElements.find, 'undefined');
+    assert.strictEqual(typeof webLoginElements.click, 'undefined');
+
+    assert.strictEqual(webLoginElements instanceof Promise, false);
+    assert.strictEqual(typeof webLoginElements.then, 'function');
+    assert.strictEqual(typeof webLoginElements.nth, 'function');
+    assert.strictEqual(typeof webLoginElements.count, 'function');
+
+    const btnWEbElements = await webLoginElements;
+    assert.strictEqual(btnWEbElements.length, 2);
+    assert.strictEqual(btnWEbElements[0] instanceof WebElement, true);
+    assert.strictEqual(await btnWEbElements[0].getId(), '5cc459b8-36a8-3042-8b4a-258883ea642b');
+  });
+
+  it('test .element.findElements()', async function() {
+    const webLoginElements = this.client.api.element.findElements('#weblogin');
+    assert.strictEqual(webLoginElements instanceof Element, false);
+    assert.strictEqual(typeof webLoginElements.find, 'undefined');
+    assert.strictEqual(typeof webLoginElements.click, 'undefined');
+
+    assert.strictEqual(webLoginElements instanceof Promise, false);
+    assert.strictEqual(typeof webLoginElements.then, 'function');
+    assert.strictEqual(typeof webLoginElements.nth, 'function');
+    assert.strictEqual(typeof webLoginElements.count, 'function');
+
+    const btnWEbElements = await webLoginElements;
+    assert.strictEqual(btnWEbElements.length, 2);
+    assert.strictEqual(btnWEbElements[0] instanceof WebElement, true);
+    assert.strictEqual(await btnWEbElements[0].getId(), '5cc459b8-36a8-3042-8b4a-258883ea642b');
+  });
+
   it('test .element().findAll().count()', async function() {
     const resultPromise = this.client.api.element('#signupSection').findAll('.btn').count();
     assert.strictEqual(resultPromise instanceof Element, false);
diff --git a/test/src/api/commands/web-element/testGetAccessibleName.js b/test/src/api/commands/web-element/testGetAccessibleName.js
index 349ddc22..5b3bca5a 100644
--- a/test/src/api/commands/web-element/testGetAccessibleName.js
+++ b/test/src/api/commands/web-element/testGetAccessibleName.js
@@ -40,6 +40,31 @@ describe('element().getAccessibleName() command', function () {
     assert.strictEqual(resultValue, 'Signup');
   });
 
+  it('test .element().accessibleName() alias', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/element/0/computedlabel',
+      method: 'GET',
+      response: JSON.stringify({
+        value: 'Signup'
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').accessibleName();
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+    assert.strictEqual(typeof resultPromise.value, 'object');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.strictEqual(result, 'Signup');
+
+    const resultValue = await resultPromise.value;
+    assert.strictEqual(resultValue, 'Signup');
+  });
+
   it('test .element().find().getAccessibleName()', async function() {
     MockServer.addMock({
       url: '/session/13521-10219-202/element/1/computedlabel',
@@ -115,4 +140,5 @@ describe('element().getAccessibleName() command', function () {
     assert.strictEqual(await resultPromise.assert.not.contains('Signupx'), 'Signup');
     assert.strictEqual(await resultPromise.assert.not.matches(/Si[a-z]{2}upx/), 'Signup');
   });
+
 });
diff --git a/test/src/api/commands/web-element/testGetAriaRole.js b/test/src/api/commands/web-element/testGetAriaRole.js
index 53e86b65..7cddaad3 100644
--- a/test/src/api/commands/web-element/testGetAriaRole.js
+++ b/test/src/api/commands/web-element/testGetAriaRole.js
@@ -38,6 +38,30 @@ describe('element().getAriaRole() command', function () {
     assert.strictEqual(resultValue, 'signupSection');
   });
 
+  it('test .element().ariaRole()', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/element/0/computedrole',
+      method: 'GET',
+      response: JSON.stringify({
+        value: 'signupSection'
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').ariaRole();
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.strictEqual(result, 'signupSection');
+
+    const resultValue = await resultPromise.value;
+    assert.strictEqual(resultValue, 'signupSection');
+  });
+
   it('test .element().find().getAriaRole()', async function() {
     MockServer.addMock({
       url: '/session/13521-10219-202/element/1/computedrole',
diff --git a/test/src/api/commands/web-element/testGetAttribute.js b/test/src/api/commands/web-element/testGetAttribute.js
index 720866a2..7a3ddc6d 100644
--- a/test/src/api/commands/web-element/testGetAttribute.js
+++ b/test/src/api/commands/web-element/testGetAttribute.js
@@ -38,6 +38,54 @@ describe('element().getAttribute() command', function () {
     assert.strictEqual(resultValue, 'text');
   });
 
+  it('test .element.attr() alias', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/execute/sync',
+      method: 'POST',
+      response: JSON.stringify({
+        value: 'text'
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').attr('type');
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.strictEqual(result, 'text');
+
+    const resultValue = await resultPromise.value;
+    assert.strictEqual(resultValue, 'text');
+  });
+
+  it('test .element().attribute() alias', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/execute/sync',
+      method: 'POST',
+      response: JSON.stringify({
+        value: 'text'
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').attribute('type');
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.strictEqual(result, 'text');
+
+    const resultValue = await resultPromise.value;
+    assert.strictEqual(resultValue, 'text');
+  });
+
   it('test .element().find().getAttribute()', async function() {
     MockServer.addMock({
       url: '/session/13521-10219-202/execute/sync',
diff --git a/test/src/api/commands/web-element/testGetCssProperty.js b/test/src/api/commands/web-element/testGetCssProperty.js
index 3a29befa..fc474399 100644
--- a/test/src/api/commands/web-element/testGetCssProperty.js
+++ b/test/src/api/commands/web-element/testGetCssProperty.js
@@ -63,6 +63,30 @@ describe('element().getCssProperty() command', function () {
     assert.strictEqual(resultValue, '150px');
   });
 
+  it('test .element().getCssValue() alias', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/element/0/css/height',
+      method: 'GET',
+      response: JSON.stringify({
+        value: '150px'
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').getCssValue('height');
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+    
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.strictEqual(result, '150px');
+
+    const resultValue = await resultPromise.value;
+    assert.strictEqual(resultValue, '150px');
+  });
+
   it('test .element().find().getCssProperty()', async function() {
     MockServer.addMock({
       url: '/session/13521-10219-202/element/1/css/height',
@@ -135,4 +159,5 @@ describe('element().getCssProperty() command', function () {
     assert.strictEqual(await resultPromise.assert.not.contains('150x'), '150px');
     assert.strictEqual(await resultPromise.assert.not.matches(/150[a-z]{2}x/), '150px');
   });
+  
 });
diff --git a/test/src/api/commands/web-element/testGetProperty.js b/test/src/api/commands/web-element/testGetProperty.js
index b68b8c3d..58dca869 100644
--- a/test/src/api/commands/web-element/testGetProperty.js
+++ b/test/src/api/commands/web-element/testGetProperty.js
@@ -62,6 +62,30 @@ describe('element().getProperty() command', function () {
     assert.deepStrictEqual(resultValue, ['.signup']);
   });
 
+  it('test .element().prop() alias', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/element/0/property/classList',
+      method: 'GET',
+      response: JSON.stringify({
+        value: ['.signup']
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').prop('classList');
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.deepStrictEqual(result, ['.signup']);
+
+    const resultValue = await resultPromise.value;
+    assert.deepStrictEqual(resultValue, ['.signup']);
+  });
+  
   it('test .element().find().getProperty()', async function() {
     MockServer.addMock({
       url: '/session/13521-10219-202/element/1/property/classList',
@@ -109,4 +133,5 @@ describe('element().getProperty() command', function () {
     const resultValue = await resultPromise.value;
     assert.deepStrictEqual(resultValue, ['.signup']);
   });
+
 });
diff --git a/test/src/api/commands/web-element/testGetTagName.js b/test/src/api/commands/web-element/testGetTagName.js
index a1b0f64e..2c7f3318 100644
--- a/test/src/api/commands/web-element/testGetTagName.js
+++ b/test/src/api/commands/web-element/testGetTagName.js
@@ -38,6 +38,30 @@ describe('element().getTagName() command', function () {
     assert.strictEqual(resultValue, 'div');
   });
 
+  it('test .element().tagName() alias', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/element/0/name',
+      method: 'GET',
+      response: JSON.stringify({
+        value: 'div'
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').tagName();
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.strictEqual(result, 'div');
+
+    const resultValue = await resultPromise.value;
+    assert.strictEqual(resultValue, 'div');
+  });
+
   it('test .element().find().getTagName()', async function() {
     MockServer.addMock({
       url: '/session/13521-10219-202/element/1/name',
@@ -110,4 +134,5 @@ describe('element().getTagName() command', function () {
     assert.strictEqual(await resultPromise.assert.not.contains('dx'), 'div');
     assert.strictEqual(await resultPromise.assert.not.matches(/di[a-z]{2}x/), 'div');
   });
+
 });
diff --git a/test/src/api/commands/web-element/testGetText.js b/test/src/api/commands/web-element/testGetText.js
index 14162147..056bb49f 100644
--- a/test/src/api/commands/web-element/testGetText.js
+++ b/test/src/api/commands/web-element/testGetText.js
@@ -38,6 +38,30 @@ describe('element().getText() command', function () {
     assert.strictEqual(resultValue, 'Signup');
   });
 
+  it('test .element().text() alias', async function() {
+    MockServer.addMock({
+      url: '/session/13521-10219-202/element/0/text',
+      method: 'GET',
+      response: JSON.stringify({
+        value: 'Signup'
+      })
+    }, true);
+
+    const resultPromise = this.client.api.element('#signupSection').text();
+    assert.strictEqual(resultPromise instanceof Element, false);
+    assert.strictEqual(typeof resultPromise.find, 'undefined');
+
+    assert.strictEqual(resultPromise instanceof Promise, false);
+    assert.strictEqual(typeof resultPromise.then, 'function');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, false);
+    assert.strictEqual(result, 'Signup');
+
+    const resultValue = await resultPromise.value;
+    assert.strictEqual(resultValue, 'Signup');
+  });
+
   it('test .element().find().getText()', async function() {
     MockServer.addMock({
       url: '/session/13521-10219-202/element/1/text',
@@ -110,4 +134,5 @@ describe('element().getText() command', function () {
     assert.strictEqual(await resultPromise.assert.not.contains('Signupx'), 'Signup');
     assert.strictEqual(await resultPromise.assert.not.matches(/Si[a-z]{2}upx/), 'Signup');
   });
+
 });
diff --git a/test/src/api/commands/web-element/testSetValue.js b/test/src/api/commands/web-element/testSetValue.js
index 561cc6cb..00110a73 100644
--- a/test/src/api/commands/web-element/testSetValue.js
+++ b/test/src/api/commands/web-element/testSetValue.js
@@ -1,5 +1,5 @@
 const assert = require('assert');
-const {WebElement} = require('selenium-webdriver');
+const {WebElement, Key} = require('selenium-webdriver');
 const MockServer  = require('../../../../lib/mockserver.js');
 const CommandGlobals = require('../../../../lib/globals/commands-w3c.js');
 const common = require('../../../../common.js');
@@ -151,4 +151,68 @@ describe('element().setValue() command', function () {
     assert.strictEqual(result instanceof WebElement, true);
     assert.strictEqual(await result.getId(), '9');
   });
+
+  it('test .element().setValue() with clear fallback sending keys', async function() {
+    let sendKeysMockCalled = 0;
+
+    MockServer
+      .addMock({
+        url: '/session/13521-10219-202/elements',
+        postdata: {
+          using: 'css selector',
+          value: 'input[name=q]'
+        },
+        method: 'POST',
+        response: JSON.stringify({
+          value: [{'element-6066-11e4-a52e-4f735466cecf': '9'}]
+        })
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/9/clear',
+        method: 'POST',
+        postdata: {},
+        response: JSON.stringify({
+          value: null
+        })
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/9/property/value',
+        method: 'GET',
+        response: {value: 'sample'}
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/9/value',
+        method: 'POST',
+        response: {value: null},
+        onRequest(_, requestData) {
+          assert.strictEqual(requestData.text, Array(6).fill(Key.BACK_SPACE).join(''));
+          sendKeysMockCalled++;
+        }
+      }, true)
+      .addMock({
+        url: '/session/13521-10219-202/element/9/value',
+        method: 'POST',
+        postdata: {
+          text: 'nightwatch',
+          value: [
+            'n', 'i', 'g', 'h', 't', 'w', 'a', 't', 'c', 'h'
+          ]
+        },
+        response: JSON.stringify({
+          value: null
+        }),
+        onRequest(_, requestData) {
+          assert.strictEqual(requestData.text, 'nightwatch');
+          sendKeysMockCalled++;
+        }
+      }, true);
+
+    const resultPromise = this.client.api.element('input[name=q]').setValue('nightwatch');
+
+    const result = await resultPromise;
+    assert.strictEqual(result instanceof WebElement, true);
+    assert.strictEqual(await result.getId(), '9');
+
+    assert.strictEqual(sendKeysMockCalled, 2);
+  });
 });
diff --git a/test/src/api/protocol/testElementCommands.js b/test/src/api/protocol/testElementCommands.js
index a916d011..933bfbe5 100644
--- a/test/src/api/protocol/testElementCommands.js
+++ b/test/src/api/protocol/testElementCommands.js
@@ -512,13 +512,20 @@ describe('element actions', function () {
         },
         commandName: 'elementIdValue',
         args: ['TEST_ELEMENT', 'test', function(result) {
+          // accounting for fallback for clearElement as well.
+          assert.strictEqual(assertions.length, 4);
+
           assert.strictEqual(assertions[0].command, 'clearElement');
           assert.ok(assertions[0].args.id instanceof WebElement);
 
-          assert.strictEqual(assertions[1].command, 'sendKeysToElement');
-          assert.strictEqual(assertions[1].args.text, 'test');
-          assert.deepStrictEqual(assertions[1].args.value, ['t', 'e', 's', 't']);
-          assert.ok(assertions[1].args.id instanceof WebElement);
+          // fallback for clearElement
+          assert.strictEqual(assertions[1].command, 'getElementProperty');
+          assert.strictEqual(assertions[2].command, 'sendKeysToElement');
+
+          assert.strictEqual(assertions[3].command, 'sendKeysToElement');
+          assert.strictEqual(assertions[3].args.text, 'test');
+          assert.deepStrictEqual(assertions[3].args.value, ['t', 'e', 's', 't']);
+          assert.ok(assertions[3].args.id instanceof WebElement);
 
           assert.deepStrictEqual(result, {value: null, status: 0});
         }]
diff --git a/test/src/core/testPageObjectCommands.js b/test/src/core/testPageObjectCommands.js
index 8ad0f690..6651b2fb 100644
--- a/test/src/core/testPageObjectCommands.js
+++ b/test/src/core/testPageObjectCommands.js
@@ -28,7 +28,7 @@ describe('test PageObject Commands', function () {
     this.client = Nightwatch.client();
   });
 
-  it('testPageObjectElementCommandWithMutliArgs', function(done) {
+  it('testPageObjectElementCommandWithMutliArgs', function (done) {
     MockServer.addMock({
       url: '/wd/hub/session/1352110219202/element/0/value',
       method: 'POST',
@@ -48,7 +48,7 @@ describe('test PageObject Commands', function () {
       }
     });
 
-    let page = this.client.api.page.simplePageObj();
+    const page = this.client.api.page.simplePageObj();
     page.setValue('@loginCss', '1', function callback(result) {
       assert.strictEqual(result.status, 0);
       done();
@@ -57,9 +57,9 @@ describe('test PageObject Commands', function () {
     this.client.start();
   });
 
-  it('testPageObjectCallbackContext', function(done) {
-    let api = this.client.api;
-    let page = api.page.simplePageObj();
+  it('testPageObjectCallbackContext', function (done) {
+    const api = this.client.api;
+    const page = api.page.simplePageObj();
 
     page
       .waitForElementPresent('#weblogin', 1000, true, function callback(result) {
@@ -79,9 +79,9 @@ describe('test PageObject Commands', function () {
     this.client.start();
   });
 
-  it('testPageObjectLocateStrategy', function(done) {
-    let client = this.client;
-    let page = client.api.page.simplePageObj();
+  it('testPageObjectLocateStrategy', function (done) {
+    const client = this.client;
+    const page = client.api.page.simplePageObj();
 
     assert.strictEqual(client.locateStrategy, 'css selector', 'locateStrategy should default to css selector');
 
@@ -93,14 +93,14 @@ describe('test PageObject Commands', function () {
         done();
       });
 
-    this.client.start(function(err) {
+    this.client.start(function (err) {
       if (err) {
         done(err);
       }
     });
   });
 
-  it('testPageObjectElementRecursion', function(done) {
+  it('testPageObjectElementRecursion', function (done) {
     MockServer.addMock({
       'url': '/wd/hub/session/1352110219202/element/1/click',
       'response': JSON.stringify({
@@ -108,8 +108,8 @@ describe('test PageObject Commands', function () {
         status: 0
       })
     }, true);
-    let client = this.client;
-    let section = client.api.page.simplePageObj().section.signUp;
+    const client = this.client;
+    const section = client.api.page.simplePageObj().section.signUp;
     section.click('@help', function callback(result) {
       assert.strictEqual(result.status, 0, result.value && result.value.message || 'An error occurred:\n' + JSON.stringify(result));
     });
@@ -120,7 +120,7 @@ describe('test PageObject Commands', function () {
     this.client.start(err => done(err));
   });
 
-  it('testPageObjectPluralElementRecursion', function(done) {
+  it('testPageObjectPluralElementRecursion', function (done) {
     MockServer.addMock({
       url: '/wd/hub/session/1352110219202/element/1/elements',
       method: 'POST',
@@ -131,7 +131,7 @@ describe('test PageObject Commands', function () {
       })
     });
 
-    let section = this.client.api.page.simplePageObj().section.signUp;
+    const section = this.client.api.page.simplePageObj().section.signUp;
     section.waitForElementPresent('@help', 1000, true, function callback(result) {
       assert.strictEqual(result.status, 0);
       assert.strictEqual(result.value.length, 1);
@@ -139,12 +139,12 @@ describe('test PageObject Commands', function () {
       assert.strictEqual(result.WebdriverElementId, '1');
     });
 
-    this.client.start(function(err) {
+    this.client.start(function (err) {
       done(err);
     });
   });
 
-  it('testPageObjectElementCommandSwitchLocateStrategy', function(done) {
+  it('testPageObjectElementCommandSwitchLocateStrategy', function (done) {
     MockServer.addMock({
       'url': '/wd/hub/session/1352110219202/element/0/click',
       'response': JSON.stringify({
@@ -160,7 +160,7 @@ describe('test PageObject Commands', function () {
       })
     }, true);
 
-    let page = this.client.api.page.simplePageObj();
+    const page = this.client.api.page.simplePageObj();
 
     page.click('@loginCss', function callback(result) {
       assert.strictEqual(result.status, 0);
@@ -172,26 +172,41 @@ describe('test PageObject Commands', function () {
     this.client.start();
   });
 
-  it('testPageObjectInvalidElementCommand', function(done) {
-    let page = this.client.api.page.simplePageObj();
+  it('testPageObjectInvalidElementCommand', function (done) {
+    const page = this.client.api.page.simplePageObj();
 
     assert.throws(
       function () {
         page.click('@invalidElement');
+      },
+      {
+        name: 'Error',
+        message: 'Element "invalidElement" was not found in "simplePageObj". Available elements: loginAsString, loginCss, loginIndexed, loginXpath, loginId'
+      }
+    );
+    done();
+  });
+
+  it('testAsyncPageObjectInvalidElementCommand', function (done) {
+    const page = this.client.api.page.simplePageObj();
+
+    assert.rejects(
+      async function () {
+        page.click('@invalidElement');
       }, 'Element command on an invalid element should throw exception'
     );
     done();
   });
 
-  it('testPageObjectPropsFunctionReturnsObject', function() {
-    let page = this.client.api.page.simplePageObj();
+  it('testPageObjectPropsFunctionReturnsObject', function () {
+    const page = this.client.api.page.simplePageObj();
 
     assert.strictEqual(typeof page.props, 'object', 'props function should be called and set page.props equals its returned object');
     assert.strictEqual(page.props.url, page.url, 'props function should be called with page context');
   });
 
-  it('testSectionObjectPropsFunctionReturnsObject', function() {
-    let page = this.client.api.page.simplePageObj();
+  it('testSectionObjectPropsFunctionReturnsObject', function () {
+    const page = this.client.api.page.simplePageObj();
 
     assert.strictEqual(typeof page.section.propTest.props, 'object', 'props function should be called and set page.props equals its returned object');
     assert.ok(page.section.propTest.props.defaults.propTest, 'props function should be called with page context');
@@ -199,8 +214,8 @@ describe('test PageObject Commands', function () {
   });
 
   it('testPageObjectWithUrlChanged', function (done) {
-    let page = this.client.api.page.simplePageObj();
-    let urlsArr = [];
+    const page = this.client.api.page.simplePageObj();
+    const urlsArr = [];
     page.api.url = function (url) {
       urlsArr.push(url);
     };
@@ -230,8 +245,8 @@ describe('test PageObject Commands', function () {
   });
 
   it('testPageObject navigate() with url param', function (done) {
-    let page = this.client.api.page.simplePageObj();
-    let urlsArr = [];
+    const page = this.client.api.page.simplePageObj();
+    const urlsArr = [];
     page.api.url = function (url) {
       urlsArr.push(url);
     };
@@ -261,14 +276,14 @@ describe('test PageObject Commands', function () {
   });
 
   it('testPageObject navigate() with url param and callback', function (done) {
-    let page = this.client.api.page.simplePageObj();
-    let urlsArr = [];
+    const page = this.client.api.page.simplePageObj();
+    const urlsArr = [];
     page.api.url = function (url, callback) {
       urlsArr.push(url);
       callback();
     };
     let called = false;
-    page.navigate('http://local', function() {
+    page.navigate('http://local', function () {
       called = true;
     });
 
@@ -297,7 +312,7 @@ describe('test PageObject Commands', function () {
 
     const page = this.client.api.page.simplePageObj();
     page.api.launch_url = 'https://nightwatchjs.org';
-    
+
     page.url = function (url) {
       return this.api.launch_url;
     };
diff --git a/types/tests/webElement.test-d.ts b/types/tests/webElement.test-d.ts
index ed24c4f5..e7a3d0ff 100644
--- a/types/tests/webElement.test-d.ts
+++ b/types/tests/webElement.test-d.ts
@@ -44,6 +44,9 @@ describe('new element() api', function () {
     expectType<ScopedElement>(elementFind);
     expectType<WebElement>(await elementFind);
 
+    expectType<ScopedElement>(browser.element.get('selector'));
+    expectType<ScopedElement>(browser.element.findElement('selector'));
+
     const elementFindByText = browser.element.findByText('some-text', {exact: true, abortOnFailure: false});
     expectType<ScopedElement>(elementFindByText);
 
@@ -65,9 +68,13 @@ describe('new element() api', function () {
     const elementFindAll = browser.element.findAll('selector');
     expectType<Elements>(elementFindAll);
     expectType<WebElement[]>(await elementFindAll);
+
     expectType<ScopedElement>(elementFindAll.nth(2));
     expectType<number>(await elementFindAll.count());
 
+    expectType<Elements>(browser.element.getAll('selector'));
+    expectType<Elements>(browser.element.findElements('selector'));
+
     const elementFindAllByText = browser.element.findAllByText('some-text', {exact: true, abortOnFailure: false});
     expectType<Elements>(elementFindAllByText);
 
@@ -102,6 +109,7 @@ describe('new element() api', function () {
 
     expectType<ScopedElement>(elem.find('selector'));
     expectType<ScopedElement>(elem.get('selector'));
+    expectType<ScopedElement>(elem.findElement('selector'));
 
     expectType<ScopedElement>(elem.findByText('some-text', {exact: true, abortOnFailure: false}));
 
@@ -114,6 +122,7 @@ describe('new element() api', function () {
     expectType<ScopedElement>(elem.findByAltText('some-text', {exact: true, abortOnFailure: false}));
 
     expectType<Elements>(elem.findAll('selector'));
+    expectType<Elements>(elem.findElements('selector'));
     expectType<Elements>(elem.getAll('selector'));
 
     expectType<Elements>(elem.findAllByText('some-text', {exact: true, abortOnFailure: false}));
@@ -135,10 +144,16 @@ describe('new element() api', function () {
 
     expectType<ElementValue<string>>(elem.getId());
     expectType<ElementValue<string>>(elem.getTagName());
+    expectType<ElementValue<string>>(elem.tagName());
     expectType<ElementValue<string>>(elem.getText());
+    expectType<ElementValue<string>>(elem.text());
 
     expectType<ElementValue<string | null>>(elem.getProperty('property-name'));
+    expectType<ElementValue<string | null>>(elem.prop('property-name'));
+    expectType<ElementValue<string | null>>(elem.property('property-name'));
     expectType<ElementValue<string | null>>(elem.getAttribute('attrib-name'));
+    expectType<ElementValue<string | null>>(elem.attr('attrib-name'));
+    expectType<ElementValue<string | null>>(elem.attribute('attrib-name'));
     expectType<ElementValue<string | null>>(elem.getValue());
     expectType<ElementValue<boolean>>(elem.isEnabled());
     expectType<ElementValue<boolean>>(elem.isVisible());
@@ -150,8 +165,12 @@ describe('new element() api', function () {
     expectType<ElementValue<ScopedElementRect>>(elem.getLocation());
 
     expectType<ElementValue<string>>(elem.getAccessibleName());
+    expectType<ElementValue<string>>(elem.accessibleName());
     expectType<ElementValue<string>>(elem.getAriaRole());
+    expectType<ElementValue<string>>(elem.ariaRole());
     expectType<ElementValue<string>>(elem.getCssProperty('height'));
+    expectType<ElementValue<string>>(elem.css('height'));
+    expectType<ElementValue<string>>(elem.getCssValue('height'));
     expectType<ElementValue<string>>(elem.takeScreenshot());
 
     expectType<Promise<WebElement>>(elem.click());