Open yashaka opened 4 months ago
This might allow to move from something like this:
# command.py class js: class __ClickWithOffset(Command[Element]): def __init__(self): self._description = 'click' @overload def __call__(self, element: Element) -> None: ... @overload def __call__(self, *, xoffset=0, yoffset=0) -> Command[Element]: ... def __call__(self, element: Element | None = None, *, xoffset=0, yoffset=0): def func(element: Element): element.execute_script( ''' const offsetX = arguments[0] const offsetY = arguments[1] const rect = element.getBoundingClientRect() function mouseEvent() { if (typeof (Event) === 'function') { return new MouseEvent('click', { view: window, bubbles: true, cancelable: true, clientX: rect.left + rect.width / 2 + offsetX, clientY: rect.top + rect.height / 2 + offsetY }) } else { const event = document.createEvent('MouseEvent') event.initEvent('click', true, true) event.type = 'click' event.view = window event.clientX = rect.left + rect.width / 2 + offsetX event.clientY = rect.top + rect.height / 2 + offsetY return event } } element.dispatchEvent(mouseEvent()) ''', xoffset, yoffset, ) if element is not None: # somebody passed command as `.perform(command.js.click)` # not as `.perform(command.js.click())` func(element) return None return Command( ( self.__str__() if (not xoffset and not yoffset) else f'click(xoffset={xoffset},yoffset={yoffset})' ), func, ) click = __ClickWithOffset()
to something like this:
# command.py class js: @staticmethod @overload def click(element: Element | None) -> None: ... @staticmethod @overload def click(*, xoffset=0, yoffset=0) -> Command[Element]: ... @staticmethod def click(element: Element | None = None, *, xoffset=0, yoffset=0): def func(element: Element): element.execute_script( ''' const offsetX = arguments[0] const offsetY = arguments[1] const rect = element.getBoundingClientRect() function mouseEvent() { if (typeof (Event) === 'function') { return new MouseEvent('click', { view: window, bubbles: true, cancelable: true, clientX: rect.left + rect.width / 2 + offsetX, clientY: rect.top + rect.height / 2 + offsetY }) } else { const event = document.createEvent('MouseEvent') event.initEvent('click', true, true) event.type = 'click' event.view = window event.clientX = rect.left + rect.width / 2 + offsetX event.clientY = rect.top + rect.height / 2 + offsetY return event } } element.dispatchEvent(mouseEvent()) ''', xoffset, yoffset, ) if isinstance(element, Element): # somebody passed command as `.perform(command.js.click)` # not as `.perform(command.js.click())` func(element) return Command( ( 'click' if (not xoffset and not yoffset) else f'click(xoffset={xoffset},yoffset={yoffset})' ), func, )
that can be kind of more KISS way to implement a command that can be called in 3 different syntax:
element.perform(command.js.click(xoffset=10, yoffset=0)) element.perform(command.js.click()) element.perform(command.js.click)
Right now, the "functional" way can hardly make autocompletion work after element.perform(command.js.click).HERE
element.perform(command.js.click).HERE
There are also other examples where we have some problems with autocompletion because of too "strict" typing based on normal classes...
This might allow to move from something like this:
to something like this:
that can be kind of more KISS way to implement a command that can be called in 3 different syntax:
Right now, the "functional" way can hardly make autocompletion work after
element.perform(command.js.click).HERE
There are also other examples where we have some problems with autocompletion because of too "strict" typing based on normal classes...