tailly_subscribers/server_test.go
admin 38d91d9f10
All checks were successful
continuous-integration/drone/push Build is passing
v.0.1 Создан микросервис подписок/подписчиков
2025-08-26 09:50:45 +03:00

409 lines
10 KiB
Go

package main
import (
"context"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"tailly_subscribers/proto"
"testing"
)
func setupTestDB(t *testing.T) *pgxpool.Pool {
dbURL := "postgres://tailly_v2:i0Oq%2675LA%26M612ceuy@79.174.89.104:15452/tailly_v2"
pool, err := pgxpool.Connect(context.Background(), dbURL)
if err != nil {
t.Fatalf("Failed to connect to database: %v", err)
}
// ОЧИСТКА ТЕСТОВЫХ ДАННЫХ ПЕРЕД ТЕСТАМИ
_, err = pool.Exec(context.Background(), "DELETE FROM subscription_notifications")
if err != nil {
t.Fatalf("Failed to clean notifications: %v", err)
}
_, err = pool.Exec(context.Background(), "DELETE FROM subscriptions")
if err != nil {
t.Fatalf("Failed to clean subscriptions: %v", err)
}
return pool
}
func TestFollowUser(t *testing.T) {
db := setupTestDB(t)
server := NewServer(db)
tests := []struct {
name string
req *proto.FollowRequest
expectError bool
errorCode codes.Code
}{
{
name: "Success - user 1 follows user 2",
req: &proto.FollowRequest{FollowerId: 1, FollowingId: 2},
expectError: false,
},
{
name: "Success - user 2 follows user 3",
req: &proto.FollowRequest{FollowerId: 2, FollowingId: 3},
expectError: false,
},
{
name: "Error - self follow",
req: &proto.FollowRequest{FollowerId: 1, FollowingId: 1},
expectError: true,
errorCode: codes.InvalidArgument,
},
{
name: "Error - non-existent user", // ИЗМЕНИЛОСЬ: теперь Internal error из-за foreign key
req: &proto.FollowRequest{FollowerId: 1, FollowingId: 999},
expectError: true,
errorCode: codes.Internal, // Foreign key violation
},
{
name: "Error - zero IDs",
req: &proto.FollowRequest{FollowerId: 0, FollowingId: 0},
expectError: true,
errorCode: codes.InvalidArgument,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
resp, err := server.FollowUser(ctx, tt.req)
if tt.expectError {
assert.Error(t, err)
if st, ok := status.FromError(err); ok {
assert.Equal(t, tt.errorCode, st.Code())
}
} else {
assert.NoError(t, err)
assert.True(t, resp.Success)
assert.Contains(t, resp.Message, "Successfully")
}
})
}
}
func TestUnfollowUser(t *testing.T) {
db := setupTestDB(t)
server := NewServer(db)
// Сначала создаем подписки для тестов
server.FollowUser(context.Background(), &proto.FollowRequest{FollowerId: 1, FollowingId: 2})
server.FollowUser(context.Background(), &proto.FollowRequest{FollowerId: 1, FollowingId: 3})
tests := []struct {
name string
req *proto.UnfollowRequest
expectError bool
errorCode codes.Code
success bool
}{
{
name: "Success - user 1 unfollows user 2",
req: &proto.UnfollowRequest{FollowerId: 1, FollowingId: 2},
expectError: false,
success: true,
},
{
name: "Success - user 1 unfollows user 3",
req: &proto.UnfollowRequest{FollowerId: 1, FollowingId: 3},
expectError: false,
success: true,
},
{
name: "Success - non-existent subscription", // ИЗМЕНИЛОСЬ: не ошибка
req: &proto.UnfollowRequest{FollowerId: 1, FollowingId: 999},
expectError: false,
success: false,
},
{
name: "Error - non-existent user", // ИЗМЕНИЛОСЬ: не ошибка, просто false
req: &proto.UnfollowRequest{FollowerId: 999, FollowingId: 1},
expectError: false,
success: false,
},
{
name: "Error - zero IDs",
req: &proto.UnfollowRequest{FollowerId: 0, FollowingId: 0},
expectError: true,
errorCode: codes.InvalidArgument,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
resp, err := server.UnfollowUser(ctx, tt.req)
if tt.expectError {
assert.Error(t, err)
if st, ok := status.FromError(err); ok {
assert.Equal(t, tt.errorCode, st.Code())
}
} else {
assert.NoError(t, err)
assert.Equal(t, tt.success, resp.Success)
if tt.success {
assert.Contains(t, resp.Message, "Successfully")
} else {
assert.Contains(t, resp.Message, "not found")
}
}
})
}
}
func TestGetFollowersCount(t *testing.T) {
db := setupTestDB(t)
server := NewServer(db)
tests := []struct {
name string
req *proto.GetCountRequest
expected int32
expectError bool
errorCode codes.Code
}{
{
name: "Success - user 2 has 0 followers initially",
req: &proto.GetCountRequest{UserId: 2},
expected: 0,
expectError: false,
},
{
name: "Success - user 1 has 0 followers",
req: &proto.GetCountRequest{UserId: 1},
expected: 0,
expectError: false,
},
{
name: "Success - user 3 has 0 followers",
req: &proto.GetCountRequest{UserId: 3},
expected: 0,
expectError: false,
},
{
name: "Success - non-existent user returns 0",
req: &proto.GetCountRequest{UserId: 999},
expected: 0,
expectError: false,
},
{
name: "Error - zero user ID",
req: &proto.GetCountRequest{UserId: 0},
expectError: true,
errorCode: codes.InvalidArgument,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
resp, err := server.GetFollowersCount(ctx, tt.req)
if tt.expectError {
assert.Error(t, err)
if st, ok := status.FromError(err); ok {
assert.Equal(t, tt.errorCode, st.Code())
}
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expected, resp.Count)
}
})
}
}
func TestGetFollowingCount(t *testing.T) {
db := setupTestDB(t)
server := NewServer(db)
tests := []struct {
name string
req *proto.GetCountRequest
expected int32
expectError bool
errorCode codes.Code
}{
{
name: "Success - user 2 follows 0 users initially",
req: &proto.GetCountRequest{UserId: 2},
expected: 0,
expectError: false,
},
{
name: "Success - user 1 follows 0 users",
req: &proto.GetCountRequest{UserId: 1},
expected: 0,
expectError: false,
},
{
name: "Success - user 3 follows 0 users",
req: &proto.GetCountRequest{UserId: 3},
expected: 0,
expectError: false,
},
{
name: "Success - non-existent user returns 0",
req: &proto.GetCountRequest{UserId: 999},
expected: 0,
expectError: false,
},
{
name: "Error - zero user ID",
req: &proto.GetCountRequest{UserId: 0},
expectError: true,
errorCode: codes.InvalidArgument,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
resp, err := server.GetFollowingCount(ctx, tt.req)
if tt.expectError {
assert.Error(t, err)
if st, ok := status.FromError(err); ok {
assert.Equal(t, tt.errorCode, st.Code())
}
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expected, resp.Count)
}
})
}
}
func TestGetFollowers(t *testing.T) {
db := setupTestDB(t)
server := NewServer(db)
tests := []struct {
name string
req *proto.GetFollowersRequest
expectedCount int
expectError bool
errorCode codes.Code
}{
{
name: "Success - user 2 has 0 followers initially",
req: &proto.GetFollowersRequest{UserId: 2, Limit: 10, Offset: 0},
expectedCount: 0,
expectError: false,
},
{
name: "Success - user 1 has 0 followers",
req: &proto.GetFollowersRequest{UserId: 1, Limit: 10, Offset: 0},
expectedCount: 0,
expectError: false,
},
{
name: "Success - get with limit 0",
req: &proto.GetFollowersRequest{UserId: 2, Limit: 0, Offset: 0},
expectedCount: 0,
expectError: false,
},
{
name: "Success - non-existent user returns empty list",
req: &proto.GetFollowersRequest{UserId: 999, Limit: 10, Offset: 0},
expectError: false,
},
{
name: "Error - zero user ID",
req: &proto.GetFollowersRequest{UserId: 0, Limit: 10, Offset: 0},
expectError: true,
errorCode: codes.InvalidArgument,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
resp, err := server.GetFollowers(ctx, tt.req)
if tt.expectError {
assert.Error(t, err)
if st, ok := status.FromError(err); ok {
assert.Equal(t, tt.errorCode, st.Code())
}
} else {
assert.NoError(t, err)
if tt.expectedCount >= 0 {
assert.Len(t, resp.Followers, tt.expectedCount)
}
assert.NotNil(t, resp.TotalCount)
}
})
}
}
func TestGetFollowing(t *testing.T) {
db := setupTestDB(t)
server := NewServer(db)
tests := []struct {
name string
req *proto.GetFollowingRequest
expectedCount int
expectError bool
errorCode codes.Code
}{
{
name: "Success - user 2 follows 0 users initially",
req: &proto.GetFollowingRequest{UserId: 2, Limit: 10, Offset: 0},
expectedCount: 0,
expectError: false,
},
{
name: "Success - user 1 follows 0 users",
req: &proto.GetFollowingRequest{UserId: 1, Limit: 10, Offset: 0},
expectedCount: 0,
expectError: false,
},
{
name: "Success - get with limit 0",
req: &proto.GetFollowingRequest{UserId: 2, Limit: 0, Offset: 0},
expectedCount: 0,
expectError: false,
},
{
name: "Success - non-existent user returns empty list",
req: &proto.GetFollowingRequest{UserId: 999, Limit: 10, Offset: 0},
expectError: false,
},
{
name: "Error - zero user ID",
req: &proto.GetFollowingRequest{UserId: 0, Limit: 10, Offset: 0},
expectError: true,
errorCode: codes.InvalidArgument,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
resp, err := server.GetFollowing(ctx, tt.req)
if tt.expectError {
assert.Error(t, err)
if st, ok := status.FromError(err); ok {
assert.Equal(t, tt.errorCode, st.Code())
}
} else {
assert.NoError(t, err)
if tt.expectedCount >= 0 {
assert.Len(t, resp.Following, tt.expectedCount)
}
assert.NotNil(t, resp.TotalCount)
}
})
}
}