Files
openserp/google/search_test.go
2026-06-02 03:54:55 +03:00

397 lines
11 KiB
Go

package google
import (
"net/url"
"testing"
"github.com/karust/openserp/core"
)
func TestBuildSearchURL(t *testing.T) {
tests := []struct {
name string
query core.Query
wantErr bool
check func(*testing.T, url.Values, string)
}{
{
name: "combined params with unicode and start zero",
query: core.Query{
Text: "golang тест",
Site: "example.com",
Filetype: "pdf",
DateInterval: "20240101..20240131",
Limit: 50,
Start: 0,
Filter: false,
LangCode: "RU",
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.ru" {
t.Fatalf("unexpected host: %s", host)
}
if got := params.Get("q"); got != "golang тест site:example.com filetype:pdf" {
t.Fatalf("unexpected q value: %q", got)
}
if got := params.Get("oq"); got != params.Get("q") {
t.Fatalf("oq should match q, got %q vs %q", got, params.Get("q"))
}
if got := params.Get("tbs"); got != "cdr:1,cd_min:20240101,cd_max:20240131" {
t.Fatalf("unexpected tbs: %q", got)
}
if got := params.Get("num"); got != "50" {
t.Fatalf("unexpected num: %q", got)
}
if got := params.Get("start"); got != "" {
t.Fatalf("start should be omitted when Start=0, got %q", got)
}
if got := params.Get("filter"); got != "0" {
t.Fatalf("unexpected filter value: %q", got)
}
if got := params.Get("hl"); got != "ru" {
t.Fatalf("unexpected hl value: %q", got)
}
if got := params.Get("gl"); got != "ru" {
t.Fatalf("unexpected gl value: %q", got)
}
if got := params.Get("lr"); got != "lang_ru" {
t.Fatalf("unexpected lr value: %q", got)
}
if got := params.Get("pws"); got != "0" {
t.Fatalf("unexpected pws value: %q", got)
}
if got := params.Get("nfpr"); got != "1" {
t.Fatalf("unexpected nfpr value: %q", got)
}
},
},
{
name: "german language sets matching google locale params",
query: core.Query{
Text: "megadeth tickets",
Filter: true,
LangCode: "DE",
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.de" {
t.Fatalf("unexpected host: %s", host)
}
if got := params.Get("hl"); got != "de" {
t.Fatalf("unexpected hl value: %q", got)
}
if got := params.Get("gl"); got != "de" {
t.Fatalf("unexpected gl value: %q", got)
}
if got := params.Get("lr"); got != "lang_de" {
t.Fatalf("unexpected lr value: %q", got)
}
},
},
{
name: "region overrides google market without changing language",
query: core.Query{
Text: "weather",
LangCode: "en",
Region: "RU",
Filter: true,
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.ru" {
t.Fatalf("unexpected host: %s", host)
}
if got := params.Get("hl"); got != "en" {
t.Fatalf("unexpected hl value: %q", got)
}
if got := params.Get("gl"); got != "ru" {
t.Fatalf("unexpected gl value: %q", got)
}
if got := params.Get("lr"); got != "lang_en" {
t.Fatalf("unexpected lr value: %q", got)
}
},
},
{
name: "region only sets google market",
query: core.Query{
Text: "weather",
Region: "de",
Filter: true,
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.de" {
t.Fatalf("unexpected host: %s", host)
}
if got := params.Get("gl"); got != "de" {
t.Fatalf("unexpected gl value: %q", got)
}
if got := params.Get("hl"); got != "" {
t.Fatalf("hl should be omitted without language, got %q", got)
}
},
},
{
name: "curated city region resolves to canonical google uule without country market",
query: core.Query{
Text: "weather",
Region: "New York",
Filter: true,
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.com" {
t.Fatalf("unexpected host: %s", host)
}
// "New York" resolves to the exact Google canonical name
// "New York,New York,United States", which is what Google
// actually honors (a bare city name is ignored).
if got := params.Get("uule"); got != "w+CAIQICIfTmV3IFlvcmssTmV3IFlvcmssVW5pdGVkIFN0YXRlcw==" {
t.Fatalf("unexpected uule value: %q", got)
}
if got := params.Get("gl"); got != "" {
t.Fatalf("city region should not set gl, got %q", got)
}
},
},
{
name: "bare city Berlin resolves to canonical google uule",
query: core.Query{
Text: "weather",
Region: "Berlin",
Filter: true,
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
// region=Berlin -> "Berlin,Berlin,Germany" canonical, which is
// the form Google honors. A bare "Berlin" UULE is ignored.
if got := params.Get("uule"); got != "w+CAIQICIVQmVybGluLEJlcmxpbixHZXJtYW55" {
t.Fatalf("unexpected uule value: %q", got)
}
if got := params.Get("gl"); got != "" {
t.Fatalf("city region should not set gl, got %q", got)
}
},
},
{
name: "numeric yandex region does not set google market",
query: core.Query{
Text: "weather",
Region: "213",
Filter: true,
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.com" {
t.Fatalf("unexpected host: %s", host)
}
if got := params.Get("gl"); got != "" {
t.Fatalf("numeric region should not set gl, got %q", got)
}
if got := params.Get("uule"); got != "" {
t.Fatalf("numeric region should not set uule, got %q", got)
}
},
},
{
name: "site and filetype without text",
query: core.Query{
Site: "example.com",
Filetype: "txt",
Filter: true,
},
check: func(t *testing.T, params url.Values, _ string) {
t.Helper()
if got := params.Get("q"); got != " site:example.com filetype:txt" {
t.Fatalf("unexpected q value: %q", got)
}
if got := params.Get("filter"); got != "" {
t.Fatalf("filter should be omitted when Filter=true, got %q", got)
}
},
},
{
name: "very large start",
query: core.Query{
Text: "golang",
Start: 2147483647,
Filter: true,
},
check: func(t *testing.T, params url.Values, _ string) {
t.Helper()
if got := params.Get("start"); got != "2147483647" {
t.Fatalf("unexpected start value: %q", got)
}
},
},
{
name: "negative start returns error",
query: core.Query{
Text: "golang",
Start: -1,
},
wantErr: true,
},
{
name: "empty query returns error",
query: core.Query{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := BuildURL(tt.query)
if (err != nil) != tt.wantErr {
t.Fatalf("BuildURL() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantErr {
return
}
parsed, err := url.Parse(got)
if err != nil {
t.Fatalf("invalid URL returned: %v", err)
}
if tt.check != nil {
tt.check(t, parsed.Query(), parsed.Host)
}
})
}
}
func TestBuildImageSearchURL(t *testing.T) {
tests := []struct {
name string
query core.Query
wantErr bool
check func(*testing.T, url.Values, string)
}{
{
name: "combined params with unicode",
query: core.Query{
Text: "горы",
Site: "example.com",
Filetype: "jpg",
DateInterval: "20240301..20240315",
Limit: 25,
LangCode: "EN",
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.com" {
t.Fatalf("unexpected host: %s", host)
}
if got := params.Get("tbm"); got != "isch" {
t.Fatalf("unexpected tbm: %q", got)
}
if got := params.Get("q"); got != "горы site:example.com filetype:jpg" {
t.Fatalf("unexpected q value: %q", got)
}
if got := params.Get("oq"); got != params.Get("q") {
t.Fatalf("oq should match q, got %q vs %q", got, params.Get("q"))
}
if got := params.Get("num"); got != "25" {
t.Fatalf("unexpected num value: %q", got)
}
if got := params.Get("tbs"); got != "cdr:1,cd_min:20240301,cd_max:20240315" {
t.Fatalf("unexpected tbs value: %q", got)
}
if got := params.Get("hl"); got != "en" {
t.Fatalf("unexpected hl value: %q", got)
}
if got := params.Get("gl"); got != "us" {
t.Fatalf("unexpected gl value: %q", got)
}
if got := params.Get("lr"); got != "lang_en" {
t.Fatalf("unexpected lr value: %q", got)
}
},
},
{
name: "image region overrides google market",
query: core.Query{
Text: "mountains",
LangCode: "en",
Region: "GB",
},
check: func(t *testing.T, params url.Values, host string) {
t.Helper()
if host != "www.google.co.uk" {
t.Fatalf("unexpected host: %s", host)
}
if got := params.Get("gl"); got != "gb" {
t.Fatalf("unexpected gl value: %q", got)
}
if got := params.Get("hl"); got != "en" {
t.Fatalf("unexpected hl value: %q", got)
}
},
},
{
name: "invalid date interval returns error",
query: core.Query{
Text: "golang",
DateInterval: "20240101",
},
wantErr: true,
},
{
name: "empty query returns error",
query: core.Query{
Text: "",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := BuildImageURL(tt.query)
if (err != nil) != tt.wantErr {
t.Fatalf("BuildImageURL() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantErr {
return
}
parsed, err := url.Parse(got)
if err != nil {
t.Fatalf("invalid URL returned: %v", err)
}
if tt.check != nil {
tt.check(t, parsed.Query(), parsed.Host)
}
})
}
}
func TestParseSourceImageURL(t *testing.T) {
//href1 := `/imgres?imgurl=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F2%2F26%2FMarmota_marmota_Alpes2.jpg&tbnid=Be_RycOe8xzlpM&vet=12ahUKEwjkh6WzwIeAAxWV_yoKHRzHC9wQMygAegUIARD0AQ..i&imgrefurl=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FAlpine_marmot&docid=7miWbc2QiSw9uM&w=801&h=599&q=alpine%20marmot&ved=2ahUKEwjkh6WzwIeAAxWV_yoKHRzHC9wQMygAegUIARD0AQ`
href2 := `/imgres?imgurl=https%3A%2F%2Fstatic.wikia.nocookie.net%2Fnaturerules1%2Fimages%2Ff%2Ff2%2F13d79d934ccf6f7919777fcb6dbb6e6c.jpg%2Frevision%2Flatest%3Fcb%3D20210218225522&tbnid=JxC8NUyBjdNbdM&vet=12ahUKEwiHrJnN1YeAAxXvEBAIHfRADAAQMygCegUIARD4AQ..i&imgrefurl=https%3A%2F%2Fnaturerules1.fandom.com%2Fwiki%2FAlpine_Marmot&docid=XXYeDjL67badNM&w=1600&h=1200&q=alpine%20marmot&ved=2ahUKEwiHrJnN1YeAAxXvEBAIHfRADAAQMygCegUIARD4AQ`
want := SourceImage{
OriginalURL: "https://static.wikia.nocookie.net/naturerules1/images/f/f2/13d79d934ccf6f7919777fcb6dbb6e6c.jpg/revision/latest?cb=20210218225522",
PageURL: "https://naturerules1.fandom.com/wiki/Alpine_Marmot",
Width: "1600",
Height: "1200",
}
got, err := parseSourceImageURL(href2)
if err != nil {
t.Fatal(err)
}
if want != got {
t.Fatalf("Want: %v, Got: %v", want, got)
}
}
func TestSolveCaptchaWithoutConfiguredSolverReturnsFalse(t *testing.T) {
gogl := New(core.Browser{}, core.SearchEngineOptions{})
if got := gogl.solveCaptcha(nil, "sitekey", "datas", ""); got {
t.Fatal("expected solveCaptcha to fail without solver/page context")
}
}