Skip to content

Commit 9b41044

Browse files
code review changes applied
1 parent d9d6137 commit 9b41044

File tree

3 files changed

+107
-56
lines changed

3 files changed

+107
-56
lines changed

cmd/init_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cmd
33
import (
44
"codacy/cli-v2/config"
55
"codacy/cli-v2/tools"
6+
"codacy/cli-v2/utils"
67
"os"
78
"path/filepath"
89
"testing"
@@ -162,7 +163,7 @@ func TestCleanConfigDirectory(t *testing.T) {
162163

163164
for _, file := range testFiles {
164165
filePath := filepath.Join(tempDir, file)
165-
err := os.WriteFile(filePath, []byte("test content"), 0644)
166+
err := os.WriteFile(filePath, []byte("test content"), utils.DefaultFilePerms)
166167
assert.NoError(t, err, "Failed to create test file: %s", filePath)
167168
}
168169

@@ -209,7 +210,7 @@ func TestInitCommand_NoToken(t *testing.T) {
209210
}
210211

211212
toolsConfigDir := config.Config.ToolsConfigDirectory()
212-
if err := os.MkdirAll(toolsConfigDir, 0777); err != nil {
213+
if err := os.MkdirAll(toolsConfigDir, utils.DefaultFilePerms); err != nil {
213214
t.Fatalf("Failed to create tools-configs directory: %v", err)
214215
}
215216

codacy-client/client.go

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,32 @@ func getRequest(url string, initFlags domain.InitFlags) ([]byte, error) {
4646
return body, nil
4747
}
4848

49-
// handlePaginationGeneric fetches all paginated results of type T using a provided fetchPage function.
49+
// GetPage fetches a single page of results from the API and returns the data and next cursor
50+
func GetPage[T any](
51+
url string,
52+
initFlags domain.InitFlags,
53+
parser func([]byte) ([]T, string, error),
54+
) ([]T, string, error) {
55+
response, err := getRequest(url, initFlags)
56+
if err != nil {
57+
return nil, "", fmt.Errorf("failed to get page: %w", err)
58+
}
59+
return parser(response)
60+
}
61+
62+
// getAllPages fetches all pages of results from a paginated API endpoint
5063
// - baseURL: the base URL for the paginated API
51-
// - initialCursor: the initial cursor (empty string for first page)
52-
// - fetchPage: a function that fetches a page and returns ([]T, nextCursor, error)
64+
// - initFlags: the API token and other flags for authentication
65+
// - parser: a function that parses the response body into the desired type and returns ([]T, nextCursor, error)
5366
//
5467
// Returns a slice of all results of type T and any error encountered.
55-
func handlePaginationGeneric[T any](
68+
func getAllPages[T any](
5669
baseURL string,
57-
initialCursor string,
58-
fetchPage func(url string) ([]T, string, error),
70+
initFlags domain.InitFlags,
71+
parser func([]byte) ([]T, string, error),
5972
) ([]T, error) {
6073
var allResults []T
61-
cursor := initialCursor
74+
cursor := ""
6275
firstRequest := true
6376

6477
for {
@@ -75,7 +88,7 @@ func handlePaginationGeneric[T any](
7588
}
7689
firstRequest = false
7790

78-
results, nextCursor, err := fetchPage(pageURL)
91+
results, nextCursor, err := GetPage[T](pageURL, initFlags, parser)
7992
if err != nil {
8093
return nil, err
8194
}
@@ -90,43 +103,48 @@ func handlePaginationGeneric[T any](
90103
return allResults, nil
91104
}
92105

93-
func GetDefaultToolPatternsConfig(initFlags domain.InitFlags, toolUUID string) ([]domain.PatternConfiguration, error) {
94-
baseURL := fmt.Sprintf("%s/api/v3/tools/%s/patterns?enabled=true", CodacyApiBase, toolUUID)
95-
96-
fetchPage := func(url string) ([]domain.PatternConfiguration, string, error) {
97-
response, err := getRequest(url, initFlags)
98-
if err != nil {
99-
return nil, "", fmt.Errorf("failed to get patterns page: %w", err)
100-
}
106+
// parsePatternConfigurations parses the response body into pattern configurations
107+
func parsePatternConfigurations(response []byte) ([]domain.PatternConfiguration, string, error) {
108+
var objmap map[string]json.RawMessage
109+
if err := json.Unmarshal(response, &objmap); err != nil {
110+
return nil, "", fmt.Errorf("failed to unmarshal response: %w", err)
111+
}
101112

102-
var objmap map[string]json.RawMessage
103-
if err := json.Unmarshal(response, &objmap); err != nil {
104-
return nil, "", fmt.Errorf("failed to unmarshal response: %w", err)
105-
}
113+
var patterns []domain.PatternDefinition
114+
if err := json.Unmarshal(objmap["data"], &patterns); err != nil {
115+
return nil, "", fmt.Errorf("failed to unmarshal patterns: %w", err)
116+
}
106117

107-
var patterns []domain.PatternDefinition
108-
if err := json.Unmarshal(objmap["data"], &patterns); err != nil {
109-
return nil, "", fmt.Errorf("failed to unmarshal patterns: %w", err)
118+
patternConfigurations := make([]domain.PatternConfiguration, len(patterns))
119+
for i, pattern := range patterns {
120+
patternConfigurations[i] = domain.PatternConfiguration{
121+
PatternDefinition: pattern,
122+
Parameters: pattern.Parameters,
123+
Enabled: pattern.Enabled,
110124
}
125+
}
111126

112-
patternConfigurations := make([]domain.PatternConfiguration, len(patterns))
113-
for i, pattern := range patterns {
114-
patternConfigurations[i] = domain.PatternConfiguration{
115-
PatternDefinition: pattern,
116-
Parameters: pattern.Parameters,
117-
Enabled: pattern.Enabled,
118-
}
127+
var pagination domain.Pagination
128+
if objmap["pagination"] != nil {
129+
if err := json.Unmarshal(objmap["pagination"], &pagination); err != nil {
130+
return nil, "", fmt.Errorf("failed to unmarshal pagination: %w", err)
119131
}
132+
}
120133

121-
var pagination domain.Pagination
122-
if objmap["pagination"] != nil {
123-
if err := json.Unmarshal(objmap["pagination"], &pagination); err != nil {
124-
return nil, "", fmt.Errorf("failed to unmarshal pagination: %w", err)
125-
}
126-
}
134+
return patternConfigurations, pagination.Cursor, nil
135+
}
127136

128-
return patternConfigurations, pagination.Cursor, nil
129-
}
137+
func GetDefaultToolPatternsConfig(initFlags domain.InitFlags, toolUUID string) ([]domain.PatternConfiguration, error) {
138+
baseURL := fmt.Sprintf("%s/api/v3/tools/%s/patterns?enabled=true", CodacyApiBase, toolUUID)
139+
return getAllPages(baseURL, initFlags, parsePatternConfigurations)
140+
}
130141

131-
return handlePaginationGeneric(baseURL, "", fetchPage)
142+
func GetRepositoryToolPatterns(initFlags domain.InitFlags, toolUUID string) ([]domain.PatternConfiguration, error) {
143+
baseURL := fmt.Sprintf("%s/api/v3/analysis/organizations/%s/%s/repositories/%s/tools/%s/patterns?enabled=true",
144+
CodacyApiBase,
145+
initFlags.Provider,
146+
initFlags.Organization,
147+
initFlags.Repository,
148+
toolUUID)
149+
return getAllPages(baseURL, initFlags, parsePatternConfigurations)
132150
}

codacy-client/client_test.go

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,59 @@ func TestGetRequest_Failure(t *testing.T) {
3535
assert.Error(t, err)
3636
}
3737

38-
func TestHandlePaginationGeneric(t *testing.T) {
38+
func TestGetPageAndGetAllPages(t *testing.T) {
3939
type testItem struct{ Value int }
40-
pages := [][]testItem{
41-
{{Value: 1}, {Value: 2}},
42-
{{Value: 3}},
40+
serverPages := []struct {
41+
data []testItem
42+
cursor string
43+
}{
44+
{[]testItem{{Value: 1}, {Value: 2}}, "next"},
45+
{[]testItem{{Value: 3}}, ""},
4346
}
4447
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
48+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
49+
w.WriteHeader(http.StatusOK)
50+
resp := map[string]interface{}{
51+
"data": serverPages[calls].data,
52+
"pagination": map[string]interface{}{"cursor": serverPages[calls].cursor},
53+
}
54+
calls++
55+
json.NewEncoder(w).Encode(resp)
56+
}))
57+
defer ts.Close()
58+
59+
initFlags := domain.InitFlags{ApiToken: "dummy"}
60+
61+
parser := func(body []byte) ([]testItem, string, error) {
62+
var objmap map[string]json.RawMessage
63+
if err := json.Unmarshal(body, &objmap); err != nil {
64+
return nil, "", err
65+
}
66+
var items []testItem
67+
if err := json.Unmarshal(objmap["data"], &items); err != nil {
68+
return nil, "", err
69+
}
70+
var pagination struct {
71+
Cursor string `json:"cursor"`
5372
}
54-
return nil, "", nil
73+
if objmap["pagination"] != nil {
74+
_ = json.Unmarshal(objmap["pagination"], &pagination)
75+
}
76+
return items, pagination.Cursor, nil
5577
}
56-
results, err := handlePaginationGeneric[testItem]("base", "", fetchPage)
78+
79+
// Test GetPage
80+
calls = 0
81+
items, cursor, err := GetPage[testItem](ts.URL, initFlags, parser)
82+
assert.NoError(t, err)
83+
assert.Len(t, items, 2)
84+
assert.Equal(t, "next", cursor)
85+
86+
// Test getAllPages
87+
calls = 0
88+
allItems, err := getAllPages[testItem](ts.URL, initFlags, parser)
5789
assert.NoError(t, err)
58-
assert.Len(t, results, 3)
90+
assert.Len(t, allItems, 3)
5991
}
6092

6193
func TestGetDefaultToolPatternsConfig_Empty(t *testing.T) {

0 commit comments

Comments
 (0)