From f33c9f45bbc1d0f6e38b50f4540f38cea79adfb0 Mon Sep 17 00:00:00 2001 From: Atul Verma Date: Tue, 26 Oct 2021 00:28:18 +1100 Subject: [PATCH] Bug(range): Set range value on native element setter so that events are triggered properly (#2370) Signed-off-by: atulv --- lib/elements/element.js | 11 +++++++ lib/elements/elementHelper.js | 16 +++++++++- lib/elements/range.js | 10 ++++-- test/unit-tests/range.test.js | 60 ++++++++++++++++++++++++++++++++--- 4 files changed, 89 insertions(+), 8 deletions(-) diff --git a/lib/elements/element.js b/lib/elements/element.js index 7c25e72e4..b54aa4f27 100644 --- a/lib/elements/element.js +++ b/lib/elements/element.js @@ -1,3 +1,4 @@ +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 @@ -123,5 +124,15 @@ class Element { } return await this._executeAndGetValue(isDraggable); } + + async registerNativeValueSetter() { + return await this.runtimeHandler.runtimeEvaluate( + `if (typeof globalThis.setNativeValue === 'undefined') { + globalThis.setNativeValue = ` + + setNativeValue.toString() + + ` + }`, + ); + } } module.exports = Element; diff --git a/lib/elements/elementHelper.js b/lib/elements/elementHelper.js index 02ea1b52e..cb69c4f1e 100644 --- a/lib/elements/elementHelper.js +++ b/lib/elements/elementHelper.js @@ -16,4 +16,18 @@ const highlightElement = async (element) => { console.warn('WARNING: Taiko cannot highlight hidden elements.'); } }; -module.exports = { highlightElement }; + +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 }; diff --git a/lib/elements/range.js b/lib/elements/range.js index c0461d269..90b11b168 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 } = require('./elementHelper'); +const { highlightElement, setNativeValue } = require('./elementHelper'); const { doActionAwaitingNavigation } = require('../doActionAwaitingNavigation'); class Range extends Element { @@ -31,14 +31,16 @@ class Range extends Element { } function setRange(value) { - this.value = value; + setNativeValue(this, 'value', value); + let rangeValues = {}; rangeValues['min'] = this.min || 0; rangeValues['max'] = this.max || 100; rangeValues['current'] = this.value; let selectAndDispatchEvent = function (self, value) { - self.value = value; + setNativeValue(self, 'value', value); + ['change', 'input'].forEach((ev) => { let event = new Event(ev, { bubbles: true }); try { @@ -56,6 +58,8 @@ class Range extends Element { selectAndDispatchEvent(this, this.value); return rangeValues; } + + await this.registerNativeValueSetter(); const options = setNavigationOptions({}); let result; await doActionAwaitingNavigation(options, async () => { diff --git a/test/unit-tests/range.test.js b/test/unit-tests/range.test.js index 1ea5db61d..e8a816138 100644 --- a/test/unit-tests/range.test.js +++ b/test/unit-tests/range.test.js @@ -15,6 +15,7 @@ let { $, } = require('../../lib/taiko'); let { createHtml, removeFile, openBrowserArgs, resetConfig } = require('./test-util'); +const { assert } = require('chai'); describe('Range test', () => { let filePath; @@ -22,12 +23,12 @@ describe('Range test', () => { before(async () => { let innerHtml = `