Test_IssueWrite_MCPAppsFeature_UIGate verifies the MCP Apps feature UI gate behavior: UI clients get a form message, non-UI clients execute directly.
(t *testing.T)
| 1419 | // Test_IssueWrite_MCPAppsFeature_UIGate verifies the MCP Apps feature UI gate |
| 1420 | // behavior: UI clients get a form message, non-UI clients execute directly. |
| 1421 | func Test_IssueWrite_MCPAppsFeature_UIGate(t *testing.T) { |
| 1422 | t.Parallel() |
| 1423 | |
| 1424 | mockIssue := &github.Issue{ |
| 1425 | Number: github.Ptr(1), |
| 1426 | Title: github.Ptr("Test"), |
| 1427 | HTMLURL: github.Ptr("https://github.com/owner/repo/issues/1"), |
| 1428 | } |
| 1429 | |
| 1430 | serverTool := IssueWrite(translations.NullTranslationHelper) |
| 1431 | |
| 1432 | client := mustNewGHClient(t, MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ |
| 1433 | PostReposIssuesByOwnerByRepo: mockResponse(t, http.StatusCreated, mockIssue), |
| 1434 | })) |
| 1435 | |
| 1436 | deps := BaseDeps{ |
| 1437 | Client: client, |
| 1438 | GQLClient: githubv4.NewClient(nil), |
| 1439 | featureChecker: featureCheckerFor(MCPAppsFeatureFlag), |
| 1440 | } |
| 1441 | handler := serverTool.Handler(deps) |
| 1442 | |
| 1443 | t.Run("UI client without _ui_submitted returns form message", func(t *testing.T) { |
| 1444 | request := createMCPRequestWithSession(t, ClientNameVSCodeInsiders, true, map[string]any{ |
| 1445 | "method": "create", |
| 1446 | "owner": "owner", |
| 1447 | "repo": "repo", |
| 1448 | "title": "Test", |
| 1449 | }) |
| 1450 | result, err := handler(ContextWithDeps(context.Background(), deps), &request) |
| 1451 | require.NoError(t, err) |
| 1452 | |
| 1453 | textContent := getTextResult(t, result) |
| 1454 | assert.Contains(t, textContent.Text, "interactive form has been shown to the user for creating a new issue") |
| 1455 | assert.True(t, result.IsError, "form-routing stub should be marked IsError so agents don't claim success") |
| 1456 | }) |
| 1457 | |
| 1458 | t.Run("UI client with _ui_submitted executes directly", func(t *testing.T) { |
| 1459 | request := createMCPRequestWithSession(t, ClientNameVSCodeInsiders, true, map[string]any{ |
| 1460 | "method": "create", |
| 1461 | "owner": "owner", |
| 1462 | "repo": "repo", |
| 1463 | "title": "Test", |
| 1464 | "_ui_submitted": true, |
| 1465 | }) |
| 1466 | result, err := handler(ContextWithDeps(context.Background(), deps), &request) |
| 1467 | require.NoError(t, err) |
| 1468 | |
| 1469 | textContent := getTextResult(t, result) |
| 1470 | assert.Contains(t, textContent.Text, "https://github.com/owner/repo/issues/1", |
| 1471 | "tool should return the created issue URL") |
| 1472 | }) |
| 1473 | |
| 1474 | t.Run("non-UI client executes directly without _ui_submitted", func(t *testing.T) { |
| 1475 | request := createMCPRequest(map[string]any{ |
| 1476 | "method": "create", |
| 1477 | "owner": "owner", |
| 1478 | "repo": "repo", |
nothing calls this directly
no test coverage detected