Skip to content

Commit

Permalink
Some refactoring and Add coverage to Makefile
Browse files Browse the repository at this point in the history
  • Loading branch information
goyalmunish committed Jan 9, 2023
1 parent 1801b48 commit baf9910
Show file tree
Hide file tree
Showing 20 changed files with 1,345 additions and 582 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ fmt:
.PHONY: test
test:
. ./scripts/go_test

.PHONY: coverage
coverage:
. ./scripts/go_coverage

.PHONY: open
open:
. ./scripts/open_data_file
5 changes: 4 additions & 1 deletion cmd/reminder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ func Run() error {
// check if the data file is locked by another session
if reminderData.MutexLock {
fmt.Printf("WARNING! %s\n", model.ErrorMutexLockOn.Error())
reset := utils.AskBoolean("But, do you want to force reset the lock?")
reset, err := utils.AskBoolean("But, do you want to force reset the lock?")
if err != nil {
return err
}
if !reset {
// exit now without resetting the lock
return model.ErrorMutexLockOn
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/net v0.3.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/term v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/term v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6 // indirect
google.golang.org/grpc v1.51.0 // indirect
Expand Down
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -370,22 +370,22 @@ golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
8 changes: 4 additions & 4 deletions internal/model/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ func NewNote(tagIDs []int, useText string) (*Note, error) {
} else {
noteText = useText
}
note.Text = utils.TrimString(noteText)
note.Text = strings.TrimSpace(noteText)
if err != nil || strings.Contains(note.Text, "^C") {
return note, err
}
if len(utils.TrimString(note.Text)) == 0 {
if len(strings.TrimSpace(note.Text)) == 0 {
// this should never be encountered because of validation in earlier step
fmt.Printf("%v Skipping adding note with empty text\n", utils.Symbols["warning"])
return note, errors.New("Note's text is empty")
Expand Down Expand Up @@ -153,9 +153,9 @@ func NewTag(tagID int, useSlug string, useGroup string) (*Tag, error) {
} else {
tagSlug = useSlug
}
tag.Slug = utils.TrimString(tagSlug)
tag.Slug = strings.TrimSpace(tagSlug)
tag.Slug = strings.ToLower(tag.Slug)
if len(utils.TrimString(tag.Slug)) == 0 {
if len(strings.TrimSpace(tag.Slug)) == 0 {
// this should never be encountered because of validation in earlier step
fmt.Printf("%v Skipping adding tag with empty slug\n", utils.Symbols["warning"])
err := errors.New("Tag's slug is empty")
Expand Down
77 changes: 74 additions & 3 deletions internal/model/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package model_test

import (
"errors"
"fmt"

// "fmt"
"io/fs"
Expand All @@ -17,6 +18,7 @@ import (
model "github.com/goyalmunish/reminder/internal/model"
"github.com/goyalmunish/reminder/internal/settings"
utils "github.com/goyalmunish/reminder/pkg/utils"
gc "google.golang.org/api/calendar/v3"
)

// mocks
Expand All @@ -27,6 +29,16 @@ type MockPromptTagGroup struct {
}
type MockPromptNoteText struct {
}
type TestTagger struct{}

func (tagger TestTagger) TagsFromIds(tagIDs []int) []string {
slugs := []string{}
for i, id := range tagIDs {
slug := fmt.Sprintf("%d-%d", i, id)
slugs = append(slugs, slug)
}
return slugs
}

func (prompt *MockPromptTagSlug) Run() (string, error) {
return "test_tag_slug", nil
Expand Down Expand Up @@ -380,6 +392,26 @@ func TestWithCompleteBy(t *testing.T) {
utils.AssertEqual(t, got, want)
}

func TestOnlyMain(t *testing.T) {
var notes model.Notes
// case 1 (no notes)
utils.AssertEqual(t, notes.OnlyMain(), model.Notes{})
// add some notes
comments := model.Comments{&model.Comment{Text: "c1"}}
note1 := model.Note{Text: "big fat cat", Comments: comments, Status: model.NoteStatus_Pending, TagIds: []int{1, 2}, CompleteBy: 1609669231}
notes = append(notes, &note1)
comments = model.Comments{&model.Comment{Text: "c1"}, &model.Comment{Text: "foo bar"}}
note2 := model.Note{Text: "cute brown dog", Comments: comments, Status: model.NoteStatus_Done, TagIds: []int{1, 3}, IsMain: true, CompleteBy: 1609669232}
notes = append(notes, &note2)
comments = model.Comments{&model.Comment{Text: "foo bar"}, &model.Comment{Text: "c3"}}
note3 := model.Note{Text: "little hamster", Comments: comments, Status: model.NoteStatus_Pending, TagIds: []int{1}}
notes = append(notes, &note3)
// case 3 (with only few notes to be filtered in)
got := notes.OnlyMain()
want := model.Notes{&note2}
utils.AssertEqual(t, got, want)
}

func TestWithTagIdAndStatus(t *testing.T) {
// var tags model.Tags
var notes model.Notes
Expand Down Expand Up @@ -551,6 +583,45 @@ func TestToggleMainFlag(t *testing.T) {
utils.AssertEqual(t, originalPriority != note1.IsMain, true)
}

func TestGoogleCalendarEvent(t *testing.T) {
tagger := TestTagger{}
var tests = []struct {
name string // has to be string
note model.Note
inputRATID int
inputRMTID int
inputTimezone string
inputTagger model.Tagger
want *gc.Event
wantErr error
wantedErr bool
}{
{
name: "general case 1",
note: model.Note{Text: "original text", Status: model.NoteStatus_Pending, TagIds: []int{1, 4}, BaseStruct: model.BaseStruct{UpdatedAt: 1600000001}},
inputRATID: 1,
inputRMTID: 3,
inputTimezone: "Australia/Melbourne",
inputTagger: tagger,
want: &gc.Event{
Summary: "[reminder] original text",
},
wantedErr: false,
},
}
for position, subtest := range tests {
t.Run(subtest.name, func(t *testing.T) {
got, err := subtest.note.GoogleCalendarEvent(subtest.inputRATID, subtest.inputRMTID, subtest.inputTimezone, tagger)
if (err != nil) != subtest.wantedErr {
t.Fatalf("GoogleCalendarEvent case %q (position=%d) with input <%+v> returns error <%v>; wantError <%v>", subtest.name, position, subtest.note, err, subtest.wantErr)
}
if got.Summary != subtest.want.Summary {
t.Errorf("GoogleCalendarEvent case %q (position=%d) with input <%+v> returns <%+v>; want <%+v>", subtest.name, position, subtest.note, got, subtest.want)
}
})
}
}

func TestSortedTagsSlug(t *testing.T) {
reminderData := model.ReminderData{
User: &model.User{Name: "Test User", EmailId: "[email protected]"},
Expand Down Expand Up @@ -592,17 +663,17 @@ func TestTagsFromIds(t *testing.T) {
// case 1
tagIDs := []int{1, 3}
gotSlugs := reminderData.TagsFromIds(tagIDs)
wantSlugs := model.Tags{&tag1, &tag3}
wantSlugs := model.Tags{&tag1, &tag3}.Slugs()
utils.AssertEqual(t, gotSlugs, wantSlugs)
// case 2
tagIDs = []int{}
gotSlugs = reminderData.TagsFromIds(tagIDs)
wantSlugs = model.Tags{}
wantSlugs = model.Tags{}.Slugs()
utils.AssertEqual(t, gotSlugs, wantSlugs)
// case 3
tagIDs = []int{1, 4, 2, 3}
gotSlugs = reminderData.TagsFromIds(tagIDs)
wantSlugs = model.Tags{&tag1, &tag4, &tag2, &tag3}
wantSlugs = model.Tags{&tag1, &tag4, &tag2, &tag3}.Slugs()
utils.AssertEqual(t, gotSlugs, wantSlugs)
}

Expand Down
26 changes: 13 additions & 13 deletions internal/model/note.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ func (note *Note) Strings() ([]string, error) {
}

// externalText returns a note with its tags slugs as a slice of strings.
func (note *Note) externalText(reminderData *ReminderData) ([]string, error) {
func (note *Note) externalText(tagger Tagger) ([]string, error) {
var strs []string
strs = append(strs, fmt.Sprintln("Note Details: -------------------------------------------------"))
basicStrs, err := note.Strings()
if err != nil {
return nil, err
}
// replace tag ids with tag slugs
tagsStr := printNoteField("Tags", reminderData.TagsFromIds(note.TagIds).Slugs())
tagsStr := printNoteField("Tags", tagger.TagsFromIds(note.TagIds))
basicStrs[4] = tagsStr
// create final list of strings
strs = append(strs, basicStrs...)
Expand All @@ -101,8 +101,8 @@ func (note *Note) ExternalText(reminderData *ReminderData) (string, error) {

// SafeExtText prints a note with its tags slugs, but only the safe components.
// This is used as final external reprensentation for display of a single note to external services like Google Calendar.
func (note *Note) SafeExtText(reminderData *ReminderData) (string, error) {
strs, err := note.externalText(reminderData)
func (note *Note) SafeExtText(tagger Tagger) (string, error) {
strs, err := note.externalText(tagger)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -146,7 +146,7 @@ func (note *Note) SearchableText() (string, error) {

// AddComment adds a new comment to note.
func (note *Note) AddComment(text string) error {
if len(utils.TrimString(text)) == 0 {
if len(strings.TrimSpace(text)) == 0 {
return errors.New("Note's comment text is empty")
}
comment := &Comment{Text: text, BaseStruct: BaseStruct{CreatedAt: utils.CurrentUnixTimestamp()}}
Expand All @@ -169,7 +169,7 @@ func (note *Note) UpdateTags(tagIDs []int) error {
// UpdateStatus updates note's status ("done"/"pending").
// Status of a note tag with repeat tag cannot be mared as "done".
func (note *Note) UpdateStatus(status NoteStatus, repeatTagIDs []int) error {
noteIDsWithRepeat := utils.GetCommonMembersIntSlices(note.TagIds, repeatTagIDs)
noteIDsWithRepeat := utils.GetCommonMembersOfSlices(note.TagIds, repeatTagIDs)
if len(noteIDsWithRepeat) != 0 {
return errors.New("Note is part of a \"repeat\" group")
}
Expand All @@ -187,7 +187,7 @@ func (note *Note) UpdateStatus(status NoteStatus, repeatTagIDs []int) error {
// UpdateText updates note's text.
// Once updated, the text cannot be made empty.
func (note *Note) UpdateText(text string) error {
if len(utils.TrimString(text)) == 0 {
if len(strings.TrimSpace(text)) == 0 {
return errors.New("Note's text is empty")
}
// happy path
Expand All @@ -201,7 +201,7 @@ func (note *Note) UpdateText(text string) error {
// UpdateSummary updates note's summary.
// If input is "nil", the existing summary is cleared.
func (note *Note) UpdateSummary(text string) error {
if len(utils.TrimString(text)) == 0 {
if len(strings.TrimSpace(text)) == 0 {
return errors.New("Note's summary is empty")
}
// happy path
Expand All @@ -222,7 +222,7 @@ func (note *Note) UpdateSummary(text string) error {
// If input is "nil", the existing due date is cleared.
func (note *Note) UpdateCompleteBy(text string) error {
// handle edge-case of empty text
if len(utils.TrimString(text)) == 0 {
if len(strings.TrimSpace(text)) == 0 {
return errors.New("Note's due date is empty")
}
// happy path
Expand Down Expand Up @@ -255,9 +255,9 @@ func (note *Note) UpdateCompleteBy(text string) error {
// representing repeat-type of the note
func (note *Note) RepeatType(repeatAnnuallyTagId int, repeatMonthlyTagId int) string {
repeat := "-" // non-repeat
if utils.IntPresentInSlice(repeatAnnuallyTagId, note.TagIds) {
if utils.IsMemberOfSlice(repeatAnnuallyTagId, note.TagIds) {
repeat = "A"
} else if utils.IntPresentInSlice(repeatMonthlyTagId, note.TagIds) {
} else if utils.IsMemberOfSlice(repeatMonthlyTagId, note.TagIds) {
repeat = "M"
}
return repeat
Expand All @@ -273,7 +273,7 @@ func (note *Note) ToggleMainFlag() error {
}

// GoogleCalendarEvent converts a note to Google Calendar Event.
func (note *Note) GoogleCalendarEvent(repeatAnnuallyTagId int, repeatMonthlyTagId int, timezoneIANA string, reminderData *ReminderData) (*gc.Event, error) {
func (note *Note) GoogleCalendarEvent(repeatAnnuallyTagId int, repeatMonthlyTagId int, timezoneIANA string, tagger Tagger) (*gc.Event, error) {
// basic information
title := note.Text
start := utils.UnixTimestampToTime(note.CompleteBy) // this is the original time in 00:00:00 GMT+0000
Expand All @@ -284,7 +284,7 @@ func (note *Note) GoogleCalendarEvent(repeatAnnuallyTagId int, repeatMonthlyTagI
start = start.Add(offset) // adjusting the start to local time for notification purpose
start = start.Add(-14 * time.Hour) // set notification for 10 AM of given timezoneIANA
repeatType := note.RepeatType(repeatAnnuallyTagId, repeatMonthlyTagId)
description, err := note.SafeExtText(reminderData)
description, err := note.SafeExtText(tagger)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/model/notes.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (notes Notes) WithTagIdAndStatus(tagID int, status NoteStatus) Notes {
notesWithStatus := notes.WithStatus(status)
var result Notes
for _, note := range notesWithStatus {
if utils.IntPresentInSlice(tagID, note.TagIds) {
if utils.IsMemberOfSlice(tagID, note.TagIds) {
result = append(result, note)
}
}
Expand Down
Loading

0 comments on commit baf9910

Please sign in to comment.