github.com/joao-fontenele/go-url-shortener@v1.3.4/pkg/postgres/linkdao_test.go (about) 1 package postgres 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "os" 8 "testing" 9 "time" 10 11 "github.com/google/go-cmp/cmp" 12 "github.com/jackc/pgx/v4/pgxpool" 13 "github.com/joao-fontenele/go-url-shortener/pkg/configger" 14 "github.com/joao-fontenele/go-url-shortener/pkg/shortener" 15 ) 16 17 func testMain(m *testing.M) int { 18 var err error 19 20 // change dir because default pwd for tests are it's parent dir 21 os.Chdir("../../") 22 23 err = configger.Load() 24 if err != nil { 25 fmt.Printf("failed to load configs: %v", err) 26 return 1 27 } 28 29 env := configger.Get().Env 30 if env != "test" { 31 fmt.Println("don't run these tests on non dev environment") 32 return 1 33 } 34 35 closeDB, err := Connect() 36 if err != nil { 37 return 1 38 } 39 defer closeDB() 40 return m.Run() 41 } 42 43 func seedDB(conn *pgxpool.Pool) error { 44 _, err := conn.Exec( 45 context.Background(), 46 "INSERT INTO links (slug, url, createdAt) VALUES ('a1CDz', 'https://www.google.com', '2020-05-01T00:00:00.000Z')", 47 ) 48 49 return err 50 } 51 52 func truncateDB(conn *pgxpool.Pool) error { 53 _, err := conn.Exec(context.Background(), "TRUNCATE TABLE links") 54 55 return err 56 } 57 58 func TestMain(m *testing.M) { 59 os.Exit(testMain(m)) 60 } 61 62 func TestFind(t *testing.T) { 63 conn := GetConnection() 64 if err := truncateDB(conn); err != nil { 65 t.Fatalf("error truncating test database tables: %v", err) 66 } 67 68 err := seedDB(conn) 69 if err != nil { 70 t.Fatalf("failed to seed db: %v", err) 71 } 72 73 dao := NewLinkDao(conn) 74 75 tt := []struct { 76 Name string 77 Slug string 78 Want *shortener.Link 79 Err error 80 }{ 81 { 82 Name: "FoundSlug", 83 Slug: "a1CDz", 84 Want: &shortener.Link{ 85 URL: "https://www.google.com", 86 Slug: "a1CDz", 87 CreatedAt: time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 88 }, 89 Err: nil, 90 }, 91 { 92 Name: "NotFoundSlug", 93 Slug: "niull", 94 Want: nil, 95 Err: shortener.ErrLinkNotFound, 96 }, 97 } 98 99 for _, test := range tt { 100 t.Run(test.Name, func(t *testing.T) { 101 var got *shortener.Link 102 got, err = dao.Find(context.Background(), test.Slug) 103 104 if !errors.Is(err, test.Err) { 105 t.Fatalf("failed to find the requested link: %v", err) 106 } 107 108 if diff := cmp.Diff(test.Want, got); diff != "" { 109 t.Errorf("failed to fetch expected link (-want +got):\n%s", diff) 110 } 111 }) 112 } 113 } 114 115 func TestInsert(t *testing.T) { 116 conn := GetConnection() 117 if err := truncateDB(conn); err != nil { 118 t.Fatalf("error truncating test database tables: %v", err) 119 } 120 121 err := seedDB(conn) 122 if err != nil { 123 t.Fatalf("failed to seed db: %v", err) 124 } 125 126 dao := NewLinkDao(conn) 127 128 tt := []struct { 129 Name string 130 Link *shortener.Link 131 Error error 132 }{ 133 { 134 Name: "Success", 135 Link: &shortener.Link{ 136 URL: "https://www.google.com?s=golang", 137 Slug: "spd91", 138 }, 139 Error: nil, 140 }, 141 { 142 Name: "ConflictSlug", 143 Link: &shortener.Link{ 144 URL: "https://www.google.com?s=golang", 145 Slug: "a1CDz", 146 }, 147 Error: shortener.ErrLinkExists, 148 }, 149 } 150 151 for _, test := range tt { 152 t.Run(test.Name, func(t *testing.T) { 153 _, err := dao.Insert(context.Background(), test.Link) 154 155 if !errors.Is(err, test.Error) { 156 t.Fatalf("failed to query new inserted link %v", err) 157 } 158 159 if err != nil { 160 return 161 } 162 163 inserted := shortener.Link{} 164 err = conn.QueryRow( 165 context.Background(), 166 "SELECT slug, url, createdAt FROM links WHERE slug=$1", 167 test.Link.Slug, 168 ).Scan(&inserted.Slug, &inserted.URL, &inserted.CreatedAt) 169 170 if err != nil { 171 t.Fatalf("Unexpected error querying inserted link: %v", err) 172 } 173 174 if diff := cmp.Diff(test.Link, &inserted); diff != "" { 175 t.Errorf("failed to fetch expected link (-want +got):\n%s", diff) 176 } 177 }) 178 } 179 } 180 181 func TestList(t *testing.T) { 182 conn := GetConnection() 183 if err := truncateDB(conn); err != nil { 184 t.Fatalf("error truncating test database tables: %v", err) 185 } 186 187 err := seedDB(conn) 188 if err != nil { 189 t.Fatalf("failed to seed db: %v", err) 190 } 191 192 dao := NewLinkDao(conn) 193 194 expectedLinks := []shortener.Link{ 195 { 196 URL: "https://www.google.com", 197 Slug: "a1CDz", 198 CreatedAt: time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 199 }, 200 } 201 202 tests := []struct { 203 Name string 204 ExpectedErr error 205 ExpectedResult []shortener.Link 206 Skip int 207 Limit int 208 }{ 209 { 210 Name: "FirstPageSuccess", 211 ExpectedErr: nil, 212 ExpectedResult: expectedLinks, 213 Skip: 0, 214 Limit: 1, 215 }, 216 { 217 Name: "SecondPageEmpty", 218 ExpectedErr: nil, 219 ExpectedResult: []shortener.Link{}, 220 Skip: 1, 221 Limit: 1, 222 }, 223 } 224 225 for _, tc := range tests { 226 t.Run(tc.Name, func(t *testing.T) { 227 links, err := dao.List(context.Background(), tc.Limit, tc.Skip) 228 if err != nil { 229 t.Errorf("Failed to List links: %v", err) 230 } 231 232 if diff := cmp.Diff(tc.ExpectedResult, links); diff != "" { 233 t.Errorf("Result links list is not equal to expected (-want +got):\n%s", diff) 234 } 235 }) 236 } 237 }