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
20 changes: 11 additions & 9 deletions src/codeflare_sdk/common/widgets/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@patch.dict(
"os.environ", {"JPY_SESSION_NAME": "example-test"}
) # Mock Jupyter environment variable
def test_cluster_up_down_buttons(mocker):
def test_cluster_apply_down_buttons(mocker):
mocker.patch("kubernetes.client.ApisApi.get_api_versions")
mocker.patch(
"kubernetes.client.CustomObjectsApi.get_cluster_custom_object",
Expand All @@ -45,36 +45,38 @@ def test_cluster_up_down_buttons(mocker):
) as MockCheckbox, patch("ipywidgets.Output"), patch("ipywidgets.HBox"), patch(
"ipywidgets.VBox"
), patch.object(
cluster, "up"
) as mock_up, patch.object(
cluster, "apply"
) as mock_apply, patch.object(
cluster, "down"
) as mock_down, patch.object(
cluster, "wait_ready"
) as mock_wait_ready:
# Create mock button & CheckBox instances
mock_up_button = MagicMock()
mock_apply_button = MagicMock()
mock_down_button = MagicMock()
mock_wait_ready_check_box = MagicMock()

# Ensure the mock Button class returns the mock button instances in sequence
MockCheckbox.side_effect = [mock_wait_ready_check_box]
MockButton.side_effect = [mock_up_button, mock_down_button]
MockButton.side_effect = [mock_apply_button, mock_down_button]

# Call the method under test
cf_widgets.cluster_up_down_buttons(cluster)
cf_widgets.cluster_apply_down_buttons(cluster)

# Simulate checkbox being checked or unchecked
mock_wait_ready_check_box.value = True # Simulate checkbox being checked

# Simulate the button clicks by calling the mock on_click handlers
mock_up_button.on_click.call_args[0][0](None) # Simulate clicking "Cluster Up"
mock_apply_button.on_click.call_args[0][0](
None
) # Simulate clicking "Cluster Apply"
mock_down_button.on_click.call_args[0][0](
None
) # Simulate clicking "Cluster Down"

# Check if the `up` and `down` methods were called
# Check if the `apply` and `down` methods were called
mock_wait_ready.assert_called_once()
mock_up.assert_called_once()
mock_apply.assert_called_once()
mock_down.assert_called_once()


Expand Down
16 changes: 8 additions & 8 deletions src/codeflare_sdk/common/widgets/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,19 +271,19 @@ def display_widgets(self):
)


