Skip to content

Commit

Permalink
✨ e2e: Convert puppeteer's ti-plan.js into playwright's ti_plan.py (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
odeimaiz authored Apr 22, 2024
1 parent f909f02 commit dd80ad4
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,8 @@ qx.Class.define("osparc.dashboard.CardBase", {
resourceDetails.addListener("openStudy", e => {
const openCB = () => win.close();
const studyId = e.getData()["uuid"];
this._startStudyById(studyId, openCB, null);
const isStudyCreation = false;
this._startStudyById(studyId, openCB, null, isStudyCreation);
});
return resourceDetails;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,11 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
openButton.openResource = true;
openButton.addListener("execute", () => {
switch (resourceData["resourceType"]) {
case "study":
this._startStudyById(resourceData["uuid"]);
case "study": {
const isStudyCreation = false;
this._startStudyById(resourceData["uuid"], null, null, isStudyCreation);
break;
}
case "template":
this._createStudyFromTemplate(resourceData);
break;
Expand All @@ -428,7 +430,8 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
resourceDetails.addListener("openStudy", e => {
const openCB = () => win.close();
const studyId = e.getData()["uuid"];
this._startStudyById(studyId, openCB, null);
const isStudyCreation = false;
this._startStudyById(studyId, openCB, null, isStudyCreation);
});
resourceDetails.addListener("openTemplate", e => {
win.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
const loadStudyId = osparc.store.Store.getInstance().getCurrentStudyId();
if (loadStudyId) {
const cancelCB = () => this.reloadResources();
this._startStudyById(loadStudyId, null, cancelCB);
const isStudyCreation = false;
this._startStudyById(loadStudyId, null, cancelCB, isStudyCreation);
} else {
this.reloadResources();
}
Expand Down Expand Up @@ -807,7 +808,8 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
};
osparc.data.Resources.fetch("studies", "delete", params, studyId);
};
this._startStudyById(studyId, openCB, cancelCB);
const isStudyCreation = true;
this._startStudyById(studyId, openCB, cancelCB, isStudyCreation);
})
.catch(err => {
this._hideLoadingPage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", {
},

__editTemplate: function(studyData) {
this._startStudyById(studyData.uuid);
const isStudyCreation = false;
this._startStudyById(studyData.uuid, null, null, isStudyCreation);
},

__doDeleteTemplate: function(studyData) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,8 @@ qx.Class.define("osparc.desktop.SlideshowView", {

const node = this.__nodeView.getNode();
if (node.isDynamic()) {
// Start it. First wait a second because the function depends on the node's state which might not be available yet
setTimeout(() => node.requestStartNode(), 1000);
// Start it. First wait 2 seconds because the function depends on the node's state which might not be available yet
setTimeout(() => node.requestStartNode(), 2000);
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ qx.Class.define("osparc.node.BaseNodeView", {

if (node.isDynamic()) {
node.attachHandlersToStartButton(this.__nodeStartButton);
osparc.utils.Utils.setIdToWidget(this.__nodeStartButton, "Start_"+node.getNodeId())
node.attachVisibilityHandlerToStopButton(this.__nodeStopButton);
node.attachExecuteHandlerToStopButton(this.__nodeStopButton);
}
Expand Down
139 changes: 139 additions & 0 deletions tests/e2e-playwright/tests/ti_plan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# pylint: disable=redefined-outer-name
# pylint: disable=unused-argument
# pylint: disable=unused-variable
# pylint: disable=too-many-arguments
# pylint: disable=too-many-statements
# pylint: disable=unnecessary-lambda

import re
from http import HTTPStatus
from typing import Final

from playwright.sync_api import APIRequestContext, Page
from pydantic import AnyUrl
from pytest_simcore.playwright_utils import on_web_socket_default_handler
from tenacity import Retrying
from tenacity.retry import retry_if_exception_type
from tenacity.stop import stop_after_attempt
from tenacity.wait import wait_fixed

projects_uuid_pattern: Final[re.Pattern] = re.compile(
r"/projects/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"
)


def test_tip(
page: Page,
log_in_and_out: None,
api_request_context: APIRequestContext,
product_url: AnyUrl,
product_billable: bool,
):
# connect and listen to websocket
page.on("websocket", on_web_socket_default_handler)

# open studies tab and filter
page.get_by_test_id("studiesTabBtn").click()
_textbox = page.get_by_test_id("searchBarFilter-textField-study")
_textbox.fill("Classic TI")
_textbox.press("Enter")

with page.expect_response(re.compile(r"/projects/[^:]+:open")) as response_info:
page.get_by_test_id("newTIPlanButton").click()
if product_billable:
# Open project with default resources
page.get_by_test_id("openWithResources").click()
page.wait_for_timeout(1000)

project_data = response_info.value.json()
assert project_data
project_uuid = project_data["data"]["uuid"]
print("project uuid: ", project_uuid)
node_ids = []
for node_id in project_data["data"]["workbench"].keys():
print("node_id: ", node_id)
node_ids.append(node_id)

# Electrode Selector
es_page = page.frame_locator(f'[osparc-test-id="iframe_{node_ids[0]}"]')
es_page.get_by_test_id("TargetStructure_Selector").click(timeout=300000)
es_page.get_by_test_id(
"TargetStructure_Target_(Targets_combined) Hypothalamus"
).click()
electrode_selections = [
["E1+", "FT9"],
["E1-", "FT7"],
["E2+", "T9"],
["E2-", "T7"],
]
for selection in electrode_selections:
group_id = "ElectrodeGroup_" + selection[0] + "_Start"
electrode_id = "Electrode_" + selection[1]
es_page.get_by_test_id(group_id).click()
es_page.get_by_test_id(electrode_id).click()
es_page.get_by_test_id("FinishSetUp").click()
page.wait_for_timeout(10000)
# check outputs
expected_outputs = ["output.json"]
text_on_output_button = f"Outputs ({len(expected_outputs)})"
page.get_by_test_id("outputsBtn").get_by_text(text_on_output_button).click()
page.wait_for_timeout(5000)

# Move to next step
page.get_by_test_id("AppMode_NextBtn").click()

# Optimal Configuration Identification
ti_page = page.frame_locator(f'[osparc-test-id="iframe_{node_ids[1]}"]')
ti_page.get_by_role("button", name="Run Optimization").click(timeout=300000)
page.wait_for_timeout(20000)
ti_page.get_by_role("button", name="Load Analysis").click()
page.wait_for_timeout(20000)
ti_page.get_by_role("button", name="Load").nth(1).click() # Load Analysis is first
page.wait_for_timeout(20000)
ti_page.get_by_role("button", name="Add to Report (0)").nth(0).click()
page.wait_for_timeout(20000)
ti_page.get_by_role("button", name="Export to S4L").click()
page.wait_for_timeout(20000)
ti_page.get_by_role("button", name="Add to Report (1)").nth(1).click()
page.wait_for_timeout(20000)
ti_page.get_by_role("button", name="Export Report").click()
page.wait_for_timeout(20000)
# check outputs
expected_outputs = ["output_1.zip", "TIP_report.pdf", "results.csv"]
text_on_output_button = f"Outputs ({len(expected_outputs)})"
page.get_by_test_id("outputsBtn").get_by_text(text_on_output_button).click()
page.wait_for_timeout(5000)

# Move to next step
page.get_by_test_id("AppMode_NextBtn").click()

# Sim4Life PostPro
s4l_postpro_page = page.frame_locator(f'[osparc-test-id="iframe_{node_ids[2]}"]')
# click on the mode button
s4l_postpro_page.get_by_test_id("mode-button-postro").click(timeout=300000)
# click on the surface viewer
s4l_postpro_page.get_by_test_id("tree-item-ti_field.cache").click()
s4l_postpro_page.get_by_test_id("tree-item-SurfaceViewer").click()
page.wait_for_timeout(5000)

# Going back to dashboard
page.get_by_test_id("dashboardBtn").click()
page.get_by_test_id("confirmDashboardBtn").click()
page.wait_for_timeout(1000)

# Going back to projects/studies view (In Sim4life projects:=studies)
page.get_by_test_id("studiesTabBtn").click()
page.wait_for_timeout(1000)

# The project is closing, wait until it is closed and delete it (currently waits max=5 minutes)
for attempt in Retrying(
wait=wait_fixed(5),
stop=stop_after_attempt(60), # 5*60= 300 seconds
retry=retry_if_exception_type(AssertionError),
reraise=True,
):
with attempt:
resp = api_request_context.delete(
f"{product_url}v0/projects/{project_uuid}"
)
assert resp.status == HTTPStatus.NO_CONTENT
2 changes: 1 addition & 1 deletion tests/e2e/tutorials/ti-plan.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ async function runTutorial() {
// Click "Load Analysis" button
const buttonsLoadAnalysis = await utils.getButtonsWithText(postProIframe, "Load Analysis");
await buttonsLoadAnalysis[0].click();
await tutorial.waitFor(20000, "Loading anaylsis");
await tutorial.waitFor(20000, "Loading analysis");
await tutorial.takeScreenshot("postpro_load_analysis");
// Click on the first "Load" button
const buttonsLoad = await utils.getButtonsWithText(postProIframe, "Load");
Expand Down

0 comments on commit dd80ad4

Please sign in to comment.