diff --git a/lib/elements/checkBox.js b/lib/elements/checkBox.js
index 9a0c17070..d6c257bef 100644
--- a/lib/elements/checkBox.js
+++ b/lib/elements/checkBox.js
@@ -19,6 +19,7 @@ class CheckBox extends Element {
return result.value;
}
async check() {
+ await this.registerNativeValueSetter();
const navigationOptions = setNavigationOptions({});
await doActionAwaitingNavigation(navigationOptions, async () => {
const objectId = this.get();
@@ -49,7 +50,7 @@ class CheckBox extends Element {
}
function setChecked(value) {
- this.checked = value;
+ this.setNativeValue(this, 'checked', value);
['change', 'input', 'click'].forEach((ev) => {
let event = new Event(ev, { bubbles: true });
try {
diff --git a/lib/elements/element.js b/lib/elements/element.js
index b54aa4f27..2c3931e6b 100644
--- a/lib/elements/element.js
+++ b/lib/elements/element.js
@@ -1,8 +1,8 @@
-const { setNativeValue } = require('./elementHelper');
/**
* Abstract Element present on the web page. Extra methods are available based on the element type.
* @see {ElementWrapper} for methods available
*/
+
class Element {
constructor(objectId, description, runtimeHandler) {
this.objectId = objectId;
@@ -126,13 +126,35 @@ class Element {
}
async registerNativeValueSetter() {
- return await this.runtimeHandler.runtimeEvaluate(
- `if (typeof globalThis.setNativeValue === 'undefined') {
- globalThis.setNativeValue = ` +
- setNativeValue.toString() +
- `
- }`,
- );
+ function defineNativeSetterProperty() {
+ const setNativeValue = function (element, propName, value) {
+ const { set: valueSetter } = Object.getOwnPropertyDescriptor(element, propName) || {};
+ const prototype = Object.getPrototypeOf(element);
+ const { set: prototypeValueSetter } =
+ Object.getOwnPropertyDescriptor(prototype, propName) || {};
+
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
+ prototypeValueSetter.call(element, value);
+ } else if (valueSetter) {
+ valueSetter.call(element, value);
+ } else {
+ throw new Error('The given element does not have a value setter');
+ }
+ };
+
+ if (typeof this.setNativeValue === 'undefined') {
+ Object.defineProperty(this.constructor.prototype, 'setNativeValue', {
+ configurable: true,
+ enumerable: false,
+ value: setNativeValue,
+ });
+ }
+ }
+
+ await this.runtimeHandler.runtimeCallFunctionOn(defineNativeSetterProperty, null, {
+ objectId: this.get(),
+ });
}
}
+
module.exports = Element;
diff --git a/lib/elements/elementHelper.js b/lib/elements/elementHelper.js
index cb69c4f1e..e86218e05 100644
--- a/lib/elements/elementHelper.js
+++ b/lib/elements/elementHelper.js
@@ -17,17 +17,4 @@ const highlightElement = async (element) => {
}
};
-const setNativeValue = function (element, propName, value) {
- const { set: valueSetter } = Object.getOwnPropertyDescriptor(element, propName) || {};
- const prototype = Object.getPrototypeOf(element);
- const { set: prototypeValueSetter } = Object.getOwnPropertyDescriptor(prototype, propName) || {};
- if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
- prototypeValueSetter.call(element, value);
- } else if (valueSetter) {
- valueSetter.call(element, value);
- } else {
- throw new Error('The given element does not have a value setter');
- }
-};
-
-module.exports = { highlightElement, setNativeValue };
+module.exports = { highlightElement };
diff --git a/lib/elements/radioButton.js b/lib/elements/radioButton.js
index 13d83a966..d6e60cf8d 100644
--- a/lib/elements/radioButton.js
+++ b/lib/elements/radioButton.js
@@ -19,6 +19,7 @@ class RadioButton extends Element {
return result.value;
}
async select() {
+ await this.registerNativeValueSetter();
const navigationOptions = setNavigationOptions({});
await doActionAwaitingNavigation(navigationOptions, async () => {
const objectId = this.get();
@@ -49,7 +50,7 @@ class RadioButton extends Element {
}
function setChecked(value) {
- this.checked = value;
+ this.setNativeValue(this, 'checked', value);
['change', 'input', 'click'].forEach((ev) => {
let event = new Event(ev, { bubbles: true });
try {
diff --git a/lib/elements/range.js b/lib/elements/range.js
index 90b11b168..30509ee8f 100644
--- a/lib/elements/range.js
+++ b/lib/elements/range.js
@@ -2,7 +2,7 @@ const { setNavigationOptions } = require('../config');
const { descEvent } = require('../eventBus');
const Element = require('./element');
const { defaultConfig } = require('../config');
-const { highlightElement, setNativeValue } = require('./elementHelper');
+const { highlightElement } = require('./elementHelper');
const { doActionAwaitingNavigation } = require('../doActionAwaitingNavigation');
class Range extends Element {
@@ -31,7 +31,7 @@ class Range extends Element {
}
function setRange(value) {
- setNativeValue(this, 'value', value);
+ this.setNativeValue(this, 'value', value);
let rangeValues = {};
rangeValues['min'] = this.min || 0;
@@ -39,7 +39,7 @@ class Range extends Element {
rangeValues['current'] = this.value;
let selectAndDispatchEvent = function (self, value) {
- setNativeValue(self, 'value', value);
+ self.setNativeValue(self, 'value', value);
['change', 'input'].forEach((ev) => {
let event = new Event(ev, { bubbles: true });
diff --git a/test/functional-tests/specs/ElementsAPI.spec b/test/functional-tests/specs/ElementsAPI.spec
index 18893e728..b5f532b09 100644
--- a/test/functional-tests/specs/ElementsAPI.spec
+++ b/test/functional-tests/specs/ElementsAPI.spec
@@ -25,6 +25,12 @@ Radio Button without for
tags: knownIssue
* Radio Button "Y"
+Range
+------
+* Ensure Range "Age" exists
+* Select the value of Range "Age" to "51"
+
+
File field
----------
diff --git a/test/functional-tests/specs/ElementsAPIIFrame.spec b/test/functional-tests/specs/ElementsAPIIFrame.spec
index d4bc71458..eb7a8109a 100644
--- a/test/functional-tests/specs/ElementsAPIIFrame.spec
+++ b/test/functional-tests/specs/ElementsAPIIFrame.spec
@@ -25,6 +25,12 @@ Radio Button without for
tags: knownIssue
* Radio Button "Y"
+
+Range
+------
+* Ensure Range "Age" exists
+* Select the value of Range "Age" to "51"
+
Attach file
-----------
diff --git a/test/functional-tests/specs/browserActions.spec b/test/functional-tests/specs/browserActions.spec
index 0a90930db..93e0313cc 100644
--- a/test/functional-tests/specs/browserActions.spec
+++ b/test/functional-tests/specs/browserActions.spec
@@ -2,11 +2,11 @@
## Switch To
-
* Navigate to "http://localhost:3001/"
* Click "Multiple Windows"
* Assert page navigated to "/windows"
* Click "Click Here"
+* Switch to tab with url "http://localhost:3001/windows/new"
* Assert page navigated to "/windows/new"
* Switch to tab with url "http://localhost:3001/windows"
* Assert page navigated to "/windows"
@@ -17,7 +17,6 @@
|text|Opening a new window|
## Switch to with name
-
* Open Tab with name "newTab"
* Open Tab "http://localhost:3001/"
* Switch to tab with name "newTab"
@@ -36,6 +35,7 @@
* Open Tab "http://localhost:3001/dropdown"
* Open Tab "http://localhost:3001/"
* Close Tab
+* Switch to tab with url "http://localhost:3001/dropdown"
* Close Tab
* Assert title to be "Document"
@@ -101,7 +101,7 @@
* Set timezone "America/Jamaica"
* Assert page has set timezome
-## Click & Release To Element
+## Click & Release To Element
* Navigate to relative path "./specs/data/MouseMoveTest.html"
* Press & Release To Element with element1 and "0","100" co-ordinates
* Assert text "button2" exists on the page.
diff --git a/test/functional-tests/specs/data/HTMLElements.html b/test/functional-tests/specs/data/HTMLElements.html
index a7274cd19..9703789dc 100644
--- a/test/functional-tests/specs/data/HTMLElements.html
+++ b/test/functional-tests/specs/data/HTMLElements.html
@@ -51,6 +51,10 @@
+
+
+
+
Some text inside a div element.
diff --git a/test/functional-tests/tests/htmlElementAPI.ts b/test/functional-tests/tests/htmlElementAPI.ts
index 6bab8f43c..57bdafa12 100644
--- a/test/functional-tests/tests/htmlElementAPI.ts
+++ b/test/functional-tests/tests/htmlElementAPI.ts
@@ -10,6 +10,7 @@ import {
dropDown,
checkBox,
radioButton,
+ range,
click,
write,
attach,
@@ -86,6 +87,19 @@ export default class HtmlElementAPI {
assert.ok(await button.isSelected());
}
+ @Step('Ensure Range exists')
+ public async rangeExists(rangeName: string) {
+ const rangeInput = range(rangeName);
+ assert.ok(await rangeInput.exists());
+ }
+
+ @Step('Select the value of Range to ')
+ public async rangeValue(rangeName: string, rangeValue: string) {
+ const rangeInput = range(rangeName);
+ await rangeInput.select(rangeValue);
+ assert.equal(await rangeInput.value(), rangeValue);
+ }
+
@Step('Attach file to file field ')
public async attachFile(fileName: string, FileFieldName: SearchElement) {
const field = fileField(FileFieldName);
diff --git a/test/unit-tests/elements/checkBox.test.js b/test/unit-tests/elements/checkBox.test.js
index 4be623e79..65f367059 100644
--- a/test/unit-tests/elements/checkBox.test.js
+++ b/test/unit-tests/elements/checkBox.test.js
@@ -20,6 +20,9 @@ describe('CheckBox', () => {
},
};
},
+ async runtimeEvaluate(exp, executionContextId, opt = {}) {
+ return true;
+ },
};
beforeEach(() => {
@@ -48,10 +51,21 @@ describe('CheckBox', () => {
},
},
};
+
+ Object.defineProperty(Object.prototype, 'checked', {
+ configurable: true,
+ get: function () {
+ return this.checked;
+ },
+ set: function (val) {
+ this.checked = val;
+ },
+ });
});
afterEach(() => {
CheckBox = rewire('../../../lib/elements/checkBox');
dispatchedEvent = null;
+ delete Object.prototype.checked;
});
it('should be element', () => {
@@ -76,6 +90,7 @@ describe('CheckBox', () => {
describe('check', () => {
it('should check an uncheckedd checkbox', async () => {
let objectId = 28;
+
const checkBox = new CheckBox(objectId, 'description', runtimeHandler);
expect(nodes[objectId].checked).to.be.false;
diff --git a/test/unit-tests/elements/radioButton.test.js b/test/unit-tests/elements/radioButton.test.js
index ec293b328..d27302541 100644
--- a/test/unit-tests/elements/radioButton.test.js
+++ b/test/unit-tests/elements/radioButton.test.js
@@ -20,6 +20,9 @@ describe('RadioButton', () => {
},
};
},
+ async runtimeEvaluate(exp, executionContextId, opt = {}) {
+ return true;
+ },
};
beforeEach(() => {
RadioButton = rewire('../../../lib/elements/radioButton');
@@ -47,10 +50,20 @@ describe('RadioButton', () => {
},
},
};
+ Object.defineProperty(Object.prototype, 'checked', {
+ configurable: true,
+ get: function () {
+ return this.checked;
+ },
+ set: function (val) {
+ this.checked = val;
+ },
+ });
});
afterEach(() => {
RadioButton = rewire('../../../lib/elements/radioButton');
dispatchedEvent = null;
+ delete Object.prototype.checked;
});
it('should be element', () => {