- 新增 AdminSessionRecover:后台离线/后端重启时自动重试恢复会话,明确失效才回跳登录 - 认证 cookie 契约调整(SameSite=Lax 与刷新轮转适配),路由与守卫适配 - 访问来源统计查询优化与测试、管理端 analytics sources 页面适配 - 移动端布局修正:覆盖 body min-h-screen 避免内容区高度异常
55 lines
2.3 KiB
Go
55 lines
2.3 KiB
Go
package service
|
|
|
|
import "testing"
|
|
|
|
func TestClassifyReferrer(t *testing.T) {
|
|
cases := []struct {
|
|
raw, siteHost string
|
|
wantHost string
|
|
wantKind string
|
|
}{
|
|
{"", "example.com", "", RefKindDirect},
|
|
{"not a url", "example.com", "", RefKindDirect},
|
|
{"https://example.com/posts/1", "example.com", "example.com", RefKindInternal},
|
|
{"https://www.google.com/search?q=x", "example.com", "www.google.com", RefKindSearch},
|
|
{"https://www.baidu.com/s?wd=x", "example.com", "www.baidu.com", RefKindSearch},
|
|
{"https://cn.bing.com/search?q=x", "example.com", "cn.bing.com", RefKindSearch},
|
|
{"https://weibo.com/abc", "example.com", "weibo.com", RefKindSocial},
|
|
{"https://x.com/user/status/1", "example.com", "x.com", RefKindSocial},
|
|
{"https://v2ex.com/t/123", "example.com", "v2ex.com", RefKindSocial},
|
|
{"https://blog.other.org/post", "example.com", "blog.other.org", RefKindExternal},
|
|
{"https://google.com:443/search?q=x", "example.com", "google.com", RefKindSearch},
|
|
{"https://evil.com/?u=https://google.com", "example.com", "evil.com", RefKindExternal},
|
|
}
|
|
for _, c := range cases {
|
|
host, kind := ClassifyReferrer(c.raw, c.siteHost)
|
|
if host != c.wantHost || kind != c.wantKind {
|
|
t.Errorf("ClassifyReferrer(%q, %q) = (%q, %q), want (%q, %q)",
|
|
c.raw, c.siteHost, host, kind, c.wantHost, c.wantKind)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDecodeSearchTerm(t *testing.T) {
|
|
// 「新人报道」的 UTF-8 百分号编码前缀,模拟 512 字节截断
|
|
news := "%E6%96%B0%E4%BA%BA%E6%8A%A5%E9%81%93"
|
|
cases := []struct {
|
|
raw string
|
|
want string
|
|
}{
|
|
{"%E4%BD%A0%E5%A5%BD", "你好"}, // 完整编码
|
|
{"a+b", "a b"}, // + 按空格解码
|
|
{"plain", "plain"}, // 无编码
|
|
{"2222%E5%A6%82%E6%9E%9C", "2222如果"}, // 完整转义结尾
|
|
{news + "%E6%96", "新人报道"}, // 截断后结尾是完整转义但只是半截字符 → 去非法 UTF-8 尾巴
|
|
{news + "%E6%96%9", "新人报道"}, // 一位十六进制的残缺转义 → 剥尾重试 + 去半截字符
|
|
{news + "%", "新人报道"}, // 截断在孤立的 %
|
|
{news + "%E", "新人报道"}, // 截断在 1 位十六进制
|
|
}
|
|
for _, c := range cases {
|
|
if got := decodeSearchTerm(c.raw); got != c.want {
|
|
t.Errorf("decodeSearchTerm(%q) = %q, want %q", c.raw, got, c.want)
|
|
}
|
|
}
|
|
}
|