|
8 | 8 | import sqlite3 |
9 | 9 | import sys |
10 | 10 | import tempfile |
| 11 | +from contextlib import closing |
11 | 12 |
|
12 | 13 | import pytest |
13 | 14 |
|
@@ -116,6 +117,68 @@ def test_listing_logs_composer_schema_drift(caplog_at_warning: pytest.LogCapture |
116 | 117 | ) |
117 | 118 |
|
118 | 119 |
|
| 120 | +def test_workspace_tabs_logs_bubble_json_decode_failure( |
| 121 | + caplog_at_warning: pytest.LogCaptureFixture, |
| 122 | +) -> None: |
| 123 | + from flask import Flask |
| 124 | + |
| 125 | + app = Flask(__name__) |
| 126 | + app.config["TESTING"] = True |
| 127 | + app.config["EXCLUSION_RULES"] = [] |
| 128 | + |
| 129 | + with tempfile.TemporaryDirectory() as tmp: |
| 130 | + ws_root = _seed_tabs_with_drifted_bubble(tmp) |
| 131 | + global_db = os.path.join(tmp, "globalStorage", "state.vscdb") |
| 132 | + with closing(sqlite3.connect(global_db)) as conn: |
| 133 | + conn.execute( |
| 134 | + "INSERT INTO cursorDiskKV ([key], value) VALUES (?, ?)", |
| 135 | + ("bubbleId:cmp-ok:b-json", "{not valid json"), |
| 136 | + ) |
| 137 | + conn.commit() |
| 138 | + with caplog_at_warning.at_level(logging.WARNING, logger="services.workspace_tabs"): |
| 139 | + with app.test_request_context("/api/workspaces/global/tabs"): |
| 140 | + payload, status = assemble_workspace_tabs("global", ws_root, rules=[]) |
| 141 | + |
| 142 | + assert status == 200 |
| 143 | + messages = [r.getMessage() for r in caplog_at_warning.records] |
| 144 | + assert any("decode Bubble" in m and "b-json" in m for m in messages), ( |
| 145 | + f"expected JSON decode warning for b-json, got: {messages}" |
| 146 | + ) |
| 147 | + |
| 148 | + |
| 149 | +def test_workspace_tabs_logs_composer_json_decode_failure( |
| 150 | + caplog_at_warning: pytest.LogCaptureFixture, |
| 151 | +) -> None: |
| 152 | + from flask import Flask |
| 153 | + |
| 154 | + app = Flask(__name__) |
| 155 | + app.config["TESTING"] = True |
| 156 | + app.config["EXCLUSION_RULES"] = [] |
| 157 | + |
| 158 | + with tempfile.TemporaryDirectory() as tmp: |
| 159 | + ws_root = _seed_tabs_with_drifted_bubble(tmp) |
| 160 | + global_db = os.path.join(tmp, "globalStorage", "state.vscdb") |
| 161 | + # Value must match composer_rows LIKE '%fullConversationHeadersOnly%' to reach parse. |
| 162 | + bad_composer_value = ( |
| 163 | + '{"fullConversationHeadersOnly": [{"bubbleId": "b1"}], "createdAt":' |
| 164 | + ) |
| 165 | + with closing(sqlite3.connect(global_db)) as conn: |
| 166 | + conn.execute( |
| 167 | + "INSERT INTO cursorDiskKV ([key], value) VALUES (?, ?)", |
| 168 | + ("composerData:cmp-json", bad_composer_value), |
| 169 | + ) |
| 170 | + conn.commit() |
| 171 | + with caplog_at_warning.at_level(logging.WARNING, logger="services.workspace_tabs"): |
| 172 | + with app.test_request_context("/api/workspaces/global/tabs"): |
| 173 | + payload, status = assemble_workspace_tabs("global", ws_root, rules=[]) |
| 174 | + |
| 175 | + assert status == 200 |
| 176 | + messages = [r.getMessage() for r in caplog_at_warning.records] |
| 177 | + assert any("decode Composer" in m and "cmp-json" in m for m in messages), ( |
| 178 | + f"expected JSON decode warning for cmp-json, got: {messages}" |
| 179 | + ) |
| 180 | + |
| 181 | + |
119 | 182 | def test_workspace_tabs_logs_bubble_schema_drift(caplog_at_warning: pytest.LogCaptureFixture) -> None: |
120 | 183 | from flask import Flask |
121 | 184 |
|
|
0 commit comments