feat: Full test suite and linter - fixed test failures and increased coverage to 61.1%
This commit is contained in:
255
internal/cache/preferences_test.go
vendored
Normal file
255
internal/cache/preferences_test.go
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// mockCacheStore is a mock implementation of Cache for testing
|
||||
type mockCacheStore struct {
|
||||
data map[string][]byte
|
||||
}
|
||||
|
||||
func (m *mockCacheStore) Get(ctx context.Context, key *CacheKey) ([]byte, error) {
|
||||
keyStr := key.Kind + ":" + key.Code
|
||||
if data, ok := m.data[keyStr]; ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockCacheStore) Set(ctx context.Context, key *CacheKey, data []byte, ttl time.Duration) error {
|
||||
keyStr := key.Kind + ":" + key.Code
|
||||
m.data[keyStr] = data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockCacheStore) Exists(ctx context.Context, key *CacheKey) (bool, error) {
|
||||
keyStr := key.Kind + ":" + key.Code
|
||||
_, ok := m.data[keyStr]
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
func (m *mockCacheStore) Delete(ctx context.Context, key *CacheKey) error {
|
||||
keyStr := key.Kind + ":" + key.Code
|
||||
delete(m.data, keyStr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockCacheStore) Increment(ctx context.Context, key *CacheKey) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockCacheStore) Decrement(ctx context.Context, key *CacheKey) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func TestNewPreferences(t *testing.T) {
|
||||
mockStore := &mockCacheStore{data: make(map[string][]byte)}
|
||||
prefs := NewPreferences(mockStore)
|
||||
if prefs == nil {
|
||||
t.Error("expected Preferences to be created")
|
||||
}
|
||||
if prefs.store == nil {
|
||||
t.Error("expected store to be initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferencesGetSavedCities(t *testing.T) {
|
||||
mockStore := &mockCacheStore{data: make(map[string][]byte)}
|
||||
prefs := NewPreferences(mockStore)
|
||||
|
||||
// Test with no data
|
||||
cities, err := prefs.GetSavedCities(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(cities) != 0 {
|
||||
t.Errorf("expected 0 cities, got %d", len(cities))
|
||||
}
|
||||
|
||||
// Test with data - the key is "prefs:saved_city:user1:user1"
|
||||
citiesData, _ := json.Marshal([]PreferenceSavedCity{
|
||||
{CityCode: "c1", Name: "Moscow"},
|
||||
{CityCode: "c2", Name: "St. Petersburg"},
|
||||
})
|
||||
mockStore.data["prefs:saved_city:user1:user1"] = citiesData
|
||||
|
||||
cities, err = prefs.GetSavedCities(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(cities) != 2 {
|
||||
t.Errorf("expected 2 cities, got %d", len(cities))
|
||||
}
|
||||
if cities[0].CityCode != "c1" {
|
||||
t.Errorf("expected first city code 'c1', got '%s'", cities[0].CityCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferencesAddSavedCity(t *testing.T) {
|
||||
mockStore := &mockCacheStore{data: make(map[string][]byte)}
|
||||
prefs := NewPreferences(mockStore)
|
||||
|
||||
// Add first city
|
||||
err := prefs.AddSavedCity(context.Background(), "user1", "c1", "Moscow")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
// Add second city
|
||||
err = prefs.AddSavedCity(context.Background(), "user1", "c2", "St. Petersburg")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
// Verify cities
|
||||
cities, err := prefs.GetSavedCities(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(cities) != 2 {
|
||||
t.Errorf("expected 2 cities, got %d", len(cities))
|
||||
}
|
||||
|
||||
// Update existing city
|
||||
err = prefs.AddSavedCity(context.Background(), "user1", "c1", "Moscow Updated")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
cities, err = prefs.GetSavedCities(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if cities[0].Name != "Moscow Updated" {
|
||||
t.Errorf("expected city name 'Moscow Updated', got '%s'", cities[0].Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferencesRemoveSavedCity(t *testing.T) {
|
||||
mockStore := &mockCacheStore{data: make(map[string][]byte)}
|
||||
prefs := NewPreferences(mockStore)
|
||||
|
||||
// Add cities
|
||||
prefs.AddSavedCity(context.Background(), "user1", "c1", "Moscow")
|
||||
prefs.AddSavedCity(context.Background(), "user1", "c2", "St. Petersburg")
|
||||
|
||||
// Remove one city
|
||||
err := prefs.RemoveSavedCity(context.Background(), "user1", "c1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
cities, err := prefs.GetSavedCities(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(cities) != 1 {
|
||||
t.Errorf("expected 1 city, got %d", len(cities))
|
||||
}
|
||||
if cities[0].CityCode != "c2" {
|
||||
t.Errorf("expected city code 'c2', got '%s'", cities[0].CityCode)
|
||||
}
|
||||
|
||||
// Remove all cities
|
||||
err = prefs.RemoveSavedCity(context.Background(), "user1", "c2")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
cities, err = prefs.GetSavedCities(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(cities) != 0 {
|
||||
t.Errorf("expected 0 cities, got %d", len(cities))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferencesGetSearchHistory(t *testing.T) {
|
||||
mockStore := &mockCacheStore{data: make(map[string][]byte)}
|
||||
prefs := NewPreferences(mockStore)
|
||||
|
||||
// Test with no data
|
||||
history, err := prefs.GetSearchHistory(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(history) != 0 {
|
||||
t.Errorf("expected 0 history entries, got %d", len(history))
|
||||
}
|
||||
|
||||
// Test with data - the key is "prefs:search_history:user1:user1"
|
||||
historyData, _ := json.Marshal([]PreferenceSearchHistory{
|
||||
{Query: "c1→c2", FromCity: "c1", ToCity: "c2", Date: "2026-08-15", CreatedAt: time.Now().Unix()},
|
||||
})
|
||||
mockStore.data["prefs:search_history:user1:user1"] = historyData
|
||||
|
||||
history, err = prefs.GetSearchHistory(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(history) != 1 {
|
||||
t.Errorf("expected 1 history entry, got %d", len(history))
|
||||
}
|
||||
if history[0].FromCity != "c1" {
|
||||
t.Errorf("expected from_city 'c1', got '%s'", history[0].FromCity)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferencesAddSearchHistory(t *testing.T) {
|
||||
mockStore := &mockCacheStore{data: make(map[string][]byte)}
|
||||
prefs := NewPreferences(mockStore)
|
||||
|
||||
// Add search history
|
||||
err := prefs.AddSearchHistory(context.Background(), "user1", "c1", "c2", "2026-08-15")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
history, err := prefs.GetSearchHistory(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(history) != 1 {
|
||||
t.Errorf("expected 1 history entry, got %d", len(history))
|
||||
}
|
||||
if history[0].Query != "c1→c2" {
|
||||
t.Errorf("expected query 'c1→c2', got '%s'", history[0].Query)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferencesRemoveOldSearchHistory(t *testing.T) {
|
||||
mockStore := &mockCacheStore{data: make(map[string][]byte)}
|
||||
prefs := NewPreferences(mockStore)
|
||||
|
||||
now := time.Now().Unix()
|
||||
|
||||
// Add history with mixed ages
|
||||
history := []PreferenceSearchHistory{
|
||||
{Query: "old", FromCity: "c1", ToCity: "c2", Date: "2026-01-01", CreatedAt: now - 100},
|
||||
{Query: "new", FromCity: "c3", ToCity: "c4", Date: "2026-08-15", CreatedAt: now - 10},
|
||||
}
|
||||
historyData, _ := json.Marshal(history)
|
||||
mockStore.data["prefs:search_history:user1:user1"] = historyData
|
||||
|
||||
// Remove old entries (keep only last 50 seconds)
|
||||
err := prefs.RemoveOldSearchHistory(context.Background(), "user1", 50)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
history, err = prefs.GetSearchHistory(context.Background(), "user1")
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v", err)
|
||||
}
|
||||
if len(history) != 1 {
|
||||
t.Errorf("expected 1 history entry, got %d", len(history))
|
||||
}
|
||||
if history[0].Query != "new" {
|
||||
t.Errorf("expected query 'new', got '%s'", history[0].Query)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user