diff --git a/lib/api/web-element/commands/isVisible.js b/lib/api/web-element/commands/isVisible.js
new file mode 100644
index 0000000000..4bf41db720
--- /dev/null
+++ b/lib/api/web-element/commands/isVisible.js
@@ -0,0 +1,29 @@
+/**
+ * Determines if an element is visible.
+ *
+ * For more info on working with DOM elements in Nightwatch, refer to the Finding & interacting with DOM Elements guide page.
+ *
+ * @example
+ * describe('isVisible demo', function() {
+ * it('test isVisible', function(browser) {
+ * browser.element('#search').isVisible().assert.equals(true);
+ * });
+ *
+ * it('test async isVisible', async function(browser) {
+ * const result = await browser.element('#search').isVisible();
+ * browser.assert.equal(result, true);
+ * });
+ * });
+ *
+ * @since 3.5.0
+ * @method isVisible
+ * @memberof ScopedWebElement
+ * @instance
+ * @syntax browser.element(selector).isVisible()
+ * @see https://www.w3.org/TR/webdriver/#element-displayedness
+ * @returns {ScopedValue}
+ * @alias isDisplayed
+ */
+module.exports.command = function() {
+ return this.runQueuedCommandScoped('isElementDisplayed');
+};
diff --git a/test/lib/mockserver.js b/test/lib/mockserver.js
index c47642e6e1..8c59346e96 100644
--- a/test/lib/mockserver.js
+++ b/test/lib/mockserver.js
@@ -61,7 +61,13 @@ class MockServer {
res.writeHead(Number(item.statusCode), headers);
if (item.onRequest) {
- item.onRequest(item);
+ let requestData = '';
+ try {
+ requestData = JSON.parse(postdata);
+ // eslint-disable-next-line no-empty
+ } catch (e) {}
+
+ item.onRequest(item, requestData);
}
if (item.onResponse) {
diff --git a/test/src/api/commands/web-element/testIsVisible.js b/test/src/api/commands/web-element/testIsVisible.js
new file mode 100644
index 0000000000..c1ba6c9704
--- /dev/null
+++ b/test/src/api/commands/web-element/testIsVisible.js
@@ -0,0 +1,150 @@
+const assert = require('assert');
+const {WebElement} = require('selenium-webdriver');
+const MockServer = require('../../../../lib/mockserver.js');
+const CommandGlobals = require('../../../../lib/globals/commands-w3c.js');
+const common = require('../../../../common.js');
+const Element = common.require('element/index.js');
+
+describe('element().isVisible() command', function() {
+ before(function (done) {
+ CommandGlobals.beforeEach.call(this, done);
+ });
+
+ after(function (done) {
+ CommandGlobals.afterEach.call(this, done);
+ });
+
+ it('test .element().isVisible() displayed', async function() {
+ let elementId;
+
+ MockServer.addMock({
+ url: '/session/13521-10219-202/execute/sync',
+ method: 'POST',
+ response: JSON.stringify({
+ value: true
+ }),
+ onRequest(_, requestData) {
+ elementId = requestData.args[0]['element-6066-11e4-a52e-4f735466cecf'];
+ }
+ }, true);
+
+ const resultPromise = this.client.api.element('#signupSection').isVisible();
+ 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, true);
+ assert.strictEqual(elementId, '0');
+ });
+
+ it('test .element().isVisible() not displayed', async function() {
+ let elementId;
+
+ MockServer.addMock({
+ url: '/session/13521-10219-202/execute/sync',
+ method: 'POST',
+ response: JSON.stringify({
+ value: false
+ }),
+ onRequest(_, requestData) {
+ elementId = requestData.args[0]['element-6066-11e4-a52e-4f735466cecf'];
+ }
+ }, true);
+
+ const resultPromise = this.client.api.element('#signupSection').isVisible();
+ 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, false);
+ assert.strictEqual(elementId, '0');
+ });
+
+ it('test .element().find().isVisible()', async function() {
+ let elementId;
+
+ MockServer.addMock({
+ url: '/session/13521-10219-202/execute/sync',
+ method: 'POST',
+ response: JSON.stringify({
+ value: true
+ }),
+ onRequest(_, requestData) {
+ elementId = requestData.args[0]['element-6066-11e4-a52e-4f735466cecf'];
+ }
+ }, true);
+
+ const resultPromise = this.client.api.element('#signupSection').find('#helpBtn').isVisible();
+ 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, true);
+ assert.strictEqual(elementId, '1');
+ });
+
+ it('test .element.find().isVisible() not displayed', async function() {
+ let elementId;
+
+ MockServer.addMock({
+ url: '/session/13521-10219-202/execute/sync',
+ method: 'POST',
+ response: JSON.stringify({
+ value: false
+ }),
+ onRequest(_, requestData) {
+ elementId = requestData.args[0]['element-6066-11e4-a52e-4f735466cecf'];
+ }
+ }, true);
+
+ const resultPromise = this.client.api.element.find('#signupSection').isVisible();
+ 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, false);
+ assert.strictEqual(elementId, '0');
+ });
+
+ it('test .element().isVisible() assert', async function() {
+ let elementId;
+
+ MockServer.addMock({
+ url: '/session/13521-10219-202/execute/sync',
+ method: 'POST',
+ response: JSON.stringify({
+ value: true
+ }),
+ onRequest(_, requestData) {
+ elementId = requestData.args[0]['element-6066-11e4-a52e-4f735466cecf'];
+ }
+ }, true);
+
+ const resultPromise = this.client.api.element('#signupSection').isVisible();
+ 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(await resultPromise.assert.equals(true), true);
+ assert.strictEqual(await resultPromise.assert.not.equals(false), true);
+ assert.strictEqual(elementId, '0');
+ });
+});
diff --git a/types/tests/webElement.test-d.ts b/types/tests/webElement.test-d.ts
index f179296b6f..78edaa9015 100644
--- a/types/tests/webElement.test-d.ts
+++ b/types/tests/webElement.test-d.ts
@@ -141,6 +141,7 @@ describe('new element() api', function () {
expectType>(elem.getAttribute('attrib-name'));
expectType>(elem.getValue());
expectType>(elem.isEnabled());
+ expectType>(elem.isVisible());
expectType>(elem.getRect());
expectType>(elem.getSize());
diff --git a/types/web-element.d.ts b/types/web-element.d.ts
index ea28dc8516..dc2f87aa24 100644
--- a/types/web-element.d.ts
+++ b/types/web-element.d.ts
@@ -192,6 +192,8 @@ export interface ScopedElement extends Element, PromiseLike {
waitUntil(signalOrOptions: WaitUntilActions | WaitUntilOptions, waitOptions?: WaitUntilOptions): Promise;
isEnabled(): ElementValue;
+
+ isVisible(): ElementValue;
}
type WaitUntilOptions = {