Skip to content

Commit cba97de

Browse files
Manual Selenium tests for IDE notebook
1 parent f06c140 commit cba97de

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ __pycache__
2121
/tests/prof/
2222
/djl-serving/
2323
/src_diff/
24+
/tests/geckodriver.log

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"constructs>=10.0.0,<11.0.0",
2525
"sagemaker-studio-image-build",
2626
"sagemaker-training",
27+
"selenium"
2728
],
2829
"dev": [
2930
"sagemaker-pytorch-training",

tests/test_ide.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@
44
import time
55

66
import pytest
7+
from selenium.webdriver.support.wait import WebDriverWait
78

89
from sagemaker_ssh_helper.ide import SSHIDE
910
from sagemaker_ssh_helper.manager import SSMManager
1011
from sagemaker_ssh_helper.proxy import SSMProxy
1112

13+
from selenium import webdriver
14+
15+
from selenium.webdriver.common.by import By
16+
17+
import boto3
18+
19+
from selenium.webdriver.support import expected_conditions as EC
20+
1221
logger = logging.getLogger('sagemaker-ssh-helper:test_ide')
1322

1423

@@ -225,3 +234,81 @@ def test_studio_internet_free_mode(request):
225234
assert "127.0.0.1:5901" in services_running
226235

227236
ide.delete_kernel_app("byoi-studio-app", wait=False)
237+
238+
239+
@pytest.mark.skipif(os.getenv('PYTEST_IGNORE_SKIPS', "false") == "false",
240+
reason="Manual test")
241+
def test_studio_notebook_in_firefox(request):
242+
ide = SSHIDE(request.config.getini('sagemaker_studio_domain'), 'test-data-science')
243+
244+
# Get SageMaker Studio Presigned URL with API
245+
sagemaker_client = boto3.client('sagemaker')
246+
studio_pre_signed_url_response = sagemaker_client.create_presigned_domain_url(
247+
DomainId=ide.domain_id,
248+
UserProfileName=ide.user,
249+
)
250+
studio_pre_signed_url = studio_pre_signed_url_response['AuthorizedUrl']
251+
logging.info(f"Studio pre-signed URL: {studio_pre_signed_url}")
252+
253+
logging.info("Launching Firefox")
254+
browser = webdriver.Firefox()
255+
256+
logging.info("Launching SageMaker Studio")
257+
browser.get(studio_pre_signed_url)
258+
259+
logging.info("Checking for SageMaker Studio in Firefox")
260+
assert "JupyterLab" in browser.title
261+
262+
logging.info("Waiting for SageMaker Studio to launch")
263+
kernel_menu_xpath = "//div[@class='lm-MenuBar-itemLabel p-MenuBar-itemLabel' " \
264+
"and text()='Kernel']"
265+
WebDriverWait(browser, 30).until(
266+
EC.presence_of_element_located((By.XPATH, kernel_menu_xpath))
267+
)
268+
time.sleep(15) # wait until obscurity of the menu item is gone and UI is fully loaded
269+
kernel_menu_item = browser.find_element(By.XPATH, kernel_menu_xpath)
270+
logging.info(f"Found SageMaker Studio kernel menu item: {kernel_menu_item}")
271+
kernel_menu_item.click()
272+
273+
logging.info("Restarting kernel and running all cells")
274+
restart_menu_xpath = "//div[@class='lm-Menu-itemLabel p-Menu-itemLabel' " \
275+
"and text()='Restart Kernel and Run All Cells…']"
276+
restart_menu_item = browser.find_element(By.XPATH, restart_menu_xpath)
277+
logging.info(f"Found SageMaker Studio restart kernel menu item: {restart_menu_item}")
278+
restart_menu_item.click()
279+
280+
# TODO: check if kernel has been already started, also check that it's a correct kernel and instance type
281+
# <button type="button" class="bp3-button bp3-minimal jp-Toolbar-kernelName jp-ToolbarButtonComponent minimal jp-Button" aria-disabled="false" title="Switch kernel"><span class="bp3-button-text"><span class="jp-ToolbarButtonComponent-label">No Kernel</span></span></button>
282+
# <button type="button" class="bp3-button bp3-minimal jp-Toolbar-kernelName jp-ToolbarButtonComponent minimal jp-Button" aria-disabled="false" title=""><span class="bp3-button-text"><span class="jp-ToolbarButtonComponent-label" style="display: none;">Python 3 (Data Science 2.0)</span></span><span class="css-1jyspix newButtonTarget"><span class="css-1vcsdgo">Data Science 2.0</span><span class="css-pyakce">|</span><span>Python 3</span><span class="css-pyakce">|</span><span>2 vCPU + 4 GiB</span></span></button>
283+
284+
# TODO: check banner if kernel is still starting, wait until banner disappears, then click restart
285+
# <div class="css-a7sx0c-bannerContainer sagemaker-starting-banner" id="sagemaker-notebook-banner"><div class="css-1qyc1pu-kernelStartingBannerContainer"><div><div class="css-6wrpfe-bannerSpinDiv"></div></div><div><p class="css-g9mx5z-bannerPromptSpanTitle">Starting notebook kernel...</p></div></div></div>
286+
287+
restart_button_xpath = "//div[@class='jp-Dialog-buttonLabel' " \
288+
"and text()='Restart']"
289+
restart_button = browser.find_element(By.XPATH, restart_button_xpath)
290+
logging.info(f"Found SageMaker Studio restart button: {restart_button}")
291+
restart_button.click()
292+
293+
time.sleep(120) # Give time to restart
294+
295+
studio_ids = ide.get_kernel_instance_ids("sagemaker-data-science-ml-m5-large-6590da95dc67eec021b14bedc036",
296+
timeout_in_sec=300)
297+
studio_id = studio_ids[0]
298+
299+
with SSMProxy(10022) as ssm_proxy:
300+
ssm_proxy.connect_to_ssm_instance(studio_id)
301+
services_running = ssm_proxy.run_command_with_output("sm-ssh-ide status")
302+
services_running = services_running.decode('latin1')
303+
304+
assert "127.0.0.1:8889" in services_running
305+
assert "127.0.0.1:5901" in services_running
306+
307+
# TODO: assert the services were restarted by the test, e.g., by checking the SSM timestamp
308+
# TODO: check if the second restart also successful
309+
310+
# TODO: restart image (clean-up for the next run)
311+
# <button type="button" class="bp3-button bp3-minimal jp-ToolbarButtonComponent minimal jp-Button" aria-disabled="false" title="Shut down">...</button> """
312+
313+
logging.info("Closing Firefox")
314+
browser.close()

0 commit comments

Comments
 (0)