(self, step: dict[str, Any])
| 173 | raise ValueError(f"step {step['id']}: unknown action {action}") |
| 174 | |
| 175 | def _exec_request(self, step: dict[str, Any]): |
| 176 | path = self.resolve(step["path"]) |
| 177 | body = self.resolve_value(step["body"]) if "body" in step else None |
| 178 | ex = step.get("expect") or {} |
| 179 | |
| 180 | if self.has_auth_override(step): |
| 181 | # Auth-override scenarios bypass SDK auth by design |
| 182 | override = self.auth_override(step) |
| 183 | headers: dict[str, str] = {} |
| 184 | if override != "none": |
| 185 | headers["Authorization"] = self.resolve(override) |
| 186 | if body is not None: |
| 187 | headers["Content-Type"] = "application/json" |
| 188 | |
| 189 | resp = self._http.request( |
| 190 | step["method"], path, |
| 191 | headers=headers, |
| 192 | json=body if body is not None else None, |
| 193 | ) |
| 194 | status = resp.status_code |
| 195 | data = None |
| 196 | raw_body = resp.text |
| 197 | else: |
| 198 | # Default auth — raw bearer request. |
| 199 | resp = self._raw(step["method"], path, body) |
| 200 | status = resp.status_code |
| 201 | raw_body = resp.text |
| 202 | data = None |
| 203 | |
| 204 | if "status" in ex: |
| 205 | assert status == ex["status"], f"step {step['id']}: expected {ex['status']}, got {status}" |
| 206 | |
| 207 | if not any(k in ex for k in ("body_contains", "body_excludes", "body_match")): |
| 208 | return |
| 209 | |
| 210 | if data is None: |
| 211 | data = json_mod.loads(raw_body) |
| 212 | |
| 213 | for key in ex.get("body_contains", []): |
| 214 | resolved = self.resolve(key) |
| 215 | assert resolved in data, f"step {step['id']}: body_contains {resolved}" |
| 216 | |
| 217 | for key in ex.get("body_excludes", []): |
| 218 | resolved = self.resolve(key) |
| 219 | assert resolved not in data, f"step {step['id']}: body_excludes {resolved}" |
| 220 | |
| 221 | if "body_match" in ex: |
| 222 | for json_path, expected in ex["body_match"].items(): |
| 223 | resolved_path = self.resolve(json_path) |
| 224 | actual = json_path_get(data, resolved_path) |
| 225 | resolved_expected = self.resolve_value(expected) |
| 226 | assert values_equal(actual, resolved_expected), ( |
| 227 | f"step {step['id']}: body_match {resolved_path} = {actual!r}, want {resolved_expected!r}" |
| 228 | ) |
| 229 | |
| 230 | |
| 231 | # ── Test entry point ────────────────────────────────────────────── |
no test coverage detected