All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 8m16s
146 lines
4.4 KiB
Go
146 lines
4.4 KiB
Go
package common
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/perfect-panel/server/internal/config"
|
|
"github.com/perfect-panel/server/internal/svc"
|
|
"github.com/redis/go-redis/v9"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func buildInviteResolverForTest(t *testing.T, cfg config.Config) (*InviteLinkResolver, *miniredis.Miniredis) {
|
|
t.Helper()
|
|
|
|
redisServer, err := miniredis.Run()
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
redisServer.Close()
|
|
})
|
|
|
|
redisClient := redis.NewClient(&redis.Options{
|
|
Addr: redisServer.Addr(),
|
|
DB: 0,
|
|
})
|
|
t.Cleanup(func() {
|
|
_ = redisClient.Close()
|
|
})
|
|
|
|
serviceCtx := &svc.ServiceContext{
|
|
Config: cfg,
|
|
Redis: redisClient,
|
|
}
|
|
|
|
resolver := NewInviteLinkResolver(context.Background(), serviceCtx)
|
|
return resolver, redisServer
|
|
}
|
|
|
|
func TestInviteLinkResolverResolveInviteLink(t *testing.T) {
|
|
t.Run("kutt disabled returns long link", func(t *testing.T) {
|
|
cfg := config.Config{}
|
|
cfg.Kutt.TargetURL = "https://example.com/register"
|
|
|
|
resolver, _ := buildInviteResolverForTest(t, cfg)
|
|
link := resolver.ResolveInviteLink("abc123")
|
|
require.Equal(t, "https://example.com/register?ic=abc123", link)
|
|
})
|
|
|
|
t.Run("cache hit returns cached short link", func(t *testing.T) {
|
|
cfg := config.Config{}
|
|
cfg.Kutt.Enable = true
|
|
cfg.Kutt.ApiURL = "https://kutt.local/api/v2"
|
|
cfg.Kutt.ApiKey = "token"
|
|
cfg.Kutt.TargetURL = "https://example.com/register"
|
|
|
|
resolver, redisServer := buildInviteResolverForTest(t, cfg)
|
|
redisServer.Set(inviteShortLinkCachePrefix+"abc123", "https://sho.rt/cached")
|
|
|
|
called := 0
|
|
resolver.createShortLink = func(ctx context.Context, targetURL, domain string) (string, error) {
|
|
called++
|
|
return "", errors.New("should not call createShortLink on cache hit")
|
|
}
|
|
|
|
link := resolver.ResolveInviteLink("abc123")
|
|
require.Equal(t, "https://sho.rt/cached", link)
|
|
require.Equal(t, 0, called)
|
|
})
|
|
|
|
t.Run("cache miss kutt success returns short link and writes cache", func(t *testing.T) {
|
|
cfg := config.Config{}
|
|
cfg.Kutt.Enable = true
|
|
cfg.Kutt.ApiURL = "https://kutt.local/api/v2"
|
|
cfg.Kutt.ApiKey = "token"
|
|
cfg.Kutt.TargetURL = "https://example.com/register"
|
|
|
|
resolver, _ := buildInviteResolverForTest(t, cfg)
|
|
resolver.createShortLink = func(ctx context.Context, targetURL, domain string) (string, error) {
|
|
return "https://sho.rt/new", nil
|
|
}
|
|
|
|
link := resolver.ResolveInviteLink("abc123")
|
|
require.Equal(t, "https://sho.rt/new", link)
|
|
|
|
cached := resolver.getCachedShortLink("abc123")
|
|
require.Equal(t, "https://sho.rt/new", cached)
|
|
})
|
|
|
|
t.Run("kutt failure falls back to long link", func(t *testing.T) {
|
|
cfg := config.Config{}
|
|
cfg.Kutt.Enable = true
|
|
cfg.Kutt.ApiURL = "https://kutt.local/api/v2"
|
|
cfg.Kutt.ApiKey = "token"
|
|
cfg.Kutt.TargetURL = "https://example.com/register"
|
|
|
|
resolver, _ := buildInviteResolverForTest(t, cfg)
|
|
resolver.createShortLink = func(ctx context.Context, targetURL, domain string) (string, error) {
|
|
return "", errors.New("kutt request failed")
|
|
}
|
|
|
|
link := resolver.ResolveInviteLink("abc123")
|
|
require.Equal(t, "https://example.com/register?ic=abc123", link)
|
|
})
|
|
|
|
t.Run("long link preserves existing query string", func(t *testing.T) {
|
|
cfg := config.Config{}
|
|
cfg.Kutt.TargetURL = "https://example.com/register?channel=ios"
|
|
|
|
resolver, _ := buildInviteResolverForTest(t, cfg)
|
|
link := resolver.ResolveInviteLink("abc123")
|
|
parsed, err := url.Parse(link)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "https", parsed.Scheme)
|
|
require.Equal(t, "example.com", parsed.Host)
|
|
require.Equal(t, "/register", parsed.Path)
|
|
require.Equal(t, "ios", parsed.Query().Get("channel"))
|
|
require.Equal(t, "abc123", parsed.Query().Get("ic"))
|
|
})
|
|
|
|
t.Run("kutt target preserves existing query string", func(t *testing.T) {
|
|
cfg := config.Config{}
|
|
cfg.Kutt.Enable = true
|
|
cfg.Kutt.ApiURL = "https://kutt.local/api/v2"
|
|
cfg.Kutt.ApiKey = "token"
|
|
cfg.Kutt.TargetURL = "https://example.com/register?channel=ios"
|
|
|
|
resolver, _ := buildInviteResolverForTest(t, cfg)
|
|
capturedTargetURL := ""
|
|
resolver.createShortLink = func(ctx context.Context, targetURL, domain string) (string, error) {
|
|
capturedTargetURL = targetURL
|
|
return "https://sho.rt/query", nil
|
|
}
|
|
|
|
link := resolver.ResolveInviteLink("abc123")
|
|
require.Equal(t, "https://sho.rt/query", link)
|
|
|
|
parsed, err := url.Parse(capturedTargetURL)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "ios", parsed.Query().Get("channel"))
|
|
require.Equal(t, "abc123", parsed.Query().Get("ic"))
|
|
})
|
|
}
|