package models_test import ( "errors" "fmt" "math/rand/v2" "reflect" "strings" "testing" "time" "git.hrafn.xyz/aether/notes/internal/models" ) func TestContentCompletionNoteValidation(t *testing.T) { testcases := []struct { name string note models.Note expectedError bool expectedReasons []error }{ { name: "Completely Empty", note: models.Note{ Title: "", Content: "", ID: 1, LastUpdate: time.Now(), }, expectedError: true, expectedReasons: []error{&models.ErrEmptyNoteContent{}, &models.ErrEmptyNoteTitle{}}, }, { name: "Missing title", note: models.Note{ Title: "", Content: "Here we go!", ID: 1, LastUpdate: time.Now(), }, expectedError: true, expectedReasons: []error{&models.ErrEmptyNoteTitle{}}, }, { name: "Missing content", note: models.Note{ Title: "I am not content with this content", Content: "", ID: 1, LastUpdate: time.Now(), }, expectedError: true, expectedReasons: []error{&models.ErrEmptyNoteContent{}}, }, { name: "Good note", note: models.Note{ Title: "I am content with this content", Content: "this content", ID: 1, LastUpdate: time.Now(), }, expectedError: false, expectedReasons: []error{}, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { err := tc.note.Validate() // Early out when not needing to test because we're not expecting an error and we didn't get one if !tc.expectedError && err == nil { fmt.Printf("Test case '%s' passed.\n", tc.name) return } var expected *models.ErrNoteIncomplete if !errors.As(err, &expected) && tc.expectedError { t.Errorf("expected *ErrNoteIncomplete, got %T", err) } for _, reason := range tc.expectedReasons { if !errors.Is(err, reason) { t.Errorf(`expected error to contain "%v" but it was missing`, reason) } } rv := reflect.ValueOf(err).Elem() whyField := rv.FieldByName("why") if whyField.Len() != len(tc.expectedReasons) { t.Errorf("expected %d errors, got %d", len(tc.expectedReasons), whyField.Len()) } fmt.Printf("Test case '%s' passed.\n", tc.name) }) } } func TestTitleLengthNoteValidation(t *testing.T) { testcases := []struct { name string title string expectedError bool }{ { name: "Max valid title", title: strings.Repeat("0", models.NoteTitleMaxLength), expectedError: false, }, { name: "Just over max valid title", title: strings.Repeat("1", models.NoteTitleMaxLength + 1), expectedError: true, }, { name: "Double max valid title", title: strings.Repeat("Bd", models.NoteTitleMaxLength), expectedError: true, }, { name: "Random overmax valid title length", title: strings.Repeat("1", models.NoteTitleMaxLength + rand.IntN(150)), expectedError: true, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { note := models.Note{ Title: tc.title, Content: "Perfectly valid content " + tc.title, LastUpdate: time.Now(), ID: 1, } err := note.Validate() if !tc.expectedError { if err != nil { t.Errorf("expecting no error, got %v", err) } } else { var expected *models.ErrNoteTitleOverflow if !errors.As(err, &expected) { t.Errorf("expected *ErrNoteTitleOverflow, got %T", err) } } fmt.Printf("Test case '%s' passed.\n", tc.name) }) } }