-
Notifications
You must be signed in to change notification settings - Fork 383
Daily Test Coverage Improver - Add unit tests for pkg/cli/jq.go #3681
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,123 @@ | ||||||||||||
| //go:build integration | ||||||||||||
|
|
||||||||||||
| package cli | ||||||||||||
|
|
||||||||||||
| import ( | ||||||||||||
| "context" | ||||||||||||
| "os" | ||||||||||||
| "os/exec" | ||||||||||||
| "path/filepath" | ||||||||||||
| "testing" | ||||||||||||
| "time" | ||||||||||||
|
|
||||||||||||
| "github.com/modelcontextprotocol/go-sdk/mcp" | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| // TestMCPServer_StatusToolWithJq tests the status tool with jq filter parameter | ||||||||||||
| func TestMCPServer_StatusToolWithJq(t *testing.T) { | ||||||||||||
| // Skip if jq is not available | ||||||||||||
| if _, err := exec.LookPath("jq"); err != nil { | ||||||||||||
| t.Skip("Skipping test: jq not found in PATH") | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Skip if the binary doesn't exist | ||||||||||||
| binaryPath := "../../gh-aw" | ||||||||||||
| if _, err := os.Stat(binaryPath); os.IsNotExist(err) { | ||||||||||||
| t.Skip("Skipping test: gh-aw binary not found. Run 'make build' first.") | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Create a temporary directory with a workflow file | ||||||||||||
| tmpDir := t.TempDir() | ||||||||||||
| workflowsDir := filepath.Join(tmpDir, ".github", "workflows") | ||||||||||||
| if err := os.MkdirAll(workflowsDir, 0755); err != nil { | ||||||||||||
| t.Fatalf("Failed to create workflows directory: %v", err) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Create a test workflow file | ||||||||||||
| workflowContent := `--- | ||||||||||||
| on: push | ||||||||||||
| engine: copilot | ||||||||||||
| --- | ||||||||||||
| # Test Workflow | ||||||||||||
| ` | ||||||||||||
| workflowFile := filepath.Join(workflowsDir, "test.md") | ||||||||||||
| if err := os.WriteFile(workflowFile, []byte(workflowContent), 0644); err != nil { | ||||||||||||
| t.Fatalf("Failed to write workflow file: %v", err) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Save current directory and change to temp directory | ||||||||||||
| originalDir, _ := os.Getwd() | ||||||||||||
| defer os.Chdir(originalDir) | ||||||||||||
|
|
||||||||||||
| // Initialize git repository in the temp directory | ||||||||||||
| initCmd := exec.Command("git", "init") | ||||||||||||
| initCmd.Dir = tmpDir | ||||||||||||
| if err := initCmd.Run(); err != nil { | ||||||||||||
| t.Fatalf("Failed to initialize git repository: %v", err) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Create MCP client | ||||||||||||
| client := mcp.NewClient(&mcp.Implementation{ | ||||||||||||
| Name: "test-client", | ||||||||||||
| Version: "1.0.0", | ||||||||||||
| }, nil) | ||||||||||||
|
|
||||||||||||
| // Start the MCP server as a subprocess | ||||||||||||
| serverCmd := exec.Command(filepath.Join(originalDir, binaryPath), "mcp-server") | ||||||||||||
| serverCmd.Dir = tmpDir | ||||||||||||
| transport := &mcp.CommandTransport{Command: serverCmd} | ||||||||||||
|
|
||||||||||||
| ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||||||||||||
| defer cancel() | ||||||||||||
|
|
||||||||||||
| session, err := client.Connect(ctx, transport, nil) | ||||||||||||
| if err != nil { | ||||||||||||
| t.Fatalf("Failed to connect to MCP server: %v", err) | ||||||||||||
| } | ||||||||||||
| defer session.Close() | ||||||||||||
|
|
||||||||||||
| // Test 1: Call status tool with jq filter to get just workflow names | ||||||||||||
| params := &mcp.CallToolParams{ | ||||||||||||
| Name: "status", | ||||||||||||
| Arguments: map[string]any{ | ||||||||||||
| "jq": ".[].workflow", | ||||||||||||
| }, | ||||||||||||
| } | ||||||||||||
| result, err := session.CallTool(ctx, params) | ||||||||||||
| if err != nil { | ||||||||||||
| t.Fatalf("Failed to call status tool with jq filter: %v", err) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Verify result contains the workflow name | ||||||||||||
| if textContent, ok := result.Content[0].(*mcp.TextContent); ok { | ||||||||||||
|
||||||||||||
| if textContent.Text == "" { | ||||||||||||
| t.Error("Expected non-empty text content from status tool with jq filter") | ||||||||||||
| } | ||||||||||||
| // The output should contain "test" (the workflow name) | ||||||||||||
| t.Logf("Status tool output with jq filter: %s", textContent.Text) | ||||||||||||
| } else { | ||||||||||||
| t.Error("Expected text content from status tool with jq filter") | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Test 2: Call status tool with jq filter to count workflows | ||||||||||||
| params = &mcp.CallToolParams{ | ||||||||||||
| Name: "status", | ||||||||||||
| Arguments: map[string]any{ | ||||||||||||
| "jq": "length", | ||||||||||||
| }, | ||||||||||||
| } | ||||||||||||
| result, err = session.CallTool(ctx, params) | ||||||||||||
| if err != nil { | ||||||||||||
| t.Fatalf("Failed to call status tool with jq count filter: %v", err) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Verify result contains a number | ||||||||||||
|
||||||||||||
| // Verify result contains a number | |
| // Verify result contains a number | |
| if len(result.Content) == 0 { | |
| t.Fatal("Expected content in result, but got empty content") | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,16 +1,9 @@ | ||||||||||
| //go:build integration | ||||||||||
|
|
||||||||||
| package cli | ||||||||||
|
|
||||||||||
| import ( | ||||||||||
| "context" | ||||||||||
| "os" | ||||||||||
| "os/exec" | ||||||||||
| "path/filepath" | ||||||||||
| "strings" | ||||||||||
| "testing" | ||||||||||
| "time" | ||||||||||
|
|
||||||||||
| "github.com/modelcontextprotocol/go-sdk/mcp" | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| func TestApplyJqFilter(t *testing.T) { | ||||||||||
|
|
@@ -26,6 +19,18 @@ func TestApplyJqFilter(t *testing.T) { | |||||||||
| wantErr bool | ||||||||||
| validate func(t *testing.T, output string) | ||||||||||
| }{ | ||||||||||
| { | ||||||||||
| name: "simple filter - identity", | ||||||||||
| jsonInput: `{"name":"test"}`, | ||||||||||
| jqFilter: ".", | ||||||||||
| wantErr: false, | ||||||||||
| validate: func(t *testing.T, output string) { | ||||||||||
| output = strings.TrimSpace(output) | ||||||||||
| if !strings.Contains(output, "test") { | ||||||||||
| t.Errorf("Expected output to contain 'test', got %q", output) | ||||||||||
| } | ||||||||||
| }, | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| name: "simple filter - get first element", | ||||||||||
| jsonInput: `[{"name":"a"},{"name":"b"}]`, | ||||||||||
|
|
@@ -59,6 +64,41 @@ func TestApplyJqFilter(t *testing.T) { | |||||||||
| } | ||||||||||
| }, | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| name: "filter - extract specific field", | ||||||||||
| jsonInput: `{"name":"value","id":123}`, | ||||||||||
| jqFilter: ".name", | ||||||||||
| wantErr: false, | ||||||||||
| validate: func(t *testing.T, output string) { | ||||||||||
| output = strings.TrimSpace(output) | ||||||||||
| if !strings.Contains(output, "value") { | ||||||||||
| t.Errorf("Expected output to contain 'value', got %q", output) | ||||||||||
| } | ||||||||||
| }, | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| name: "filter - empty input", | ||||||||||
| jsonInput: `{}`, | ||||||||||
| jqFilter: ".", | ||||||||||
| wantErr: false, | ||||||||||
| validate: func(t *testing.T, output string) { | ||||||||||
| output = strings.TrimSpace(output) | ||||||||||
| if output != "{}" { | ||||||||||
| t.Errorf("Expected '{}', got %q", output) | ||||||||||
| } | ||||||||||
| }, | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| name: "filter - array transformation", | ||||||||||
| jsonInput: `[1,2,3]`, | ||||||||||
| jqFilter: "map(. * 2)", | ||||||||||
| wantErr: false, | ||||||||||
| validate: func(t *testing.T, output string) { | ||||||||||
| if !strings.Contains(output, "2") && !strings.Contains(output, "4") && !strings.Contains(output, "6") { | ||||||||||
| t.Error("Expected transformed array output") | ||||||||||
|
Comment on lines
+97
to
+98
|
||||||||||
| if !strings.Contains(output, "2") && !strings.Contains(output, "4") && !strings.Contains(output, "6") { | |
| t.Error("Expected transformed array output") | |
| if !strings.Contains(output, "2") || !strings.Contains(output, "4") || !strings.Contains(output, "6") { | |
| t.Error("Expected transformed array output containing 2, 4, and 6") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error from
os.Getwd()is being silently ignored using the blank identifier_. Ifos.Getwd()fails,originalDirwill be an empty string, and the deferredos.Chdir(originalDir)call will fail to restore the working directory, potentially affecting other tests.Consider handling the error: