Skip to content

Commit

Permalink
Merge pull request #75 from /issues/62-element-enabled
Browse files Browse the repository at this point in the history
feat: is element enabled endpoint
  • Loading branch information
poftadeh authored Nov 20, 2019
2 parents 8e3dc27 + 7ed6a23 commit 017bf4f
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/Session/Session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ class Session {
this.browser.getKnownElement(urlVariables.elementId).clear();
response = { value: null };
break;
case COMMANDS.ELEMENT_ENABLED:
if (!this.browser.dom.window) throw new NoSuchWindow();
const isEnabled = this.browser
.getKnownElement(urlVariables.elementId)
.isEnabled();
response = { value: isEnabled };
break;
default:
break;
}
Expand Down
53 changes: 53 additions & 0 deletions src/WebElement/WebElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,59 @@ class WebElement {
public serialize() {
return { [ELEMENT]: this[ELEMENT] };
}

/**
* returns true if the WebElement's HTML element is a descendant of a disabled fieldset
* and not the descendant of that fieldset's first legend element
* @returns {boolean}
*/
private isDisabledFieldsetDescendant = (): boolean => {
const fieldsetAncestor = this.findAncestor(
'fieldset',
) as HTMLFieldSetElement;

if (!fieldsetAncestor || !fieldsetAncestor.disabled) {
return false;
}

const fieldsetAncestorFirstLegendChild: HTMLLegendElement = fieldsetAncestor.querySelector(
'legend',
);

if (
fieldsetAncestorFirstLegendChild &&
this.findAncestor('legend') === fieldsetAncestorFirstLegendChild
) {
return false;
}

return true;
};

/**
* returns true if WebElement's HTML element is enabled, otherwise returns false.
* @returns {boolean}
*/
public isEnabled(): boolean {
const {
localName,
ownerDocument: { doctype },
} = this.element;

if (doctype.name === 'xml') {
return false;
}

if (this.isDisabledFieldsetDescendant()) {
return false;
}

if (['button', 'input', 'select', 'textarea'].includes(localName)) {
return !(this.element as HTMLFormElement).disabled;
}

return true;
}
}

export { WebElement };
1 change: 1 addition & 0 deletions src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ export const COMMANDS = {
DELETE_ALL_COOKIES: 'DELETE ALL COOKIES',
ELEMENT_CLICK: 'ELEMENT_CLICK',
ELEMENT_CLEAR: 'ELEMENT_CLEAR',
ELEMENT_ENABLED: 'ELEMENT_ENABLED',
};
8 changes: 8 additions & 0 deletions src/routes/elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,12 @@ element.post(
),
);

element.get(
'/enabled',
sessionEndpointExceptionHandler(
defaultSessionEndpointLogic,
COMMANDS.ELEMENT_ENABLED,
),
);

export default element;
157 changes: 157 additions & 0 deletions test/jest/element-enabled.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
const nock = require('nock');

const { Session } = require('../../build/Session/Session');
const { COMMANDS, ELEMENT } = require('../../build/constants/constants');

describe('Is Element Enabled', () => {
let session;

const setScopeAndNavigate = async pageSource => {
nock(/plumadriver\.com/)
.get('/')
.reply(200, pageSource);

await session.process({
command: COMMANDS.NAVIGATE_TO,
parameters: { url: 'http://plumadriver.com' },
});
};

const findElement = async selector => {
const { [ELEMENT]: elementId } = await session.process({
command: COMMANDS.FIND_ELEMENT,
parameters: {
using: 'css selector',
value: selector,
},
});

return elementId;
};

const checkEnabled = async (selector, expectation) => {
const elementId = await findElement(selector);
const { value } = await session.process({
command: COMMANDS.ELEMENT_ENABLED,
urlVariables: { elementId },
});
expect(value).toBe(expectation);
};

beforeAll(async () => {
const requestBody = {
desiredCapabilities: {
browserName: 'pluma',
unhandledPromptBehavior: 'ignore',
'plm:plumaOptions': { runScripts: true },
},
capabilities: {
firstMatch: [
{
browserName: 'pluma',
'plm:plumaOptions': { runScripts: true },
unhandledPromptBehavior: 'ignore',
},
],
},
};

session = new Session(requestBody);
});

it('returns false on xml document type', async () => {
const pageSource = `<!DOCTYPE xml>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<button>click</button>
</body>
</html>`;

await setScopeAndNavigate(pageSource);
await checkEnabled('button', false);
});

it('returns true on an h1', async () => {
const pageSource = `<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>`;

await setScopeAndNavigate(pageSource);
await checkEnabled('h1', true);
});

it('handles form control elements', async () => {
const pageSource = `<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<input type="text" />
<select></select>
<button>off</button>
<textarea>off</textarea>
<fieldset></fieldset>
<input type="text" disabled />
<select disabled></select>
<button disabled>off</button>
<textarea disabled>off</textarea>
<fieldset disabled></fieldset>
</body>
</html>`;

await setScopeAndNavigate(pageSource);
await checkEnabled('input[disabled]', false);
await checkEnabled('select[disabled]', false);
await checkEnabled('button[disabled]', false);
await checkEnabled('textarea[disabled]', false);

await checkEnabled('input:not([disabled])', true);
await checkEnabled('select:not([disabled])', true);
await checkEnabled('button:not([disabled])', true);
await checkEnabled('textarea:not([disabled])', true);
});

it('handles fieldset child elements', async () => {
const pageSource = `<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<fieldset disabled>
<div>
<button>click</button>
</div>
</fieldset>
<fieldset>
<legend>foo</legend>
<select disabled>click</select>
</fieldset>
<fieldset disabled>
<legend>
<textarea></textarea>
</legend>
</fieldset>
</body>
</html>`;

await setScopeAndNavigate(pageSource);
await checkEnabled('button', false);
await checkEnabled('select', false);
await checkEnabled('textarea', true);
});
});

0 comments on commit 017bf4f

Please sign in to comment.