Skip to content

Commit 227ffd6

Browse files
committed
test(branches): fix live environment-list cases for dev11 (DX-31568)
The live cases added for publish_config.environments failed on dev11: generate_valid_uid("branch_env") gives 16 characters (the API caps branch uids at 15), and a fetch of a branch that does not exist returns 422 (error_code 905), not 404. Use a shorter prefix and compare a rejected create's fetch with the response for a nonexistent branch (TC-16/TC-17). Also, per the test cases page: create three class environments so two is a strict subset (TC-13), add the one-name, no-list (TC-15) and case-variant cases, and delete every branch and environment created. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XifDUYYvn7GfSpLcKarg5S
1 parent 12f76cf commit 227ffd6

1 file changed

Lines changed: 95 additions & 38 deletions

File tree

‎tests/integration/api/test_18_branch.py‎

Lines changed: 95 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,35 @@ def test_delete(self, stack, store):
5959
h.wait(h.SHORT_DELAY)
6060

6161

62-
def _environment_names(stack):
63-
resp = stack.environments().find()
64-
h.assert_status(resp, 200)
65-
return [env["name"] for env in h.body(resp).get("environments", [])]
62+
def _create_branch(stack, uid, environments=None):
63+
branch = {"uid": uid, "source": "main"}
64+
if environments is not None:
65+
branch["publish_config"] = {"environments": environments}
66+
return stack.branch().create({"branch": branch})
6667

6768

68-
def _create_with_environments(stack, uid, environments):
69-
data = {"branch": {"uid": uid, "source": "main", "publish_config": {"environments": environments}}}
70-
return stack.branch().create(data)
69+
def _branch(response):
70+
return h.body(response).get("branch", {})
7171

7272

7373
def _branch_environments(response):
74-
return h.body(response).get("branch", {}).get("publish_config", {}).get("environments")
74+
return (_branch(response).get("publish_config") or {}).get("environments")
75+
76+
77+
def _fetch_when_ready(stack, uid):
78+
# Branch provisioning is async: poll until the fetch succeeds
79+
resp = None
80+
for _ in range(10):
81+
resp = stack.branch(uid).fetch()
82+
if resp.status_code == 200:
83+
return resp
84+
h.wait(h.SHORT_DELAY)
85+
return resp
7586

7687

7788
def _delete_created_branch(stack, uid):
7889
# Same retry as TestBranchDelete: a freshly created branch can briefly be "not valid" (422, code 905).
90+
resp = None
7991
for _ in range(4):
8092
branch = stack.branch(uid)
8193
branch.add_param("force", "true")
@@ -86,54 +98,99 @@ def _delete_created_branch(stack, uid):
8698
raise AssertionError(f"branch {uid} was not deleted after retries; status {resp.status_code}")
8799

88100

101+
def _not_found(response):
102+
return response.status_code, h.body(response).get("error_code")
103+
104+
105+
@pytest.fixture(scope="class")
106+
def env_names(stack):
107+
"""Three environments of this class, so a list of two is a strict subset; deleted after."""
108+
names = [h.generate_valid_uid("bev") for _ in range(3)]
109+
for name in names:
110+
data = {"environment": {"name": name, "urls": [{"url": "https://example.com", "locale": "en-us"}]}}
111+
h.assert_status(stack.environments().create(data), 201)
112+
yield names
113+
for name in names:
114+
stack.environments(name).delete()
115+
116+
117+
@pytest.fixture(scope="class")
118+
def nonexistent(stack):
119+
"""The response for a branch that does not exist (dev11: 422, error_code 905)."""
120+
resp = stack.branch(h.generate_valid_uid("nob")).fetch()
121+
assert resp.status_code != 200
122+
return _not_found(resp)
123+
124+
89125
class TestBranchEnvironmentList:
90126
"""Branch create with publish_config.environments. Each test deletes its branch (stack branch cap)."""
91127

