diff --git a/internal/display/formatter.go b/internal/display/formatter.go index dd5afda..df39075 100644 --- a/internal/display/formatter.go +++ b/internal/display/formatter.go @@ -151,10 +151,7 @@ func PrintWarning(w io.Writer, msg string) { } func printDeal(w io.Writer, item api.SavingItem) { - title := filter.CleanText(filter.Deref(item.Title)) - if title == "" { - title = "Unknown" - } + title := fallbackDealTitle(item) savings := filter.CleanText(filter.Deref(item.Savings)) desc := filter.CleanText(filter.Deref(item.Description)) dept := filter.CleanText(filter.Deref(item.Department)) @@ -198,6 +195,37 @@ func printDeal(w io.Writer, item api.SavingItem) { } } +func fallbackDealTitle(item api.SavingItem) string { + if title := filter.CleanText(filter.Deref(item.Title)); title != "" { + return title + } + + brand := filter.CleanText(filter.Deref(item.Brand)) + dept := filter.CleanText(filter.Deref(item.Department)) + switch { + case brand != "" && dept != "": + return fmt.Sprintf("%s deal (%s)", brand, dept) + case brand != "": + return brand + " deal" + case dept != "": + return dept + " deal" + } + + if desc := filter.CleanText(filter.Deref(item.Description)); desc != "" { + const max = 48 + if len(desc) > max { + return desc[:max-3] + "..." + } + return desc + } + + if item.ID != "" { + return "Deal " + item.ID + } + + return "Untitled deal" +} + func toDealJSON(item api.SavingItem) DealJSON { categories := item.Categories if categories == nil { diff --git a/internal/display/formatter_test.go b/internal/display/formatter_test.go index f0ab272..9aa3307 100644 --- a/internal/display/formatter_test.go +++ b/internal/display/formatter_test.go @@ -55,6 +55,41 @@ func TestPrintDeals_ContainsExpectedContent(t *testing.T) { assert.NotContains(t, output, "&") } +func TestPrintDeals_FallbackTitleFromBrandAndDepartment(t *testing.T) { + items := []api.SavingItem{ + { + ID: "fallback-1", + Title: nil, + Brand: ptr("Publix"), + Department: ptr("Meat"), + Categories: []string{"meat"}, + }, + } + + var buf bytes.Buffer + display.PrintDeals(&buf, items) + output := buf.String() + + assert.Contains(t, output, "Publix deal (Meat)") + assert.NotContains(t, output, "Unknown") +} + +func TestPrintDeals_FallbackTitleFromID(t *testing.T) { + items := []api.SavingItem{ + { + ID: "fallback-2", + Title: nil, + }, + } + + var buf bytes.Buffer + display.PrintDeals(&buf, items) + output := buf.String() + + assert.Contains(t, output, "Deal fallback-2") + assert.NotContains(t, output, "Unknown") +} + func TestPrintDealsJSON(t *testing.T) { var buf bytes.Buffer err := display.PrintDealsJSON(&buf, sampleDeals())