def cluster_up_down_buttons(
def cluster_apply_down_buttons(
cluster: "codeflare_sdk.ray.cluster.cluster.Cluster",
) -> widgets.Button:
"""
The cluster_up_down_buttons function returns two button widgets for a create and delete button.
The cluster_apply_down_buttons function returns two button widgets for a create and delete button.
The function uses the appwrapper bool to distinguish between resource type for the tool tip.
"""
resource = "Ray Cluster"
if cluster.config.appwrapper:
resource = "AppWrapper"

up_button = widgets.Button(
description="Cluster Up",
apply_button = widgets.Button(
description="Cluster Apply",
tooltip=f"Create the {resource}",
icon="play",
)
Expand All @@ -298,13 +298,13 @@ def cluster_up_down_buttons(
output = widgets.Output()

# Display the buttons in an HBox wrapped in a VBox which includes the wait_ready Checkbox
button_display = widgets.HBox([up_button, delete_button])
button_display = widgets.HBox([apply_button, delete_button])
display(widgets.VBox([button_display, wait_ready_check]), output)

def on_up_button_clicked(b): # Handle the up button click event
def on_apply_button_clicked(b): # Handle the apply button click event
with output:
output.clear_output()
cluster.up()
cluster.apply()

# If the wait_ready Checkbox is clicked(value == True) trigger the wait_ready function
if wait_ready_check.value:
Expand All @@ -315,7 +315,7 @@ def on_down_button_clicked(b): # Handle the down button click event
output.clear_output()
cluster.down()

up_button.on_click(on_up_button_clicked)
apply_button.on_click(on_apply_button_clicked)
delete_button.on_click(on_down_button_clicked)


Expand Down
4 changes: 2 additions & 2 deletions src/codeflare_sdk/ray/cluster/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
AppWrapperStatus,
)
from ...common.widgets.widgets import (
cluster_up_down_buttons,
cluster_apply_down_buttons,
is_notebook,
)
from kubernetes import client
Expand Down Expand Up @@ -88,7 +88,7 @@ def __init__(self, config: ClusterConfiguration):
self.resource_yaml = self.create_resource()

if is_notebook():
cluster_up_down_buttons(self)
cluster_apply_down_buttons(self)

def get_dynamic_client(self): # pragma: no cover
return DynamicClient(get_api_client())
Expand Down
18 changes: 9 additions & 9 deletions ui-tests/tests/widget_notebook_example.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,25 @@ test.describe("Visual Regression", () => {

// At this point, all cells have been ran, and their screenshots have been captured.
// We now interact with the widgets in the notebook.
const upDownWidgetCellIndex = 3; // 4 on OpenShift
const applyDownWidgetCellIndex = 3; // 4 on OpenShift

await waitForWidget(page, upDownWidgetCellIndex, 'input[type="checkbox"]');
await waitForWidget(page, upDownWidgetCellIndex, 'button:has-text("Cluster Down")');
await waitForWidget(page, upDownWidgetCellIndex, 'button:has-text("Cluster Up")');
await waitForWidget(page, applyDownWidgetCellIndex, 'input[type="checkbox"]');
await waitForWidget(page, applyDownWidgetCellIndex, 'button:has-text("Cluster Down")');
await waitForWidget(page, applyDownWidgetCellIndex, 'button:has-text("Cluster Apply")');

await interactWithWidget(page, upDownWidgetCellIndex, 'input[type="checkbox"]', async (checkbox) => {
await interactWithWidget(page, applyDownWidgetCellIndex, 'input[type="checkbox"]', async (checkbox) => {
await checkbox.click();
const isChecked = await checkbox.isChecked();
expect(isChecked).toBe(true);
});

await interactWithWidget(page, upDownWidgetCellIndex, 'button:has-text("Cluster Down")', async (button) => {
await interactWithWidget(page, applyDownWidgetCellIndex, 'button:has-text("Cluster Down")', async (button) => {
await button.click();
const clusterDownMessage = await page.waitForSelector('text=The requested resource could not be located.', { timeout: 5000 });
expect(await clusterDownMessage.innerText()).toContain('The requested resource could not be located.');
});

await interactWithWidget(page, upDownWidgetCellIndex, 'button:has-text("Cluster Up")', async (button) => {
await interactWithWidget(page, applyDownWidgetCellIndex, 'button:has-text("Cluster Apply")', async (button) => {
await button.click();

const successMessage = await page.waitForSelector('text=Ray Cluster: \'widgettest\' has successfully been created', { timeout: 10000 });
Expand All @@ -103,7 +103,7 @@ test.describe("Visual Regression", () => {

await runPreviousCell(page, cellCount, '(<CodeFlareClusterStatus.READY: 1>, True)');

await interactWithWidget(page, upDownWidgetCellIndex, 'button:has-text("Cluster Down")', async (button) => {
await interactWithWidget(page, applyDownWidgetCellIndex, 'button:has-text("Cluster Down")', async (button) => {
await button.click();
const clusterDownMessage = await page.waitForSelector('text=Ray Cluster: \'widgettest\' has successfully been deleted', { timeout: 5000 });
expect(clusterDownMessage).not.toBeNull();
Expand All @@ -116,7 +116,7 @@ test.describe("Visual Regression", () => {
await cell.fill('"widgettest-1"');
await page.notebook.runCell(cellCount - 3, true); // Run ClusterConfiguration cell

await interactWithWidget(page, upDownWidgetCellIndex, 'button:has-text("Cluster Up")', async (button) => {
await interactWithWidget(page, applyDownWidgetCellIndex, 'button:has-text("Cluster Apply")', async (button) => {
await button.click();
const successMessage = await page.waitForSelector('text=Ray Cluster: \'widgettest-1\' has successfully been created', { timeout: 10000 });
expect(successMessage).not.toBeNull();
Expand Down