Skip to content

Commit eb1aed8

Browse files
test: add Test_GetIssue_FieldValues_FlagOn to cover the enrichment path
Companion to Test_GetIssue_FieldValues: when remote_mcp_issue_fields is enabled, the GraphQL nodes() round-trip populates the enriched field_values while the raw REST issue_field_values stays cleared. Addresses the Copilot review suggestion on #2558. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 39dfc2f commit eb1aed8

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

pkg/github/issues_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,102 @@ func Test_GetIssue_FieldValues(t *testing.T) {
464464
assert.Empty(t, returnedIssue.FieldValues, "enriched field_values should not be present when flag is off")
465465
}
466466

467+
func Test_GetIssue_FieldValues_FlagOn(t *testing.T) {
468+
// Verify the enriched field_values are populated via GraphQL when the
469+
// remote_mcp_issue_fields flag is on, and the raw REST issue_field_values
470+
// stays cleared.
471+
serverTool := IssueRead(translations.NullTranslationHelper)
472+
473+
mockIssueWithFields := &github.Issue{
474+
Number: github.Ptr(99),
475+
NodeID: github.Ptr("I_node_99"),
476+
Title: github.Ptr("Issue with field values"),
477+
Body: github.Ptr("body"),
478+
State: github.Ptr("open"),
479+
HTMLURL: github.Ptr("https://github.com/owner/repo/issues/99"),
480+
User: &github.User{
481+
Login: github.Ptr("testuser"),
482+
},
483+
IssueFieldValues: []*github.IssueFieldValue{
484+
{
485+
IssueFieldID: 1001,
486+
NodeID: "FV_node_1",
487+
DataType: "single_select",
488+
Value: "High",
489+
},
490+
},
491+
}
492+
493+
restClient := MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
494+
GetReposIssuesByOwnerByRepoByIssueNumber: mockResponse(t, http.StatusOK, mockIssueWithFields),
495+
})
496+
497+
gqlVars := map[string]any{
498+
"ids": []any{"I_node_99"},
499+
}
500+
gqlResponse := githubv4mock.DataResponse(map[string]any{
501+
"nodes": []map[string]any{
502+
{
503+
"id": "I_node_99",
504+
"issueFieldValues": map[string]any{
505+
"nodes": []map[string]any{
506+
{
507+
"__typename": "IssueFieldSingleSelectValue",
508+
"field": map[string]any{"name": "priority"},
509+
"value": "P1",
510+
},
511+
{
512+
"__typename": "IssueFieldNumberValue",
513+
"field": map[string]any{"name": "estimate"},
514+
"valueNumber": 2.5,
515+
},
516+
},
517+
},
518+
},
519+
},
520+
})
521+
522+
const nodesQueryString = "query($ids:[ID!]!){nodes(ids: $ids){... on Issue{id,issueFieldValues(first: 25){nodes{__typename,... on IssueFieldDateValue{field{... on IssueFieldDate{name,fullDatabaseId},... on IssueFieldNumber{name,fullDatabaseId},... on IssueFieldSingleSelect{name,fullDatabaseId},... on IssueFieldText{name,fullDatabaseId}},value},... on IssueFieldNumberValue{field{... on IssueFieldDate{name,fullDatabaseId},... on IssueFieldNumber{name,fullDatabaseId},... on IssueFieldSingleSelect{name,fullDatabaseId},... on IssueFieldText{name,fullDatabaseId}},valueNumber: value},... on IssueFieldSingleSelectValue{field{... on IssueFieldDate{name,fullDatabaseId},... on IssueFieldNumber{name,fullDatabaseId},... on IssueFieldSingleSelect{name,fullDatabaseId},... on IssueFieldText{name,fullDatabaseId}},value},... on IssueFieldTextValue{field{... on IssueFieldDate{name,fullDatabaseId},... on IssueFieldNumber{name,fullDatabaseId},... on IssueFieldSingleSelect{name,fullDatabaseId},... on IssueFieldText{name,fullDatabaseId}},value}}}}}}"
523+
matcher := githubv4mock.NewQueryMatcher(nodesQueryString, gqlVars, gqlResponse)
524+
gqlClient := githubv4.NewClient(githubv4mock.NewMockedHTTPClient(matcher))
525+
526+
cache := stubRepoAccessCache(nil, 15*time.Minute)
527+
deps := BaseDeps{
528+
Client: mustNewGHClient(t, restClient),
529+
GQLClient: gqlClient,
530+
RepoAccessCache: cache,
531+
featureChecker: featureCheckerFor(FeatureFlagIssueFields),
532+
}
533+
handler := serverTool.Handler(deps)
534+
535+
request := createMCPRequest(map[string]any{
536+
"method": "get",
537+
"owner": "owner",
538+
"repo": "repo",
539+
"issue_number": float64(99),
540+
})
541+
result, err := handler(ContextWithDeps(context.Background(), deps), &request)
542+
require.NoError(t, err)
543+
require.NotNil(t, result)
544+
require.False(t, result.IsError, "expected result to not be an error")
545+
546+
textContent := getTextResult(t, result)
547+
548+
var returnedIssue MinimalIssue
549+
err = json.Unmarshal([]byte(textContent.Text), &returnedIssue)
550+
require.NoError(t, err)
551+
552+
// Raw REST IssueFieldValues is always cleared, even when flag is on.
553+
assert.Empty(t, returnedIssue.IssueFieldValues, "raw REST issue_field_values should not be exposed even when flag is on")
554+
555+
// Enriched FieldValues comes from the GraphQL nodes() round-trip.
556+
require.Len(t, returnedIssue.FieldValues, 2, "field_values should be populated from GraphQL when flag is on")
557+
assert.Equal(t, "priority", returnedIssue.FieldValues[0].Field)
558+
assert.Equal(t, "P1", returnedIssue.FieldValues[0].Value)
559+
assert.Equal(t, "estimate", returnedIssue.FieldValues[1].Field)
560+
assert.Equal(t, "2.5", returnedIssue.FieldValues[1].Value)
561+
}
562+
467563
func Test_AddIssueComment(t *testing.T) {
468564
// Verify tool definition once
469565
serverTool := AddIssueComment(translations.NullTranslationHelper)

0 commit comments

Comments
 (0)