Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion src/ucode/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def prompt_for_workspace(
choice = questionary.select(
"Select workspace:", choices=choices, style=style, pointer="›", qmark=""
).ask()
if choice is not None:
if isinstance(choice, tuple):
host, profile_name = choice
return normalize_workspace_url(host), profile_name

Expand Down
48 changes: 48 additions & 0 deletions tests/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
from __future__ import annotations

from datetime import timedelta
from unittest.mock import patch

import pytest

from ucode.ui import (
format_duration,
format_token_count,
normalize_workspace_url,
prompt_for_workspace,
render_box_table,
status_badge,
)
Expand Down Expand Up @@ -144,3 +146,49 @@ def test_cell_wraps_when_max_width_set(self):
def test_dash_for_empty_cell(self):
result = render_box_table(["A"], [[""]])
assert "-" in result


class TestPromptForWorkspace:
"""Cover the three things `questionary.select(...).ask()` can return:
a (host, profile) tuple, None (cancel or "Enter a different URL"),
or — in some questionary versions — the choice's title string."""

PROFILES = [("https://a.databricks.com", "prof-a"), ("https://b.databricks.com", "prof-b")]

def test_returns_selected_profile_tuple(self):
with patch("ucode.ui.questionary.select") as mock_select:
mock_select.return_value.ask.return_value = (
"https://a.databricks.com",
"prof-a",
)
url, profile = prompt_for_workspace("desc", profiles=self.PROFILES)
assert url == "https://a.databricks.com"
assert profile == "prof-a"

def test_none_falls_through_to_manual_prompt(self):
with (
patch("ucode.ui.questionary.select") as mock_select,
patch("ucode.ui.console.input", return_value="https://manual.databricks.com"),
):
mock_select.return_value.ask.return_value = None
url, profile = prompt_for_workspace("desc", profiles=self.PROFILES)
assert url == "https://manual.databricks.com"
assert profile is None

def test_string_value_falls_through_to_manual_prompt(self):
# Regression: if questionary returns the choice title (e.g. "Enter a
# different URL") instead of its value, we must not try to unpack it.
with (
patch("ucode.ui.questionary.select") as mock_select,
patch("ucode.ui.console.input", return_value="https://manual.databricks.com"),
):
mock_select.return_value.ask.return_value = "Enter a different URL"
url, profile = prompt_for_workspace("desc", profiles=self.PROFILES)
assert url == "https://manual.databricks.com"
assert profile is None

def test_no_profiles_goes_straight_to_manual_prompt(self):
with patch("ucode.ui.console.input", return_value="example.databricks.com"):
url, profile = prompt_for_workspace("desc", profiles=None)
assert url == "https://example.databricks.com"
assert profile is None
Loading