92-
def test_create_two_names_clones_only_those(self, stack):
93-
names = _environment_names(stack)
94-
if len(names) < 2:
95-
pytest.skip("stack has fewer than two environments")
96-
wanted = names[:2]
97-
uid = h.generate_valid_uid("branch_env")
98-
resp = _create_with_environments(stack, uid, wanted)
128+
def test_create_two_names_clones_only_those(self, stack, env_names):
129+
wanted = env_names[:2]
130+
uid = h.generate_valid_uid("bev")
131+
resp = _create_branch(stack, uid, wanted)
99132
try:
100133
h.assert_status(resp, 201)
101-
assert _branch_environments(resp) == wanted
102-
h.wait(h.LONG_DELAY)
103-
fetched = stack.branch(uid).fetch()
134+
assert sorted(_branch_environments(resp)) == sorted(wanted)
135+
fetched = _fetch_when_ready(stack, uid)
136+
h.assert_status(fetched, 200)
137+
assert sorted(_branch_environments(fetched)) == sorted(wanted)
138+
assert env_names[2] not in _branch_environments(fetched)
139+
finally:
140+
if resp.status_code == 201:
141+
_delete_created_branch(stack, uid)
142+
143+
def test_create_one_name_reads_back_that_one(self, stack, env_names):
144+
uid = h.generate_valid_uid("bev")
145+
resp = _create_branch(stack, uid, env_names[:1])
146+
try:
147+
h.assert_status(resp, 201)
148+
fetched = _fetch_when_ready(stack, uid)
104149
h.assert_status(fetched, 200)
105-
assert _branch_environments(fetched) == wanted
150+
assert _branch_environments(fetched) == env_names[:1]
106151
finally:
107152
if resp.status_code == 201:
108153
_delete_created_branch(stack, uid)
109154

110-
def test_create_empty_list_clones_none(self, stack):
111-
uid = h.generate_valid_uid("branch_env")
112-
resp = _create_with_environments(stack, uid, [])
155+
def test_create_empty_list_clones_none(self, stack, env_names):
156+
uid = h.generate_valid_uid("bev")
157+
resp = _create_branch(stack, uid, [])
113158
try:
114159
h.assert_status(resp, 201)
115160
assert _branch_environments(resp) == []
116-
h.wait(h.LONG_DELAY)
117-
fetched = stack.branch(uid).fetch()
161+
fetched = _fetch_when_ready(stack, uid)
118162
h.assert_status(fetched, 200)
163+
assert "publish_config" in _branch(fetched)
119164
assert _branch_environments(fetched) == []
120165
finally:
121166
if resp.status_code == 201:
122167
_delete_created_branch(stack, uid)
123168

124-
def test_unknown_name_returns_422_and_creates_no_branch(self, stack):
125-
uid = h.generate_valid_uid("branch_env")
126-
resp = _create_with_environments(stack, uid, ["no_such_env_for_integration"])
127-
h.assert_status(resp, 422)
128-
assert "publish_config.environments" in h.body(resp).get("errors", {})
129-
h.assert_status(stack.branch(uid).fetch(), 404)
130-
131-
def test_mix_of_valid_and_unknown_names_returns_422_and_creates_no_branch(self, stack):
132-
names = _environment_names(stack)
133-
if not names:
134-
pytest.skip("stack has no environments")
135-
uid = h.generate_valid_uid("branch_env")
136-
resp = _create_with_environments(stack, uid, [names[0], "no_such_env_for_integration"])
169+
def test_create_without_list_reads_back_no_publish_config(self, stack, env_names):
170+
uid = h.generate_valid_uid("bev")
171+
resp = _create_branch(stack, uid)
172+
try:
173+
h.assert_status(resp, 201)
174+
fetched = _fetch_when_ready(stack, uid)
175+
h.assert_status(fetched, 200)
176+
assert "publish_config" not in _branch(fetched)
177+
finally:
178+
if resp.status_code == 201:
179+
_delete_created_branch(stack, uid)
180+
181+
@pytest.mark.parametrize("case", ["unknown", "other_case", "mix"])
182+
def test_rejected_names_return_422_and_create_no_branch(self, stack, env_names, nonexistent, case):
183+
environments = {
184+
"unknown": [h.generate_valid_uid("nos")],
185+
"other_case": [env_names[0].upper()],
186+
"mix": [env_names[0], h.generate_valid_uid("nos")],
187+
}[case]
188+
uid = h.generate_valid_uid("bev")
189+
resp = _create_branch(stack, uid, environments)
190+
fetched = stack.branch(uid).fetch()
191+
if fetched.status_code == 200:
192+
_delete_created_branch(stack, uid)
137193
h.assert_status(resp, 422)
194+
assert h.body(resp).get("error_message")
138195
assert "publish_config.environments" in h.body(resp).get("errors", {})
139-
h.assert_status(stack.branch(uid).fetch(), 404)
196+
assert _not_found(fetched) == nonexistent, "a rejected create must leave no branch behind"

0 commit comments

Comments
 (0)