diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 359f5153..9f395dc6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,13 +28,12 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - - name: Install env - run: echo "PERCY_TOKEN=${{ secrets.PERCY_TOKEN }}" >> $GITHUB_ENV + - run: npm install --save-dev @percy/cli - name: Percy Test - uses: percy/exec-action@v0.3.1 - with: - working-directory: ./test - command: "./run_all.sh" + run: npx percy exec -- bash ./run_all.sh + working-directory: ./test + env: + PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} - name: Upload test output uses: actions/upload-artifact@v1 if: failure() diff --git a/pywebio/platform/tornado.py b/pywebio/platform/tornado.py index a12cdb8e..8e82ad85 100644 --- a/pywebio/platform/tornado.py +++ b/pywebio/platform/tornado.py @@ -276,7 +276,7 @@ def start_server(applications: Union[Callable[[], None], List[Callable[[], None] page.MAX_PAYLOAD_SIZE = max_payload_size = parse_file_size(max_payload_size) - # covered `os.environ.get()` func with `bool()` to pervent type check error + # covered `os.environ.get()` func with `bool()` to prevent type check error debug = Session.debug = bool(os.environ.get('PYWEBIO_DEBUG', debug)) # Since some cloud server may close idle connections (such as heroku), diff --git a/requirements.txt b/requirements.txt index 4bc7da57..a24b29cd 100755 --- a/requirements.txt +++ b/requirements.txt @@ -16,8 +16,8 @@ plotly Pillow # test requirements -selenium==3.* -percy-python-selenium==0.1.3 +selenium +percy-selenium coverage # doc building requirements diff --git a/test/.percy.yml b/test/.percy.yml index bdeff16b..063b355b 100644 --- a/test/.percy.yml +++ b/test/.percy.yml @@ -1,3 +1,6 @@ -version: 1 +version: 2 snapshot: - widths: [1000] \ No newline at end of file + widths: + - 1000 +discovery: + disable-cache: true diff --git a/test/11.charts.py b/test/11.charts.py index eecf94e6..1450dfff 100644 --- a/test/11.charts.py +++ b/test/11.charts.py @@ -6,7 +6,7 @@ from cutecharts.charts import Line from cutecharts.charts import Pie from cutecharts.charts import Radar -from percy import percySnapshot +from percy import percy_snapshot from selenium.webdriver import Chrome import pywebio @@ -376,7 +376,7 @@ def target(): def test(server_proc: subprocess.Popen, browser: Chrome): time.sleep(8) - percySnapshot(browser, name='bokeh') + percy_snapshot(browser, name='bokeh') def start_test_server(): diff --git a/test/13.misc.py b/test/13.misc.py index a71ba85a..a55dfdc4 100644 --- a/test/13.misc.py +++ b/test/13.misc.py @@ -2,8 +2,9 @@ import subprocess from functools import partial -from percy import percySnapshot +from percy import percy_snapshot from selenium.webdriver import Chrome +from selenium.webdriver.common.by import By import pywebio import template @@ -208,7 +209,7 @@ def test(server_proc: subprocess.Popen, browser: Chrome): # browser.get('http://localhost:8080/?app=thread') browser.execute_script("arguments[0].click();", - browser.find_element_by_css_selector('#pywebio-scope-go_app button')) + browser.find_element(By.CSS_SELECTOR, '#pywebio-scope-go_app button')) time.sleep(2) thread_out = template.save_output(browser)[-1] @@ -220,10 +221,10 @@ def test(server_proc: subprocess.Popen, browser: Chrome): time.sleep(6) browser.execute_script("arguments[0].click();", - browser.find_element_by_css_selector('#pywebio-scope-error button')) + browser.find_element(By.CSS_SELECTOR, '#pywebio-scope-error button')) browser.execute_script("$('button[type=submit]').click();") time.sleep(2) - percySnapshot(browser, name='misc') + percy_snapshot(browser, name='misc') def start_test_server(): diff --git a/test/16.path_deploy.py b/test/16.path_deploy.py index ac701c94..c0d4ac90 100644 --- a/test/16.path_deploy.py +++ b/test/16.path_deploy.py @@ -1,8 +1,9 @@ import os import subprocess -from percy import percySnapshot +from percy import percy_snapshot from selenium.webdriver import Chrome +from selenium.webdriver.common.by import By import util from pywebio.platform import path_deploy @@ -14,10 +15,10 @@ def test(server_proc: subprocess.Popen, browser: Chrome): time.sleep(10) - percySnapshot(browser, name='path_deploy_1') + percy_snapshot(browser, name='path_deploy_1') browser.get('http://localhost:8080/') time.sleep(2) - page_html = browser.find_element_by_tag_name('body').get_attribute('innerHTML') + page_html = browser.find_element(By.TAG_NAME, 'body').get_attribute('innerHTML') print(page_html) for f in ['bmi', 'bokeh_app', 'chat_room', 'input_usage', 'output_usage', 'set_env_demo']: assert f in page_html, f'{f} not in page' diff --git a/test/18.pin_test.py b/test/18.pin_test.py index 9b54f8b6..8336b82b 100644 --- a/test/18.pin_test.py +++ b/test/18.pin_test.py @@ -1,8 +1,9 @@ import subprocess import time -from percy import percySnapshot +from percy import percy_snapshot from selenium.webdriver import Chrome +from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import Select @@ -67,25 +68,25 @@ async def coro_target(): def test_one_page(browser: Chrome): - browser.find_element_by_css_selector('[name=input]').send_keys("1") + browser.find_element(By.CSS_SELECTOR, '[name=input]').send_keys("1") time.sleep(0.5) - browser.find_element_by_css_selector('[name=textarea]').send_keys("2") + browser.find_element(By.CSS_SELECTOR, '[name=textarea]').send_keys("2") time.sleep(0.5) - Select(browser.find_element_by_css_selector('[name=select]')).select_by_visible_text('B') + Select(browser.find_element(By.CSS_SELECTOR, '[name=select]')).select_by_visible_text('B') time.sleep(0.5) - Select(browser.find_element_by_css_selector('[name=select_multiple]')).select_by_visible_text('A') + Select(browser.find_element(By.CSS_SELECTOR, '[name=select_multiple]')).select_by_visible_text('A') time.sleep(0.5) - browser.find_element_by_css_selector('[name=checkbox]').click() + browser.find_element(By.CSS_SELECTOR, '[name=checkbox]').click() time.sleep(0.5) - browser.find_element_by_css_selector('[name=checkbox_inline]').click() + browser.find_element(By.CSS_SELECTOR, '[name=checkbox_inline]').click() time.sleep(0.5) - browser.find_element_by_css_selector('[name=radio]').click() + browser.find_element(By.CSS_SELECTOR, '[name=radio]').click() time.sleep(0.5) - browser.find_element_by_css_selector('[name=radio_inline]').click() + browser.find_element(By.CSS_SELECTOR, '[name=radio_inline]').click() time.sleep(0.5) - browser.find_element_by_css_selector('button[type=\"submit\"]').click() + browser.find_element(By.CSS_SELECTOR, 'button[type=\"submit\"]').click() time.sleep(0.5) - codeMirror = browser.find_element_by_css_selector(".CodeMirror pre") + codeMirror = browser.find_element(By.CSS_SELECTOR, ".CodeMirror pre") action_chains = ActionChains(browser) action_chains.move_to_element(codeMirror).click(codeMirror).send_keys('3').perform() @@ -95,14 +96,14 @@ def test(server_proc: subprocess.Popen, browser: Chrome): time.sleep(2) test_one_page(browser) time.sleep(2) - percySnapshot(browser, name='pin') - assert PASSED_TEXT in browser.find_element_by_id('markdown-body').get_attribute('innerHTML') + percy_snapshot(browser, name='pin') + assert PASSED_TEXT in browser.find_element(By.ID, 'markdown-body').get_attribute('innerHTML') browser.get('http://localhost:8080/?app=coro_target') time.sleep(2) test_one_page(browser) time.sleep(1) - assert PASSED_TEXT in browser.find_element_by_id('markdown-body').get_attribute('innerHTML') + assert PASSED_TEXT in browser.find_element(By.ID, 'markdown-body').get_attribute('innerHTML') def start_test_server(): diff --git a/test/Readme.md b/test/Readme.md index db42d1d4..04c3f784 100644 --- a/test/Readme.md +++ b/test/Readme.md @@ -10,11 +10,11 @@ ### 运行测试用例 ```bash -pip3 install -e ".[dev]" -npm install -D @percy/agent +pip3 install -r ../requirements.txt +npm install --save-dev @percy/cli export PERCY_TOKEN=[projects-token] -npx percy exec -- python3 1.basic_output.py auto +npx percy exec -- python3 1.basic.py auto ``` diff --git a/test/template.py b/test/template.py index 96186b3d..6cff5f08 100644 --- a/test/template.py +++ b/test/template.py @@ -7,9 +7,10 @@ from functools import partial from os import path -from percy import percySnapshot +from percy import percy_snapshot from selenium.webdriver import Chrome from selenium.webdriver.support.ui import Select +from selenium.webdriver.common.by import By from pywebio.input import * from pywebio.output import * @@ -19,7 +20,7 @@ def get_visible_form(browser): - forms = browser.find_elements_by_css_selector('#input-cards > div') + forms = browser.find_elements(By.CSS_SELECTOR, '#input-cards > div') for f in forms: if f.is_displayed(): return f @@ -347,25 +348,26 @@ def test_output(browser: Chrome, enable_percy=False, action_delay=0.5): time.sleep(action_delay * 2) # 等待输出完毕 # get focus - browser.find_element_by_tag_name('body').click() + browser.find_element(By.TAG_NAME, 'body').click() time.sleep(action_delay * 2) browser.execute_script('$("html, body").scrollTop( $(document).height()+100);') time.sleep(action_delay) - enable_percy and percySnapshot(browser, name='begin output') + if enable_percy: + percy_snapshot(browser, name='begin output') - tab_btns = browser.find_elements_by_css_selector('#pywebio-scope-table_cell_buttons button') + tab_btns = browser.find_elements(By.CSS_SELECTOR, '#pywebio-scope-table_cell_buttons button') for btn in tab_btns: time.sleep(action_delay) browser.execute_script("arguments[0].click();", btn) - btns = browser.find_elements_by_css_selector('#pywebio-scope-put_buttons button') + btns = browser.find_elements(By.CSS_SELECTOR, '#pywebio-scope-put_buttons button') for btn in btns: time.sleep(action_delay) browser.execute_script("arguments[0].click();", btn) # 滚动窗口 - btns = browser.find_elements_by_css_selector('#pywebio-scope-scroll_basis_btns button') + btns = browser.find_elements(By.CSS_SELECTOR, '#pywebio-scope-scroll_basis_btns button') for btn in btns: time.sleep(action_delay * 2) browser.execute_script("arguments[0].click();", btn) @@ -373,14 +375,16 @@ def test_output(browser: Chrome, enable_percy=False, action_delay=0.5): time.sleep(action_delay * 2) browser.execute_script('$("html, body").scrollTop( $(document).height()+100);') time.sleep(action_delay) - enable_percy and percySnapshot(browser, name='basic output') + if enable_percy: + percy_snapshot(browser, name='basic output') # popup - btn = browser.find_element_by_css_selector('#pywebio-scope-popup_btn button') + btn = browser.find_element(By.CSS_SELECTOR, '#pywebio-scope-popup_btn button') browser.execute_script("arguments[0].click();", btn) time.sleep(action_delay * 2) - enable_percy and percySnapshot(browser, name='popup') + if enable_percy: + percy_snapshot(browser, name='popup') browser.execute_script("$('.modal').modal('hide');") @@ -603,128 +607,132 @@ def test_input(browser: Chrome, enable_percy=False, action_delay=0.5): template.background_input() # 或者 await template.coro_background_input() / flask_coro_background_input """ - browser.find_element_by_css_selector('#input-container input').send_keys("22") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container input').send_keys("22") + browser.find_element(By.TAG_NAME, 'form').submit() time.sleep(action_delay) - browser.find_element_by_css_selector('#input-container input').send_keys("secret") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container input').send_keys("secret") + browser.find_element(By.TAG_NAME, 'form').submit() time.sleep(action_delay) - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.TAG_NAME, 'form').submit() # checkbox time.sleep(action_delay) - browser.execute_script("arguments[0].click();", browser.find_element_by_css_selector('#input-container input')) - browser.find_element_by_tag_name('form').submit() + browser.execute_script("arguments[0].click();", browser.find_element(By.CSS_SELECTOR, '#input-container input')) + browser.find_element(By.TAG_NAME, 'form').submit() # Text Area time.sleep(action_delay) - browser.find_element_by_css_selector('#input-container textarea').send_keys(" ".join(str(i) for i in range(20))) - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container textarea').send_keys(" ".join(str(i) for i in range(20))) + browser.find_element(By.TAG_NAME, 'form').submit() # file time.sleep(action_delay) img_path = path.join(here_dir, 'assets', 'img.png') - browser.find_element_by_css_selector('#input-container input').send_keys(img_path) - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container input').send_keys(img_path) + browser.find_element(By.TAG_NAME, 'form').submit() # text time.sleep(action_delay) - browser.find_element_by_css_selector('#input-container input').send_keys("text") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container input').send_keys("text") + browser.find_element(By.TAG_NAME, 'form').submit() # 表单取消 time.sleep(action_delay) - browser.execute_script("arguments[0].click();", browser.find_element_by_css_selector('.pywebio_cancel_btn')) + browser.execute_script("arguments[0].click();", browser.find_element(By.CSS_SELECTOR, '.pywebio_cancel_btn')) # valid func, age in [10, 60] time.sleep(action_delay) - browser.find_element_by_css_selector('#input-container input').send_keys("1") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container input').send_keys("1") + browser.find_element(By.TAG_NAME, 'form').submit() time.sleep(action_delay) - browser.find_element_by_css_selector('#input-container input').clear() - browser.find_element_by_css_selector('#input-container input').send_keys("90") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container input').clear() + browser.find_element(By.CSS_SELECTOR, '#input-container input').send_keys("90") + browser.find_element(By.TAG_NAME, 'form').submit() time.sleep(action_delay) - browser.find_element_by_css_selector('#input-container input').clear() - browser.find_element_by_css_selector('#input-container input').send_keys("23") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.CSS_SELECTOR, '#input-container input').clear() + browser.find_element(By.CSS_SELECTOR, '#input-container input').send_keys("23") + browser.find_element(By.TAG_NAME, 'form').submit() # code time.sleep(action_delay) - # browser.find_element_by_css_selector('textarea').send_keys(" ".join(str(i) for i in range(20))) - browser.find_element_by_tag_name('form').submit() + # browser.find_element(By.CSS_SELECTOR, 'textarea').send_keys(" ".join(str(i) for i in range(20))) + browser.find_element(By.TAG_NAME, 'form').submit() # Cancelable from group time.sleep(action_delay) - browser.find_element_by_name('name').send_keys("name") + browser.find_element(By.NAME, 'name').send_keys("name") time.sleep(action_delay * 2) - browser.find_element_by_name('age').send_keys("90") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.NAME, 'age').send_keys("90") + browser.find_element(By.TAG_NAME, 'form').submit() browser.execute_script('$("html, body").scrollTop( $(document).height()+100);') time.sleep(action_delay) - enable_percy and percySnapshot(browser, name='input group invalid') + if enable_percy: + percy_snapshot(browser, name='input group invalid') time.sleep(action_delay) - browser.find_element_by_name('age').clear() - browser.find_element_by_name('age').send_keys("23") - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.NAME, 'age').clear() + browser.find_element(By.NAME, 'age').send_keys("23") + browser.find_element(By.TAG_NAME, 'form').submit() # callback actions time.sleep(action_delay) - browser.execute_script("arguments[0].click();", browser.find_element_by_css_selector('form button[type="button"]')) + browser.execute_script("arguments[0].click();", browser.find_element(By.CSS_SELECTOR, 'form button[type="button"]')) time.sleep(action_delay) # input action time.sleep(action_delay) - browser.execute_script("arguments[0].click();", browser.find_element_by_css_selector('form button[type="button"]')) + browser.execute_script("arguments[0].click();", browser.find_element(By.CSS_SELECTOR, 'form button[type="button"]')) time.sleep(action_delay) - browser.find_element_by_tag_name('form').submit() + browser.find_element(By.TAG_NAME, 'form').submit() # Input group time.sleep(action_delay) browser.execute_script('$("html, body").scrollTop( $(document).height()+100);') time.sleep(action_delay) - enable_percy and percySnapshot(browser, name='input group all') - browser.find_element_by_name('text').send_keys("name") - browser.find_element_by_name('number').send_keys("20") - browser.find_element_by_name('float').send_keys("3.1415") - browser.find_element_by_name('password').send_keys("password") - browser.find_element_by_name('textarea').send_keys(" ".join(str(i) for i in range(20))) - # browser.find_element_by_css_selector('[name="code"]').send_keys(" ".join(str(i) for i in range(10))) - Select(browser.find_element_by_name('select-multiple')).select_by_index(0) + if enable_percy: + percy_snapshot(browser, name='input group all') + browser.find_element(By.NAME, 'text').send_keys("name") + browser.find_element(By.NAME, 'number').send_keys("20") + browser.find_element(By.NAME, 'float').send_keys("3.1415") + browser.find_element(By.NAME, 'password').send_keys("password") + browser.find_element(By.NAME, 'textarea').send_keys(" ".join(str(i) for i in range(20))) + # browser.find_element(By.CSS_SELECTOR, '[name="code"]').send_keys(" ".join(str(i) for i in range(10))) + Select(browser.find_element(By.NAME, 'select-multiple')).select_by_index(0) # browser. find_element_by_css_selector('[name="select"]'). send_keys("name") # browser. find_element_by_css_selector('[name="checkbox-inline"]'). send_keys("name") # browser. find_element_by_css_selector('[name="checkbox"]'). send_keys("name") # browser. find_element_by_css_selector('[name="radio-inline"]'). send_keys("name") # browser. find_element_by_css_selector('[name="radio"]'). send_keys("name") - browser.find_element_by_name('file_upload').send_keys(path.join(here_dir, 'assets', 'helloworld.txt')) + browser.find_element(By.NAME, 'file_upload').send_keys(path.join(here_dir, 'assets', 'helloworld.txt')) browser.execute_script("$('form button').eq(1).click()") time.sleep(action_delay * 2) browser.execute_script('$("html, body").scrollTop( $(document).height()+100);') time.sleep(action_delay) - enable_percy and percySnapshot(browser, name='input group all invalid') + if enable_percy: + percy_snapshot(browser, name='input group all invalid') - browser.find_element_by_name('password').clear() - browser.find_element_by_name('password').send_keys("123") + browser.find_element(By.NAME, 'password').clear() + browser.find_element(By.NAME, 'password').send_keys("123") browser.execute_script("$('form button[type=\"submit\"]').eq(1).click()") time.sleep(action_delay * 2) browser.execute_script('$("html, body").scrollTop( $(document).height()+100);') time.sleep(action_delay * 2) - enable_percy and percySnapshot(browser, name='input group all submit') + if enable_percy: + percy_snapshot(browser, name='input group all submit') - browser.find_element_by_css_selector('form').submit() + browser.find_element(By.CSS_SELECTOR, 'form').submit() # background time.sleep(action_delay * 6) - get_visible_form(browser).find_element_by_css_selector('#input-container input').send_keys("background") - get_visible_form(browser).find_element_by_tag_name('form').submit() + get_visible_form(browser).find_element(By.CSS_SELECTOR, '#input-container input').send_keys("background") + get_visible_form(browser).find_element(By.TAG_NAME, 'form').submit() # front time.sleep(action_delay * 2) - get_visible_form(browser).find_element_by_css_selector('#input-container input').send_keys("front") - get_visible_form(browser).find_element_by_tag_name('form').submit() + get_visible_form(browser).find_element(By.CSS_SELECTOR, '#input-container input').send_keys("front") + get_visible_form(browser).find_element(By.TAG_NAME, 'form').submit() def set_defer_call(): @@ -754,7 +762,7 @@ def save_output(browser: Chrome, filename=None, process_func=None): :param process_func: 自定义数据处理函数 :return: 处理前后的html文本 """ - raw_html = browser.find_element_by_id('markdown-body').get_attribute('innerHTML') + raw_html = browser.find_element(By.ID, 'markdown-body').get_attribute('innerHTML') html = re.sub(r'"pywebio-scope-.*?"', '', raw_html) html = re.sub(r'id="pywebio-.*?"', '', html) html = re.sub(r"\('pywebio-.*?'\)", '', html) diff --git a/test/util.py b/test/util.py index 9f63ba5c..8ed172bf 100644 --- a/test/util.py +++ b/test/util.py @@ -55,7 +55,7 @@ def run_test(server_func, test_func, address='http://localhost:8080?_pywebio_deb browser = None try: - browser = webdriver.Chrome(chrome_options=chrome_options) + browser = webdriver.Chrome(options=chrome_options) browser.set_window_size(1000, 900) port_str = urlparse(address).netloc.split(':', 1)[-1] or '80' asyncio.run(wait_host_port('localhost', int(port_str)))