Skip to content

Commit

Permalink
refactor: format expiration date for the ignored details panel [IDE-4…
Browse files Browse the repository at this point in the history
…89] (#581)
  • Loading branch information
Cata authored Jul 11, 2024
1 parent b61e6b8 commit 1958e00
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 13 deletions.
22 changes: 21 additions & 1 deletion infrastructure/code/code_html.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func getLineToIgnoreAction(issue snyk.Issue) int {
func prepareIgnoreDetailsRow(ignoreDetails *snyk.IgnoreDetails) []IgnoreDetail {
return []IgnoreDetail{
{"Category", parseCategory(ignoreDetails.Category)},
{"Expiration", ignoreDetails.Expiration},
{"Expiration", formatExpirationDate(ignoreDetails.Expiration)},
{"Ignored On", formatDate(ignoreDetails.IgnoredOn)},
{"Ignored By", ignoreDetails.IgnoredBy},
{"Reason", ignoreDetails.Reason},
Expand Down Expand Up @@ -246,6 +246,26 @@ func getRepoName(commitURL string) string {
return tabTitle
}

func formatExpirationDate(expiration string) string {
if expiration == "" {
return "No expiration"
}
parsedDate, err := time.Parse(time.RFC3339, expiration)
if err != nil {
return expiration // Original string if parsing fails
}

// Calculate the difference in days
daysRemaining := int(time.Until(parsedDate).Hours() / 24)

if daysRemaining < 0 {
return "Expired"
} else if daysRemaining == 1 {
return "1 day"
}
return fmt.Sprintf("%d days", daysRemaining)
}

func formatDate(date time.Time) string {
month := date.Format("January")
return fmt.Sprintf("%s %d, %d", month, date.Day(), date.Year())
Expand Down
30 changes: 29 additions & 1 deletion infrastructure/code/code_html_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func Test_Code_Html_getCodeDetailsHtml_ignored(t *testing.T) {
IgnoreDetails: &snyk.IgnoreDetails{
Category: "wont-fix",
Reason: getIgnoreReason("long"),
Expiration: "13 days",
Expiration: "",
IgnoredOn: time.Now(),
IgnoredBy: "John Smith",
},
Expand All @@ -163,11 +163,39 @@ func Test_Code_Html_getCodeDetailsHtml_ignored(t *testing.T) {
assert.Contains(t, codePanelHtml, `class="ignore-badge"`)
assert.Contains(t, codePanelHtml, `data-content="ignore-details"`)
assert.Contains(t, codePanelHtml, `class="ignore-details-value">Ignored permanently</div>`)
assert.Contains(t, codePanelHtml, `class="ignore-details-value">No expiration</div>`) // Because category is "wont-fix"

// assert Footer buttons are not present when issue is ignored
assert.NotContains(t, codePanelHtml, `id="ignore-actions"`)
}

func Test_Code_Html_getCodeDetailsHtml_ignored_expired(t *testing.T) {
_ = testutil.UnitTest(t)

issue := snyk.Issue{
ID: "scala/DontUsePrintStackTrace",
Severity: 2,
LessonUrl: "https://learn.snyk.io/lesson/no-rate-limiting/?loc=ide",
CWEs: []string{"CWE-123", "CWE-456"},
IsIgnored: true,
IgnoreDetails: &snyk.IgnoreDetails{
Category: "temporary-ignore",
Reason: getIgnoreReason("long"),
Expiration: "2023-08-26T13:16:53.177Z",
IgnoredOn: time.Now(),
IgnoredBy: "John Smith",
},
AdditionalData: snyk.CodeIssueData{},
}

// invoke method under test
codePanelHtml := getCodeDetailsHtml(issue)

// assert Ignore Details section
// Asserting an expired date to prevent the test from breaking in the future as the current date changes
assert.Contains(t, codePanelHtml, `class="ignore-details-value">Expired</div>`)
}

func Test_Code_Html_getCodeDetailsHtml_ignored_customEndpoint(t *testing.T) {
c := testutil.UnitTest(t)

Expand Down
2 changes: 1 addition & 1 deletion infrastructure/code/code_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ func TestUploadAndAnalyzeWithIgnores(t *testing.T) {
assert.Equal(t, true, issues[1].IsIgnored)
assert.Equal(t, "wont-fix", issues[1].IgnoreDetails.Category)
assert.Equal(t, "False positive", issues[1].IgnoreDetails.Reason)
assert.Equal(t, "13 days", issues[1].IgnoreDetails.Expiration)
assert.Equal(t, "2024-07-11T10:06:44Z", issues[1].IgnoreDetails.Expiration)
assert.Equal(t, 2024, issues[1].IgnoreDetails.IgnoredOn.Year())
assert.Equal(t, "Neil M", issues[1].IgnoreDetails.IgnoredBy)

Expand Down
15 changes: 10 additions & 5 deletions infrastructure/code/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,10 +410,6 @@ func (s *SarifConverter) getIgnoreDetails(result codeClientSarif.Result) (bool,
}
isIgnored = true
suppression := result.Suppressions[0]
expiration := ""
if suppression.Properties.Expiration != nil {
expiration = *suppression.Properties.Expiration
}

reason := suppression.Justification
if reason == "" {
Expand All @@ -422,14 +418,23 @@ func (s *SarifConverter) getIgnoreDetails(result codeClientSarif.Result) (bool,
ignoreDetails = &snyk.IgnoreDetails{
Category: string(suppression.Properties.Category),
Reason: reason,
Expiration: expiration,
Expiration: parseExpirationDateFromString(suppression.Properties.Expiration),
IgnoredOn: parseDateFromString(suppression.Properties.IgnoredOn),
IgnoredBy: suppression.Properties.IgnoredBy.Name,
}
}
return isIgnored, ignoreDetails
}

func parseExpirationDateFromString(date *string) string {
if date == nil {
return ""
}

parsedDate := parseDateFromString(*date)
return parsedDate.Format(time.RFC3339)
}

func parseDateFromString(date string) time.Time {
logger := config.CurrentConfig().Logger().With().Str("method", "convert.parseDateFromString").Logger()
layouts := []string{
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/code/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ func Test_Result_getIgnoreDetails(t *testing.T) {
})

t.Run("does return ignore details if one suppression", func(t *testing.T) {
expiration := "expiration"
expiration := "2024-08-06T13:16:53Z"
r := codeClientSarif.Result{
Message: codeClientSarif.ResultMessage{
Text: "",
Expand Down Expand Up @@ -957,13 +957,13 @@ func Test_Result_getIgnoreDetails(t *testing.T) {
assert.NotNil(t, ignoreDetails)
assert.Equal(t, "reason", ignoreDetails.Reason)
assert.Equal(t, "category", ignoreDetails.Category)
assert.Equal(t, "expiration", ignoreDetails.Expiration)
assert.Equal(t, expiration, ignoreDetails.Expiration)
assert.Equal(t, 2024, ignoreDetails.IgnoredOn.Year())
assert.Equal(t, "name", ignoreDetails.IgnoredBy)
})

t.Run("sets reason to a default value if justification not provided in suppression", func(t *testing.T) {
expiration := "expiration"
expiration := "2024-08-06T13:16:53Z"
r := codeClientSarif.Result{
Message: codeClientSarif.ResultMessage{
Text: "",
Expand Down Expand Up @@ -991,7 +991,7 @@ func Test_Result_getIgnoreDetails(t *testing.T) {
assert.NotNil(t, ignoreDetails)
assert.Equal(t, "None given", ignoreDetails.Reason)
assert.Equal(t, "category", ignoreDetails.Category)
assert.Equal(t, "expiration", ignoreDetails.Expiration)
assert.Equal(t, expiration, ignoreDetails.Expiration)
assert.Equal(t, 2024, ignoreDetails.IgnoredOn.Year())
assert.Equal(t, "name", ignoreDetails.IgnoredBy)
})
Expand Down
2 changes: 1 addition & 1 deletion infrastructure/code/fake_code_client_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func getSarifResponseJson2(filePath string) string {
"justification": "False positive",
"properties": {
"category": "wont-fix",
"expiration": "13 days",
"expiration": "2024-07-11T10:06:44Z",
"ignoredOn": "2024-02-23T16:08:25Z",
"ignoredBy": {
"name": "Neil M",
Expand Down

0 comments on commit 1958e00

Please sign in to comment.