summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormihna123 <mihailonvojinovic@gmail.com>2026-08-23 17:47:16 +0200
committermihna123 <mihailonvojinovic@gmail.com>2026-08-23 17:47:16 +0200
commit1e43f2a59bba0462494066767fac140601791718 (patch)
tree45a4d0c4f3159f4acd7949eebbbfe138e4c1bc3f
parent516ed55e09a253255e7056d31eb59acfd68db3a8 (diff)
downloadopenstore-1e43f2a59bba0462494066767fac140601791718.tar.gz
openstore-1e43f2a59bba0462494066767fac140601791718.zip
listing: implement a service layer stub along with tests
-rw-r--r--internal/listing/mock_test.go89
-rw-r--r--internal/listing/service.go36
-rw-r--r--internal/listing/service_test.go89
3 files changed, 214 insertions, 0 deletions
diff --git a/internal/listing/mock_test.go b/internal/listing/mock_test.go
new file mode 100644
index 0000000..5aa6d68
--- /dev/null
+++ b/internal/listing/mock_test.go
@@ -0,0 +1,89 @@
+package listing
+
+import "time"
+
+type RepositoryMock struct {
+ listings []Listing
+ err error
+}
+
+func (r *RepositoryMock) GetAll() ([]Listing, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+
+ return r.listings, nil
+}
+
+func (r *RepositoryMock) GetByCategory(c string) ([]Listing, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+
+ var res []Listing
+ for _, l := range r.listings {
+ for _, cat := range l.category {
+ if cat == c {
+ res = append(res, l)
+ break
+ }
+ }
+ }
+
+ return res, nil
+}
+
+func NewRepositoryMock() *RepositoryMock {
+ mockListings := []Listing{
+ {
+ id: 0,
+ title: "Audi a5 2.0 2015 godiste",
+ slug: "audi-a5-2-0-2015-godiste",
+ location: Location{city: "Novi Sad", street: "Bulevar Cara Lazara", premise: "3"},
+ status: PublishedStatus,
+ category: []string{"automobile", "audi", "a5"},
+ price: 5000,
+ currency: "EUR",
+ description: "Pali odma ide lepo",
+ images: []string{},
+ views: 10,
+ createdAt: time.Now(),
+ author: nil,
+ isExternal: false,
+ },
+ {
+ id: 1,
+ title: "Led lampa za glavu TJ-1608",
+ slug: "led-lampa-za-glavu-tj-1608",
+ location: Location{city: "Belgrade"},
+ status: PublishedStatus,
+ category: []string{"hunting", "hunting-lamps"},
+ price: 1200,
+ currency: "RSD",
+ description: "Odlična lampa, svetli super",
+ images: []string{},
+ views: 21,
+ createdAt: time.Now(),
+ author: nil,
+ isExternal: false,
+ },
+ {
+ id: 2,
+ title: "Školski anatomski ranac Minnie Mouse metalik",
+ slug: "skolski-anatomski-ranac-minnie-mouse-metalik",
+ location: Location{city: "Mladenovac"},
+ status: PublishedStatus,
+ category: []string{"school", "backpacks"},
+ price: 3400,
+ currency: "RSD",
+ description: "Minnie ranac mnogo lep za devojčice",
+ images: []string{},
+ views: 131,
+ createdAt: time.Now(),
+ author: nil,
+ isExternal: false,
+ },
+ }
+
+ return &RepositoryMock{listings: mockListings}
+}
diff --git a/internal/listing/service.go b/internal/listing/service.go
new file mode 100644
index 0000000..302628b
--- /dev/null
+++ b/internal/listing/service.go
@@ -0,0 +1,36 @@
+package listing
+
+import "log/slog"
+
+type Repository interface {
+ GetAll() ([]Listing, error)
+ GetByCategory(category string) ([]Listing, error)
+}
+
+type Service struct {
+ repository Repository
+}
+
+func New(r Repository) *Service {
+ return &Service{repository: r}
+}
+
+func (s *Service) GetAll() ([]Listing, error) {
+ listings, err := s.repository.GetAll()
+ if err != nil {
+ slog.Error("listing service", "error", err)
+ return nil, err
+ }
+
+ return listings, nil
+}
+
+func (s *Service) GetByCategory(c string) ([]Listing, error) {
+ listings, err := s.repository.GetByCategory(c)
+ if err != nil {
+ slog.Error("listing service", "error", err)
+ return nil, err
+ }
+
+ return listings, nil
+}
diff --git a/internal/listing/service_test.go b/internal/listing/service_test.go
new file mode 100644
index 0000000..1d555c9
--- /dev/null
+++ b/internal/listing/service_test.go
@@ -0,0 +1,89 @@
+package listing
+
+import (
+ "errors"
+ "log/slog"
+ "os"
+ "slices"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ slog.SetDefault(slog.New(slog.DiscardHandler))
+ os.Exit(m.Run())
+}
+
+func TestGetAll(t *testing.T) {
+ mock := NewRepositoryMock()
+ s := New(mock)
+ listings, err := s.GetAll()
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ if len(listings) != 3 {
+ t.Errorf("Listings lengths don't match. Have %d, want 3",
+ len(listings))
+ }
+}
+
+func TestGetAllWithError(t *testing.T) {
+ mock := &RepositoryMock{err: errors.New("db exploded")}
+ s := New(mock)
+ listings, err := s.GetAll()
+
+ if err == nil {
+ t.Error("No error returned from faulty GetAll call")
+ }
+
+ if listings != nil {
+ t.Error("Listings not nil when returned from faulty GetAll call")
+ }
+}
+
+func TestGetByCategory(t *testing.T) {
+ mock := NewRepositoryMock()
+ s := New(mock)
+
+ listings, err := s.GetByCategory("audi")
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ if len(listings) != 1 {
+ t.Errorf("Listings by category have wrong length. Have %d, want %d",
+ len(listings), 1)
+ }
+ if !slices.Contains(listings[0].category, "audi") {
+ t.Errorf("Returned listing has wrong category. Have %s, want audi",
+ listings[0].category)
+ }
+}
+
+func TestGetByCategoryNoMatches(t *testing.T) {
+ mock := &RepositoryMock{}
+ s := New(mock)
+
+ listings, err := s.GetByCategory("nonexistantcategory")
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ if listings != nil {
+ t.Error("Listings should be nil if no category matches")
+ }
+}
+
+func TestGetByCategoryWithError(t *testing.T) {
+ mock := &RepositoryMock{err: errors.New("datacenter hit by asteroid")}
+ s := New(mock)
+
+ listings, err := s.GetByCategory("mercedes")
+ if err == nil {
+ t.Error("Error nil when GetByCategory failed")
+ }
+
+ if listings != nil {
+ t.Error("Listings not nil when GetByCategory failed")
+ }
+}