Как установить содержимое в mui-rte с помощью селенового веб-драйвера в python? - PullRequest
0 голосов
/ 30 ноября 2019

Я использую mui-rte форматированный текстовый редактор (https://github.com/niuware/mui-rte) в реактивном проекте. Я не могу понять, как вводить текст в область ввода rte при написании интеграционного теста селенового веб-драйвера.

Как я правильно понимаю, mui-rte - это materia-ui-оболочка draftjs. Код реакции просто:

<MUIRichTextEditor
        onChange={onChange}
        value={initial}
        {...rest}
/ >

Это генерирует следующие элементы html:

<div id="mui-rte-container" class="MUIRichTextEditor-container-73">
<div id="mui-rte-toolbar" class="MUIRichTextEditor-toolbar-84">
    ...
</div>
<div id="mui-rte-editor" class="MUIRichTextEditor-editor-75">
    <div id="mui-rte-editor-container" class="MUIRichTextEditor-hidePlaceholder-79 MUIRichTextEditor-editorContainer-76">
        <div class="DraftEditor-root">
            <div class="DraftEditor-editorContainer">
                <div aria-describedby="placeholder-9mnek" class="notranslate public-DraftEditor-content" role="textbox" spellcheck="false" style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word" contenteditable="true">
                    <div data-contents="true"><div class="" data-block="true" data-editor="7kjuh" data-offset-key="8a2rc-0-0">
                        <div data-offset-key="8a2rc-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr">
                            <span data-offset-key="8a2rc-0-0">
                                <br data-text="true">
                            </span>
                        </div>
                    </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Я легко могу найти любой элемент, но когда я попробую это, например:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from selenium.webdriver.common.by import By

rte_editor = WebDriverWait(self.driver, 2).until(
        EC.presence_of_element_located((By.ID, id))
    )
rte_input = bio_rte.find_element_by_xpath("//div[@role='textbox']")
rte_input.send_keys("Hello")

Я получу:

E       selenium.common.exceptions.ElementNotInteractableException: Message: Element <div class="notranslate public-DraftEditor-content"> is not reachable by keyboard

Со всеми элементами, которые япопробовал.

Как правильно вводить текст в draft.js rte с помощью selenium-webdriver в python? Я новичок в selenium + webdriver, и любая помощь будет оценена, будь то в python, JavaScriptили другой вариант API Selen-Webdriver.

У меня есть пример проекта здесь: https://github.com/vessper/formik-mui-rte-example

Обновление:

Включение трассировки стека от ошибки:

self = <test.TestBase testMethod=test_input_text_in_rte>

    def test_input_text_in_rte(self):
        rte_input = WebDriverWait(self.driver, 20).until(
            EC.element_to_be_clickable(
>               (By.XPATH, '//div[@class="notranslate public-DraftEditor-content" and @role="textbox"]'))
        )

test.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.support.wait.WebDriverWait (session="38c21bf5-27ea-499d-9831-e8755a10f57a")>
method = <selenium.webdriver.support.expected_conditions.element_to_be_clickable object at 0x7f7115fe7198>, message = ''

    def until(self, method, message=''):
        """Calls the method provided with the driver as an argument until the \
        return value is not False."""
        screen = None
        stacktrace = None

        end_time = time.time() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, 'screen', None)
                stacktrace = getattr(exc, 'stacktrace', None)
            time.sleep(self._poll)
            if time.time() > end_time:
                break
>       raise TimeoutException(message, screen, stacktrace)
E       selenium.common.exceptions.TimeoutException: Message:

../../../.virtualenvs/ml2/lib/python3.7/site-packages/selenium/webdriver/support/wait.py:80: TimeoutException
================================================================= 1 failed in 24.70s ==================================================================

Ответы [ 2 ]

0 голосов
/ 03 декабря 2019

Существует встроенный элемент метки из Material-UI, который нужно сначала щелкнуть, чтобы раскрыть основное текстовое поле. Поэтому следующая работа для меня.

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import unittest


class TestBase(unittest.TestCase):

def setUp(self):
    self.driver = webdriver.Firefox()
    self.driver.get(URL)

def tearDown(self):
    self.driver.close()

def get_by_id(self, id):
    return WebDriverWait(self.driver, 5).until(
        EC.presence_of_element_located((By.ID, id))
    )
def test_input_text_in_rte(self):
    description_msg = "Hello There"
    rte_container = self.get_by_id('mui-rte-container')
    rte_label = rte_container.find_element_by_xpath("//*[contains(text(), 'Description:')]")
    actions = ActionChains(self.driver)
    actions.move_to_element(rte_label)
    actions.click(rte_label)
    actions.perform()

    rte_input = WebDriverWait(self.driver, 5).until(
        EC.presence_of_element_located((By.XPATH,
            '//div[@class="notranslate public-DraftEditor-content" and @role="textbox"]'))
    )

    rte_input.send_keys(description_msg)

Спасибо @DebanjanB за предложения, которые включены в приведенный выше код.

0 голосов
/ 30 ноября 2019

Требуемый элемент - это элемент с поддержкой ReactJS , чтобы найти и отправить последовательность символов в элемент, который необходимо вызвать WebDriverWait для element_to_be_clickable()и вы можете использовать любое из следующих решений:

  • Использование CSS_SELECTOR:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.notranslate.public-DraftEditor-content[role='textbox']"))).send_keys("Vess_Perfanov")
    
  • Использование XPATH:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='notranslate public-DraftEditor-content' and @role='textbox']"))).send_keys("Vess_Perfanov")
    
  • Примечание : необходимо добавить следующие операции импорта:

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    

Обновление

Поскольку click() по-прежнему не вызывается с WebDriverWait , вы можете использовать ActionChains следующим образом:

  • Используя CSS_SELECTOR:

    element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.notranslate.public-DraftEditor-content[role='textbox']"))).send_keys("Vess_Perfanov")
    ActionChains(driver).move_to_element(element).click(element).send_keys("Vess_Perfanov").perform()
    
  • Использование XPATH:

    element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='notranslate public-DraftEditor-content' and @role='textbox']"))).send_keys("Vess_Perfanov")
    ActionChains(driver).move_to_element(element).click(element).send_keys_to_element(element, "Vess_Perfanov").perform()
    
...