Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 32 additions & 18 deletions scripts/grdm.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,11 @@ async def expect_dashboard(page, transition_timeout=30000, retries=3):
# 1分待って再チャレンジ
await asyncio.sleep(60)

async def ensure_project_exists(page, project_name, transition_timeout=30000):
async def ensure_project_exists(page, project_name, transition_timeout=30000, existence_timeout=10000):
await expect(page.locator('//*[@data-test-create-project-modal-button]')).to_have_count(1, timeout=transition_timeout)
try:
await expect(page.locator(f'//*[@data-test-dashboard-item-title and text()="{project_name}"]')).to_be_visible()
# 不存在(タイムアウト)が作成フローへの正常分岐のため、既定の長いexpectタイムアウトを使わない
await expect(page.locator(f'//*[@data-test-dashboard-item-title and text()="{project_name}"]')).to_be_visible(timeout=existence_timeout)
return False
except:
# プロジェクトが存在しない
Expand Down Expand Up @@ -371,26 +372,39 @@ async def drop_file(page, element_locator, path):
async def drag_and_drop(page, source, dest):
await expect(source).to_have_class(re.compile('.*ui-draggable.*'))

center_coordinates_source = await source.evaluate('''element => {
const rect = element.getBoundingClientRect();
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
}''')
# ドロップ先→ソースの順で可視化し、両方がビューポート内にあることを保証する
await dest.scroll_into_view_if_needed()
await source.scroll_into_view_if_needed()
await expect(dest).to_be_in_viewport()
await expect(source).to_be_in_viewport()

async def centers():
result = []
for locator in (source, dest):
result.append(await locator.evaluate('''element => {
const rect = element.getBoundingClientRect();
return [rect.left + rect.width / 2, rect.top + rect.height / 2];
}'''))
return result

# jQuery UIはドラッグ開始時にドロップ先の位置をキャッシュするため、開始前に
# レイアウトが静止していること(バナー出現や再描画の途中でないこと)を確認する
previous = await centers()
for _ in range(25):
await page.wait_for_timeout(200)
current = await centers()
if current == previous:
break
previous = current
else:
raise AssertionError(f'layout did not settle before drag and drop: {current}')

center_coordinates_dest = await dest.evaluate('''element => {
const rect = element.getBoundingClientRect();
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
}''')
(source_x, source_y), (dest_x, dest_y) = current

await page.mouse.move(center_coordinates_source['x'], center_coordinates_source['y'])
await page.mouse.move(source_x, source_y)
await page.mouse.down()
await page.wait_for_timeout(1000)
await page.mouse.move(center_coordinates_dest['x'], center_coordinates_dest['y'], steps=30)
await page.mouse.move(dest_x, dest_y, steps=30)
await page.wait_for_timeout(1000)
await page.mouse.up()

