@@ -16,13 +16,10 @@ import (
1616 "github.com/stretchr/testify/require"
1717)
1818
19- // Test_IssueRequest_EmptyFieldValues_OmittedByJSON pins the omitempty behaviour
20- // that motivates the DELETE-endpoint fallback in UpdateIssue. If go-github's
21- // IssueRequest ever drops the `omitempty` tag from `issue_field_values`, this
22- // test will fail — at which point the fallback could potentially be revisited.
23- // Until then, an empty `[]*IssueRequestFieldValue{}` is serialised as nothing
24- // at all, so the REST PATCH alone can never clear a field's last value via
25- // the set-semantics path.
19+ // Test_IssueRequest_EmptyFieldValues_OmittedByJSON pins the omitempty
20+ // behaviour that makes the DELETE fallback necessary. If go-github ever drops
21+ // the tag, the REST PATCH alone could clear field values and this test would
22+ // fail to remind us.
2623func Test_IssueRequest_EmptyFieldValues_OmittedByJSON (t * testing.T ) {
2724 t .Parallel ()
2825
@@ -39,19 +36,10 @@ func Test_IssueRequest_EmptyFieldValues_OmittedByJSON(t *testing.T) {
3936 "sanity check: other fields still serialise" )
4037}
4138
42- // Test_UpdateIssue_DeleteLastFieldValueCallsDeleteEndpoint: regression test for
43- // the delete:true bug. When the kept set after merge + filter ends up empty
44- // (e.g. deleting the only remaining field value), the PATCH alone cannot carry
45- // the deletion intent because go-github strips the empty issue_field_values
46- // slice via omitempty. UpdateIssue follows up with a per-field DELETE to the
47- // dedicated `/repos/{owner}/{repo}/issues/{number}/issue-field-values/{id}`
48- // endpoint.
49- //
50- // Asserts both halves:
51- //
52- // - the PATCH body does NOT carry an `issue_field_values` key (we don't want
53- // to double-clear or rely on a value omitempty is about to strip)
54- // - a DELETE for the field ID fires after the PATCH
39+ // Test_UpdateIssue_DeleteLastFieldValueCallsDeleteEndpoint covers the bug fix:
40+ // when the kept set ends up empty, the PATCH alone can't clear the field
41+ // (omitempty strips the empty slice), so UpdateIssue follows up with a DELETE
42+ // to the dedicated endpoint.
5543func Test_UpdateIssue_DeleteLastFieldValueCallsDeleteEndpoint (t * testing.T ) {
5644 t .Parallel ()
5745
@@ -86,9 +74,8 @@ func Test_UpdateIssue_DeleteLastFieldValueCallsDeleteEndpoint(t *testing.T) {
8674 },
8775 }))
8876
89- // Existing field values for the merge step. Returning only the field about
90- // to be deleted is the worst case: the kept list ends up empty and the
91- // fallback DELETE is the only thing that can clear it.
77+ // Existing field values for the merge step. Returning the field we're
78+ // about to delete makes the kept list empty, triggering the fallback DELETE.
9279 existingFieldsResponse := githubv4mock .DataResponse (map [string ]any {
9380 "repository" : map [string ]any {
9481 "issue" : map [string ]any {
@@ -151,10 +138,9 @@ func Test_UpdateIssue_DeleteLastFieldValueCallsDeleteEndpoint(t *testing.T) {
151138 "expected exactly one DELETE call to the dedicated endpoint for field id 101" )
152139}
153140
154- // Test_UpdateIssue_DeleteOneOfManyUsesSetSemantics verifies that when the kept
155- // set after merge + filter is non-empty (deleting 1 of N existing fields), the
156- // PATCH carries the kept fields and the dotcom REST handler's set semantics do
157- // the deletion implicitly — no fallback DELETE call is needed.
141+ // Test_UpdateIssue_DeleteOneOfManyUsesSetSemantics: when the kept set is
142+ // non-empty, set semantics handle the deletion implicitly via the PATCH — no
143+ // DELETE follow-up needed.
158144func Test_UpdateIssue_DeleteOneOfManyUsesSetSemantics (t * testing.T ) {
159145 t .Parallel ()
160146
@@ -248,12 +234,10 @@ func Test_UpdateIssue_DeleteOneOfManyUsesSetSemantics(t *testing.T) {
248234 "no DELETE call should fire when the kept set is non-empty — the PATCH's set semantics clear the deleted field on the server side" )
249235}
250236
251- // Test_UpdateIssue_DeleteAbsentFieldIsNoOp verifies that asking to delete a
252- // field that isn't currently set on the issue does not fire a DELETE request
253- // to the dedicated endpoint (which would 404). This preserves the pre-fix
254- // behaviour of treating "delete a field that isn't set" as a silent no-op —
255- // important because callers often use delete:true idempotently ("ensure
256- // field X is cleared"), and the second invocation should succeed not error.
237+ // Test_UpdateIssue_DeleteAbsentFieldIsNoOp: deleting a field that isn't set
238+ // must not fire a DELETE (the endpoint would 404), preserving the pre-fix
239+ // silent-no-op behaviour so idempotent delete:true callers don't break on
240+ // retry.
257241func Test_UpdateIssue_DeleteAbsentFieldIsNoOp (t * testing.T ) {
258242 t .Parallel ()
259243
@@ -343,11 +327,9 @@ func Test_UpdateIssue_DeleteAbsentFieldIsNoOp(t *testing.T) {
343327 "no DELETE call should fire for a field that isn't present on the issue — preserves the pre-fix silent-no-op behaviour and avoids a guaranteed 404" )
344328}
345329
346- // Test_UpdateIssue_DeleteFallbackContinuesOnPartialFailure verifies that when
347- // one DELETE in the fallback loop fails, the remaining DELETEs still fire and
348- // the aggregated error names the failed and succeeded field IDs. The pre-fix
349- // loop short-circuited on the first failure, which left the caller blind to
350- // which deletions had landed.
330+ // Test_UpdateIssue_DeleteFallbackContinuesOnPartialFailure: a failing DELETE
331+ // must not short-circuit subsequent ones, and the error must name which IDs
332+ // succeeded and which failed so callers can retry the right ones.
351333func Test_UpdateIssue_DeleteFallbackContinuesOnPartialFailure (t * testing.T ) {
352334 t .Parallel ()
353335
@@ -373,10 +355,8 @@ func Test_UpdateIssue_DeleteFallbackContinuesOnPartialFailure(t *testing.T) {
373355 mu .Lock ()
374356 deletePaths = append (deletePaths , r .URL .Path )
375357 mu .Unlock ()
376- // Field 202 returns 500; fields 101 and 303 succeed. We expect
377- // all three calls to fire even though the middle one errors, and
378- // the final tool result must mention 202 as failed and 101/303
379- // as cleared.
358+ // Field 202 fails; 101 and 303 succeed. All three should fire and
359+ // the error must name 202 as failed and 101/303 as cleared.
380360 if strings .HasSuffix (r .URL .Path , "/202" ) {
381361 w .WriteHeader (http .StatusInternalServerError )
382362 _ , _ = w .Write ([]byte (`{"message":"simulated failure"}` ))
0 commit comments