- /api/search traduit les filtres en requête GitHub (langage, étoiles, activité, création, licence, topic, forks, archivés, good first issues) - cache mémoire des recherches identiques (CACHE_TTL) et suivi du quota - /api/status, /healthz, authentification basique optionnelle - Dockerfile et docker-compose.yml Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
53 lines
1.4 KiB
Go
53 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"net/url"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestQuery(t *testing.T) {
|
|
now := time.Date(2026, 10, 1, 12, 0, 0, 0, time.UTC)
|
|
tests := []struct {
|
|
params string
|
|
want string
|
|
}{
|
|
{"", "archived:false stars:>=1"},
|
|
{"q=log+viewer&in=name", "log viewer in:name archived:false"},
|
|
{"language=Go&stars=100", "language:Go stars:>=100 archived:false"},
|
|
{"stars=10&maxstars=500&minforks=5", "stars:10..500 forks:>=5 archived:false"},
|
|
{"topic=CLI&license=MIT&archived=1&forks=1", "topic:cli license:mit fork:true"},
|
|
{"q=syslog&pushed=1y&created=1m&goodfirst=1", "syslog pushed:>=2025-10-01 created:>=2026-09-01 archived:false good-first-issues:>0"},
|
|
}
|
|
for _, tt := range tests {
|
|
v, _ := url.ParseQuery(tt.params)
|
|
c, err := ParseCriteria(v)
|
|
if err != nil {
|
|
t.Fatalf("%q: %v", tt.params, err)
|
|
}
|
|
if got := c.Query(now); got != tt.want {
|
|
t.Errorf("%q:\n got %q\n want %q", tt.params, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseCriteriaErrors(t *testing.T) {
|
|
for _, p := range []string{
|
|
"stars=-1", "stars=abc", "pushed=3d", "sort=name", "in=code",
|
|
"language=go%20lang%3Arm", "topic=a:b", "page=40&per_page=30",
|
|
} {
|
|
v, _ := url.ParseQuery(p)
|
|
if _, err := ParseCriteria(v); err == nil {
|
|
t.Errorf("%q: expected an error", p)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPerPageCap(t *testing.T) {
|
|
v, _ := url.ParseQuery("per_page=500")
|
|
c, err := ParseCriteria(v)
|
|
if err != nil || c.PerPage != 100 {
|
|
t.Fatalf("per_page=500: got %d, %v", c.PerPage, err)
|
|
}
|
|
}
|