Skip to content

Commit f7f5189

Browse files
Merge pull request #973 from Checkmarx/feature/MiryamFoifer/emptyTagsForProjectFilter
Project list command filtered by tag with empty values - project without tag (AST-48293)
2 parents 05632e9 + 00fb8c3 commit f7f5189

File tree

4 files changed

+146
-0
lines changed

4 files changed

+146
-0
lines changed

internal/commands/project.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const (
2929
sshConfKey = "scan.handler.git.sshKey"
3030
mandatoryRepoURLError = "flag --repo-url is mandatory when --ssh-key is provided"
3131
invalidRepoURL = "provided repository url doesn't need a key. Make sure you are defining the right repository or remove the flag --ssh-key"
32+
emptyTag = "NONE"
3233
)
3334

3435
var (
@@ -398,6 +399,8 @@ func runListProjectsCommand(projectsWrapper wrappers.ProjectsWrapper) func(cmd *
398399
return errors.Wrapf(err, "%s", failedGettingAll)
399400
}
400401

402+
supportEmptyTags(params)
403+
401404
allProjectsModel, errorModel, err = projectsWrapper.Get(params)
402405
if err != nil {
403406
return errors.Wrapf(err, "%s\n", failedGettingAll)
@@ -416,6 +419,47 @@ func runListProjectsCommand(projectsWrapper wrappers.ProjectsWrapper) func(cmd *
416419
}
417420
}
418421

422+
func supportEmptyTags(params map[string]string) {
423+
if hasNoneKeyAndValue(params) {
424+
addEmptyTagsParam(params)
425+
}
426+
}
427+
428+
func hasNoneKeyAndValue(params map[string]string) bool {
429+
hasNoneKey := hasNoneValueInAttribute(params, commonParams.TagsKeyQueryParam)
430+
hasNoneValue := hasNoneValueInAttribute(params, commonParams.TagsValueQueryParam)
431+
return hasNoneKey && hasNoneValue
432+
}
433+
434+
func hasNoneValueInAttribute(params map[string]string, attribute string) bool {
435+
values, exists := params[attribute]
436+
return exists && strings.Contains(values, emptyTag)
437+
}
438+
439+
func addEmptyTagsParam(params map[string]string) {
440+
removeNoneKeyAndValue(params)
441+
params[commonParams.TagsEmptyQueryParam] = "true"
442+
}
443+
444+
func removeNoneKeyAndValue(params map[string]string) {
445+
removeNoneAttribute(params, commonParams.TagsKeyQueryParam)
446+
removeNoneAttribute(params, commonParams.TagsValueQueryParam)
447+
}
448+
449+
func removeNoneAttribute(params map[string]string, attribute string) {
450+
values, exists := params[attribute]
451+
if exists {
452+
values = strings.ReplaceAll(values, ","+emptyTag, "")
453+
values = strings.ReplaceAll(values, emptyTag+",", "")
454+
values = strings.ReplaceAll(values, emptyTag, "")
455+
if values == "" {
456+
delete(params, attribute)
457+
} else {
458+
params[attribute] = values
459+
}
460+
}
461+
}
462+
419463
func runGetProjectByIDCommand(projectsWrapper wrappers.ProjectsWrapper) func(cmd *cobra.Command, args []string) error {
420464
return func(cmd *cobra.Command, args []string) error {
421465
var projectResponseModel *wrappers.ProjectResponseModel

internal/commands/project_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package commands
55
import (
66
"testing"
77

8+
asserts "github.com/stretchr/testify/assert"
9+
810
errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors"
911
"github.com/checkmarx/ast-cli/internal/wrappers/mock"
1012
"github.com/checkmarx/ast-cli/internal/wrappers/utils"
@@ -197,3 +199,73 @@ func TestGetProjectByName(t *testing.T) {
197199
assert.Equal(t, result.Name, projectName)
198200
assert.Equal(t, result.ID, "3")
199201
}
202+
203+
func TestSupportEmptyTags_whenTagsFlagsNotExists_shouldNotChangeParams(t *testing.T) {
204+
params := map[string]string{
205+
"limit": "10",
206+
"ids": "1,2,3",
207+
}
208+
209+
supportEmptyTags(params)
210+
211+
assert.Equal(t, params["limit"], "10")
212+
assert.Equal(t, params["ids"], "1,2,3")
213+
assert.Equal(t, len(params), 2)
214+
}
215+
216+
func TestSupportEmptyTags_whenTagsFlagsHasOnlyEmptyValues_shouldAddEmptyTagParamAndRemoveNoneTags(t *testing.T) {
217+
params := map[string]string{
218+
"limit": "10",
219+
"ids": "1,2,3",
220+
"tags-keys": emptyTag,
221+
"tags-values": emptyTag,
222+
}
223+
224+
supportEmptyTags(params)
225+
226+
assert.Equal(t, params["limit"], "10")
227+
assert.Equal(t, params["ids"], "1,2,3")
228+
assert.Equal(t, params["empty-tags"], "true")
229+
_, existsKey := params["tags-keys"]
230+
_, existsValue := params["tags-values"]
231+
asserts.False(t, existsKey, "tags-keys should not exist")
232+
asserts.False(t, existsValue, "tags-values should not exist")
233+
assert.Equal(t, len(params), 3)
234+
}
235+
236+
func TestSupportEmptyTags_whenTagsFlagsHaveAlsoEmptyValues_shouldAddEmptyTagParamAndRemoveNoneTags(t *testing.T) {
237+
params := map[string]string{
238+
"limit": "10",
239+
"ids": "1,2,3",
240+
"tags-keys": "key1,key2," + emptyTag,
241+
"tags-values": emptyTag + ",value1",
242+
}
243+
244+
supportEmptyTags(params)
245+
246+
assert.Equal(t, params["limit"], "10")
247+
assert.Equal(t, params["ids"], "1,2,3")
248+
keys := params["tags-keys"]
249+
values := params["tags-values"]
250+
assert.Equal(t, keys, "key1,key2")
251+
assert.Equal(t, values, "value1")
252+
assert.Equal(t, params["empty-tags"], "true")
253+
assert.Equal(t, len(params), 5)
254+
}
255+
256+
func TestSupportEmptyTags_whenOnlyKeysFlagHasEmptyValue_shouldNotChangeParams(t *testing.T) {
257+
params := map[string]string{
258+
"limit": "10",
259+
"ids": "1,2,3",
260+
"tags-keys": "key1,key2," + emptyTag,
261+
"tags-values": "value1",
262+
}
263+
264+
supportEmptyTags(params)
265+
266+
assert.Equal(t, params["limit"], "10")
267+
assert.Equal(t, params["ids"], "1,2,3")
268+
assert.Equal(t, params["tags-keys"], "key1,key2,"+emptyTag)
269+
assert.Equal(t, params["tags-values"], "value1")
270+
assert.Equal(t, len(params), 4)
271+
}

internal/params/flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ const (
221221
QueryIDQueryParam = "query-id"
222222
TagsKeyQueryParam = "tags-keys"
223223
TagsValueQueryParam = "tags-values"
224+
TagsEmptyQueryParam = "empty-tags"
224225
StatusesQueryParam = "statuses"
225226
StatusQueryParam = "status"
226227
BranchNameQueryParam = "branch-name"

test/integration/project_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ func TestProjectsE2E(t *testing.T) {
5252
assert.Equal(t, len(response), 0, "Total projects should be 0 as the project was deleted")
5353
}
5454

55+
func TestGetProjectByTagsFilter_whenProjectHasNoneTags_shouldReturnProjectWithNoTags(t *testing.T) {
56+
projectID, _ := createProject(t, nil, nil)
57+
defer deleteProject(t, projectID)
58+
59+
projects := listProjectByTagsAndLimit(t, "NONE", "NONE", "5")
60+
fmt.Println("Projects length: ", len(projects))
61+
for _, project := range projects {
62+
assert.Equal(t, len(project.Tags), 0, "Project should have no tags")
63+
}
64+
}
65+
5566
// Assert project contains created tags and groups
5667
func assertTagsAndGroups(t *testing.T, project wrappers.ProjectResponseModel, groups []string) {
5768

@@ -221,6 +232,24 @@ func listProjectByID(t *testing.T, projectID string) []wrappers.ProjectResponseM
221232
return projects
222233
}
223234

235+
func listProjectByTagsAndLimit(t *testing.T, tagsKeys string, tagsValues string, limit string) []wrappers.ProjectResponseModel {
236+
tagsFilter := fmt.Sprintf("%s=%s,%s=%s", params.TagsKeyQueryParam, tagsKeys, params.TagsValueQueryParam, tagsValues)
237+
limitFilter := fmt.Sprintf("%s=%s", params.LimitQueryParam, limit)
238+
fmt.Println("Listing project for filters: ", tagsFilter, ",", limitFilter)
239+
filters := tagsFilter + "," + limitFilter
240+
outputBuffer := executeCmdNilAssertion(
241+
t,
242+
"Getting the project should pass",
243+
"project", "list",
244+
flag(params.FormatFlag), printer.FormatJSON, flag(params.FilterFlag), filters,
245+
)
246+
var projects []wrappers.ProjectResponseModel
247+
_ = unmarshall(t, outputBuffer, &projects, "Reading all projects response JSON should pass")
248+
fmt.Println("Listing project for tags projects length: ", len(projects))
249+
250+
return projects
251+
}
252+
224253
func showProject(t *testing.T, projectID string) wrappers.ProjectResponseModel {
225254
assertRequiredParameter(t, "Failed getting a project: Please provide a project ID", "project", "show")
226255

0 commit comments

Comments
 (0)