Skip to content

Commit 63cdfcb

Browse files
refactor(api): remove test-only model re-export from workspaces
1 parent ae468e9 commit 63cdfcb

2 files changed

Lines changed: 23 additions & 22 deletions

File tree

api/workspaces.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
warn_workspace_json_read,
2525
)
2626
from utils.workspace_descriptor import read_json_file
27-
from services.workspace_resolver import (
28-
infer_workspace_name_from_context,
29-
lookup_workspace_display_name,
30-
)
27+
from services.workspace_resolver import infer_workspace_name_from_context
3128
from services.cli_tabs import get_cli_workspace_tabs
3229
from services.workspace_listing import list_workspace_projects
3330
from services.workspace_tabs import (
@@ -36,13 +33,6 @@
3633
list_workspace_tab_summaries,
3734
)
3835

39-
# Re-exported for tests/test_models_wired_at_read_sites.py — the typed-model
40-
# spy harness patches `workspaces_mod.Bubble` / `.Composer` / `.Workspace` to
41-
# verify that production read paths actually call from_dict. The classes
42-
# themselves are wired inside the services modules now (post-#25 split);
43-
# importing them here keeps the spy resolution stable.
44-
from models import Bubble, Composer, Workspace # noqa: F401
45-
4636
bp = Blueprint("workspaces", __name__)
4737
_logger = logging.getLogger(__name__)
4838

tests/test_models_wired_at_read_sites.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,14 @@ def test_search_endpoint_calls_bubble_from_dict(self):
117117

118118
def test_workspace_tabs_endpoint_calls_bubble_from_dict(self):
119119
from app import create_app
120-
import api.workspaces as workspaces_mod
120+
import services.workspace_db as workspace_db_mod
121+
from models import Bubble
121122
app = create_app()
122123
app.config["TESTING"] = True
123124
app.config["EXCLUSION_RULES"] = []
124-
with patch.object(workspaces_mod.Bubble, "from_dict", wraps=workspaces_mod.Bubble.from_dict) as spy:
125+
with patch.object(
126+
workspace_db_mod.Bubble, "from_dict", wraps=Bubble.from_dict
127+
) as spy:
125128
client = app.test_client()
126129
response = client.get(f"/api/workspaces/{WORKSPACE_ID}/tabs")
127130
self.assertEqual(response.status_code, 200)
@@ -163,17 +166,20 @@ def test_bubble_schema_drift_is_logged_not_swallowed_silently(self):
163166
msg="drift log must include the offending bubble id")
164167

165168
def test_workspace_tabs_endpoint_calls_composer_from_dict(self):
166-
# Brad's most-important finding: list_workspaces() at api/workspaces.py:605
167-
# validates each composer with Composer.from_dict, but get_workspace_tabs()
168-
# in the same file used raw json.loads. Schema drift would have been hidden
169-
# from one of the two primary conversation-browsing paths. This test pins
170-
# that BOTH paths must now validate via the model.
169+
# Brad's most-important finding: list_workspaces() validates each composer
170+
# with Composer.from_dict, but get_workspace_tabs() used raw json.loads.
171+
# Schema drift would have been hidden from one of the two primary
172+
# conversation-browsing paths. This test pins that BOTH paths must now
173+
# validate via the model.
171174
from app import create_app
172-
import api.workspaces as workspaces_mod
175+
import services.workspace_tabs as workspace_tabs_mod
176+
from models import Composer
173177
app = create_app()
174178
app.config["TESTING"] = True
175179
app.config["EXCLUSION_RULES"] = []
176-
with patch.object(workspaces_mod.Composer, "from_dict", wraps=workspaces_mod.Composer.from_dict) as spy:
180+
with patch.object(
181+
workspace_tabs_mod.Composer, "from_dict", wraps=Composer.from_dict
182+
) as spy:
177183
client = app.test_client()
178184
response = client.get(f"/api/workspaces/{WORKSPACE_ID}/tabs")
179185
self.assertEqual(response.status_code, 200)
@@ -220,8 +226,13 @@ def test_composers_endpoint_calls_workspace_from_dict(self):
220226

221227
def test_workspace_display_name_calls_workspace_from_dict(self):
222228
from services.workspace_resolver import lookup_workspace_display_name
223-
import api.workspaces as workspaces_mod
224-
with patch.object(workspaces_mod.Workspace, "from_dict", wraps=workspaces_mod.Workspace.from_dict) as spy:
229+
import services.workspace_resolver as workspace_resolver_mod
230+
from models import Workspace
231+
with patch.object(
232+
workspace_resolver_mod.Workspace,
233+
"from_dict",
234+
wraps=Workspace.from_dict,
235+
) as spy:
225236
name = lookup_workspace_display_name(self.workspace_path, WORKSPACE_ID)
226237
self.assertIsInstance(name, str)
227238
self.assertGreaterEqual(

0 commit comments

Comments
 (0)