Python 88.3%
TypeScript 7.6%
Shell 4.1%
1"""Smoke tests for xAI Chat Completions (grok-4.3 by default; every call bills ~100-180 reasoning tokens, ~$0.0005).2Uses the `xai` fixture (scripts.live.xai_request) and models["xai"] from tests/conftest.py.3"""4from __future__ import annotations56import json7import time89import pytest1011MSGS = [{"role": "user", "content": "Reply with OK."}]121314def test_minimal_chat_completion_has_reasoning_content(xai, models):15 st, body, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": MSGS, "max_completion_tokens": 32}, est_cost_usd=0.0005, note="test_chat minimal")16 assert st == 200 and body["object"] == "chat.completion"17 msg = body["choices"][0]["message"]18 # Reasoning is always-on and billed inside max_completion_tokens: a long trace can end the turn with19 # finish_reason "length" and an empty content (observed once on 2026-09-19) — tolerate that race.20 fr = body["choices"][0]["finish_reason"]21 assert fr in ("stop", "length")22 if fr == "stop":23 assert "OK" in (msg.get("content") or "")24 assert "reasoning_content" in msg # reasoning models expose the trace25 u = body["usage"]26 assert u["total_tokens"] == u["prompt_tokens"] + u["completion_tokens"] + u["completion_tokens_details"]["reasoning_tokens"]27 assert "cached_tokens" in u["prompt_tokens_details"] and "cost_in_usd_ticks" in u28 assert body["service_tier"] == "default"293031def test_streaming_chunks_usage_and_done(xai, models):32 st, lines, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": MSGS, "max_completion_tokens": 32, "stream": True, "stream_options": {"include_usage": True}}, stream=True, est_cost_usd=0.0005, note="test_chat stream")33 assert st == 20034 data = [l[5:].strip() for l in lines if l.startswith("data:")]35 assert data[-1] == "[DONE]"36 chunks = [json.loads(d) for d in data[:-1]]37 assert all(c["object"] == "chat.completion.chunk" for c in chunks)38 assert chunks[-1]["choices"] == [] and chunks[-1]["usage"]["total_tokens"] > 039 assert any(c["choices"] and c["choices"][0].get("finish_reason") == "stop" for c in chunks)40 assert "OK" in "".join(c["choices"][0]["delta"].get("content") or "" for c in chunks if c["choices"])414243def test_json_schema_strict(xai, models):44 schema = {"type": "object", "properties": {"answer": {"type": "string"}, "n": {"type": "integer"}}, "required": ["answer", "n"], "additionalProperties": False}45 st, body, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": [{"role": "user", "content": "Reply with answer OK and n 1."}], "max_completion_tokens": 32, "response_format": {"type": "json_schema", "json_schema": {"name": "ok", "strict": True, "schema": schema}}}, est_cost_usd=0.0005, note="test_chat json_schema")46 assert st == 20047 parsed = json.loads(body["choices"][0]["message"]["content"])48 assert set(parsed) == {"answer", "n"} and parsed["n"] == 1495051def test_reasoning_effort_values(xai, models):52 st, body, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": MSGS, "max_completion_tokens": 32, "reasoning_effort": "low"}, est_cost_usd=0.0005, note="test_chat reasoning_effort=low")53 assert st == 200 and body["usage"]["completion_tokens_details"]["reasoning_tokens"] >= 054 st, body, _ = xai("POST", "/v1/chat/completions", {"model": "grok-4.20-0309-non-reasoning", "messages": MSGS, "max_completion_tokens": 32, "reasoning_effort": "low"}, est_cost_usd=0.0002, note="test_chat reasoning_effort on non-reasoning model")55 assert st == 400 and "reasoningEffort" in json.dumps(body)565758def test_unsupported_params_rejected(xai, models):59 st, body, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": MSGS, "max_completion_tokens": 32, "logit_bias": {"1": 1}}, est_cost_usd=0, note="test_chat logit_bias")60 assert st == 400 and "logit_bias" in json.dumps(body)61 st, body, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": MSGS, "max_completion_tokens": 32, "search_parameters": {"mode": "on"}}, est_cost_usd=0, note="test_chat search_parameters retired")62 assert st == 410 and "deprecated" in json.dumps(body).lower()636465def test_deferred_completion_roundtrip(xai, models):66 st, body, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": MSGS, "max_completion_tokens": 32, "deferred": True}, est_cost_usd=0.0005, note="test_chat deferred start")67 assert st == 200 and set(body) == {"request_id"}68 for _ in range(15):69 st, res, _ = xai("GET", f"/v1/chat/deferred-completion/{body['request_id']}", note="test_chat deferred poll")70 if st == 200:71 break72 assert st == 20273 time.sleep(2)74 assert st == 200 and res["object"] == "chat.completion" and "OK" in res["choices"][0]["message"]["content"]757677def test_legacy_completions_retired(xai, models):78 st, body, _ = xai("POST", "/v1/completions", {"model": models["xai"], "prompt": "1, 2, 3,", "max_tokens": 4}, est_cost_usd=0, note="test_chat legacy completions")79 assert st == 400 and "Raw sampling" in json.dumps(body)808182@pytest.mark.run_expensive_tests83def test_prompt_cache_hit_with_prompt_cache_key(xai, models):84 import uuid85 key = str(uuid.uuid4())86 big = "You are a helpful assistant. " * 12087 cached = []88 for i in range(2):89 st, body, _ = xai("POST", "/v1/chat/completions", {"model": models["xai"], "messages": [{"role": "system", "content": big}] + MSGS, "max_completion_tokens": 32, "prompt_cache_key": key}, extra_headers={"x-grok-conv-id": key}, est_cost_usd=0.001, note=f"test_chat cache turn {i+1}")90 assert st == 20091 cached.append(body["usage"]["prompt_tokens_details"]["cached_tokens"])92 time.sleep(1)93 assert cached[1] >= cached[0]94