Expand Down
3 changes: 3 additions & 0 deletions scripts/playwright.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ async def init_pw_context(close_on_fail=True, last_path=None, browser_type='chro
await playwright.stop()
playwright = None
playwright = await async_playwright().start()
# timeout未指定のexpectはライブラリ既定の5秒に落ちてタイミング起因の失敗源になる
# ため、既定を transition_timeout の慣行値へ引き上げる (明示指定は影響を受けない)
expect.set_options(timeout=60000)
current_session_id = datetime.now().strftime('%Y%m%d-%H%M%S')
default_last_path = last_path or os.path.join(os.path.expanduser('~/last-screenshots'), current_session_id)
temp_dir = tempfile.mkdtemp()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,10 @@
"id": "837d6c63",
"metadata": {},
"source": [
"## テンプレート管理プロジェクトのURLを開き、テンプレート登録者でログインする"
"## テンプレート管理プロジェクトのURLを開き、テンプレート登録者でログインする\n",
"\n",
"プロジェクトページが表示されること\n",
""
]
},
{
Expand All @@ -634,8 +637,10 @@
"async def _step(page):\n",
" await page.goto(template_project_url)\n",
" await grdm.login(page, idp_name_registrar, idp_username_registrar, idp_password_registrar, transition_timeout=transition_timeout)\n",
" await expect(page.locator('//span[@id = \"nodeTitleEditable\"]')).to_be_visible(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand Down
56 changes: 35 additions & 21 deletions テスト手順-Workflowアドオン-有効化・無効化.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,12 @@
"async def _step(page):\n",
" await page.locator('//a[text() = \"アドオン\"]').click()\n",
" await expect(page.locator('//h3[text() = \"アドオンを選択\"]')).to_be_visible(timeout=transition_timeout)\n",
" await page.locator('#activationsPanel').locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await expect(page.locator('#activationsPanel').locator('//button[*[text() = \"無効にする\"]]')).to_be_enabled(timeout=transition_timeout)\n",
" row = page.locator('#activationsPanel').locator(f'//tr[.//strong[text()=\"{workflow_name}\"]]')\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await expect(row.locator('//button[*[text() = \"無効にする\"]]')).to_be_enabled(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand All @@ -229,10 +231,12 @@
"outputs": [],
"source": [
"async def _step(page):\n",
" await page.locator('#activationsPanel').locator('//button[*[text() = \"無効にする\"]]').click()\n",
" row = page.locator('#activationsPanel').locator(f'//tr[.//strong[text()=\"{workflow_name}\"]]')\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').click()\n",
" await expect(page.locator('//h4[text() = \"ワークフローの無効化\"]')).to_be_visible(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand Down Expand Up @@ -455,10 +459,12 @@
"async def _step(page):\n",
" await page.locator('//a[text() = \"アドオン\"]').click()\n",
" await expect(page.locator('//h3[text() = \"アドオンを選択\"]')).to_be_visible(timeout=transition_timeout)\n",
" await page.locator('#activationsPanel').locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await expect(page.locator('#activationsPanel').locator('//button[*[text() = \"無効にする\"]]')).to_be_enabled(timeout=transition_timeout)\n",
" row = page.locator('#activationsPanel').locator(f'//tr[.//strong[text()=\"{workflow_name}\"]]')\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await expect(row.locator('//button[*[text() = \"無効にする\"]]')).to_be_enabled(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand All @@ -478,12 +484,14 @@
"outputs": [],
"source": [
"async def _step(page):\n",
" await page.locator('#activationsPanel').locator('//button[*[text() = \"無効にする\"]]').click()\n",
" row = page.locator('#activationsPanel').locator(f'//tr[.//strong[text()=\"{workflow_name}\"]]')\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').click()\n",
" await expect(page.locator('//h4[text() = \"ワークフローの無効化\"]')).to_be_visible(timeout=transition_timeout)\n",
" await page.locator('//button[contains(@data-bind, \"confirmDisableActivation\")]').click()\n",
" await expect(page.locator('#activationsPanel').locator('//*[contains(@class, \"label\") and text() = \"無効\"]')).to_be_visible(timeout=transition_timeout)\n",
" await expect(row.locator('//*[contains(@class, \"label\") and text() = \"無効\"]')).to_be_visible(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand Down Expand Up @@ -775,10 +783,12 @@
"async def _step(page):\n",
" await page.locator('//a[text() = \"アドオン\"]').click()\n",
" await expect(page.locator('//h3[text() = \"アドオンを選択\"]')).to_be_visible(timeout=transition_timeout)\n",
" await page.locator('#localWorkflowsPanel').locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await expect(page.locator('#localWorkflowsPanel').locator('//button[*[text() = \"無効にする\"]]')).to_be_enabled(timeout=transition_timeout)\n",
" row = page.locator('#localWorkflowsPanel').locator(f'//tr[.//strong[text()=\"{workflow_name}\"]]')\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await expect(row.locator('//button[*[text() = \"無効にする\"]]')).to_be_enabled(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand All @@ -799,10 +809,12 @@
"outputs": [],
"source": [
"async def _step(page):\n",
" await page.locator('#localWorkflowsPanel').locator('//button[*[text() = \"無効にする\"]]').click()\n",
" row = page.locator('#localWorkflowsPanel').locator(f'//tr[.//strong[text()=\"{workflow_name}\"]]')\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').click()\n",
" await expect(page.locator('//h4[text() = \"ワークフローテンプレートの無効化\"]')).to_be_visible(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand Down Expand Up @@ -916,13 +928,15 @@
"outputs": [],
"source": [
"async def _step(page):\n",
" await page.locator('#localWorkflowsPanel').locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await page.locator('#localWorkflowsPanel').locator('//button[*[text() = \"無効にする\"]]').click()\n",
" row = page.locator('#localWorkflowsPanel').locator(f'//tr[.//strong[text()=\"{workflow_name}\"]]')\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').scroll_into_view_if_needed()\n",
" await row.locator('//button[*[text() = \"無効にする\"]]').click()\n",
" await expect(page.locator('//h4[text() = \"ワークフローテンプレートの無効化\"]')).to_be_visible(timeout=transition_timeout)\n",
" await page.locator('//button[contains(@data-bind, \"confirmDisableTemplate\")]').click()\n",
" await expect(page.locator('#localWorkflowsPanel').locator('//*[contains(@class, \"label\") and text() = \"無効\"]')).to_be_visible(timeout=transition_timeout)\n",
" await expect(row.locator('//*[contains(@class, \"label\") and text() = \"無効\"]')).to_be_visible(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand Down Expand Up @@ -1635,4 +1649,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
9 changes: 7 additions & 2 deletions テスト手順-Workflowアドオン-自動有効化.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,10 @@
"id": "2816ee79",
"metadata": {},
"source": [
"## テンプレート管理プロジェクトのURLを開き、テンプレート登録者でログインする"
"## テンプレート管理プロジェクトのURLを開き、テンプレート登録者でログインする\n",
"\n",
"プロジェクトページが表示されること\n",
""
]
},
{
Expand All @@ -667,8 +670,10 @@
"async def _step(page):\n",
" await page.goto(template_project_url)\n",
" await grdm.login(page, idp_name_registrar, idp_username_registrar, idp_password_registrar, transition_timeout=transition_timeout)\n",
" await expect(page.locator('//span[@id = \"nodeTitleEditable\"]')).to_be_visible(timeout=transition_timeout)\n",
"\n",
"await run_pw(_step)"
"await run_pw(_step)\n",
""
]
},
{
Expand Down
Loading