github.com/k0marov/go-socnet@v0.0.0-20220715154813-90d07867c782/features/profiles/domain/service/service_test.go (about)

     1  package service_test
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/k0marov/go-socnet/core/general/client_errors"
     6  	"github.com/k0marov/go-socnet/core/general/core_err"
     7  	"github.com/k0marov/go-socnet/core/general/core_values"
     8  	"github.com/k0marov/go-socnet/core/general/core_values/ref"
     9  	"github.com/k0marov/go-socnet/core/general/static_store"
    10  	. "github.com/k0marov/go-socnet/core/helpers/test_helpers"
    11  	"testing"
    12  
    13  	"github.com/k0marov/go-socnet/features/profiles/domain/models"
    14  
    15  	"github.com/k0marov/go-socnet/features/profiles/domain/entities"
    16  	"github.com/k0marov/go-socnet/features/profiles/domain/service"
    17  	"github.com/k0marov/go-socnet/features/profiles/domain/values"
    18  )
    19  
    20  func TestProfileGetter(t *testing.T) {
    21  	target := RandomString()
    22  	caller := RandomString()
    23  	profile := RandomProfile()
    24  	contextedProfile := RandomContextedProfile()
    25  	getProfile := func(id core_values.UserId) (entities.Profile, error) {
    26  		if id == target {
    27  			return profile, nil
    28  		}
    29  		panic("called with unexpected arguments")
    30  	}
    31  	t.Run("error case - store returns NotFoundErr", func(t *testing.T) {
    32  		getProfile := func(core_values.UserId) (entities.Profile, error) {
    33  			return entities.Profile{}, core_err.ErrNotFound
    34  		}
    35  		sut := service.NewProfileGetter(getProfile, nil)
    36  		_, err := sut(target, caller)
    37  		AssertError(t, err, client_errors.NotFound)
    38  	})
    39  	t.Run("error case - store returns some other error", func(t *testing.T) {
    40  		getProfile := func(core_values.UserId) (entities.Profile, error) {
    41  			return entities.Profile{}, RandomError()
    42  		}
    43  		sut := service.NewProfileGetter(getProfile, nil)
    44  		_, err := sut(target, caller)
    45  		AssertSomeError(t, err)
    46  	})
    47  	addContext := func(prof entities.Profile, callerId core_values.UserId) (entities.ContextedProfile, error) {
    48  		if prof == profile && callerId == caller {
    49  			return contextedProfile, nil
    50  		}
    51  		panic("unexpected args")
    52  	}
    53  	t.Run("error case - adding context returns some error", func(t *testing.T) {
    54  		addContext := func(profile2 entities.Profile, id core_values.UserId) (entities.ContextedProfile, error) {
    55  			return entities.ContextedProfile{}, RandomError()
    56  		}
    57  		_, err := service.NewProfileGetter(getProfile, addContext)(target, caller)
    58  		AssertSomeError(t, err)
    59  	})
    60  	t.Run("happy case", func(t *testing.T) {
    61  		gotProfile, err := service.NewProfileGetter(getProfile, addContext)(target, caller)
    62  		AssertNoError(t, err)
    63  		Assert(t, gotProfile, contextedProfile, "returned profile")
    64  	})
    65  }
    66  
    67  func TestFollowsGetter(t *testing.T) {
    68  	target := RandomId()
    69  	caller := RandomId()
    70  	follows := []core_values.UserId{RandomId()}
    71  	wantFollows := []entities.ContextedProfile{RandomContextedProfile()}
    72  
    73  	getFollows := func(id core_values.UserId) ([]core_values.UserId, error) {
    74  		if id == target {
    75  			return follows, nil
    76  		}
    77  		panic("unexpected args")
    78  	}
    79  	t.Run("error case - getting follows throws", func(t *testing.T) {
    80  		getFollows := func(core_values.UserId) ([]core_values.UserId, error) {
    81  			return nil, RandomError()
    82  		}
    83  		_, err := service.NewFollowsGetter(getFollows, nil)(target, caller)
    84  		AssertSomeError(t, err)
    85  
    86  	})
    87  	getProfile := func(targetId, callerId core_values.UserId) (entities.ContextedProfile, error) {
    88  		if targetId == follows[0] && callerId == caller {
    89  			return wantFollows[0], nil
    90  		}
    91  		panic("unexpected args")
    92  	}
    93  	t.Run("error case - getting profile throws", func(t *testing.T) {
    94  		getProfile := func(target, caller core_values.UserId) (entities.ContextedProfile, error) {
    95  			return entities.ContextedProfile{}, RandomError()
    96  		}
    97  		_, err := service.NewFollowsGetter(getFollows, getProfile)(target, caller)
    98  		AssertSomeError(t, err)
    99  	})
   100  
   101  	t.Run("happy case", func(t *testing.T) {
   102  		sut := service.NewFollowsGetter(getFollows, getProfile)
   103  		gotFollows, err := sut(target, caller)
   104  		AssertNoError(t, err)
   105  		Assert(t, gotFollows, wantFollows, "returned follows")
   106  	})
   107  }
   108  
   109  func TestProfileCreator(t *testing.T) {
   110  	user := RandomUser()
   111  	t.Run("happy case", func(t *testing.T) {
   112  		testNewProfile := models.ProfileModel{
   113  			Id:         user.Id,
   114  			Username:   user.Username,
   115  			About:      service.DefaultAbout,
   116  			AvatarPath: service.DefaultAvatarPath,
   117  		}
   118  		wantCreatedProfile := entities.Profile{
   119  			ProfileModel: testNewProfile,
   120  			Follows:      0,
   121  			Followers:    0,
   122  		}
   123  		storeNew := func(profile models.ProfileModel) error {
   124  			if profile == testNewProfile {
   125  				return nil
   126  			}
   127  			panic(fmt.Sprintf("StoreNew called with unexpected profile: %v", profile))
   128  		}
   129  		sut := service.NewProfileCreator(storeNew)
   130  
   131  		gotProfile, err := sut(user)
   132  		AssertNoError(t, err)
   133  		Assert(t, gotProfile, wantCreatedProfile, "created profile")
   134  	})
   135  	t.Run("error case - store throws, it is NOT a client error", func(t *testing.T) {
   136  		storeNew := func(model models.ProfileModel) error {
   137  			return RandomError()
   138  		}
   139  		sut := service.NewProfileCreator(storeNew)
   140  
   141  		_, err := sut(user)
   142  
   143  		AssertSomeError(t, err)
   144  	})
   145  }
   146  
   147  func TestProfileUpdater(t *testing.T) {
   148  	user := RandomUser()
   149  	testUpdateData := values.ProfileUpdateData{
   150  		About: RandomString(),
   151  	}
   152  	validator := func(values.ProfileUpdateData) (client_errors.ClientError, bool) {
   153  		return client_errors.ClientError{}, true
   154  	}
   155  	t.Run("error case - validator throws", func(t *testing.T) {
   156  		clientError := RandomClientError()
   157  		validator := func(updData values.ProfileUpdateData) (client_errors.ClientError, bool) {
   158  			if updData == testUpdateData {
   159  				return clientError, false
   160  			}
   161  			panic(fmt.Sprintf("validator called with unexpected args, updData=%v", updData))
   162  		}
   163  		sut := service.NewProfileUpdater(validator, nil, nil) // store is nil, since it shouldn't be accessed
   164  		_, gotErr := sut(user, testUpdateData)
   165  		AssertError(t, gotErr, clientError)
   166  	})
   167  	storeUpdater := func(id string, updData values.ProfileUpdateData) error {
   168  		if id == user.Id && updData == testUpdateData {
   169  			return nil
   170  		}
   171  		panic(fmt.Sprintf("update called with unexpected arguments: id: %v and updateData: %v", id, updData))
   172  	}
   173  	t.Run("error case - store throws an error", func(t *testing.T) {
   174  		storeUpdater := func(string, values.ProfileUpdateData) error {
   175  			return RandomError()
   176  		}
   177  		sut := service.NewProfileUpdater(validator, storeUpdater, nil)
   178  		_, err := sut(user, testUpdateData)
   179  		AssertSomeError(t, err)
   180  	})
   181  	wantUpdatedProfile := RandomContextedProfile()
   182  	profileGetter := func(target, caller core_values.UserId) (entities.ContextedProfile, error) {
   183  		if target == user.Id && caller == user.Id {
   184  			return wantUpdatedProfile, nil
   185  		}
   186  		panic("unexpected args")
   187  	}
   188  	t.Run("error case - getting updated profile throws", func(t *testing.T) {
   189  		tErr := RandomError()
   190  		profileGetter := func(target, caller core_values.UserId) (entities.ContextedProfile, error) {
   191  			return entities.ContextedProfile{}, tErr
   192  		}
   193  		_, err := service.NewProfileUpdater(validator, storeUpdater, profileGetter)(user, testUpdateData)
   194  		AssertError(t, err, tErr)
   195  	})
   196  	t.Run("happy case", func(t *testing.T) {
   197  		sut := service.NewProfileUpdater(validator, storeUpdater, profileGetter)
   198  
   199  		gotUpdatedProfile, err := sut(user, testUpdateData)
   200  		AssertNoError(t, err)
   201  		Assert(t, gotUpdatedProfile, wantUpdatedProfile, "the returned profile")
   202  	})
   203  }
   204  
   205  func TestAvatarUpdater(t *testing.T) {
   206  	user := RandomUser()
   207  	data := []byte(RandomString())
   208  	dataRef, _ := ref.NewRef(&data)
   209  	testAvatarData := values.AvatarData{
   210  		Data: dataRef,
   211  	}
   212  
   213  	silentValidator := func(values.AvatarData) (client_errors.ClientError, bool) {
   214  		return client_errors.ClientError{}, true
   215  	}
   216  
   217  	t.Run("happy case", func(t *testing.T) {
   218  		path := RandomString()
   219  		wantURL := static_store.PathToURL(path)
   220  		storeAvatar := func(userId string, avatarData values.AvatarData) (core_values.FileURL, error) {
   221  			if userId == user.Id && avatarData == testAvatarData {
   222  				return path, nil
   223  			}
   224  			panic(fmt.Sprintf("StoreAvatar called with unexpected arguments: userId=%v and avatarData=%v", userId, avatarData))
   225  		}
   226  		sut := service.NewAvatarUpdater(silentValidator, storeAvatar)
   227  
   228  		gotURL, err := sut(user, testAvatarData)
   229  		AssertNoError(t, err)
   230  		Assert(t, gotURL, wantURL, "returned profile")
   231  	})
   232  	t.Run("validator throws", func(t *testing.T) {
   233  		clientError := RandomClientError()
   234  		validator := func(avatar values.AvatarData) (client_errors.ClientError, bool) {
   235  			if avatar == testAvatarData {
   236  				return clientError, false
   237  			}
   238  			panic(fmt.Sprintf("validator called with unexpected args, avatar=%v", avatar))
   239  		}
   240  		sut := service.NewAvatarUpdater(validator, nil) // storeAvatar is nil, since it shouldn't be called
   241  
   242  		_, err := sut(user, testAvatarData)
   243  		AssertError(t, err, clientError)
   244  	})
   245  	t.Run("store throws an error", func(t *testing.T) {
   246  		storeAvatar := func(string, values.AvatarData) (core_values.FileURL, error) {
   247  			return "", RandomError()
   248  		}
   249  		sut := service.NewAvatarUpdater(silentValidator, storeAvatar)
   250  
   251  		_, err := sut(user, testAvatarData)
   252  		AssertSomeError(t, err)
   253  	})
   254  }