Skip to content

Commit d9d6137

Browse files
added tests and fixed log
1 parent b751631 commit d9d6137

File tree

4 files changed

+159
-19
lines changed

4 files changed

+159
-19
lines changed

cmd/init.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ var initCmd = &cobra.Command{
5454

5555
if cliLocalMode {
5656
fmt.Println()
57-
fmt.Println("ℹ️ No project token was specified, skipping fetch configurations")
57+
fmt.Println("ℹ️ No project token was specified, fetching codacy default configurations")
5858
noTools := []tools.Tool{}
5959
err := createConfigurationFiles(noTools, cliLocalMode)
6060
if err != nil {
@@ -555,7 +555,6 @@ func createLizardConfigFile(toolsConfigDir string, patternConfiguration []domain
555555
patterns[i] = pattern.PatternDefinition
556556
}
557557

558-
fmt.Println("Lizard configuration created based on Codacy settings")
559558
}
560559

561560
content, err := lizard.CreateLizardConfig(patterns)
@@ -588,37 +587,30 @@ func buildDefaultConfigurationFiles(toolsConfigDir string) error {
588587
if err != nil {
589588
return fmt.Errorf("failed to write eslint config: %v", err)
590589
}
591-
fmt.Println("ESLint configuration created. Ignoring plugin rules. ESLint plugins are not supported yet.")
592590
case Trivy:
593591
if err := createTrivyConfigFile(patternsConfig, toolsConfigDir); err != nil {
594592
return fmt.Errorf("failed to create default Trivy configuration: %w", err)
595593
}
596-
fmt.Println("Trivy configuration created")
597594
case PMD:
598595
if err := createPMDConfigFile(patternsConfig, toolsConfigDir); err != nil {
599596
return fmt.Errorf("failed to create default PMD configuration: %w", err)
600597
}
601-
fmt.Println("PMD configuration created")
602598
case PyLint:
603599
if err := createPylintConfigFile(patternsConfig, toolsConfigDir); err != nil {
604600
return fmt.Errorf("failed to create default Pylint configuration: %w", err)
605601
}
606-
fmt.Println("Pylint configuration created")
607602
case DartAnalyzer:
608603
if err := createDartAnalyzerConfigFile(patternsConfig, toolsConfigDir); err != nil {
609604
return fmt.Errorf("failed to create default Dart Analyzer configuration: %w", err)
610605
}
611-
fmt.Println("Dart Analyzer configuration created")
612606
case Semgrep:
613607
if err := createSemgrepConfigFile(patternsConfig, toolsConfigDir); err != nil {
614608
return fmt.Errorf("failed to create default Semgrep configuration: %w", err)
615609
}
616-
fmt.Println("Semgrep configuration created")
617610
case Lizard:
618611
if err := createLizardConfigFile(toolsConfigDir, patternsConfig); err != nil {
619612
return fmt.Errorf("failed to create default Lizard configuration: %w", err)
620613
}
621-
fmt.Println("Lizard configuration created")
622614
}
623615
}
624616

@@ -635,6 +627,7 @@ const (
635627
Lizard string = "76348462-84b3-409a-90d3-955e90abfb87"
636628
)
637629

630+
// AvailableTools lists all tool UUIDs supported by Codacy CLI.
638631
var AvailableTools = []string{
639632
ESLint,
640633
Trivy,

cmd/init_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"codacy/cli-v2/config"
45
"codacy/cli-v2/tools"
56
"os"
67
"path/filepath"
@@ -179,3 +180,66 @@ func TestCleanConfigDirectory(t *testing.T) {
179180
assert.NoError(t, err)
180181
assert.Equal(t, 0, len(files), "Expected 0 files after cleaning, got %d", len(files))
181182
}
183+
184+
func TestInitCommand_NoToken(t *testing.T) {
185+
tempDir := t.TempDir()
186+
originalWD, err := os.Getwd()
187+
assert.NoError(t, err, "Failed to get current working directory")
188+
defer os.Chdir(originalWD)
189+
190+
// Use the real plugins/tools/semgrep/rules.yaml file
191+
rulesPath := filepath.Join("plugins", "tools", "semgrep", "rules.yaml")
192+
if _, err := os.Stat(rulesPath); os.IsNotExist(err) {
193+
t.Skip("plugins/tools/semgrep/rules.yaml not found; skipping test")
194+
}
195+
196+
// Change to the temp directory to simulate a new project
197+
err = os.Chdir(tempDir)
198+
assert.NoError(t, err, "Failed to change working directory to tempDir")
199+
200+
// Simulate running init with no token
201+
initFlags.ApiToken = ""
202+
initFlags.Provider = ""
203+
initFlags.Organization = ""
204+
initFlags.Repository = ""
205+
206+
// Call the Run logic from initCmd
207+
if err := config.Config.CreateLocalCodacyDir(); err != nil {
208+
t.Fatalf("Failed to create local codacy directory: %v", err)
209+
}
210+
211+
toolsConfigDir := config.Config.ToolsConfigDirectory()
212+
if err := os.MkdirAll(toolsConfigDir, 0777); err != nil {
213+
t.Fatalf("Failed to create tools-configs directory: %v", err)
214+
}
215+
216+
cliLocalMode := len(initFlags.ApiToken) == 0
217+
if cliLocalMode {
218+
noTools := []tools.Tool{}
219+
err := createConfigurationFiles(noTools, cliLocalMode)
220+
assert.NoError(t, err, "createConfigurationFiles should not return an error")
221+
if err := buildDefaultConfigurationFiles(toolsConfigDir); err != nil {
222+
t.Fatalf("Failed to build default configuration files: %v", err)
223+
}
224+
}
225+
226+
// Assert that the expected config files are created
227+
codacyDir := config.Config.LocalCodacyDirectory()
228+
expectedFiles := []string{
229+
"tools-configs/eslint.config.mjs",
230+
"tools-configs/trivy.yaml",
231+
"tools-configs/ruleset.xml",
232+
"tools-configs/pylint.rc",
233+
"tools-configs/analysis_options.yaml",
234+
"tools-configs/semgrep.yaml",
235+
"tools-configs/lizard.yaml",
236+
"codacy.yaml",
237+
"cli-config.yaml",
238+
}
239+
240+
for _, file := range expectedFiles {
241+
filePath := filepath.Join(codacyDir, file)
242+
_, err := os.Stat(filePath)
243+
assert.NoError(t, err, "Expected config file %s to be created", file)
244+
}
245+
}

codacy-client/client.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ package codacyclient
33
import (
44
"codacy/cli-v2/domain"
55
"encoding/json"
6-
"errors"
76
"fmt"
87
"io"
98
"net/http"
9+
"net/url"
1010
"time"
1111
)
1212

@@ -20,23 +20,21 @@ func getRequest(url string, initFlags domain.InitFlags) ([]byte, error) {
2020

2121
req, err := http.NewRequest("GET", url, nil)
2222
if err != nil {
23-
return nil, err
23+
return nil, fmt.Errorf("failed to create request: %w", err)
2424
}
2525

2626
req.Header.Set("api-token", initFlags.ApiToken)
2727

2828
resp, err := client.Do(req)
2929

3030
if err != nil {
31-
fmt.Printf("Error sending request: %v\n", err)
32-
return nil, err
31+
return nil, fmt.Errorf("error sending request: %w", err)
3332
}
3433

3534
defer resp.Body.Close()
3635

3736
if resp.StatusCode != 200 {
38-
fmt.Println("Error:", url)
39-
return nil, errors.New("Failed in request to " + url)
37+
return nil, fmt.Errorf("request to %s failed with status %d", url, resp.StatusCode)
4038
}
4139

4240
// Read the response body
@@ -66,11 +64,14 @@ func handlePaginationGeneric[T any](
6664
for {
6765
pageURL := baseURL
6866
if !firstRequest && cursor != "" {
69-
if pageURL[len(pageURL)-1] == '?' || pageURL[len(pageURL)-1] == '&' {
70-
pageURL += fmt.Sprintf("cursor=%s", cursor)
71-
} else {
72-
pageURL += fmt.Sprintf("&cursor=%s", cursor)
67+
u, err := url.Parse(pageURL)
68+
if err != nil {
69+
return nil, err
7370
}
71+
q := u.Query()
72+
q.Set("cursor", cursor)
73+
u.RawQuery = q.Encode()
74+
pageURL = u.String()
7475
}
7576
firstRequest = false
7677

codacy-client/client_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package codacyclient
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"codacy/cli-v2/domain"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestGetRequest_Success(t *testing.T) {
15+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
16+
w.WriteHeader(http.StatusOK)
17+
w.Write([]byte(`{"data": "ok"}`))
18+
}))
19+
defer ts.Close()
20+
21+
initFlags := domain.InitFlags{ApiToken: "dummy"}
22+
resp, err := getRequest(ts.URL, initFlags)
23+
assert.NoError(t, err)
24+
assert.Contains(t, string(resp), "ok")
25+
}
26+
27+
func TestGetRequest_Failure(t *testing.T) {
28+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29+
w.WriteHeader(http.StatusInternalServerError)
30+
}))
31+
defer ts.Close()
32+
33+
initFlags := domain.InitFlags{ApiToken: "dummy"}
34+
_, err := getRequest(ts.URL, initFlags)
35+
assert.Error(t, err)
36+
}
37+
38+
func TestHandlePaginationGeneric(t *testing.T) {
39+
type testItem struct{ Value int }
40+
pages := [][]testItem{
41+
{{Value: 1}, {Value: 2}},
42+
{{Value: 3}},
43+
}
44+
calls := 0
45+
fetchPage := func(url string) ([]testItem, string, error) {
46+
if calls < len(pages) {
47+
page := pages[calls]
48+
calls++
49+
if calls < len(pages) {
50+
return page, "next", nil
51+
}
52+
return page, "", nil
53+
}
54+
return nil, "", nil
55+
}
56+
results, err := handlePaginationGeneric[testItem]("base", "", fetchPage)
57+
assert.NoError(t, err)
58+
assert.Len(t, results, 3)
59+
}
60+
61+
func TestGetDefaultToolPatternsConfig_Empty(t *testing.T) {
62+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
63+
resp := map[string]interface{}{
64+
"data": []interface{}{},
65+
"pagination": map[string]interface{}{"cursor": ""},
66+
}
67+
json.NewEncoder(w).Encode(resp)
68+
}))
69+
defer ts.Close()
70+
71+
// TODO: Refactor GetDefaultToolPatternsConfig to accept a baseURL for easier testing
72+
// oldBase := CodacyApiBase
73+
// CodacyApiBase = ts.URL
74+
// defer func() { CodacyApiBase = oldBase }()
75+
76+
// Placeholder: test cannot be run until function is refactored for testability
77+
_ = ts // avoid unused warning
78+
// initFlags := domain.InitFlags{ApiToken: "dummy"}
79+
// patterns, err := GetDefaultToolPatternsConfig(initFlags, "tool-uuid")
80+
// assert.NoError(t, err)
81+
// assert.Empty(t, patterns)
82+
}

0 commit comments

Comments
 (0)