diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 885624ae..1e668a1d 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -40,18 +40,10 @@ The `cdp` requests of each test will be recorded and output to folder `tmp/cdp-l
[artifacts](https://docs.github.com/en/actions/guides/storing-workflow-data-as-artifacts) so that we can download
them for debugging.
-### Filter tests
-
-Use regex: `go test -run /^Click$`.
-
-Test a specific package: `go test ./lib/launcher`.
-
-Run all tests: `go test ./...`
-
### Disable headless mode
```bash
-rod=show,trace,slow=2s go test -run /Click
+rod=show,trace,slow=2s go test
```
Check type `defaults.ResetWithEnv` for how it works.
@@ -98,7 +90,7 @@ There are several helper functions for it:
1. Run lint in the container: `go run ./lib/utils/lint`
-1. Run tests in the container: `go test -run /Click`
+1. Run tests in the container: `go test`
1. After you exit the container with `exit`, you can restart it by: `docker start -i rod`
diff --git a/browser_test.go b/browser_test.go
index 7ea0faf5..968347d4 100644
--- a/browser_test.go
+++ b/browser_test.go
@@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"runtime"
+ "testing"
"time"
"github.com/go-rod/rod"
@@ -20,110 +21,124 @@ import (
"github.com/ysmood/gson"
)
-func (t T) Incognito() {
- k := t.Srand(16)
+func TestIncognito(t *testing.T) {
+ g := setup(t)
- b := t.browser.MustIncognito().Sleeper(rod.DefaultSleeper)
+ k := g.RandStr(16)
+
+ b := g.browser.MustIncognito().Sleeper(rod.DefaultSleeper)
defer b.MustClose()
- page := b.MustPage(t.blank())
+ page := b.MustPage(g.blank())
defer page.MustClose()
page.MustEval(`k => localStorage[k] = 1`, k)
- t.True(t.page.MustNavigate(t.blank()).MustEval(`k => localStorage[k]`, k).Nil())
- t.Eq(page.MustEval(`k => localStorage[k]`, k).Str(), "1") // localStorage can only store string
+ g.True(g.page.MustNavigate(g.blank()).MustEval(`k => localStorage[k]`, k).Nil())
+ g.Eq(page.MustEval(`k => localStorage[k]`, k).Str(), "1") // localStorage can only store string
}
-func (t T) BrowserResetControlURL() {
+func TestBrowserResetControlURL(t *testing.T) {
rod.New().ControlURL("test").ControlURL("")
}
-func (t T) DefaultDevice() {
+func TestDefaultDevice(t *testing.T) {
+ g := setup(t)
+
ua := ""
- s := t.Serve()
+ s := g.Serve()
s.Mux.HandleFunc("/t", func(rw http.ResponseWriter, r *http.Request) {
ua = r.Header.Get("User-Agent")
})
- t.browser.DefaultDevice(devices.IPhoneX)
- defer t.browser.DefaultDevice(devices.LaptopWithMDPIScreen.Landescape())
+ g.browser.DefaultDevice(devices.IPhoneX)
+ defer g.browser.DefaultDevice(devices.LaptopWithMDPIScreen.Landescape())
- t.newPage(s.URL("/t"))
- t.Eq(ua, devices.IPhoneX.UserAgentEmulation().UserAgent)
+ g.newPage(s.URL("/t"))
+ g.Eq(ua, devices.IPhoneX.UserAgentEmulation().UserAgent)
- t.browser.NoDefaultDevice()
- t.newPage(s.URL("/t"))
- t.Neq(ua, devices.IPhoneX.UserAgentEmulation().UserAgent)
+ g.browser.NoDefaultDevice()
+ g.newPage(s.URL("/t"))
+ g.Neq(ua, devices.IPhoneX.UserAgentEmulation().UserAgent)
}
-func (t T) PageErr() {
- t.Panic(func() {
- t.mc.stubErr(1, proto.TargetAttachToTarget{})
- t.browser.MustPage()
+func TestPageErr(t *testing.T) {
+ g := setup(t)
+
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.TargetAttachToTarget{})
+ g.browser.MustPage()
})
}
-func (t T) PageFromTarget() {
- t.Panic(func() {
- res, err := proto.TargetCreateTarget{URL: "about:blank"}.Call(t.browser)
- t.E(err)
+func TestPageFromTarget(t *testing.T) {
+ g := setup(t)
+
+ g.Panic(func() {
+ res, err := proto.TargetCreateTarget{URL: "about:blank"}.Call(g.browser)
+ g.E(err)
defer func() {
- t.browser.MustPageFromTargetID(res.TargetID).MustClose()
+ g.browser.MustPageFromTargetID(res.TargetID).MustClose()
}()
- t.mc.stubErr(1, proto.EmulationSetDeviceMetricsOverride{})
- t.browser.MustPageFromTargetID(res.TargetID)
+ g.mc.stubErr(1, proto.EmulationSetDeviceMetricsOverride{})
+ g.browser.MustPageFromTargetID(res.TargetID)
})
}
-func (t T) BrowserPages() {
- t.newPage(t.blank()).MustWaitLoad()
+func TestBrowserPages(t *testing.T) {
+ g := setup(t)
+
+ g.newPage(g.blank()).MustWaitLoad()
- pages := t.browser.MustPages()
+ pages := g.browser.MustPages()
- t.Len(pages, 3)
+ g.Len(pages, 3)
{
- t.mc.stub(1, proto.TargetGetTargets{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.TargetGetTargets{}, func(send StubSend) (gson.JSON, error) {
d, _ := send()
return *d.Set("targetInfos.0.type", "iframe"), nil
})
- pages := t.browser.MustPages()
- t.Len(pages, 2)
+ pages := g.browser.MustPages()
+ g.Len(pages, 2)
}
- t.Panic(func() {
- t.mc.stubErr(1, proto.TargetCreateTarget{})
- t.browser.MustPage()
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.TargetCreateTarget{})
+ g.browser.MustPage()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.TargetGetTargets{})
- t.browser.MustPages()
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.TargetGetTargets{})
+ g.browser.MustPages()
})
- t.Panic(func() {
- res, err := proto.TargetCreateTarget{URL: "about:blank"}.Call(t.browser)
- t.E(err)
+ g.Panic(func() {
+ res, err := proto.TargetCreateTarget{URL: "about:blank"}.Call(g.browser)
+ g.E(err)
defer func() {
- t.browser.MustPageFromTargetID(res.TargetID).MustClose()
+ g.browser.MustPageFromTargetID(res.TargetID).MustClose()
}()
- t.mc.stubErr(1, proto.TargetAttachToTarget{})
- t.browser.MustPages()
+ g.mc.stubErr(1, proto.TargetAttachToTarget{})
+ g.browser.MustPages()
})
}
-func (t T) BrowserClearStates() {
- t.E(proto.EmulationClearGeolocationOverride{}.Call(t.page))
+func TestBrowserClearStates(t *testing.T) {
+ g := setup(t)
+
+ g.E(proto.EmulationClearGeolocationOverride{}.Call(g.page))
}
-func (t T) BrowserEvent() {
- messages := t.browser.Context(t.Context()).Event()
- p := t.newPage()
+func TestBrowserEvent(t *testing.T) {
+ g := setup(t)
+
+ messages := g.browser.Context(g.Context()).Event()
+ p := g.newPage()
wait := make(chan struct{})
for msg := range messages {
e := proto.TargetAttachedToTarget{}
if msg.Load(&e) {
- t.Eq(e.TargetInfo.TargetID, p.TargetID)
+ g.Eq(e.TargetInfo.TargetID, p.TargetID)
close(wait)
break
}
@@ -131,7 +146,7 @@ func (t T) BrowserEvent() {
<-wait
}
-func (t T) BrowserEventClose() {
+func TestBrowserEventClose(t *testing.T) {
event := make(chan *cdp.Event)
c := &MockClient{
connect: func() error { return nil },
@@ -146,26 +161,30 @@ func (t T) BrowserEventClose() {
close(event)
}
-func (t T) BrowserWaitEvent() {
- t.NotNil(t.browser.Context(t.Context()).Event())
+func TestBrowserWaitEvent(t *testing.T) {
+ g := setup(t)
+
+ g.NotNil(g.browser.Context(g.Context()).Event())
- wait := t.page.WaitEvent(proto.PageFrameNavigated{})
- t.page.MustNavigate(t.blank())
+ wait := g.page.WaitEvent(proto.PageFrameNavigated{})
+ g.page.MustNavigate(g.blank())
wait()
- wait = t.browser.EachEvent(func(e *proto.PageFrameNavigated, id proto.TargetSessionID) bool {
+ wait = g.browser.EachEvent(func(e *proto.PageFrameNavigated, id proto.TargetSessionID) bool {
return true
})
- t.page.MustNavigate(t.blank())
+ g.page.MustNavigate(g.blank())
wait()
}
-func (t T) BrowserCrash() {
- browser := rod.New().Context(t.Context()).MustConnect()
+func TestBrowserCrash(t *testing.T) {
+ g := setup(t)
+
+ browser := rod.New().Context(g.Context()).MustConnect()
page := browser.MustPage()
js := `() => new Promise(r => setTimeout(r, 10000))`
- go t.Panic(func() {
+ go g.Panic(func() {
page.MustEval(js)
})
@@ -176,88 +195,100 @@ func (t T) BrowserCrash() {
utils.Sleep(0.3)
_, err := page.Eval(js)
- t.Is(err, cdp.ErrConnClosed)
+ g.Is(err, cdp.ErrConnClosed)
}
-func (t T) BrowserCall() {
- v, err := proto.BrowserGetVersion{}.Call(t.browser)
- t.E(err)
+func TestBrowserCall(t *testing.T) {
+ g := setup(t)
- t.Regex("1.3", v.ProtocolVersion)
+ v, err := proto.BrowserGetVersion{}.Call(g.browser)
+ g.E(err)
+
+ g.Regex("1.3", v.ProtocolVersion)
}
-func (t T) BlockingNavigation() {
+func TestBlockingNavigation(t *testing.T) {
+ g := setup(t)
+
/*
Navigate can take forever if a page doesn't response.
If one page is blocked, other pages should still work.
*/
- s := t.Serve()
- pause := t.Context()
+ s := g.Serve()
+ pause := g.Context()
s.Mux.HandleFunc("/a", func(w http.ResponseWriter, r *http.Request) {
<-pause.Done()
})
s.Route("/b", ".html", `ok`)
- blocked := t.newPage()
+ blocked := g.newPage()
go func() {
- t.Panic(func() {
+ g.Panic(func() {
blocked.MustNavigate(s.URL("/a"))
})
}()
utils.Sleep(0.3)
- t.newPage(s.URL("/b"))
+ g.newPage(s.URL("/b"))
}
-func (t T) ResolveBlocking() {
- s := t.Serve()
+func TestResolveBlocking(t *testing.T) {
+ g := setup(t)
- pause := t.Context()
+ s := g.Serve()
+
+ pause := g.Context()
s.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
<-pause.Done()
})
- p := t.newPage()
+ p := g.newPage()
go func() {
utils.Sleep(0.1)
p.MustStopLoading()
}()
- t.Panic(func() {
+ g.Panic(func() {
p.MustNavigate(s.URL())
})
}
-func (t T) TestTry() {
- t.Nil(rod.Try(func() {}))
+func TestTestTry(t *testing.T) {
+ g := setup(t)
+
+ g.Nil(rod.Try(func() {}))
err := rod.Try(func() { panic(1) })
var errVal *rod.ErrTry
- t.True(errors.As(err, &errVal))
- t.Is(err, &rod.ErrTry{})
- t.Eq(1, errVal.Value)
- t.Eq(errVal.Error(), "error value: 1")
+ g.True(errors.As(err, &errVal))
+ g.Is(err, &rod.ErrTry{})
+ g.Eq(1, errVal.Value)
+ g.Eq(errVal.Error(), "error value: 1")
}
-func (t T) BrowserOthers() {
- t.browser.Timeout(time.Second).CancelTimeout().MustGetCookies()
+func TestBrowserOthers(t *testing.T) {
+ g := setup(t)
+
+ g.browser.Timeout(time.Second).CancelTimeout().MustGetCookies()
- t.Panic(func() {
- b, cancel := t.browser.WithCancel()
+ g.Panic(func() {
+ b, cancel := g.browser.WithCancel()
cancel()
b.MustIncognito()
})
}
-func (t T) BinarySize() {
+func TestBinarySize(t *testing.T) {
+ g := setup(t)
+
if runtime.GOOS == "windows" {
- t.SkipNow()
+ g.SkipNow()
}
cmd := exec.Command("go", "build",
@@ -268,16 +299,18 @@ func (t T) BinarySize() {
cmd.Env = append(os.Environ(), "GOOS=linux")
- t.Nil(cmd.Run())
+ g.Nil(cmd.Run())
stat, err := os.Stat("tmp/translator")
- t.E(err)
+ g.E(err)
- t.Lte(float64(stat.Size())/1024/1024, 9.3) // mb
+ g.Lte(float64(stat.Size())/1024/1024, 9.3) // mb
}
-func (t T) BrowserCookies() {
- b := t.browser.MustIncognito()
+func TestBrowserCookies(t *testing.T) {
+ g := setup(t)
+
+ b := g.browser.MustIncognito()
defer b.MustClose()
b.MustSetCookies(&proto.NetworkCookie{
@@ -288,38 +321,42 @@ func (t T) BrowserCookies() {
cookies := b.MustGetCookies()
- t.Len(cookies, 1)
- t.Eq(cookies[0].Name, "a")
- t.Eq(cookies[0].Value, "val")
+ g.Len(cookies, 1)
+ g.Eq(cookies[0].Name, "a")
+ g.Eq(cookies[0].Value, "val")
{
b.MustSetCookies()
cookies := b.MustGetCookies()
- t.Len(cookies, 0)
+ g.Len(cookies, 0)
}
- t.mc.stubErr(1, proto.StorageGetCookies{})
- t.Err(b.GetCookies())
+ g.mc.stubErr(1, proto.StorageGetCookies{})
+ g.Err(b.GetCookies())
}
-func (t T) WaitDownload() {
- s := t.Serve()
+func TestWaitDownload(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
content := "test content"
s.Route("/d", ".bin", []byte(content))
s.Route("/page", ".html", fmt.Sprintf(`click `, s.URL()))
- page := t.page.MustNavigate(s.URL("/page"))
+ page := g.page.MustNavigate(s.URL("/page"))
- wait := t.browser.MustWaitDownload()
+ wait := g.browser.MustWaitDownload()
page.MustElement("a").MustClick()
data := wait()
- t.Eq(content, string(data))
+ g.Eq(content, string(data))
}
-func (t T) WaitDownloadDataURI() {
- s := t.Serve()
+func TestWaitDownloadDataURI(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
s.Route("/", ".html",
`
@@ -334,21 +371,23 @@ func (t T) WaitDownloadDataURI() {
`,
)
- page := t.page.MustNavigate(s.URL())
+ page := g.page.MustNavigate(s.URL())
- wait1 := t.browser.MustWaitDownload()
+ wait1 := g.browser.MustWaitDownload()
page.MustElement("#a").MustClick()
data := wait1()
- t.Eq("test data", string(data))
+ g.Eq("test data", string(data))
- wait2 := t.browser.MustWaitDownload()
+ wait2 := g.browser.MustWaitDownload()
page.MustElement("#b").MustClick()
data = wait2()
- t.Eq("test blob", string(data))
+ g.Eq("test blob", string(data))
}
-func (t T) WaitDownloadFromNewPage() {
- s := t.Serve()
+func TestWaitDownloadFromNewPage(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
content := "test content"
s.Route("/d", ".bin", content)
@@ -357,20 +396,22 @@ func (t T) WaitDownloadFromNewPage() {
s.URL()),
)
- page := t.page.MustNavigate(s.URL("/page"))
- wait := t.browser.MustWaitDownload()
+ page := g.page.MustNavigate(s.URL("/page"))
+ wait := g.browser.MustWaitDownload()
page.MustElement("a").MustClick()
data := wait()
- t.Eq(content, string(data))
+ g.Eq(content, string(data))
}
-func (t T) BrowserConnectErr() {
- t.Panic(func() {
+func TestBrowserConnectErr(t *testing.T) {
+ g := setup(t)
+
+ g.Panic(func() {
c := &MockClient{connect: func() error { return errors.New("err") }}
rod.New().Client(c).MustConnect()
})
- t.Panic(func() {
+ g.Panic(func() {
ch := make(chan *cdp.Event)
defer close(ch)
@@ -380,42 +421,46 @@ func (t T) BrowserConnectErr() {
})
}
-func (t T) StreamReader() {
- r := rod.NewStreamReader(t.page, "")
+func TestStreamReader(t *testing.T) {
+ g := setup(t)
- t.mc.stub(1, proto.IORead{}, func(send StubSend) (gson.JSON, error) {
+ r := rod.NewStreamReader(g.page, "")
+
+ g.mc.stub(1, proto.IORead{}, func(send StubSend) (gson.JSON, error) {
return gson.New(proto.IOReadResult{
Data: "test",
}), nil
})
b := make([]byte, 4)
_, _ = r.Read(b)
- t.Eq("test", string(b))
+ g.Eq("test", string(b))
- t.mc.stubErr(1, proto.IORead{})
+ g.mc.stubErr(1, proto.IORead{})
_, err := r.Read(nil)
- t.Err(err)
+ g.Err(err)
- t.mc.stub(1, proto.IORead{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.IORead{}, func(send StubSend) (gson.JSON, error) {
return gson.New(proto.IOReadResult{
Base64Encoded: true,
Data: "@",
}), nil
})
_, err = r.Read(nil)
- t.Err(err)
+ g.Err(err)
}
-func (t T) BrowserConnectFailure() {
- c := t.Context()
+func TestBrowserConnectFailure(t *testing.T) {
+ g := setup(t)
+
+ c := g.Context()
c.Cancel()
err := rod.New().Context(c).Connect()
if err == nil {
- t.Fatal("expected an error on connect failure")
+ g.Fatal("expected an error on connect failure")
}
}
-func (t T) BrowserPool() {
+func TestBrowserPool(t *testing.T) {
pool := rod.NewBrowserPool(3)
create := func() *rod.Browser { return rod.New().MustConnect() }
b := pool.Get(create)
@@ -425,11 +470,11 @@ func (t T) BrowserPool() {
})
}
-func (t T) OldBrowser(got.Skip) {
+func (g G) OldBrowser(got.Skip) {
u := launcher.New().Revision(686378).MustLaunch()
b := rod.New().ControlURL(u).MustConnect()
- t.Cleanup(b.MustClose)
+ g.Cleanup(b.MustClose)
res, err := proto.BrowserGetVersion{}.Call(b)
- t.E(err)
- t.Eq(res.Revision, "@19d4547535ab5aba70b4730443f84e8153052174")
+ g.E(err)
+ g.Eq(res.Revision, "@19d4547535ab5aba70b4730443f84e8153052174")
}
diff --git a/dev_helpers_test.go b/dev_helpers_test.go
index 43ae8cc4..e163e337 100644
--- a/dev_helpers_test.go
+++ b/dev_helpers_test.go
@@ -1,6 +1,7 @@
package rod_test
import (
+ "testing"
"time"
"github.com/go-rod/rod"
@@ -12,86 +13,96 @@ import (
"github.com/ysmood/gson"
)
-func (t T) Monitor() {
+func TestMonitor(t *testing.T) {
+ g := setup(t)
+
b := rod.New().MustConnect()
defer b.MustClose()
- p := b.MustPage(t.blank()).MustWaitLoad()
+ p := b.MustPage(g.blank()).MustWaitLoad()
b, cancel := b.WithCancel()
defer cancel()
- host := b.Context(t.Context()).ServeMonitor("")
+ host := b.Context(g.Context()).ServeMonitor("")
- page := t.page.MustNavigate(host)
- t.Has(page.MustElement("#targets a").MustParent().MustHTML(), string(p.TargetID))
+ page := g.page.MustNavigate(host)
+ g.Has(page.MustElement("#targets a").MustParent().MustHTML(), string(p.TargetID))
page.MustNavigate(host + "/page/" + string(p.TargetID))
page.MustWait(`(id) => document.title.includes(id)`, p.TargetID)
- img := t.Req("", host+"/screenshot").Bytes()
- t.Gt(img.Len(), 10)
+ img := g.Req("", host+"/screenshot").Bytes()
+ g.Gt(img.Len(), 10)
- res := t.Req("", host+"/api/page/test")
- t.Eq(400, res.StatusCode)
- t.Eq(-32602, gson.New(res.Body).Get("code").Int())
+ res := g.Req("", host+"/api/page/test")
+ g.Eq(400, res.StatusCode)
+ g.Eq(-32602, gson.New(res.Body).Get("code").Int())
}
-func (t T) MonitorErr() {
+func TestMonitorErr(t *testing.T) {
+ g := setup(t)
+
l := launcher.New()
u := l.MustLaunch()
defer l.Kill()
- t.Panic(func() {
+ g.Panic(func() {
rod.New().Monitor("abc").ControlURL(u).MustConnect()
})
}
-func (t T) Trace() {
- t.Eq(rod.TraceTypeInput.String(), "[input]")
+func TestTrace(t *testing.T) {
+ g := setup(t)
+
+ g.Eq(rod.TraceTypeInput.String(), "[input]")
var msg []interface{}
- t.browser.Logger(utils.Log(func(list ...interface{}) { msg = list }))
- t.browser.Trace(true).SlowMotion(time.Microsecond)
+ g.browser.Logger(utils.Log(func(list ...interface{}) { msg = list }))
+ g.browser.Trace(true).SlowMotion(time.Microsecond)
defer func() {
- t.browser.Logger(rod.DefaultLogger)
- t.browser.Trace(defaults.Trace).SlowMotion(defaults.Slow)
+ g.browser.Logger(rod.DefaultLogger)
+ g.browser.Trace(defaults.Trace).SlowMotion(defaults.Slow)
}()
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html")).MustWaitLoad()
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html")).MustWaitLoad()
- t.Eq(rod.TraceTypeWait, msg[0])
- t.Eq("load", msg[1])
- t.Eq(p, msg[2])
+ g.Eq(rod.TraceTypeWait, msg[0])
+ g.Eq("load", msg[1])
+ g.Eq(p, msg[2])
el := p.MustElement("button")
el.MustClick()
- t.Eq(rod.TraceTypeInput, msg[0])
- t.Eq("left click", msg[1])
- t.Eq(el, msg[2])
+ g.Eq(rod.TraceTypeInput, msg[0])
+ g.Eq("left click", msg[1])
+ g.Eq(el, msg[2])
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
_ = p.Mouse.Move(10, 10, 1)
}
-func (t T) TraceLogs() {
- t.browser.Logger(utils.LoggerQuiet)
- t.browser.Trace(true)
+func TestTraceLogs(t *testing.T) {
+ g := setup(t)
+
+ g.browser.Logger(utils.LoggerQuiet)
+ g.browser.Trace(true)
defer func() {
- t.browser.Logger(rod.DefaultLogger)
- t.browser.Trace(defaults.Trace)
+ g.browser.Logger(rod.DefaultLogger)
+ g.browser.Trace(defaults.Trace)
}()
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
el.MustClick()
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
p.Overlay(0, 0, 100, 30, "")
}
-func (t T) ExposeHelpers() {
- p := t.newPage(t.srcFile("fixtures/click.html"))
+func TestExposeHelpers(t *testing.T) {
+ g := setup(t)
+
+ p := g.newPage(g.srcFile("fixtures/click.html"))
p.ExposeHelpers(js.ElementR)
- t.Eq(p.MustElementByJS(`() => rod.elementR('button', 'click me')`).MustText(), "click me")
+ g.Eq(p.MustElementByJS(`() => rod.elementR('button', 'click me')`).MustText(), "click me")
}
diff --git a/element_test.go b/element_test.go
index e860f882..cecf2a7b 100644
--- a/element_test.go
+++ b/element_test.go
@@ -8,6 +8,7 @@ import (
"image/png"
"os"
"path/filepath"
+ "testing"
"time"
"github.com/go-rod/rod"
@@ -19,80 +20,92 @@ import (
"github.com/ysmood/gson"
)
-func (t T) GetElementPage() {
- el := t.page.MustNavigate(t.blank()).MustElement("html")
- t.Eq(el.Page().SessionID, t.page.SessionID)
+func TestGetElementPage(t *testing.T) {
+ g := setup(t)
+
+ el := g.page.MustNavigate(g.blank()).MustElement("html")
+ g.Eq(el.Page().SessionID, g.page.SessionID)
}
-func (t T) Click() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestClick(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
el.MustClick()
- t.True(p.MustHas("[a=ok]"))
+ g.True(p.MustHas("[a=ok]"))
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustClick()
})
- t.Panic(func() {
- t.mc.stubErr(8, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(8, proto.RuntimeCallFunctionOn{})
el.MustClick()
})
}
-func (t T) ClickWrapped() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click-wrapped.html")).MustWaitLoad()
+func TestClickWrapped(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click-wrapped.html")).MustWaitLoad()
el := p.MustElement("#target")
shape := el.MustShape()
- t.Len(shape.Quads, 2)
+ g.Len(shape.Quads, 2)
el.MustClick()
- t.True(p.MustHas("[a=ok]"))
+ g.True(p.MustHas("[a=ok]"))
}
-func (t T) Tap() {
- page := t.newPage()
+func TestTap(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage()
page.MustEmulate(devices.IPad).
- MustNavigate(t.srcFile("fixtures/touch.html")).
+ MustNavigate(g.srcFile("fixtures/touch.html")).
MustWaitLoad()
el := page.MustElement("button")
el.MustTap()
- t.True(page.MustHas("[tapped=true]"))
+ g.True(page.MustHas("[tapped=true]"))
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustTap()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
el.MustTap()
})
- t.Panic(func() {
- t.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
el.MustTap()
})
- t.Panic(func() {
- t.mc.stubErr(7, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(7, proto.RuntimeCallFunctionOn{})
el.MustTap()
})
}
-func (t T) Interactable() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestInteractable(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
- t.True(el.MustInteractable())
+ g.True(el.MustInteractable())
- t.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
- t.Err(el.Interactable())
+ g.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
+ g.Err(el.Interactable())
}
-func (t T) NotInteractable() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestNotInteractable(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
// cover the button with a green div
@@ -102,58 +115,64 @@ func (t T) NotInteractable() {
document.body.append(div)
}`)
_, err := el.Interactable()
- t.Has(err.Error(), "element covered by:
")
- t.Is(err, &rod.ErrNotInteractable{})
- t.Is(err, &rod.ErrCovered{})
- t.False(el.MustInteractable())
+ g.Has(err.Error(), "element covered by:
")
+ g.Is(err, &rod.ErrNotInteractable{})
+ g.Is(err, &rod.ErrCovered{})
+ g.False(el.MustInteractable())
var ee *rod.ErrNotInteractable
- t.True(errors.As(err, &ee))
- t.Eq(ee.Error(), "element is not cursor interactable")
+ g.True(errors.As(err, &ee))
+ g.Eq(ee.Error(), "element is not cursor interactable")
p.MustElement("div").MustRemove()
- t.mc.stubErr(1, proto.DOMGetContentQuads{})
+ g.mc.stubErr(1, proto.DOMGetContentQuads{})
_, err = el.Interactable()
- t.Err(err)
+ g.Err(err)
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(el.Interactable())
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(el.Interactable())
- t.mc.stubErr(1, proto.DOMDescribeNode{})
- t.Err(el.Interactable())
+ g.mc.stubErr(1, proto.DOMDescribeNode{})
+ g.Err(el.Interactable())
- t.mc.stubErr(2, proto.RuntimeCallFunctionOn{})
- t.Err(el.Interactable())
+ g.mc.stubErr(2, proto.RuntimeCallFunctionOn{})
+ g.Err(el.Interactable())
}
-func (t T) InteractableWithNoShape() {
- p := t.page.MustNavigate(t.srcFile("fixtures/interactable.html"))
+func TestInteractableWithNoShape(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/interactable.html"))
el := p.MustElement("#no-shape")
_, err := el.Interactable()
- t.Is(err, &rod.ErrInvisibleShape{})
- t.Is(err, &rod.ErrNotInteractable{})
- t.Eq(err.Error(), "element has no visible shape or outside the viewport:
")
+ g.Is(err, &rod.ErrInvisibleShape{})
+ g.Is(err, &rod.ErrNotInteractable{})
+ g.Eq(err.Error(), "element has no visible shape or outside the viewport:
")
el = p.MustElement("#outside")
_, err = el.Interactable()
- t.Is(err, &rod.ErrInvisibleShape{})
+ g.Is(err, &rod.ErrInvisibleShape{})
el = p.MustElement("#invisible")
_, err = el.Interactable()
- t.Is(err, &rod.ErrInvisibleShape{})
+ g.Is(err, &rod.ErrInvisibleShape{})
}
-func (t T) NotInteractableWithNoPointerEvents() {
- p := t.page.MustNavigate(t.srcFile("fixtures/interactable.html"))
+func TestNotInteractableWithNoPointerEvents(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/interactable.html"))
_, err := p.MustElementR("#no-pointer-events", "click me").Interactable()
- t.Is(err, &rod.ErrNoPointerEvents{})
- t.Is(err, &rod.ErrNotInteractable{})
- t.Eq(err.Error(), "element's pointer-events is none:
")
+ g.Is(err, &rod.ErrNoPointerEvents{})
+ g.Is(err, &rod.ErrNotInteractable{})
+ g.Eq(err.Error(), "element's pointer-events is none: ")
}
-func (t T) WaitInteractable() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestWaitInteractable(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
start := time.Now()
@@ -168,58 +187,68 @@ func (t T) WaitInteractable() {
el.MustWaitInteractable()
- t.Gt(time.Since(start), time.Second)
+ g.Gt(time.Since(start), time.Second)
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
- t.Err(el.WaitInteractable())
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Err(el.WaitInteractable())
}
-func (t T) Hover() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestHover(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
el.MustEval(`() => this.onmouseenter = () => this.dataset['a'] = 1`)
el.MustHover()
- t.Eq("1", el.MustEval(`() => this.dataset['a']`).String())
+ g.Eq("1", el.MustEval(`() => this.dataset['a']`).String())
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
- t.Err(el.Hover())
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Err(el.Hover())
- t.mc.stubErr(1, proto.DOMGetContentQuads{})
- t.Err(el.Hover())
+ g.mc.stubErr(1, proto.DOMGetContentQuads{})
+ g.Err(el.Hover())
- t.mc.stubErr(3, proto.DOMGetContentQuads{})
- t.Err(el.Hover())
+ g.mc.stubErr(3, proto.DOMGetContentQuads{})
+ g.Err(el.Hover())
- t.mc.stubErr(1, proto.InputDispatchMouseEvent{})
- t.Err(el.Hover())
+ g.mc.stubErr(1, proto.InputDispatchMouseEvent{})
+ g.Err(el.Hover())
}
-func (t T) ElementMoveMouseOut() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestElementMoveMouseOut(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
btn := p.MustElement("button")
btn.MustEval(`() => this.onmouseout = () => this.setAttribute('name', 'mouse moved.')`)
- t.Eq("mouse moved.", *btn.MustHover().MustMoveMouseOut().MustAttribute("name"))
+ g.Eq("mouse moved.", *btn.MustHover().MustMoveMouseOut().MustAttribute("name"))
- t.mc.stubErr(1, proto.DOMGetContentQuads{})
- t.Err(btn.MoveMouseOut())
+ g.mc.stubErr(1, proto.DOMGetContentQuads{})
+ g.Err(btn.MoveMouseOut())
}
-func (t T) MouseMoveErr() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
- t.mc.stubErr(1, proto.InputDispatchMouseEvent{})
- t.Err(p.Mouse.Move(10, 10, 1))
+func TestMouseMoveErr(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
+ g.mc.stubErr(1, proto.InputDispatchMouseEvent{})
+ g.Err(p.Mouse.Move(10, 10, 1))
}
-func (t T) ElementContext() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestElementContext(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button").Timeout(time.Hour).CancelTimeout()
el, cancel := el.WithCancel()
defer cancel()
el.Sleeper(rod.DefaultSleeper).MustClick()
}
-func (t T) Iframes() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click-iframes.html"))
+func TestIframes(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click-iframes.html"))
frame01 := p.MustElement("iframe").MustFrame()
@@ -227,293 +256,325 @@ func (t T) Iframes() {
el := frame02.MustElement("button")
el.MustClick()
- t.Eq(frame01.MustEval(`() => testIsolation()`).Str(), "ok")
- t.True(frame02.MustHas("[a=ok]"))
+ g.Eq(frame01.MustEval(`() => testIsolation()`).Str(), "ok")
+ g.True(frame02.MustHas("[a=ok]"))
}
-func (t T) Contains() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestContains(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
a := p.MustElement("button")
b := p.MustElementFromNode(a.MustDescribe())
- t.True(a.MustContainsElement(b))
+ g.True(a.MustContainsElement(b))
pt := a.MustShape().OnePointInside()
el := p.MustElementFromPoint(int(pt.X), int(pt.Y))
- t.True(a.MustContainsElement(el))
+ g.True(a.MustContainsElement(el))
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(a.ContainsElement(el))
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(a.ContainsElement(el))
}
-func (t T) ShadowDOM() {
- p := t.page.MustNavigate(t.srcFile("fixtures/shadow-dom.html")).MustWaitLoad()
+func TestShadowDOM(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/shadow-dom.html")).MustWaitLoad()
el := p.MustElement("#container")
- t.Eq("inside", el.MustShadowRoot().MustElement("p").MustText())
+ g.Eq("inside", el.MustShadowRoot().MustElement("p").MustText())
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMDescribeNode{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMDescribeNode{})
el.MustShadowRoot()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMResolveNode{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMResolveNode{})
el.MustShadowRoot()
})
}
-func (t T) Press() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestPress(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("[type=text]")
el.MustPress('1', '2', input.Backspace, ' ')
el.MustPress([]rune("A b")...)
- t.Eq("1 A b", el.MustText())
+ g.Eq("1 A b", el.MustText())
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
el.MustPress(' ')
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
el.MustSelectAllText()
})
}
-func (t T) KeyDown() {
- p := t.page.MustNavigate(t.srcFile("fixtures/keys.html"))
+func TestKeyDown(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/keys.html"))
p.MustElement("body")
p.Keyboard.MustDown('j')
- t.True(p.MustHas("body[event=key-down-j]"))
+ g.True(p.MustHas("body[event=key-down-j]"))
}
-func (t T) KeyUp() {
- p := t.page.MustNavigate(t.srcFile("fixtures/keys.html"))
+func TestKeyUp(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/keys.html"))
p.MustElement("body")
p.Keyboard.MustUp('x')
- t.True(p.MustHas("body[event=key-up-x]"))
+ g.True(p.MustHas("body[event=key-up-x]"))
}
-func (t T) Input() {
+func TestInput(t *testing.T) {
+ g := setup(t)
+
text := "雲の上は\nいつも晴れ"
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
{
el := p.MustElement("[contenteditable=true]").MustInput(text)
- t.Eq(text, el.MustText())
+ g.Eq(text, el.MustText())
}
el := p.MustElement("textarea")
el.MustInput(text)
- t.Eq(text, el.MustText())
- t.True(p.MustHas("[event=textarea-change]"))
+ g.Eq(text, el.MustText())
+ g.True(p.MustHas("[event=textarea-change]"))
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustText()
})
- t.Panic(func() {
- t.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
el.MustInput("")
})
- t.Panic(func() {
- t.mc.stubErr(5, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(5, proto.RuntimeCallFunctionOn{})
el.MustInput("")
})
- t.Panic(func() {
- t.mc.stubErr(6, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(6, proto.RuntimeCallFunctionOn{})
el.MustInput("")
})
- t.Panic(func() {
- t.mc.stubErr(7, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(7, proto.RuntimeCallFunctionOn{})
el.MustInput("")
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputInsertText{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputInsertText{})
el.MustInput("")
})
}
-func (t T) InputTime() {
+func TestInputTime(t *testing.T) {
+ g := setup(t)
+
now := time.Now()
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
var el *rod.Element
{
el = p.MustElement("[type=date]")
el.MustInputTime(now)
- t.Eq(el.MustText(), now.Format("2006-01-02"))
- t.True(p.MustHas("[event=input-date-change]"))
+ g.Eq(el.MustText(), now.Format("2006-01-02"))
+ g.True(p.MustHas("[event=input-date-change]"))
}
{
el = p.MustElement("[type=datetime-local]")
el.MustInputTime(now)
- t.Eq(el.MustText(), now.Format("2006-01-02T15:04"))
- t.True(p.MustHas("[event=input-datetime-local-change]"))
+ g.Eq(el.MustText(), now.Format("2006-01-02T15:04"))
+ g.True(p.MustHas("[event=input-datetime-local-change]"))
}
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustInputTime(now)
})
- t.Panic(func() {
- t.mc.stubErr(5, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(5, proto.RuntimeCallFunctionOn{})
el.MustInputTime(now)
})
- t.Panic(func() {
- t.mc.stubErr(6, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(6, proto.RuntimeCallFunctionOn{})
el.MustInputTime(now)
})
- t.Panic(func() {
- t.mc.stubErr(7, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(7, proto.RuntimeCallFunctionOn{})
el.MustInputTime(now)
})
}
-func (t T) Checkbox() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestCheckbox(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("[type=checkbox]")
- t.True(el.MustClick().MustProperty("checked").Bool())
+ g.True(el.MustClick().MustProperty("checked").Bool())
}
-func (t T) SelectText() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestSelectText(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("textarea")
el.MustInput("test")
el.MustSelectAllText()
el.MustInput("test")
- t.Eq("test", el.MustText())
+ g.Eq("test", el.MustText())
el.MustSelectText(`es`)
el.MustInput("__")
- t.Eq("t__t", el.MustText())
+ g.Eq("t__t", el.MustText())
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
el.MustSelectText("")
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
el.MustSelectAllText()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
el.MustInput("")
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputInsertText{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputInsertText{})
el.MustInput("")
})
}
-func (t T) Blur() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestBlur(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("#blur").MustInput("test").MustBlur()
- t.Eq("ok", *el.MustAttribute("a"))
+ g.Eq("ok", *el.MustAttribute("a"))
}
-func (t T) SelectQuery() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestSelectQuery(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("select")
err := el.Select([]string{`[value="c"]`}, true, rod.SelectorTypeCSSSector)
- t.E(err)
+ g.E(err)
- t.Eq(2, el.MustEval("() => this.selectedIndex").Int())
+ g.Eq(2, el.MustEval("() => this.selectedIndex").Int())
}
-func (t T) SelectOptions() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestSelectOptions(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("select")
el.MustSelect("B", "C")
- t.Eq("B,C", el.MustText())
- t.Eq(1, el.MustProperty("selectedIndex").Int())
+ g.Eq("B,C", el.MustText())
+ g.Eq(1, el.MustProperty("selectedIndex").Int())
// unselect with regex
err := el.Select([]string{`^B$`}, false, rod.SelectorTypeRegex)
- t.E(err)
- t.Eq("C", el.MustText())
+ g.E(err)
+ g.Eq("C", el.MustText())
// unselect with css selector
err = el.Select([]string{`[value="c"]`}, false, rod.SelectorTypeCSSSector)
- t.E(err)
- t.Eq("", el.MustText())
+ g.E(err)
+ g.Eq("", el.MustText())
// option not found error
- t.Is(el.Select([]string{"not-exists"}, true, rod.SelectorTypeCSSSector), &rod.ErrElementNotFound{})
+ g.Is(el.Select([]string{"not-exists"}, true, rod.SelectorTypeCSSSector), &rod.ErrElementNotFound{})
{
- t.mc.stubErr(5, proto.RuntimeCallFunctionOn{})
- t.Err(el.Select([]string{"B"}, true, rod.SelectorTypeText))
+ g.mc.stubErr(5, proto.RuntimeCallFunctionOn{})
+ g.Err(el.Select([]string{"B"}, true, rod.SelectorTypeText))
}
}
-func (t T) Matches() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestMatches(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("textarea")
- t.True(el.MustMatches(`[cols="30"]`))
+ g.True(el.MustMatches(`[cols="30"]`))
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustMatches("")
})
}
-func (t T) Attribute() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestAttribute(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("textarea")
cols := el.MustAttribute("cols")
rows := el.MustAttribute("rows")
- t.Eq("30", *cols)
- t.Eq("10", *rows)
+ g.Eq("30", *cols)
+ g.Eq("10", *rows)
- p = t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+ p = g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el = p.MustElement("button").MustClick()
- t.Eq("ok", *el.MustAttribute("a"))
- t.Nil(el.MustAttribute("b"))
+ g.Eq("ok", *el.MustAttribute("a"))
+ g.Nil(el.MustAttribute("b"))
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustAttribute("")
})
}
-func (t T) Property() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestProperty(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("textarea")
cols := el.MustProperty("cols")
rows := el.MustProperty("rows")
- t.Eq(float64(30), cols.Num())
- t.Eq(float64(10), rows.Num())
+ g.Eq(float64(30), cols.Num())
+ g.Eq(float64(10), rows.Num())
- p = t.page.MustNavigate(t.srcFile("fixtures/open-page.html"))
+ p = g.page.MustNavigate(g.srcFile("fixtures/open-page.html"))
el = p.MustElement("a")
- t.Eq("link", el.MustProperty("id").Str())
- t.Eq("_blank", el.MustProperty("target").Str())
- t.True(el.MustProperty("test").Nil())
+ g.Eq("link", el.MustProperty("id").Str())
+ g.Eq("_blank", el.MustProperty("target").Str())
+ g.True(el.MustProperty("test").Nil())
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustProperty("")
})
}
-func (t T) SetFiles() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestSetFiles(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement(`[type=file]`)
el.MustSetFiles(
slash("fixtures/click.html"),
@@ -521,24 +582,28 @@ func (t T) SetFiles() {
)
list := el.MustEval("() => Array.from(this.files).map(f => f.name)").Arr()
- t.Len(list, 2)
- t.Eq("alert.html", list[1].String())
+ g.Len(list, 2)
+ g.Eq("alert.html", list[1].String())
}
-func (t T) Enter() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestEnter(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("[type=submit]")
el.MustPress(input.Enter)
- t.True(p.MustHas("[event=submit]"))
+ g.True(p.MustHas("[event=submit]"))
}
-func (t T) WaitInvisible() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestWaitInvisible(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
h4 := p.MustElement("h4")
btn := p.MustElement("button")
- t.True(h4.MustVisible())
+ g.True(h4.MustVisible())
h4.MustWaitVisible()
@@ -552,276 +617,314 @@ func (t T) WaitInvisible() {
h4.MustWaitInvisible()
btn.MustWaitInvisible()
- t.False(p.MustHas("h4"))
+ g.False(p.MustHas("h4"))
}
-func (t T) WaitEnabled() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestWaitEnabled(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
p.MustElement("button").MustWaitEnabled()
}
-func (t T) WaitWritable() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestWaitWritable(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
p.MustElement("input").MustWaitWritable()
}
-func (t T) WaitStable() {
- p := t.page.MustNavigate(t.srcFile("fixtures/wait-stable.html"))
+func TestWaitStable(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/wait-stable.html"))
el := p.MustElement("button")
el.MustEval(`() => this.classList.add("play")`)
start := time.Now()
el.MustWaitStable()
- t.Gt(time.Since(start), time.Second)
+ g.Gt(time.Since(start), time.Second)
- ctx := t.Context()
- t.mc.stub(1, proto.DOMGetContentQuads{}, func(send StubSend) (gson.JSON, error) {
+ ctx := g.Context()
+ g.mc.stub(1, proto.DOMGetContentQuads{}, func(send StubSend) (gson.JSON, error) {
go func() {
utils.Sleep(0.1)
ctx.Cancel()
}()
return send()
})
- t.Err(el.Context(ctx).WaitStable(time.Minute))
+ g.Err(el.Context(ctx).WaitStable(time.Minute))
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMGetContentQuads{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMGetContentQuads{})
el.MustWaitStable()
})
- t.Panic(func() {
- t.mc.stubErr(2, proto.DOMGetContentQuads{})
+ g.Panic(func() {
+ g.mc.stubErr(2, proto.DOMGetContentQuads{})
el.MustWaitStable()
})
}
-func (t T) WaitStableRAP() {
- p := t.page.MustNavigate(t.srcFile("fixtures/wait-stable.html"))
+func TestWaitStableRAP(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/wait-stable.html"))
el := p.MustElement("button")
el.MustEval(`() => this.classList.add("play")`)
start := time.Now()
- t.E(el.WaitStableRAF())
- t.Gt(time.Since(start), time.Second)
+ g.E(el.WaitStableRAF())
+ g.Gt(time.Since(start), time.Second)
- t.mc.stubErr(2, proto.RuntimeCallFunctionOn{})
- t.Err(el.WaitStableRAF())
+ g.mc.stubErr(2, proto.RuntimeCallFunctionOn{})
+ g.Err(el.WaitStableRAF())
- t.mc.stubErr(1, proto.DOMGetContentQuads{})
- t.Err(el.WaitStableRAF())
+ g.mc.stubErr(1, proto.DOMGetContentQuads{})
+ g.Err(el.WaitStableRAF())
}
-func (t T) CanvasToImage() {
- p := t.page.MustNavigate(t.srcFile("fixtures/canvas.html"))
+func TestCanvasToImage(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/canvas.html"))
src, err := png.Decode(bytes.NewBuffer(p.MustElement("#canvas").MustCanvasToImage()))
- t.E(err)
- t.Eq(src.At(50, 50), color.NRGBA{0xFF, 0x00, 0x00, 0xFF})
+ g.E(err)
+ g.Eq(src.At(50, 50), color.NRGBA{0xFF, 0x00, 0x00, 0xFF})
}
-func (t T) ElementWaitLoad() {
- p := t.page.MustNavigate(t.srcFile("fixtures/resource.html"))
+func TestElementWaitLoad(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/resource.html"))
p.MustElement("img").MustWaitLoad()
}
-func (t T) Resource() {
- p := t.page.MustNavigate(t.srcFile("fixtures/resource.html"))
+func TestResource(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/resource.html"))
el := p.MustElement("img")
- t.Eq(len(el.MustResource()), 22661)
+ g.Eq(len(el.MustResource()), 22661)
- t.mc.stub(1, proto.PageGetResourceContent{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.PageGetResourceContent{}, func(send StubSend) (gson.JSON, error) {
return gson.New(proto.PageGetResourceContentResult{
Content: "ok",
Base64Encoded: false,
}), nil
})
- t.Eq([]byte("ok"), el.MustResource())
+ g.Eq([]byte("ok"), el.MustResource())
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustResource()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageGetResourceContent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageGetResourceContent{})
el.MustResource()
})
}
-func (t T) BackgroundImage() {
- p := t.page.MustNavigate(t.srcFile("fixtures/resource.html"))
+func TestBackgroundImage(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/resource.html"))
el := p.MustElement("div")
- t.Eq(len(el.MustBackgroundImage()), 22661)
+ g.Eq(len(el.MustBackgroundImage()), 22661)
{
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(el.BackgroundImage())
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(el.BackgroundImage())
}
}
-func (t T) ElementScreenshot() {
- f := filepath.Join("tmp", "screenshots", t.Srand(16)+".png")
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestElementScreenshot(t *testing.T) {
+ g := setup(t)
+
+ f := filepath.Join("tmp", "screenshots", g.RandStr(16)+".png")
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("h4")
data := el.MustScreenshot(f)
img, err := png.Decode(bytes.NewBuffer(data))
- t.E(err)
- t.Eq(200, img.Bounds().Dx())
- t.Eq(30, img.Bounds().Dy())
- t.Nil(os.Stat(f))
+ g.E(err)
+ g.Eq(200, img.Bounds().Dx())
+ g.Eq(30, img.Bounds().Dy())
+ g.Nil(os.Stat(f))
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMScrollIntoViewIfNeeded{})
el.MustScreenshot()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageCaptureScreenshot{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageCaptureScreenshot{})
el.MustScreenshot()
})
- t.Panic(func() {
- t.mc.stubErr(3, proto.DOMGetContentQuads{})
+ g.Panic(func() {
+ g.mc.stubErr(3, proto.DOMGetContentQuads{})
el.MustScreenshot()
})
}
-func (t T) UseReleasedElement() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestUseReleasedElement(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
btn := p.MustElement("button")
btn.MustRelease()
- t.Err(btn.Click("left"))
+ g.Err(btn.Click("left"))
btn = p.MustElement("button")
- t.E(proto.RuntimeReleaseObject{ObjectID: btn.Object.ObjectID}.Call(p))
- t.Is(btn.Click("left"), cdp.ErrObjNotFound)
+ g.E(proto.RuntimeReleaseObject{ObjectID: btn.Object.ObjectID}.Call(p))
+ g.Is(btn.Click("left"), cdp.ErrObjNotFound)
}
-func (t T) ElementRemove() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestElementRemove(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
btn := p.MustElement("button")
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(btn.Remove())
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(btn.Remove())
}
-func (t T) ElementMultipleTimes() {
+func TestElementMultipleTimes(t *testing.T) {
+ g := setup(t)
+
// To see whether chrome will reuse the remote object ID or not.
// Seems like it will not.
- page := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+ page := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
btn01 := page.MustElement("button")
btn02 := page.MustElement("button")
- t.Eq(btn01.MustText(), btn02.MustText())
- t.Neq(btn01.Object, btn02.Object)
+ g.Eq(btn01.MustText(), btn02.MustText())
+ g.Neq(btn01.Object, btn02.Object)
}
-func (t T) FnErr() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestFnErr(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
_, err := el.Eval("foo()")
- t.Err(err)
- t.Has(err.Error(), "ReferenceError: foo is not defined")
+ g.Err(err)
+ g.Has(err.Error(), "ReferenceError: foo is not defined")
var e *rod.ErrEval
- t.True(errors.As(err, &e))
- t.Eq(proto.RuntimeRemoteObjectSubtypeError, e.Exception.Subtype)
+ g.True(errors.As(err, &e))
+ g.Eq(proto.RuntimeRemoteObjectSubtypeError, e.Exception.Subtype)
_, err = el.ElementByJS(rod.Eval("() => foo()"))
- t.Err(err)
- t.Has(err.Error(), "ReferenceError: foo is not defined")
- t.True(errors.Is(err, &rod.ErrEval{}))
+ g.Err(err)
+ g.Has(err.Error(), "ReferenceError: foo is not defined")
+ g.True(errors.Is(err, &rod.ErrEval{}))
}
-func (t T) ElementEWithDepth() {
+func TestElementEWithDepth(t *testing.T) {
+ g := setup(t)
+
checkStr := `green tea`
- p := t.page.MustNavigate(t.srcFile("fixtures/describe.html"))
+ p := g.page.MustNavigate(g.srcFile("fixtures/describe.html"))
ulDOMNode, err := p.MustElement(`ul`).Describe(-1, true)
- t.Nil(errors.Unwrap(err))
+ g.Nil(errors.Unwrap(err))
data, err := json.Marshal(ulDOMNode)
- t.Nil(errors.Unwrap(err))
+ g.Nil(errors.Unwrap(err))
// The depth is -1, should contain checkStr
- t.Has(string(data), checkStr)
+ g.Has(string(data), checkStr)
}
-func (t T) ElementOthers() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestElementOthers(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("form")
el.MustFocus()
el.MustScrollIntoView()
- t.Eq("submit", el.MustElement("[type=submit]").MustText())
- t.Eq(" ", el.MustElement("[type=submit]").MustHTML())
+ g.Eq("submit", el.MustElement("[type=submit]").MustText())
+ g.Eq(" ", el.MustElement("[type=submit]").MustHTML())
el.MustWait(`() => true`)
- t.Eq("form", el.MustElementByJS(`() => this`).MustDescribe().LocalName)
- t.Len(el.MustElementsByJS(`() => []`), 0)
+ g.Eq("form", el.MustElementByJS(`() => this`).MustDescribe().LocalName)
+ g.Len(el.MustElementsByJS(`() => []`), 0)
}
-func (t T) ElementEqual() {
- p := t.page.MustNavigate(t.srcFile("fixtures/describe.html"))
+func TestElementEqual(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/describe.html"))
el1 := p.MustElement("body > ul")
el2 := p.MustElement("html > body > ul")
- t.True(el1.MustEqual(el2))
+ g.True(el1.MustEqual(el2))
el3 := p.MustElement("ul ul")
- t.False(el1.MustEqual(el3))
+ g.False(el1.MustEqual(el3))
}
-func (t T) ElementFromPointErr() {
- t.mc.stubErr(1, proto.DOMGetNodeForLocation{})
- t.Err(t.page.ElementFromPoint(10, 10))
+func TestElementFromPointErr(t *testing.T) {
+ g := setup(t)
+
+ g.mc.stubErr(1, proto.DOMGetNodeForLocation{})
+ g.Err(g.page.ElementFromPoint(10, 10))
}
-func (t T) ElementFromNodeErr() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestElementFromNodeErr(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElementX("//button/text()")
- t.mc.stubErr(3, proto.RuntimeCallFunctionOn{})
- t.Err(p.ElementFromNode(el.MustDescribe()))
+ g.mc.stubErr(3, proto.RuntimeCallFunctionOn{})
+ g.Err(p.ElementFromNode(el.MustDescribe()))
}
-func (t T) ElementErrors() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestElementErrors(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("form")
- ctx := t.Timeout(0)
+ ctx := g.Timeout(0)
_, err := el.Context(ctx).Describe(-1, true)
- t.Err(err)
+ g.Err(err)
_, err = el.Context(ctx).Frame()
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).Focus()
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).Press('a')
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).Input("a")
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).Select([]string{"a"}, true, rod.SelectorTypeText)
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).WaitStable(0)
- t.Err(err)
+ g.Err(err)
_, err = el.Context(ctx).Resource()
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).Input("a")
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).Input("a")
- t.Err(err)
+ g.Err(err)
_, err = el.Context(ctx).HTML()
- t.Err(err)
+ g.Err(err)
_, err = el.Context(ctx).Visible()
- t.Err(err)
+ g.Err(err)
_, err = el.Context(ctx).CanvasToImage("", 0)
- t.Err(err)
+ g.Err(err)
err = el.Context(ctx).Release()
- t.Err(err)
+ g.Err(err)
}
diff --git a/go.mod b/go.mod
index 7f113b5b..93aa01b7 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,8 @@ go 1.16
require (
github.com/ysmood/goob v0.3.1
- github.com/ysmood/got v0.16.2
- github.com/ysmood/gotrace v0.2.2
- github.com/ysmood/gson v0.6.4
+ github.com/ysmood/got v0.19.0
+ github.com/ysmood/gotrace v0.4.0
+ github.com/ysmood/gson v0.7.0
github.com/ysmood/leakless v0.7.0
)
diff --git a/go.sum b/go.sum
index 2b96e3d2..01704552 100644
--- a/go.sum
+++ b/go.sum
@@ -1,10 +1,10 @@
github.com/ysmood/goob v0.3.1 h1:qMp5364BGS1DLJVrAqUxTF6KOFt0YDot8GC70u/0jbI=
github.com/ysmood/goob v0.3.1/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs=
-github.com/ysmood/got v0.16.2 h1:uedkfJYynagDxD2YfW6b7AySAVeh2IwchTwmqUGSREs=
-github.com/ysmood/got v0.16.2/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY=
-github.com/ysmood/gotrace v0.2.2 h1:006KHGRThSRf8lwh4EyhNmuuq/l+Ygs+JqojkhEG1/E=
-github.com/ysmood/gotrace v0.2.2/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=
-github.com/ysmood/gson v0.6.4 h1:Yb6tosv6bk59HqjZu2/7o4BFherpYEMkDkXmlhgryZ4=
-github.com/ysmood/gson v0.6.4/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
+github.com/ysmood/got v0.19.0 h1:AdsvaOIzsfRS+wqVvjUvIbK7MhuQI4qAmO2W6v/74Ko=
+github.com/ysmood/got v0.19.0/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY=
+github.com/ysmood/gotrace v0.4.0 h1:NkiFGkr8AXxkEosLFudsvw5aGoBY5N7wFPOI4ZSCkb4=
+github.com/ysmood/gotrace v0.4.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=
+github.com/ysmood/gson v0.7.0 h1:oQhY2FQtfy3+bgaNeqopd7NGAB6Me+UpG0n7oO4VDko=
+github.com/ysmood/gson v0.7.0/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
github.com/ysmood/leakless v0.7.0 h1:XCGdaPExyoreoQd+H5qgxM3ReNbSPFsEXpSKwbXbwQw=
github.com/ysmood/leakless v0.7.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
diff --git a/hijack_test.go b/hijack_test.go
index 6292ede1..ca1d8616 100644
--- a/hijack_test.go
+++ b/hijack_test.go
@@ -6,6 +6,7 @@ import (
"mime"
"net/http"
"sync"
+ "testing"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/proto"
@@ -13,8 +14,10 @@ import (
"github.com/ysmood/gson"
)
-func (t T) Hijack() {
- s := t.Serve()
+func TestHijack(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
// to simulate a backend server
s.Route("/", slash("fixtures/fetch.html"))
@@ -23,21 +26,21 @@ func (t T) Hijack() {
panic("wrong http method")
}
- t.Eq("header", r.Header.Get("Test"))
+ g.Eq("header", r.Header.Get("Test"))
b, err := ioutil.ReadAll(r.Body)
- t.E(err)
- t.Eq("a", string(b))
+ g.E(err)
+ g.Eq("a", string(b))
- t.HandleHTTP(".html", "test")(w, r)
+ g.HandleHTTP(".html", "test")(w, r)
})
s.Route("/b", "", "b")
- router := t.page.HijackRequests()
+ router := g.page.HijackRequests()
defer router.MustStop()
router.MustAdd(s.URL("/a"), func(ctx *rod.Hijack) {
- r := ctx.Request.SetContext(t.Context())
+ r := ctx.Request.SetContext(g.Context())
r.Req().Header.Set("Test", "header") // override request header
r.SetBody([]byte("test")) // override request body
r.SetBody(123) // override request body
@@ -49,25 +52,25 @@ func (t T) Hijack() {
ctx.CustomState = &MyState{10}
- t.Eq(http.MethodPost, r.Method())
- t.Eq(s.URL("/a"), r.URL().String())
+ g.Eq(http.MethodPost, r.Method())
+ g.Eq(s.URL("/a"), r.URL().String())
- t.Eq(proto.NetworkResourceTypeXHR, ctx.Request.Type())
- t.Is(ctx.Request.IsNavigation(), false)
- t.Has(ctx.Request.Header("Origin"), s.URL())
- t.Len(ctx.Request.Headers(), 6)
- t.True(ctx.Request.JSONBody().Nil())
+ g.Eq(proto.NetworkResourceTypeXHR, ctx.Request.Type())
+ g.Is(ctx.Request.IsNavigation(), false)
+ g.Has(ctx.Request.Header("Origin"), s.URL())
+ g.Len(ctx.Request.Headers(), 6)
+ g.True(ctx.Request.JSONBody().Nil())
// send request load response from real destination as the default value to hijack
ctx.MustLoadResponse()
- t.Eq(200, ctx.Response.Payload().ResponseCode)
+ g.Eq(200, ctx.Response.Payload().ResponseCode)
// override status code
ctx.Response.Payload().ResponseCode = http.StatusCreated
- t.Eq("4", ctx.Response.Headers().Get("Content-Length"))
- t.Has(ctx.Response.Headers().Get("Content-Type"), "text/html; charset=utf-8")
+ g.Eq("4", ctx.Response.Headers().Get("Content-Length"))
+ g.Has(ctx.Response.Headers().Get("Content-Type"), "text/html; charset=utf-8")
// override response header
ctx.Response.SetHeader("Set-Cookie", "key=val")
@@ -79,7 +82,7 @@ func (t T) Hijack() {
"text": "test",
})
- t.Eq("{\"text\":\"test\"}", ctx.Response.Body())
+ g.Eq("{\"text\":\"test\"}", ctx.Response.Body())
})
router.MustAdd(s.URL("/b"), func(ctx *rod.Hijack) {
@@ -94,16 +97,18 @@ func (t T) Hijack() {
go router.Run()
- t.page.MustNavigate(s.URL())
+ g.page.MustNavigate(s.URL())
- t.Eq("201 test key=val", t.page.MustElement("#a").MustText())
- t.Eq("b", t.page.MustElement("#b").MustText())
+ g.Eq("201 test key=val", g.page.MustElement("#a").MustText())
+ g.Eq("b", g.page.MustElement("#b").MustText())
}
-func (t T) HijackContinue() {
- s := t.Serve().Route("/", ".html", `ok`)
+func TestHijackContinue(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve().Route("/", ".html", `ok`)
- router := t.page.HijackRequests()
+ router := g.page.HijackRequests()
defer router.MustStop()
wg := &sync.WaitGroup{}
@@ -115,14 +120,16 @@ func (t T) HijackContinue() {
go router.Run()
- t.page.MustNavigate(s.URL("/a"))
+ g.page.MustNavigate(s.URL("/a"))
- t.Eq("ok", t.page.MustElement("body").MustText())
+ g.Eq("ok", g.page.MustElement("body").MustText())
wg.Wait()
}
-func (t T) HijackMockWholeResponse() {
- router := t.page.HijackRequests()
+func TestHijackMockWholeResponse(t *testing.T) {
+ g := setup(t)
+
+ router := g.page.HijackRequests()
defer router.MustStop()
router.MustAdd("*", func(ctx *rod.Hijack) {
@@ -132,15 +139,17 @@ func (t T) HijackMockWholeResponse() {
go router.Run()
- t.page.MustNavigate("http://test.com")
+ g.page.MustNavigate("http://test.com")
- t.Eq("ok", t.page.MustElement("body").MustText())
+ g.Eq("ok", g.page.MustElement("body").MustText())
}
-func (t T) HijackSkip() {
- s := t.Serve()
+func TestHijackSkip(t *testing.T) {
+ g := setup(t)
- router := t.page.HijackRequests()
+ s := g.Serve()
+
+ router := g.page.HijackRequests()
defer router.MustStop()
wg := &sync.WaitGroup{}
@@ -156,15 +165,17 @@ func (t T) HijackSkip() {
go router.Run()
- t.page.MustNavigate(s.URL("/a"))
+ g.page.MustNavigate(s.URL("/a"))
wg.Wait()
}
-func (t T) HijackOnErrorLog() {
- s := t.Serve().Route("/", ".html", `ok`)
+func TestHijackOnErrorLog(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve().Route("/", ".html", `ok`)
- router := t.page.HijackRequests()
+ router := g.page.HijackRequests()
defer router.MustStop()
wg := &sync.WaitGroup{}
@@ -181,20 +192,22 @@ func (t T) HijackOnErrorLog() {
go router.Run()
- t.mc.stub(1, proto.FetchContinueRequest{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.FetchContinueRequest{}, func(send StubSend) (gson.JSON, error) {
return gson.New(nil), errors.New("err")
})
go func() {
- _ = t.page.Context(t.Context()).Navigate(s.URL("/a"))
+ _ = g.page.Context(g.Context()).Navigate(s.URL("/a"))
}()
wg.Wait()
- t.Eq(err.Error(), "err")
+ g.Eq(err.Error(), "err")
}
-func (t T) HijackFailRequest() {
- s := t.Serve().Route("/page", ".html", `
+func TestHijackFailRequest(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve().Route("/page", ".html", `
`)
- router := t.browser.HijackRequests()
+ router := g.browser.HijackRequests()
defer router.MustStop()
router.MustAdd(s.URL("/a"), func(ctx *rod.Hijack) {
@@ -211,21 +224,23 @@ func (t T) HijackFailRequest() {
go router.Run()
- t.page.MustNavigate(s.URL("/page")).MustWaitLoad()
+ g.page.MustNavigate(s.URL("/page")).MustWaitLoad()
- t.page.MustWait(`() => document.title === 'Failed to fetch'`)
+ g.page.MustWait(`() => document.title === 'Failed to fetch'`)
{ // test error log
- t.mc.stub(1, proto.FetchFailRequest{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.FetchFailRequest{}, func(send StubSend) (gson.JSON, error) {
_, _ = send()
return gson.JSON{}, errors.New("err")
})
- _ = t.page.Navigate(s.URL("/a"))
+ _ = g.page.Navigate(s.URL("/a"))
}
}
-func (t T) HijackLoadResponseErr() {
- p := t.newPage().Context(t.Context())
+func TestHijackLoadResponseErr(t *testing.T) {
+ g := setup(t)
+
+ p := g.newPage().Context(g.Context())
router := p.HijackRequests()
defer router.MustStop()
@@ -233,11 +248,11 @@ func (t T) HijackLoadResponseErr() {
wg.Add(1)
router.MustAdd("http://test.com/a", func(ctx *rod.Hijack) {
- t.Err(ctx.LoadResponse(&http.Client{
+ g.Err(ctx.LoadResponse(&http.Client{
Transport: &MockRoundTripper{err: errors.New("err")},
}, true))
- t.Err(ctx.LoadResponse(&http.Client{
+ g.Err(ctx.LoadResponse(&http.Client{
Transport: &MockRoundTripper{res: &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(&MockReader{err: errors.New("err")}),
@@ -256,10 +271,12 @@ func (t T) HijackLoadResponseErr() {
wg.Wait()
}
-func (t T) HijackResponseErr() {
- s := t.Serve().Route("/", ".html", `ok`)
+func TestHijackResponseErr(t *testing.T) {
+ g := setup(t)
- p := t.newPage().Context(t.Context())
+ s := g.Serve().Route("/", ".html", `ok`)
+
+ p := g.newPage().Context(g.Context())
router := p.HijackRequests()
defer router.MustStop()
@@ -268,12 +285,12 @@ func (t T) HijackResponseErr() {
router.MustAdd(s.URL("/a"), func(ctx *rod.Hijack) { // to ignore favicon
ctx.OnError = func(err error) {
- t.Err(err)
+ g.Err(err)
wg.Done()
}
ctx.MustLoadResponse()
- t.mc.stub(1, proto.FetchFulfillRequest{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.FetchFulfillRequest{}, func(send StubSend) (gson.JSON, error) {
res, _ := send()
return res, errors.New("err")
})
@@ -286,8 +303,10 @@ func (t T) HijackResponseErr() {
wg.Wait()
}
-func (t T) HandleAuth() {
- s := t.Serve()
+func TestHandleAuth(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
// mock the server
s.Mux.HandleFunc("/a", func(w http.ResponseWriter, r *http.Request) {
@@ -298,24 +317,24 @@ func (t T) HandleAuth() {
return
}
- t.Eq("a", u)
- t.Eq("b", p)
- t.HandleHTTP(".html", `ok
`)(w, r)
+ g.Eq("a", u)
+ g.Eq("b", p)
+ g.HandleHTTP(".html", `ok
`)(w, r)
})
s.Route("/err", ".html", "err page")
- go t.browser.MustHandleAuth("a", "b")()
+ go g.browser.MustHandleAuth("a", "b")()
- page := t.newPage(s.URL("/a"))
+ page := g.newPage(s.URL("/a"))
page.MustElementR("p", "ok")
- wait := t.browser.HandleAuth("a", "b")
+ wait := g.browser.HandleAuth("a", "b")
var page2 *rod.Page
wait2 := utils.All(func() {
- page2, _ = t.browser.Page(proto.TargetCreateTarget{URL: s.URL("/err")})
+ page2, _ = g.browser.Page(proto.TargetCreateTarget{URL: s.URL("/err")})
})
- t.mc.stubErr(1, proto.FetchContinueRequest{})
- t.Err(wait())
+ g.mc.stubErr(1, proto.FetchContinueRequest{})
+ g.Err(wait())
wait2()
page2.MustClose()
}
diff --git a/lib/cdp/client_private_test.go b/lib/cdp/client_private_test.go
index 53c9fba8..405009a3 100644
--- a/lib/cdp/client_private_test.go
+++ b/lib/cdp/client_private_test.go
@@ -11,13 +11,7 @@ import (
"github.com/ysmood/got"
)
-func Test(t *testing.T) {
- got.Each(t, T{})
-}
-
-type T struct {
- got.G
-}
+var setup = got.Setup(nil)
type MockWebSocket struct {
send func([]byte) error
@@ -37,18 +31,22 @@ func (c *MockWebSocket) Read() ([]byte, error) {
return c.read()
}
-func (t T) CancelCall() {
+func TestCancelCall(t *testing.T) {
+ g := setup(t)
+
cdp := New("")
go func() {
<-cdp.chReq
}()
- cdp.ctx = t.Context()
- _, err := cdp.Call(t.Timeout(0), "", "", nil)
- t.Err(err)
+ cdp.ctx = g.Context()
+ _, err := cdp.Call(g.Timeout(0), "", "", nil)
+ g.Err(err)
}
-func (t T) ReqErr() {
- ctx := t.Context()
+func TestReqErr(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
cdp := New("")
cdp.ctx = ctx
cdp.close = ctx.Cancel
@@ -56,19 +54,23 @@ func (t T) ReqErr() {
send: func([]byte) error { return errors.New("err") },
}
- _, err := cdp.Call(t.Context(), "", "", nil)
- t.Err(err)
+ _, err := cdp.Call(g.Context(), "", "", nil)
+ g.Err(err)
}
-func (t T) CancelBeforeSend() {
+func TestCancelBeforeSend(t *testing.T) {
+ g := setup(t)
+
cdp := New("")
- cdp.ctx = t.Context()
- _, err := cdp.Call(t.Timeout(0), "", "", nil)
- t.Eq(err, context.DeadlineExceeded)
+ cdp.ctx = g.Context()
+ _, err := cdp.Call(g.Timeout(0), "", "", nil)
+ g.Eq(err, context.DeadlineExceeded)
}
-func (t T) CancelBeforeCallback() {
- ctx := t.Context()
+func TestCancelBeforeCallback(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
cdp := New("")
cdp.ws = &MockWebSocket{
read: func() ([]byte, error) {
@@ -84,11 +86,13 @@ func (t T) CancelBeforeCallback() {
cdp.MustConnect(ctx)
_, err := cdp.Call(ctx, "", "", nil)
- t.Eq(err.Error(), "context canceled")
+ g.Eq(err.Error(), "context canceled")
}
-func (t T) CancelOnReadRes() {
- ctx := t.Context()
+func TestCancelOnReadRes(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
cdp := New("")
cdp.ws = &MockWebSocket{
send: func(bytes []byte) error {
@@ -106,11 +110,13 @@ func (t T) CancelOnReadRes() {
cdp.MustConnect(ctx)
_, err := cdp.Call(ctx, "", "", nil)
- t.Err(err)
+ g.Err(err)
}
-func (t T) CallAfterBrowserDone() {
- ctx := t.Context()
+func TestCallAfterBrowserDone(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
cdp := New("")
cdp.ws = &MockWebSocket{
send: func(bytes []byte) error { return io.EOF },
@@ -120,13 +126,15 @@ func (t T) CallAfterBrowserDone() {
utils.Sleep(0.1)
_, err := cdp.Call(ctx, "", "", nil)
- t.Err(err)
- t.Is(err, io.EOF)
- t.Eq(err.Error(), "cdp connection closed: EOF")
+ g.Err(err)
+ g.Is(err, io.EOF)
+ g.Eq(err.Error(), "cdp connection closed: EOF")
}
-func (t T) CancelOnReadEvent() {
- ctx, cancel := context.WithCancel(t.Context())
+func TestCancelOnReadEvent(t *testing.T) {
+ g := setup(t)
+
+ ctx, cancel := context.WithCancel(g.Context())
cdp := New("")
cdp.ws = &MockWebSocket{
send: func(bytes []byte) error {
@@ -139,21 +147,25 @@ func (t T) CancelOnReadEvent() {
}
cdp.MustConnect(ctx)
- _, err := cdp.Call(t.Context(), "", "", nil)
- t.Err(err)
+ _, err := cdp.Call(g.Context(), "", "", nil)
+ g.Err(err)
}
-func (t T) TestError() {
- t.Is(&Error{Code: -123}, &Error{Code: -123})
+func TestTestError(t *testing.T) {
+ g := setup(t)
+
+ g.Is(&Error{Code: -123}, &Error{Code: -123})
}
-func (t T) PendingRequests() {
+func TestPendingRequests(t *testing.T) {
+ g := setup(t)
+
pending := newPendingRequests()
err := pending.add(1, newPendingRequest())
- t.Nil(err)
+ g.Nil(err)
err = pending.add(2, newPendingRequest())
- t.Nil(err)
+ g.Nil(err)
pending.fulfill(1, &Response{})
// resolving something where no-one is waiting is fine
@@ -165,12 +177,12 @@ func (t T) PendingRequests() {
pending.close(errors.New("this will be ignored"))
err = pending.add(3, newPendingRequest())
- t.Is(err, io.EOF)
- t.Err(err)
+ g.Is(err, io.EOF)
+ g.Err(err)
pending = newPendingRequests()
pending.close(nil)
err = pending.add(3, newPendingRequest())
- t.Err(err)
- t.Eq(err.Error(), "browser has shut down")
+ g.Err(err)
+ g.Eq(err.Error(), "browser has shut down")
}
diff --git a/lib/cdp/client_test.go b/lib/cdp/client_test.go
index 291f724b..0ab1f44f 100644
--- a/lib/cdp/client_test.go
+++ b/lib/cdp/client_test.go
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"log"
"net/http"
+ "os"
"path/filepath"
"testing"
"time"
@@ -20,20 +21,20 @@ import (
var loud = flag.Bool("loud", false, "log everything")
-func Test(t *testing.T) {
+func TestMain(m *testing.M) {
if !*loud {
log.SetOutput(ioutil.Discard)
}
- got.Each(t, T{})
+ os.Exit(m.Run())
}
-type T struct {
- got.G
-}
+var setup = got.Setup(nil)
+
+func TestBasic(t *testing.T) {
+ g := setup(t)
-func (t T) Basic() {
- ctx := t.Context()
+ ctx := g.Context()
url := launcher.New().MustLaunch()
@@ -51,12 +52,12 @@ func (t T) Basic() {
}()
file, err := filepath.Abs(filepath.FromSlash("fixtures/iframe.html"))
- t.E(err)
+ g.E(err)
res, err := client.Call(ctx, "", "Target.createTarget", map[string]string{
"url": "file://" + file,
})
- t.E(err)
+ g.E(err)
targetID := gson.New(res).Get("targetId").String()
@@ -64,19 +65,19 @@ func (t T) Basic() {
"targetId": targetID,
"flatten": true, // if it's not set no response will return
})
- t.E(err)
+ g.E(err)
sessionID := gson.New(res).Get("sessionId").String()
_, err = client.Call(ctx, sessionID, "Page.enable", nil)
- t.E(err)
+ g.E(err)
_, err = client.Call(ctx, "", "Target.attachToTarget", map[string]interface{}{
"targetId": "abc",
})
- t.Err(err)
+ g.Err(err)
- timeout := t.Context()
+ timeout := g.Context()
sleeper := func() utils.Sleeper {
return utils.BackoffSleeper(30*time.Millisecond, 3*time.Second, nil)
@@ -88,9 +89,9 @@ func (t T) Basic() {
_, err = client.Call(tmpCtx, sessionID, "Runtime.evaluate", map[string]interface{}{
"expression": `10`,
})
- t.Eq(err.Error(), context.Canceled.Error())
+ g.Eq(err.Error(), context.Canceled.Error())
- t.E(utils.Retry(timeout, sleeper(), func() (bool, error) {
+ g.E(utils.Retry(timeout, sleeper(), func() (bool, error) {
res, err = client.Call(ctx, sessionID, "Runtime.evaluate", map[string]interface{}{
"expression": `document.querySelector('iframe')`,
})
@@ -101,19 +102,19 @@ func (t T) Basic() {
res, err = client.Call(ctx, sessionID, "DOM.describeNode", map[string]interface{}{
"objectId": gson.New(res).Get("result.objectId").String(),
})
- t.E(err)
+ g.E(err)
frameID := gson.New(res).Get("node.frameId").String()
- timeout = t.Context()
+ timeout = g.Context()
- t.E(utils.Retry(timeout, sleeper(), func() (bool, error) {
+ g.E(utils.Retry(timeout, sleeper(), func() (bool, error) {
// we might need to recreate the world because world can be
// destroyed after the frame is reloaded
res, err = client.Call(ctx, sessionID, "Page.createIsolatedWorld", map[string]interface{}{
"frameId": frameID,
})
- t.E(err)
+ g.E(err)
res, err = client.Call(ctx, sessionID, "Runtime.evaluate", map[string]interface{}{
"contextId": gson.New(res).Get("executionContextId").Int(),
@@ -126,29 +127,34 @@ func (t T) Basic() {
res, err = client.Call(ctx, sessionID, "DOM.getOuterHTML", map[string]interface{}{
"objectId": gson.New(res).Get("result.objectId").String(),
})
- t.E(err)
+ g.E(err)
- t.Eq("it works ", gson.New(res).Get("outerHTML").String())
+ g.Eq("it works ", gson.New(res).Get("outerHTML").String())
}
-func (t T) TestError() {
+func TestTestError(t *testing.T) {
+ g := setup(t)
+
cdpErr := cdp.Error{10, "err", "data"}
- t.Eq(cdpErr.Error(), "{10 err data}")
+ g.Eq(cdpErr.Error(), "{10 err data}")
- t.Panic(func() {
- cdp.New("").MustConnect(t.Context())
+ g.Panic(func() {
+ cdp.New("").MustConnect(g.Context())
})
}
-func (t T) NewWithLogger() {
+func TestNewWithLogger(t *testing.T) {
+ g := setup(t)
- t.Panic(func() {
- cdp.New("").MustConnect(t.Context())
+ g.Panic(func() {
+ cdp.New("").MustConnect(g.Context())
})
}
-func (t T) Crash() {
- ctx := t.Context()
+func TestCrash(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
l := launcher.New()
client := cdp.New(l.MustLaunch()).Logger(utils.LoggerQuiet).MustConnect(ctx)
@@ -159,12 +165,12 @@ func (t T) Crash() {
}()
file, err := filepath.Abs(filepath.FromSlash("fixtures/iframe.html"))
- t.E(err)
+ g.E(err)
res, err := client.Call(ctx, "", "Target.createTarget", map[string]interface{}{
"url": "file://" + file,
})
- t.E(err)
+ g.E(err)
targetID := gson.New(res).Get("targetId").String()
@@ -172,12 +178,12 @@ func (t T) Crash() {
"targetId": targetID,
"flatten": true,
})
- t.E(err)
+ g.E(err)
sessionID := gson.New(res).Get("sessionId").String()
_, err = client.Call(ctx, sessionID, "Page.enable", nil)
- t.E(err)
+ g.E(err)
go func() {
utils.Sleep(2)
@@ -188,6 +194,6 @@ func (t T) Crash() {
"expression": `new Promise(() => {})`,
"awaitPromise": true,
})
- t.Is(err, cdp.ErrConnClosed)
- t.Eq(err.Error(), "cdp connection closed: EOF")
+ g.Is(err, cdp.ErrConnClosed)
+ g.Eq(err.Error(), "cdp connection closed: EOF")
}
diff --git a/lib/cdp/websocket_private_test.go b/lib/cdp/websocket_private_test.go
index a9aab3b4..3054f252 100644
--- a/lib/cdp/websocket_private_test.go
+++ b/lib/cdp/websocket_private_test.go
@@ -6,37 +6,40 @@ import (
"errors"
"net"
"net/url"
+ "testing"
"time"
)
-func (t T) WebSocketErr() {
+func TestWebSocketErr(t *testing.T) {
+ g := setup(t)
+
ws := WebSocket{}
- t.Err(ws.Connect(t.Context(), "://", nil))
+ g.Err(ws.Connect(g.Context(), "://", nil))
ws.Dialer = &net.Dialer{}
ws.initDialer(nil)
u, err := url.Parse("wss://no-exist")
- t.E(err)
+ g.E(err)
ws.Dialer = nil
ws.initDialer(u)
mc := &MockConn{}
ws.conn = mc
- t.Err(ws.Send([]byte("test")))
+ g.Err(ws.Send([]byte("test")))
mc.errOnCount = 1
mc.frame = []byte{0, 127, 1}
ws.r = bufio.NewReader(mc)
- t.Err(ws.Read())
+ g.Err(ws.Read())
- t.Err(ws.handshake(t.Timeout(0), nil, nil))
+ g.Err(ws.handshake(g.Timeout(0), nil, nil))
mc.errOnCount = 1
- t.Err(ws.handshake(t.Context(), u, nil))
+ g.Err(ws.handshake(g.Context(), u, nil))
tls := &tlsDialer{}
- t.Err(tls.DialContext(context.Background(), "", ""))
+ g.Err(tls.DialContext(context.Background(), "", ""))
}
type MockConn struct {
diff --git a/lib/cdp/websocket_test.go b/lib/cdp/websocket_test.go
index 8564b6bb..2deca453 100644
--- a/lib/cdp/websocket_test.go
+++ b/lib/cdp/websocket_test.go
@@ -6,48 +6,54 @@ import (
"net/http"
"path/filepath"
"strings"
+ "testing"
"github.com/go-rod/rod/lib/cdp"
"github.com/go-rod/rod/lib/launcher"
+ "github.com/ysmood/got"
"github.com/ysmood/gson"
)
-func (t T) WebSocketLargePayload() {
- ctx := t.Context()
- client, id := t.newPage(ctx)
+func TestWebSocketLargePayload(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
+ client, id := newPage(ctx, g)
res, err := client.Call(ctx, id, "Runtime.evaluate", map[string]interface{}{
"expression": fmt.Sprintf(`"%s"`, strings.Repeat("a", 2*1024*1024)),
"returnByValue": true,
})
- t.E(err)
- t.Gt(res, 2*1024*1024) // 2MB
+ g.E(err)
+ g.Gt(res, 2*1024*1024) // 2MB
}
-func (t T) WebSocketHeader() {
- s := t.Serve()
+func TestWebSocketHeader(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
wait := make(chan struct{})
s.Mux.HandleFunc("/a", func(rw http.ResponseWriter, r *http.Request) {
- t.Eq(r.Header.Get("Test"), "header")
- t.Eq(r.Host, "test.com")
- t.Eq(r.URL.Query().Get("q"), "ok")
+ g.Eq(r.Header.Get("Test"), "header")
+ g.Eq(r.Host, "test.com")
+ g.Eq(r.URL.Query().Get("q"), "ok")
close(wait)
})
ws := cdp.WebSocket{}
- err := ws.Connect(t.Context(), s.URL("/a?q=ok"), http.Header{
+ err := ws.Connect(g.Context(), s.URL("/a?q=ok"), http.Header{
"Host": {"test.com"},
"Test": {"header"},
})
<-wait
- t.Eq(err.Error(), "websocket bad handshake: 200 OK. ")
+ g.Eq(err.Error(), "websocket bad handshake: 200 OK. ")
}
-func (t T) newPage(ctx context.Context) (*cdp.Client, string) {
+func newPage(ctx context.Context, g got.G) (*cdp.Client, string) {
l := launcher.New()
- t.Cleanup(l.Kill)
+ g.Cleanup(l.Kill)
client := cdp.New(l.MustLaunch()).MustConnect(ctx)
@@ -57,12 +63,12 @@ func (t T) newPage(ctx context.Context) (*cdp.Client, string) {
}()
file, err := filepath.Abs(filepath.FromSlash("fixtures/basic.html"))
- t.E(err)
+ g.E(err)
res, err := client.Call(ctx, "", "Target.createTarget", map[string]interface{}{
"url": "file://" + file,
})
- t.E(err)
+ g.E(err)
targetID := gson.New(res).Get("targetId").String()
@@ -70,23 +76,25 @@ func (t T) newPage(ctx context.Context) (*cdp.Client, string) {
"targetId": targetID,
"flatten": true,
})
- t.E(err)
+ g.E(err)
sessionID := gson.New(res).Get("sessionId").String()
return client, sessionID
}
-func (t T) DuplicatedConnectErr() {
+func TestDuplicatedConnectErr(t *testing.T) {
+ g := setup(t)
+
l := launcher.New()
- t.Cleanup(l.Kill)
+ g.Cleanup(l.Kill)
u := l.MustLaunch()
ws := &cdp.WebSocket{}
- t.E(ws.Connect(t.Context(), u, nil))
+ g.E(ws.Connect(g.Context(), u, nil))
- t.Panic(func() {
- _ = ws.Connect(t.Context(), u, nil)
+ g.Panic(func() {
+ _ = ws.Connect(g.Context(), u, nil)
})
}
diff --git a/lib/js/helper.js b/lib/js/helper.js
index df1e8fd3..50fc3051 100644
--- a/lib/js/helper.js
+++ b/lib/js/helper.js
@@ -2,7 +2,7 @@
// To debug just add "debugger" keyword to the line you want to pause, then run something like:
//
// go run ./lib/js/generate
-// rod=show,devtools go test -run /Click
+// rod=show,devtools go test -run ^TestClick$
const functions = {
element(selector) {
diff --git a/lib/launcher/launcher_test.go b/lib/launcher/launcher_test.go
index 9b6406ca..b4894847 100644
--- a/lib/launcher/launcher_test.go
+++ b/lib/launcher/launcher_test.go
@@ -21,23 +21,19 @@ import (
"github.com/ysmood/got"
)
-type T struct {
- got.G
-}
+var setup = got.Setup(nil)
-func Test(t *testing.T) {
- launcher.NewBrowser().MustGet() // preload browser to local
+func TestDownloadHosts(t *testing.T) {
+ g := setup(t)
- got.Each(t, T{})
+ g.Has(launcher.HostGoogle(launcher.DefaultRevision), "https://storage.googleapis.com/chromium-browser-snapshots")
+ g.Has(launcher.HostNPM(launcher.DefaultRevision), "https://registry.npmmirror.com/-/binary/chromium-browser-snapshots")
}
-func (t T) DownloadHosts() {
- t.Has(launcher.HostGoogle(launcher.DefaultRevision), "https://storage.googleapis.com/chromium-browser-snapshots")
- t.Has(launcher.HostNPM(launcher.DefaultRevision), "https://registry.npmmirror.com/-/binary/chromium-browser-snapshots")
-}
+func TestDownload(t *testing.T) {
+ g := setup(t)
-func (t T) Download() {
- s := t.Serve()
+ s := g.Serve()
s.Mux.HandleFunc("/fast/", func(rw http.ResponseWriter, r *http.Request) {
buf := bytes.NewBuffer(nil)
zw := zip.NewWriter(buf)
@@ -46,15 +42,15 @@ func (t T) Download() {
h := &zip.FileHeader{Name: "to/"}
h.SetMode(0755)
_, err := zw.CreateHeader(h)
- t.E(err)
+ g.E(err)
// file "file.txt"
w, err := zw.CreateHeader(&zip.FileHeader{Name: "to/file.txt"})
- t.E(err)
- b := []byte(t.Srand(2 * 1024 * 1024))
- t.E(w.Write(b))
+ g.E(err)
+ b := []byte(g.RandStr(2 * 1024 * 1024))
+ g.E(w.Write(b))
- t.E(zw.Close())
+ g.E(zw.Close())
rw.Header().Add("Content-Length", fmt.Sprintf("%d", buf.Len()))
_, _ = io.Copy(rw, buf)
@@ -72,16 +68,20 @@ func (t T) Download() {
b.Logger = ioutil.Discard
defer cancel()
b.Hosts = []launcher.Host{launcher.HostTest(s.URL("/slow")), launcher.HostTest(s.URL("/fast"))}
- b.Dir = filepath.Join("tmp", "browser-from-mirror", t.Srand(16))
- t.E(b.Download())
- t.Nil(os.Stat(b.Dir))
+ b.Dir = filepath.Join("tmp", "browser-from-mirror", g.RandStr(16))
+ g.E(b.Download())
+ g.Nil(os.Stat(b.Dir))
}
-func (t T) BrowserGet() {
- t.Nil(os.Stat(launcher.NewBrowser().MustGet()))
+func TestBrowserGet(t *testing.T) {
+ g := setup(t)
+
+ g.Nil(os.Stat(launcher.NewBrowser().MustGet()))
}
-func (t T) Launch() {
+func TestLaunch(t *testing.T) {
+ g := setup(t)
+
defaults.Proxy = "test.com"
defer func() { defaults.ResetWithEnv("") }()
@@ -89,49 +89,51 @@ func (t T) Launch() {
defer l.Kill()
u := l.MustLaunch()
- t.Regex(`\Aws://.+\z`, u)
+ g.Regex(`\Aws://.+\z`, u)
parsed, _ := url.Parse(u)
{ // test GetWebSocketDebuggerURL
for _, prefix := range []string{"", ":", "127.0.0.1:", "ws://127.0.0.1:"} {
u2 := launcher.MustResolveURL(prefix + parsed.Port())
- t.Regex(u, u2)
+ g.Regex(u, u2)
}
_, err := launcher.ResolveURL("")
- t.Err(err)
+ g.Err(err)
}
{
_, err := launcher.NewManaged("")
- t.Err(err)
+ g.Err(err)
_, err = launcher.NewManaged("1://")
- t.Err(err)
+ g.Err(err)
_, err = launcher.NewManaged("ws://not-exists")
- t.Err(err)
+ g.Err(err)
}
}
-func (t T) LaunchUserMode() {
+func TestLaunchUserMode(t *testing.T) {
+ g := setup(t)
+
l := launcher.NewUserMode()
defer l.Kill()
l.Kill() // empty kill should do nothing
has := l.Has("not-exists")
- t.False(has)
+ g.False(has)
l.Append("test-append", "a")
f := l.Get("test-append")
- t.Eq("a", f)
+ g.Eq("a", f)
dir := l.Get(flags.UserDataDir)
port := 58472
- url := l.Context(t.Context()).Delete("test").Bin("").
+ url := l.Context(g.Context()).Delete("test").Bin("").
Revision(launcher.DefaultRevision).
Logger(ioutil.Discard).
Leakless(false).Leakless(true).
@@ -145,30 +147,36 @@ func (t T) LaunchUserMode() {
Env("TZ=Asia/Tokyo").
MustLaunch()
- t.Eq(url, launcher.NewUserMode().RemoteDebuggingPort(port).MustLaunch())
+ g.Eq(url, launcher.NewUserMode().RemoteDebuggingPort(port).MustLaunch())
}
-func (t T) UserModeErr() {
+func TestUserModeErr(t *testing.T) {
+ g := setup(t)
+
_, err := launcher.NewUserMode().RemoteDebuggingPort(48277).Bin("not-exists").Launch()
- t.Err(err)
+ g.Err(err)
_, err = launcher.NewUserMode().RemoteDebuggingPort(58217).Bin("echo").Launch()
- t.Err(err)
+ g.Err(err)
}
-func (t T) GetWebSocketDebuggerURLErr() {
+func TestGetWebSocketDebuggerURLErr(t *testing.T) {
+ g := setup(t)
+
_, err := launcher.ResolveURL("1://")
- t.Err(err)
+ g.Err(err)
}
-func (t T) LaunchErr() {
- t.Panic(func() {
+func TestLaunchErr(t *testing.T) {
+ g := setup(t)
+
+ g.Panic(func() {
launcher.New().Bin("not-exists").MustLaunch()
})
- t.Panic(func() {
+ g.Panic(func() {
launcher.New().Headless(false).Bin("not-exists").MustLaunch()
})
- t.Panic(func() {
+ g.Panic(func() {
launcher.New().Client()
})
{
@@ -190,12 +198,14 @@ func newBrowser() (*launcher.Browser, func()) {
var testProfileDir = flag.Bool("test-profile-dir", false, "set it to test profile dir")
-func (t T) ProfileDir() {
+func TestProfileDir(t *testing.T) {
+ g := setup(t)
+
url := launcher.New().Headless(false).
ProfileDir("").ProfileDir("test-profile-dir")
if !*testProfileDir {
- t.Skip("It's not CI friendly, so we skip it!")
+ g.Skip("It's not CI friendly, so we skip it!")
}
url.MustLaunch()
@@ -203,6 +213,6 @@ func (t T) ProfileDir() {
userDataDir := url.Get(flags.UserDataDir)
file, err := os.Stat(filepath.Join(userDataDir, "test-profile-dir"))
- t.E(err)
- t.True(file.IsDir())
+ g.E(err)
+ g.True(file.IsDir())
}
diff --git a/lib/launcher/private_test.go b/lib/launcher/private_test.go
index 1c65b2b5..22986ba0 100644
--- a/lib/launcher/private_test.go
+++ b/lib/launcher/private_test.go
@@ -30,37 +30,43 @@ func HostTest(host string) Host {
}
}
-type T struct {
- got.G
-}
+var setup = got.Setup(nil)
-func TestPrivate(t *testing.T) {
+func TestMain(m *testing.M) {
NewBrowser().MustGet() // preload browser to local
- got.Each(t, T{})
+ os.Exit(m.Run())
}
-func (t T) ToHTTP() {
+func TestToHTTP(t *testing.T) {
+ g := setup(t)
+
u, _ := url.Parse("wss://a.com")
- t.Eq("https", toHTTP(*u).Scheme)
+ g.Eq("https", toHTTP(*u).Scheme)
u, _ = url.Parse("ws://a.com")
- t.Eq("http", toHTTP(*u).Scheme)
+ g.Eq("http", toHTTP(*u).Scheme)
}
-func (t T) ToWS() {
+func TestToWS(t *testing.T) {
+ g := setup(t)
+
u, _ := url.Parse("https://a.com")
- t.Eq("wss", toWS(*u).Scheme)
+ g.Eq("wss", toWS(*u).Scheme)
u, _ = url.Parse("http://a.com")
- t.Eq("ws", toWS(*u).Scheme)
+ g.Eq("ws", toWS(*u).Scheme)
}
-func (t T) Unzip() {
- t.Err(unzip(ioutil.Discard, "", ""))
+func TestUnzip(t *testing.T) {
+ g := setup(t)
+
+ g.Err(unzip(ioutil.Discard, "", ""))
}
-func (t T) LaunchOptions() {
+func TestLaunchOptions(t *testing.T) {
+ g := setup(t)
+
defaults.Show = true
defaults.Devtools = true
inContainer = true
@@ -73,19 +79,21 @@ func (t T) LaunchOptions() {
l := New()
- t.False(l.Has(flags.Headless))
+ g.False(l.Has(flags.Headless))
- t.True(l.Has(flags.NoSandbox))
+ g.True(l.Has(flags.NoSandbox))
- t.True(l.Has("auto-open-devtools-for-tabs"))
+ g.True(l.Has("auto-open-devtools-for-tabs"))
}
-func (t T) GetURLErr() {
+func TestGetURLErr(t *testing.T) {
+ g := setup(t)
+
l := New()
l.ctxCancel()
_, err := l.getURL()
- t.Err(err)
+ g.Err(err)
l = New()
l.parser.lock.Lock()
@@ -93,20 +101,22 @@ func (t T) GetURLErr() {
l.parser.lock.Unlock()
close(l.exit)
_, err = l.getURL()
- t.Eq("[launcher] Failed to get the debug url: err", err.Error())
+ g.Eq("[launcher] Failed to get the debug url: err", err.Error())
}
-func (t T) RemoteLaunch() {
- ctx := t.Timeout(5 * time.Second)
+func TestRemoteLaunch(t *testing.T) {
+ g := setup(t)
- s := got.New(t).Serve()
+ ctx := g.Timeout(5 * time.Second)
+
+ s := got.New(g).Serve()
rl := NewManager()
s.Mux.Handle("/", rl)
l := MustNewManaged(s.URL()).KeepUserDataDir().Delete(flags.KeepUserDataDir)
client := l.Client()
b := client.MustConnect(ctx)
- t.E(b.Call(ctx, "", "Browser.getVersion", nil))
+ g.E(b.Call(ctx, "", "Browser.getVersion", nil))
utils.Sleep(1)
_, _ = b.Call(ctx, "", "Browser.crash", nil)
dir := l.Get(flags.UserDataDir)
@@ -118,55 +128,63 @@ func (t T) RemoteLaunch() {
break
}
}
- t.Err(os.Stat(dir))
+ g.Err(os.Stat(dir))
err := MustNewManaged(s.URL()).Bin("go").Client().Connect(ctx).(*cdp.ErrBadHandshake)
- t.Eq(err.Body, "not allowed rod-bin path: go")
+ g.Eq(err.Body, "not allowed rod-bin path: go")
}
-func (t T) LaunchErrs() {
+func TestLaunchErrs(t *testing.T) {
+ g := setup(t)
+
l := New().Bin("echo")
_, err := l.Launch()
- t.Err(err)
+ g.Err(err)
- s := t.Serve()
+ s := g.Serve()
s.Route("/", "", nil)
l = New().Bin("")
l.browser.Logger = ioutil.Discard
- l.browser.Dir = filepath.Join("tmp", "browser-from-mirror", t.Srand(16))
+ l.browser.Dir = filepath.Join("tmp", "browser-from-mirror", g.RandStr(16))
l.browser.Hosts = []Host{HostTest(s.URL())}
_, err = l.Launch()
- t.Err(err)
+ g.Err(err)
}
-func (t T) Progresser() {
+func TestProgresser(t *testing.T) {
+ g := setup(t)
+
p := progresser{size: 100, logger: ioutil.Discard}
- t.E(p.Write(make([]byte, 100)))
- t.E(p.Write(make([]byte, 100)))
- t.E(p.Write(make([]byte, 100)))
+ g.E(p.Write(make([]byte, 100)))
+ g.E(p.Write(make([]byte, 100)))
+ g.E(p.Write(make([]byte, 100)))
}
-func (t T) URLParserErr() {
+func TestURLParserErr(t *testing.T) {
+ g := setup(t)
+
u := &URLParser{
Buffer: "error",
lock: &sync.Mutex{},
}
- t.Eq(u.Err().Error(), "[launcher] Failed to get the debug url: error")
+ g.Eq(u.Err().Error(), "[launcher] Failed to get the debug url: error")
u.Buffer = "/tmp/rod/chromium-818858/chrome-linux/chrome: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory"
- t.Eq(u.Err().Error(), "[launcher] Failed to launch the browser, the doc might help https://go-rod.github.io/#/compatibility?id=os: /tmp/rod/chromium-818858/chrome-linux/chrome: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory")
+ g.Eq(u.Err().Error(), "[launcher] Failed to launch the browser, the doc might help https://go-rod.github.io/#/compatibility?id=os: /tmp/rod/chromium-818858/chrome-linux/chrome: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory")
}
-func (t T) BrowserDownloadErr() {
+func TestBrowserDownloadErr(t *testing.T) {
+ g := setup(t)
+
b := NewBrowser()
b.Logger = ioutil.Discard
malURL := "https://npm.taobao.org/mirrors/chromium-browser-snapshots//869685/"
- t.Has(b.download(t.Context(), malURL).Error(), "failed to download the browser: 200")
+ g.Has(b.download(g.Context(), malURL).Error(), "failed to download the browser: 200")
}
-func (t T) TestOpen() {
+func TestTestOpen(t *testing.T) {
openExec = func(name string, arg ...string) *exec.Cmd {
cmd := exec.Command("not-exists")
cmd.Process = &os.Process{}
diff --git a/lib/utils/sleeper_test.go b/lib/utils/sleeper_test.go
index b7a574c1..812e5f26 100644
--- a/lib/utils/sleeper_test.go
+++ b/lib/utils/sleeper_test.go
@@ -3,20 +3,25 @@ package utils_test
import (
"context"
"io"
+ "testing"
"time"
"github.com/go-rod/rod/lib/utils"
)
-func (t T) BackoffSleeperWakeNow() {
- t.E(utils.BackoffSleeper(0, 0, nil)(t.Context()))
+func TestBackoffSleeperWakeNow(t *testing.T) {
+ g := setup(t)
+
+ g.E(utils.BackoffSleeper(0, 0, nil)(g.Context()))
}
-func (t T) Retry() {
+func TestRetry(t *testing.T) {
+ g := setup(t)
+
count := 0
s1 := utils.BackoffSleeper(1, 5, nil)
- err := utils.Retry(t.Context(), s1, func() (bool, error) {
+ err := utils.Retry(g.Context(), s1, func() (bool, error) {
if count > 5 {
return true, io.EOF
}
@@ -24,11 +29,13 @@ func (t T) Retry() {
return false, nil
})
- t.Eq(err.Error(), io.EOF.Error())
+ g.Eq(err.Error(), io.EOF.Error())
}
-func (t T) RetryCancel() {
- ctx := t.Context()
+func TestRetryCancel(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
go ctx.Cancel()
s := utils.BackoffSleeper(time.Second, time.Second, nil)
@@ -36,24 +43,30 @@ func (t T) RetryCancel() {
return false, nil
})
- t.Eq(err.Error(), context.Canceled.Error())
+ g.Eq(err.Error(), context.Canceled.Error())
}
-func (t T) CountSleeperErr() {
- ctx := t.Context()
+func TestCountSleeperErr(t *testing.T) {
+ g := setup(t)
+
+ ctx := g.Context()
s := utils.CountSleeper(5)
for i := 0; i < 5; i++ {
_ = s(ctx)
}
- t.Err(s(ctx))
+ g.Err(s(ctx))
}
-func (t T) CountSleeperCancel() {
+func TestCountSleeperCancel(t *testing.T) {
+ g := setup(t)
+
s := utils.CountSleeper(5)
- t.Eq(s(t.Timeout(0)), context.DeadlineExceeded)
+ g.Eq(s(g.Timeout(0)), context.DeadlineExceeded)
}
-func (t T) EachSleepers() {
+func TestEachSleepers(t *testing.T) {
+ g := setup(t)
+
s1 := utils.BackoffSleeper(1, 5, nil)
s2 := utils.CountSleeper(5)
s := utils.EachSleepers(s1, s2)
@@ -62,11 +75,13 @@ func (t T) EachSleepers() {
return false, nil
})
- t.Is(err, &utils.ErrMaxSleepCount{})
- t.Eq(err.Error(), "max sleep count 5 exceeded")
+ g.Is(err, &utils.ErrMaxSleepCount{})
+ g.Eq(err.Error(), "max sleep count 5 exceeded")
}
-func (t T) RaceSleepers() {
+func TestRaceSleepers(t *testing.T) {
+ g := setup(t)
+
s1 := utils.BackoffSleeper(1, 5, nil)
s2 := utils.CountSleeper(5)
s := utils.RaceSleepers(s1, s2)
@@ -75,6 +90,6 @@ func (t T) RaceSleepers() {
return false, nil
})
- t.Is(err, &utils.ErrMaxSleepCount{})
- t.Eq(err.Error(), "max sleep count 5 exceeded")
+ g.Is(err, &utils.ErrMaxSleepCount{})
+ g.Eq(err.Error(), "max sleep count 5 exceeded")
}
diff --git a/lib/utils/utils_test.go b/lib/utils/utils_test.go
index 03b82c06..db8e440d 100644
--- a/lib/utils/utils_test.go
+++ b/lib/utils/utils_test.go
@@ -15,35 +15,35 @@ import (
"github.com/ysmood/got"
)
-type T struct {
- got.G
-}
+var setup = got.Setup(nil)
-func Test(t *testing.T) {
- got.Each(t, T{})
-}
+func TestTestLog(t *testing.T) {
+ g := setup(t)
-func (t T) TestLog() {
var res []interface{}
lg := utils.Log(func(msg ...interface{}) { res = append(res, msg[0]) })
lg.Println("ok")
- t.Eq(res[0], "ok")
+ g.Eq(res[0], "ok")
utils.LoggerQuiet.Println()
utils.MultiLogger(lg, lg).Println("ok")
- t.Eq(res, []interface{}{"ok", "ok", "ok"})
+ g.Eq(res, []interface{}{"ok", "ok", "ok"})
}
-func (t T) TestE() {
+func TestTestE(t *testing.T) {
+ g := setup(t)
+
utils.E(nil)
- t.Panic(func() {
+ g.Panic(func() {
utils.E(errors.New("err"))
})
}
-func (t T) STemplate() {
+func TestSTemplate(t *testing.T) {
+ g := setup(t)
+
out := utils.S(
"{{.a}} {{.b}} {{.c.A}} {{d}}",
"a", "",
@@ -53,22 +53,28 @@ func (t T) STemplate() {
return "ok"
},
)
- t.Eq(" 10 ok ok", out)
+ g.Eq(" 10 ok ok", out)
}
-func (t T) GenerateRandomString() {
+func TestGenerateRandomString(t *testing.T) {
+ g := setup(t)
+
v := utils.RandString(10)
raw, _ := hex.DecodeString(v)
- t.Len(raw, 10)
+ g.Len(raw, 10)
}
-func (t T) Mkdir() {
- p := filepath.Join(t.Testable.(*testing.T).TempDir(), "t")
- t.E(utils.Mkdir(p))
+func TestMkdir(t *testing.T) {
+ g := setup(t)
+
+ p := filepath.Join(g.Testable.(*testing.T).TempDir(), "t")
+ g.E(utils.Mkdir(p))
}
-func (t T) OutputString() {
- p := "tmp/" + t.Srand(16)
+func TestOutputString(t *testing.T) {
+ g := setup(t)
+
+ p := "tmp/" + g.RandStr(16)
_ = utils.OutputFile(p, p)
@@ -78,11 +84,13 @@ func (t T) OutputString() {
panic(err)
}
- t.Eq(s, p)
+ g.Eq(s, p)
}
-func (t T) OutputBytes() {
- p := "tmp/" + t.Srand(16)
+func TestOutputBytes(t *testing.T) {
+ g := setup(t)
+
+ p := "tmp/" + g.RandStr(16)
_ = utils.OutputFile(p, []byte("test"))
@@ -92,11 +100,13 @@ func (t T) OutputBytes() {
panic(err)
}
- t.Eq(s, "test")
+ g.Eq(s, "test")
}
-func (t T) OutputStream() {
- p := "tmp/" + t.Srand(16)
+func TestOutputStream(t *testing.T) {
+ g := setup(t)
+
+ p := "tmp/" + g.RandStr(16)
b := bytes.NewBufferString("test")
_ = utils.OutputFile(p, b)
@@ -107,52 +117,66 @@ func (t T) OutputStream() {
panic(err)
}
- t.Eq("test", s)
+ g.Eq("test", s)
}
-func (t T) OutputJSONErr() {
- p := "tmp/" + t.Srand(16)
+func TestOutputJSONErr(t *testing.T) {
+ g := setup(t)
- t.Panic(func() {
+ p := "tmp/" + g.RandStr(16)
+
+ g.Panic(func() {
_ = utils.OutputFile(p, make(chan struct{}))
})
}
-func (t T) Sleep() {
+func TestSleep(t *testing.T) {
utils.Sleep(0.01)
}
-func (t T) All() {
- c := t.Count(3)
+func TestAll(t *testing.T) {
+ g := setup(t)
+
+ c := g.Count(3)
utils.All(c, c, c)()
}
-func (t T) Pause() {
+func TestPause(t *testing.T) {
go utils.Pause()
}
-func (t T) MustToJSON() {
- t.Eq(utils.Dump("a", 10), `"a" 10`)
- t.Eq(`{"a":1}`, utils.MustToJSON(map[string]int{"a": 1}))
+func TestMustToJSON(t *testing.T) {
+ g := setup(t)
+
+ g.Eq(utils.Dump("a", 10), `"a" 10`)
+ g.Eq(`{"a":1}`, utils.MustToJSON(map[string]int{"a": 1}))
}
-func (t T) FileExists() {
- t.Eq(false, utils.FileExists("."))
- t.Eq(true, utils.FileExists("utils.go"))
- t.Eq(false, utils.FileExists(t.Srand(16)))
+func TestFileExists(t *testing.T) {
+ g := setup(t)
+
+ g.Eq(false, utils.FileExists("."))
+ g.Eq(true, utils.FileExists("utils.go"))
+ g.Eq(false, utils.FileExists(g.RandStr(16)))
}
-func (t T) ExecErr() {
- t.Panic(func() {
+func TestExecErr(t *testing.T) {
+ g := setup(t)
+
+ g.Panic(func() {
utils.ExecLine("")
})
}
-func (t T) EscapeGoString() {
- t.Eq("`` + \"`\" + `test` + \"`\" + ``", utils.EscapeGoString("`test`"))
+func TestEscapeGoString(t *testing.T) {
+ g := setup(t)
+
+ g.Eq("`` + \"`\" + `test` + \"`\" + ``", utils.EscapeGoString("`test`"))
}
-func (t T) IdleCounter() {
+func TestIdleCounter(t *testing.T) {
+ g := setup(t)
+
utils.All(func() {
ct := utils.NewIdleCounter(100 * time.Millisecond)
@@ -164,15 +188,15 @@ func (t T) IdleCounter() {
ct.Done()
}()
- ctx := t.Context()
+ ctx := g.Context()
start := time.Now()
ct.Wait(ctx)
d := time.Since(start)
- t.Gt(d, 400*time.Millisecond)
- t.Lt(d, 450*time.Millisecond)
+ g.Gt(d, 400*time.Millisecond)
+ g.Lt(d, 450*time.Millisecond)
- t.Panic(func() {
+ g.Panic(func() {
ct.Done()
})
@@ -181,26 +205,28 @@ func (t T) IdleCounter() {
}, func() {
ct := utils.NewIdleCounter(100 * time.Millisecond)
start := time.Now()
- ct.Wait(t.Context())
- t.Lt(time.Since(start), 150*time.Millisecond)
+ ct.Wait(g.Context())
+ g.Lt(time.Since(start), 150*time.Millisecond)
}, func() {
ct := utils.NewIdleCounter(0)
start := time.Now()
- ct.Wait(t.Context())
- t.Lt(time.Since(start), 10*time.Millisecond)
+ ct.Wait(g.Context())
+ g.Lt(time.Since(start), 10*time.Millisecond)
})()
}
-func (t T) CropImage() {
+func TestCropImage(t *testing.T) {
+ g := setup(t)
+
img := image.NewNRGBA(image.Rect(0, 0, 100, 100))
- t.Err(utils.CropImage(nil, 0, 0, 0, 0, 0))
+ g.Err(utils.CropImage(nil, 0, 0, 0, 0, 0))
bin := bytes.NewBuffer(nil)
- t.E(png.Encode(bin, img))
- t.E(utils.CropImage(bin.Bytes(), 0, 10, 10, 30, 30))
+ g.E(png.Encode(bin, img))
+ g.E(utils.CropImage(bin.Bytes(), 0, 10, 10, 30, 30))
bin = bytes.NewBuffer(nil)
- t.E(jpeg.Encode(bin, img, &jpeg.Options{Quality: 80}))
- t.E(utils.CropImage(bin.Bytes(), 0, 10, 10, 30, 30))
+ g.E(jpeg.Encode(bin, img, &jpeg.Options{Quality: 80}))
+ g.E(utils.CropImage(bin.Bytes(), 0, 10, 10, 30, 30))
}
diff --git a/must_test.go b/must_test.go
index f4aedb5c..1fa57965 100644
--- a/must_test.go
+++ b/must_test.go
@@ -1,84 +1,92 @@
package rod_test
import (
+ "testing"
+
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/proto"
)
-func (t T) BrowserWithPanic() {
+func TestBrowserWithPanic(t *testing.T) {
+ g := setup(t)
+
var triggers int
trigger := func(x interface{}) {
triggers++
panic(x)
}
- browser := t.browser.Sleeper(rod.NotFoundSleeper).WithPanic(trigger)
- t.Panic(func() { browser.MustPage("____") })
- t.Eq(1, triggers)
+ browser := g.browser.Sleeper(rod.NotFoundSleeper).WithPanic(trigger)
+ g.Panic(func() { browser.MustPage("____") })
+ g.Eq(1, triggers)
- page := browser.MustPage(t.blank())
+ page := browser.MustPage(g.blank())
defer page.MustClose()
- t.Panic(func() { page.MustElement("____") })
- t.Eq(2, triggers)
+ g.Panic(func() { page.MustElement("____") })
+ g.Eq(2, triggers)
el := page.MustElement("html")
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustClick()
})
- t.Eq(3, triggers)
+ g.Eq(3, triggers)
}
-func (t T) PageWithPanic() {
+func TestPageWithPanic(t *testing.T) {
+ g := setup(t)
+
var triggers int
trigger := func(x interface{}) {
triggers++
panic(x)
}
- browser := t.browser.Sleeper(rod.NotFoundSleeper)
- t.Panic(func() { browser.MustPage("____") })
- t.Eq(0, triggers)
+ browser := g.browser.Sleeper(rod.NotFoundSleeper)
+ g.Panic(func() { browser.MustPage("____") })
+ g.Eq(0, triggers)
- page := browser.MustPage(t.blank()).WithPanic(trigger)
+ page := browser.MustPage(g.blank()).WithPanic(trigger)
defer page.MustClose()
- t.Panic(func() { page.MustElement("____") })
- t.Eq(1, triggers)
+ g.Panic(func() { page.MustElement("____") })
+ g.Eq(1, triggers)
el := page.MustElement("html")
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustClick()
})
- t.Eq(2, triggers)
+ g.Eq(2, triggers)
}
-func (t T) ElementWithPanic() {
+func TestElementWithPanic(t *testing.T) {
+ g := setup(t)
+
var triggers int
trigger := func(x interface{}) {
triggers++
panic(x)
}
- browser := t.browser.Sleeper(rod.NotFoundSleeper)
- t.Panic(func() { browser.MustPage("____") })
- t.Eq(0, triggers)
+ browser := g.browser.Sleeper(rod.NotFoundSleeper)
+ g.Panic(func() { browser.MustPage("____") })
+ g.Eq(0, triggers)
- page := browser.MustPage(t.blank())
+ page := browser.MustPage(g.blank())
defer page.MustClose()
- t.Panic(func() { page.MustElement("____") })
- t.Eq(0, triggers)
+ g.Panic(func() { page.MustElement("____") })
+ g.Eq(0, triggers)
el := page.MustElement("html").WithPanic(trigger)
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
el.MustClick()
})
- t.Eq(1, triggers)
+ g.Eq(1, triggers)
}
diff --git a/page_eval_test.go b/page_eval_test.go
index 125fc087..bb8519ed 100644
--- a/page_eval_test.go
+++ b/page_eval_test.go
@@ -1,6 +1,7 @@
package rod_test
import (
+ "testing"
"time"
"github.com/go-rod/rod"
@@ -10,77 +11,87 @@ import (
"github.com/ysmood/gson"
)
-func (t T) PageEvalOnNewDocument() {
- p := t.newPage()
+func TestPageEvalOnNewDocument(t *testing.T) {
+ g := setup(t)
+
+ p := g.newPage()
p.MustEvalOnNewDocument(`window.rod = 'ok'`)
// to activate the script
- p.MustNavigate(t.blank())
+ p.MustNavigate(g.blank())
- t.Eq(p.MustEval("() => rod").String(), "ok")
+ g.Eq(p.MustEval("() => rod").String(), "ok")
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageAddScriptToEvaluateOnNewDocument{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageAddScriptToEvaluateOnNewDocument{})
p.MustEvalOnNewDocument(`1`)
})
}
-func (t T) PageEval() {
- page := t.page.MustNavigate(t.blank())
+func TestPageEval(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.blank())
- t.Eq(3, page.MustEval(`
+ g.Eq(3, page.MustEval(`
(a, b) => a + b
`, 1, 2).Int())
- t.Eq(page.MustEval(`function() {
+ g.Eq(page.MustEval(`function() {
return 11
}`).Int(), 11)
- t.Eq(page.MustEval(` ; () => 1; `).Int(), 1)
+ g.Eq(page.MustEval(` ; () => 1; `).Int(), 1)
// reuse obj
obj := page.MustEvaluate(rod.Eval(`() => () => 'ok'`).ByObject())
- t.Eq("ok", page.MustEval(`f => f()`, obj).Str())
+ g.Eq("ok", page.MustEval(`f => f()`, obj).Str())
_, err := page.Eval(`10`)
- t.Has(err.Error(), `eval js error: TypeError: 10.apply is not a function`)
+ g.Has(err.Error(), `eval js error: TypeError: 10.apply is not a function`)
}
-func (t T) PageEvaluateRetry() {
- page := t.page.MustNavigate(t.blank())
+func TestPageEvaluateRetry(t *testing.T) {
+ g := setup(t)
- t.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
- t.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
+ page := g.page.MustNavigate(g.blank())
+
+ g.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
return gson.New(nil), cdp.ErrCtxNotFound
})
return gson.New(nil), cdp.ErrCtxNotFound
})
- t.Eq(1, page.MustEval(`() => 1`).Int())
+ g.Eq(1, page.MustEval(`() => 1`).Int())
}
-func (t T) PageUpdateJSCtxIDErr() {
- page := t.page.MustNavigate(t.srcFile("./fixtures/click-iframe.html"))
+func TestPageUpdateJSCtxIDErr(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.srcFile("./fixtures/click-iframe.html"))
- t.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
- t.mc.stubErr(1, proto.RuntimeEvaluate{})
+ g.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stubErr(1, proto.RuntimeEvaluate{})
return gson.New(nil), cdp.ErrCtxNotFound
})
- t.Err(page.Eval(`() => 1`))
+ g.Err(page.Eval(`() => 1`))
frame := page.MustElement("iframe").MustFrame()
frame.MustReload()
- t.mc.stubErr(1, proto.DOMDescribeNode{})
- t.Err(frame.Element(`button`))
+ g.mc.stubErr(1, proto.DOMDescribeNode{})
+ g.Err(frame.Element(`button`))
frame.MustReload()
- t.mc.stubErr(1, proto.DOMResolveNode{})
- t.Err(frame.Element(`button`))
+ g.mc.stubErr(1, proto.DOMResolveNode{})
+ g.Err(frame.Element(`button`))
}
-func (t T) PageExpose() {
- page := t.newPage(t.blank()).MustWaitLoad()
+func TestPageExpose(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage(g.blank()).MustWaitLoad()
stop := page.MustExpose("exposedFunc", func(g gson.JSON) (interface{}, error) {
return g.Get("k").Str(), nil
@@ -88,103 +99,115 @@ func (t T) PageExpose() {
utils.All(func() {
res := page.MustEval(`() => exposedFunc({k: 'a'})`)
- t.Eq("a", res.Str())
+ g.Eq("a", res.Str())
}, func() {
res := page.MustEval(`() => exposedFunc({k: 'b'})`)
- t.Eq("b", res.Str())
+ g.Eq("b", res.Str())
})()
// survive the reload
page.MustReload().MustWaitLoad()
res := page.MustEval(`() => exposedFunc({k: 'ok'})`)
- t.Eq("ok", res.Str())
+ g.Eq("ok", res.Str())
stop()
- t.Panic(func() {
+ g.Panic(func() {
stop()
})
- t.Panic(func() {
+ g.Panic(func() {
page.MustReload().MustWaitLoad().MustEval(`() => exposedFunc()`)
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
page.MustExpose("exposedFunc", nil)
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeAddBinding{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeAddBinding{})
page.MustExpose("exposedFunc2", nil)
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageAddScriptToEvaluateOnNewDocument{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageAddScriptToEvaluateOnNewDocument{})
page.MustExpose("exposedFunc", nil)
})
}
-func (t T) Release() {
- res, err := t.page.Evaluate(rod.Eval(`() => document`).ByObject())
- t.E(err)
- t.page.MustRelease(res)
+func TestRelease(t *testing.T) {
+ g := setup(t)
+
+ res, err := g.page.Evaluate(rod.Eval(`() => document`).ByObject())
+ g.E(err)
+ g.page.MustRelease(res)
}
-func (t T) PromiseLeak() {
+func TestPromiseLeak(t *testing.T) {
+ g := setup(t)
+
/*
Perform a slow action then navigate the page to another url,
we can see the slow operation will still be executed.
*/
- p := t.page.MustNavigate(t.blank())
+ p := g.page.MustNavigate(g.blank())
utils.All(func() {
_, err := p.Eval(`() => new Promise(r => setTimeout(() => r(location.href), 1000))`)
- t.Is(err, cdp.ErrCtxDestroyed)
+ g.Is(err, cdp.ErrCtxDestroyed)
}, func() {
utils.Sleep(0.3)
- p.MustNavigate(t.blank())
+ p.MustNavigate(g.blank())
})()
}
-func (t T) ObjectLeak() {
+func TestObjectLeak(t *testing.T) {
+ g := setup(t)
+
/*
Seems like it won't leak
*/
- p := t.page.MustNavigate(t.blank())
+ p := g.page.MustNavigate(g.blank())
obj := p.MustEvaluate(rod.Eval("() => ({a:1})").ByObject())
p.MustReload().MustWaitLoad()
- t.Panic(func() {
+ g.Panic(func() {
p.MustEvaluate(rod.Eval(`obj => obj`, obj))
})
}
-func (t T) PageObjectErr() {
- t.Panic(func() {
- t.page.MustObjectToJSON(&proto.RuntimeRemoteObject{
+func TestPageObjectErr(t *testing.T) {
+ g := setup(t)
+
+ g.Panic(func() {
+ g.page.MustObjectToJSON(&proto.RuntimeRemoteObject{
ObjectID: "not-exists",
})
})
- t.Panic(func() {
- t.page.MustElementFromNode(&proto.DOMNode{NodeID: -1})
+ g.Panic(func() {
+ g.page.MustElementFromNode(&proto.DOMNode{NodeID: -1})
})
- t.Panic(func() {
- node := t.page.MustNavigate(t.blank()).MustElement(`body`).MustDescribe()
- t.mc.stubErr(1, proto.DOMResolveNode{})
- t.page.MustElementFromNode(node)
+ g.Panic(func() {
+ node := g.page.MustNavigate(g.blank()).MustElement(`body`).MustDescribe()
+ g.mc.stubErr(1, proto.DOMResolveNode{})
+ g.page.MustElementFromNode(node)
})
}
-func (t T) GetJSHelperRetry() {
- t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestGetJSHelperRetry(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/click.html"))
- t.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.RuntimeCallFunctionOn{}, func(send StubSend) (gson.JSON, error) {
return gson.JSON{}, cdp.ErrCtxNotFound
})
- t.page.MustElements("button")
+ g.page.MustElements("button")
}
-func (t T) ConcurrentEval() {
- p := t.page.MustNavigate(t.blank())
+func TestConcurrentEval(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.blank())
list := make(chan int, 2)
start := time.Now()
@@ -195,50 +218,60 @@ func (t T) ConcurrentEval() {
})()
duration := time.Since(start)
- t.Lt(duration, 1500*time.Millisecond)
- t.Gt(duration, 1000*time.Millisecond)
- t.Eq([]int{<-list, <-list}, []int{1, 2})
+ g.Lt(duration, 1500*time.Millisecond)
+ g.Gt(duration, 1000*time.Millisecond)
+ g.Eq([]int{<-list, <-list}, []int{1, 2})
}
-func (t T) PageSlowRender() {
- p := t.page.MustNavigate(t.srcFile("./fixtures/slow-render.html"))
- t.Eq(p.MustElement("div").MustText(), "ok")
+func TestPageSlowRender(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("./fixtures/slow-render.html"))
+ g.Eq(p.MustElement("div").MustText(), "ok")
}
-func (t T) PageIframeReload() {
- p := t.page.MustNavigate(t.srcFile("./fixtures/click-iframe.html"))
+func TestPageIframeReload(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("./fixtures/click-iframe.html"))
frame := p.MustElement("iframe").MustFrame()
btn := frame.MustElement("button")
- t.Eq(btn.MustText(), "click me")
+ g.Eq(btn.MustText(), "click me")
frame.MustReload()
btn = frame.MustElement("button")
- t.Eq(btn.MustText(), "click me")
+ g.Eq(btn.MustText(), "click me")
- t.Has(*p.MustElement("iframe").MustAttribute("src"), "click.html")
+ g.Has(*p.MustElement("iframe").MustAttribute("src"), "click.html")
}
-func (t T) PageObjCrossNavigation() {
- p := t.page.MustNavigate(t.blank())
+func TestPageObjCrossNavigation(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.blank())
obj := p.MustEvaluate(rod.Eval(`() => ({})`).ByObject())
- t.page.MustNavigate(t.blank())
+ g.page.MustNavigate(g.blank())
_, err := p.Evaluate(rod.Eval(`() => 1`).This(obj))
- t.Is(err, &rod.ErrObjectNotFound{})
- t.Has(err.Error(), "cannot find object: {\"type\":\"object\"")
+ g.Is(err, &rod.ErrObjectNotFound{})
+ g.Has(err.Error(), "cannot find object: {\"type\":\"object\"")
}
-func (t T) EnsureJSHelperErr() {
- p := t.page.MustNavigate(t.blank())
+func TestEnsureJSHelperErr(t *testing.T) {
+ g := setup(t)
- t.mc.stubErr(2, proto.RuntimeCallFunctionOn{})
- t.Err(p.Elements(`button`))
+ p := g.page.MustNavigate(g.blank())
+
+ g.mc.stubErr(2, proto.RuntimeCallFunctionOn{})
+ g.Err(p.Elements(`button`))
}
-func (t T) EvalOptionsString() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestEvalOptionsString(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustElement("button")
- t.Eq(rod.Eval(`() => this.parentElement`).This(el.Object).String(), "() => this.parentElement() button")
+ g.Eq(rod.Eval(`() => this.parentElement`).This(el.Object).String(), "() => this.parentElement() button")
}
diff --git a/page_test.go b/page_test.go
index 0486bf06..98df0af6 100644
--- a/page_test.go
+++ b/page_test.go
@@ -10,6 +10,7 @@ import (
"path/filepath"
"sort"
"sync"
+ "testing"
"time"
"github.com/go-rod/rod"
@@ -21,19 +22,25 @@ import (
"github.com/ysmood/got"
)
-func (t T) GetPageBrowser() {
- t.Equal(t.page.Browser(), t.browser)
+func TestGetPageBrowser(t *testing.T) {
+ g := setup(t)
+
+ g.Equal(g.page.Browser(), g.browser)
}
-func (t T) GetPageURL() {
- t.page.MustNavigate(t.srcFile("fixtures/click-iframe.html")).MustWaitLoad()
- t.Regex(`/fixtures/click-iframe.html\z`, t.page.MustInfo().URL)
+func TestGetPageURL(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/click-iframe.html")).MustWaitLoad()
+ g.Regex(`/fixtures/click-iframe.html\z`, g.page.MustInfo().URL)
}
-func (t T) SetCookies() {
- s := t.Serve()
+func TestSetCookies(t *testing.T) {
+ g := setup(t)
- page := t.page.MustSetCookies([]*proto.NetworkCookieParam{{
+ s := g.Serve()
+
+ page := g.page.MustSetCookies([]*proto.NetworkCookieParam{{
Name: "cookie-a",
Value: "1",
URL: s.URL(),
@@ -49,26 +56,28 @@ func (t T) SetCookies() {
return cookies[i].Value < cookies[j].Value
})
- t.Eq("1", cookies[0].Value)
- t.Eq("2", cookies[1].Value)
+ g.Eq("1", cookies[0].Value)
+ g.Eq("2", cookies[1].Value)
page.MustSetCookies()
cookies = page.MustCookies()
- t.Len(cookies, 0)
+ g.Len(cookies, 0)
- t.Panic(func() {
- t.mc.stubErr(1, proto.TargetGetTargetInfo{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.TargetGetTargetInfo{})
page.MustCookies()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.NetworkGetCookies{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.NetworkGetCookies{})
page.MustCookies()
})
}
-func (t T) SetExtraHeaders() {
- s := t.Serve()
+func TestSetExtraHeaders(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
wg := sync.WaitGroup{}
var header http.Header
@@ -77,15 +86,15 @@ func (t T) SetExtraHeaders() {
wg.Done()
})
- p := t.newPage()
+ p := g.newPage()
cleanup := p.MustSetExtraHeaders("a", "1", "b", "2")
wg.Add(1)
p.MustNavigate(s.URL())
wg.Wait()
- t.Eq(header.Get("a"), "1")
- t.Eq(header.Get("b"), "2")
+ g.Eq(header.Get("a"), "1")
+ g.Eq(header.Get("b"), "2")
cleanup()
@@ -95,13 +104,15 @@ func (t T) SetExtraHeaders() {
p.MustReload()
wg.Wait()
- t.Eq(header.Get("a"), "")
- t.Eq(header.Get("b"), "")
+ g.Eq(header.Get("a"), "")
+ g.Eq(header.Get("b"), "")
}
}
-func (t T) SetUserAgent() {
- s := t.Serve()
+func TestSetUserAgent(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
ua := ""
lang := ""
@@ -115,28 +126,34 @@ func (t T) SetUserAgent() {
wg.Done()
})
- t.newPage().MustSetUserAgent(nil).MustNavigate(s.URL())
+ g.newPage().MustSetUserAgent(nil).MustNavigate(s.URL())
wg.Wait()
- t.Eq(ua, "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
- t.Eq(lang, "en")
+ g.Eq(ua, "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
+ g.Eq(lang, "en")
}
-func (t T) PageHTML() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html")).MustWaitLoad()
- t.Has(p.MustHTML(), "")
+func TestPageHTML(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html")).MustWaitLoad()
+ g.Has(p.MustHTML(), "")
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(p.HTML())
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(p.HTML())
}
-func (t T) MustWaitElementsMoreThan() {
- p := t.page.MustNavigate(t.srcFile("fixtures/wait_elements.html")).MustWaitElementsMoreThan("li", 5)
- t.Gt(len(p.MustElements("li")), 5)
+func TestMustWaitElementsMoreThan(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/wait_elements.html")).MustWaitElementsMoreThan("li", 5)
+ g.Gt(len(p.MustElements("li")), 5)
}
-func (t T) PageCloseCancel() {
- page := t.browser.MustPage(t.srcFile("fixtures/prevent-close.html"))
+func TestPageCloseCancel(t *testing.T) {
+ g := setup(t)
+
+ page := g.browser.MustPage(g.srcFile("fixtures/prevent-close.html"))
page.MustElement("body").MustClick() // only focused page will handle beforeunload event
w, h := page.MustHandleDialog()
@@ -144,32 +161,42 @@ func (t T) PageCloseCancel() {
w()
h(false, "")
}()
- t.Eq(page.Close().Error(), "page close canceled")
+ g.Eq(page.Close().Error(), "page close canceled")
page.MustEval(`() => window.onbeforeunload = null`)
page.MustClose()
}
-func (t T) LoadState() {
- t.True(t.page.LoadState(&proto.PageEnable{}))
+func TestLoadState(t *testing.T) {
+ g := setup(t)
+
+ g.True(g.page.LoadState(&proto.PageEnable{}))
}
-func (t T) DisableDomain() {
- defer t.page.DisableDomain(&proto.PageEnable{})()
+func TestDisableDomain(t *testing.T) {
+ g := setup(t)
+
+ defer g.page.DisableDomain(&proto.PageEnable{})()
}
-func (t T) PageContext() {
- t.page.Timeout(time.Hour).CancelTimeout().MustEval(`() => 1`)
+func TestPageContext(t *testing.T) {
+ g := setup(t)
+
+ g.page.Timeout(time.Hour).CancelTimeout().MustEval(`() => 1`)
}
-func (t T) PageActivate() {
- t.page.MustActivate()
+func TestPageActivate(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustActivate()
}
-func (t T) Window() {
- page := t.newPage(t.blank())
+func TestWindow(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage(g.blank())
- t.E(page.SetViewport(nil))
+ g.E(page.SetViewport(nil))
bounds := page.MustGetWindow()
defer page.MustSetWindow(
@@ -186,37 +213,41 @@ func (t T) Window() {
page.MustWindowMinimize()
page.MustWindowNormal()
page.MustSetWindow(0, 0, 1211, 611)
- t.Eq(1211, page.MustEval(`() => window.innerWidth`).Int())
- t.Eq(611, page.MustEval(`() => window.innerHeight`).Int())
+ g.Eq(1211, page.MustEval(`() => window.innerWidth`).Int())
+ g.Eq(611, page.MustEval(`() => window.innerHeight`).Int())
- t.Panic(func() {
- t.mc.stubErr(1, proto.BrowserGetWindowForTarget{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.BrowserGetWindowForTarget{})
page.MustGetWindow()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.BrowserGetWindowBounds{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.BrowserGetWindowBounds{})
page.MustGetWindow()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.BrowserGetWindowForTarget{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.BrowserGetWindowForTarget{})
page.MustSetWindow(0, 0, 1000, 1000)
})
}
-func (t T) SetViewport() {
- page := t.newPage(t.blank())
+func TestSetViewport(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage(g.blank())
page.MustSetViewport(317, 419, 0, false)
res := page.MustEval(`() => [window.innerWidth, window.innerHeight]`)
- t.Eq(317, res.Get("0").Int())
- t.Eq(419, res.Get("1").Int())
+ g.Eq(317, res.Get("0").Int())
+ g.Eq(419, res.Get("1").Int())
- page2 := t.newPage(t.blank())
+ page2 := g.newPage(g.blank())
res = page2.MustEval(`() => [window.innerWidth, window.innerHeight]`)
- t.Neq(int(317), res.Get("0").Int())
+ g.Neq(int(317), res.Get("0").Int())
}
-func (t T) SetDocumentContent() {
- page := t.newPage(t.blank())
+func TestSetDocumentContent(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage(g.blank())
doctype := ""
html4StrictDoctype := ``
@@ -226,112 +257,122 @@ func (t T) SetDocumentContent() {
exampleWithHTML4StrictDoctype := html4StrictDoctype + "test
"
page.MustSetDocumentContent(exampleWithHTML4StrictDoctype)
exp1 := page.MustEval(`() => new XMLSerializer().serializeToString(document)`).Str()
- t.Eq(exp1, `test
`)
- t.Eq(page.MustElement("html").MustHTML(), "test
")
- t.Eq(page.MustElement("head").MustText(), "")
+ g.Eq(exp1, `test
`)
+ g.Eq(page.MustElement("html").MustHTML(), "test
")
+ g.Eq(page.MustElement("head").MustText(), "")
exampleWithHTML4LooseDoctype := html4LooseDoctype + "test
"
page.MustSetDocumentContent(exampleWithHTML4LooseDoctype)
exp2 := page.MustEval(`() => new XMLSerializer().serializeToString(document)`).Str()
- t.Eq(exp2, `test
`)
- t.Eq(page.MustElement("html").MustHTML(), "test
")
- t.Eq(page.MustElement("head").MustText(), "")
+ g.Eq(exp2, `test
`)
+ g.Eq(page.MustElement("html").MustHTML(), "test
")
+ g.Eq(page.MustElement("head").MustText(), "")
exampleWithXHTMLDoctype := xhtml11Doctype + "test
"
page.MustSetDocumentContent(exampleWithXHTMLDoctype)
exp3 := page.MustEval(`() => new XMLSerializer().serializeToString(document)`).Str()
- t.Eq(exp3, `test
`)
- t.Eq(page.MustElement("html").MustHTML(), "test
")
- t.Eq(page.MustElement("head").MustText(), "")
+ g.Eq(exp3, `test
`)
+ g.Eq(page.MustElement("html").MustHTML(), "test
")
+ g.Eq(page.MustElement("head").MustText(), "")
exampleWithHTML5Doctype := doctype + "test
"
page.MustSetDocumentContent(exampleWithHTML5Doctype)
exp4 := page.MustEval(`() => new XMLSerializer().serializeToString(document)`).Str()
- t.Eq(exp4, `test
`)
- t.Eq(page.MustElement("html").MustHTML(), "test
")
- t.Eq(page.MustElement("head").MustText(), "")
+ g.Eq(exp4, `test
`)
+ g.Eq(page.MustElement("html").MustHTML(), "test
")
+ g.Eq(page.MustElement("head").MustText(), "")
exampleWithoutDoctype := "test
"
page.MustSetDocumentContent(exampleWithoutDoctype)
- t.Eq(page.MustElement("html").MustHTML(), "test
")
+ g.Eq(page.MustElement("html").MustHTML(), "test
")
exampleBasic := doctype + "test
"
page.MustSetDocumentContent(exampleBasic)
- t.Eq(page.MustElement("div").MustText(), "test")
+ g.Eq(page.MustElement("div").MustText(), "test")
exampleWithTrickyContent := "test
\x7F"
page.MustSetDocumentContent(exampleWithTrickyContent)
- t.Eq(page.MustElement("div").MustText(), "test")
+ g.Eq(page.MustElement("div").MustText(), "test")
exampleWithEmoji := "💪
"
page.MustSetDocumentContent(exampleWithEmoji)
- t.Eq(page.MustElement("div").MustText(), "💪")
+ g.Eq(page.MustElement("div").MustText(), "💪")
}
-func (t T) EmulateDevice() {
- page := t.newPage(t.blank())
+func TestEmulateDevice(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage(g.blank())
page.MustEmulate(devices.IPhone6or7or8)
res := page.MustEval(`() => [window.innerWidth, window.innerHeight, navigator.userAgent]`)
// TODO: this seems like a bug of chromium
{
- t.Lt(math.Abs(float64(980-res.Get("0").Int())), 10)
- t.Lt(math.Abs(float64(1743-res.Get("1").Int())), 10)
+ g.Lt(math.Abs(float64(980-res.Get("0").Int())), 10)
+ g.Lt(math.Abs(float64(1743-res.Get("1").Int())), 10)
}
- t.Eq(
+ g.Eq(
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1",
res.Get("2").String(),
)
- t.Panic(func() {
- t.mc.stubErr(1, proto.EmulationSetDeviceMetricsOverride{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.EmulationSetDeviceMetricsOverride{})
page.MustEmulate(devices.IPad)
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.EmulationSetTouchEmulationEnabled{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.EmulationSetTouchEmulationEnabled{})
page.MustEmulate(devices.IPad)
})
}
-func (t T) PageCloseErr() {
- page := t.newPage(t.blank())
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageClose{})
+func TestPageCloseErr(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage(g.blank())
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageClose{})
page.MustClose()
})
}
-func (t T) PageAddScriptTag() {
- p := t.page.MustNavigate(t.blank()).MustWaitLoad()
+func TestPageAddScriptTag(t *testing.T) {
+ g := setup(t)
- res := p.MustAddScriptTag(t.srcFile("fixtures/add-script-tag.js")).MustEval(`() => count()`)
- t.Eq(0, res.Int())
+ p := g.page.MustNavigate(g.blank()).MustWaitLoad()
- res = p.MustAddScriptTag(t.srcFile("fixtures/add-script-tag.js")).MustEval(`() => count()`)
- t.Eq(1, res.Int())
+ res := p.MustAddScriptTag(g.srcFile("fixtures/add-script-tag.js")).MustEval(`() => count()`)
+ g.Eq(0, res.Int())
- t.E(p.AddScriptTag("", `let ok = 'yes'`))
+ res = p.MustAddScriptTag(g.srcFile("fixtures/add-script-tag.js")).MustEval(`() => count()`)
+ g.Eq(1, res.Int())
+
+ g.E(p.AddScriptTag("", `let ok = 'yes'`))
res = p.MustEval(`() => ok`)
- t.Eq("yes", res.String())
+ g.Eq("yes", res.String())
}
-func (t T) PageAddStyleTag() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html")).MustWaitLoad()
+func TestPageAddStyleTag(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html")).MustWaitLoad()
- res := p.MustAddStyleTag(t.srcFile("fixtures/add-style-tag.css")).
+ res := p.MustAddStyleTag(g.srcFile("fixtures/add-style-tag.css")).
MustElement("h4").MustEval(`() => getComputedStyle(this).color`)
- t.Eq("rgb(255, 0, 0)", res.String())
+ g.Eq("rgb(255, 0, 0)", res.String())
- p.MustAddStyleTag(t.srcFile("fixtures/add-style-tag.css"))
- t.Len(p.MustElements("link"), 1)
+ p.MustAddStyleTag(g.srcFile("fixtures/add-style-tag.css"))
+ g.Len(p.MustElements("link"), 1)
- t.E(p.AddStyleTag("", "h4 { color: green; }"))
+ g.E(p.AddStyleTag("", "h4 { color: green; }"))
res = p.MustElement("h4").MustEval(`() => getComputedStyle(this).color`)
- t.Eq("rgb(0, 128, 0)", res.String())
+ g.Eq("rgb(0, 128, 0)", res.String())
}
-func (t T) PageWaitOpen() {
- page := t.page.MustNavigate(t.srcFile("fixtures/open-page.html"))
+func TestPageWaitOpen(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.srcFile("fixtures/open-page.html"))
wait := page.MustWaitOpen()
@@ -340,39 +381,47 @@ func (t T) PageWaitOpen() {
newPage := wait()
defer newPage.MustClose()
- t.Eq("new page", newPage.MustEval("() => window.a").String())
+ g.Eq("new page", newPage.MustEval("() => window.a").String())
}
-func (t T) PageWait() {
- page := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestPageWait(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
page.MustWait(`() => document.querySelector('button') !== null`)
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
page.MustWait(``)
})
}
-func (t T) PageNavigateBlank() {
- t.page.MustNavigate("")
+func TestPageNavigateBlank(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate("")
}
-func (t T) PageWaitNavigation() {
- s := t.Serve().Route("/", "")
- wait := t.page.MustWaitNavigation()
- t.page.MustNavigate(s.URL())
+func TestPageWaitNavigation(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve().Route("/", "")
+ wait := g.page.MustWaitNavigation()
+ g.page.MustNavigate(s.URL())
wait()
}
-func (t T) PageWaitRequestIdle() {
- s := t.Serve()
+func TestPageWaitRequestIdle(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
sleep := time.Second
s.Route("/r1", "")
s.Mux.HandleFunc("/r2", func(w http.ResponseWriter, r *http.Request) {
- t.E(w.Write([]byte("part")))
- ctx, cancel := context.WithTimeout(t.Context(), sleep)
+ g.E(w.Write([]byte("part")))
+ ctx, cancel := context.WithTimeout(g.Context(), sleep)
defer cancel()
<-ctx.Done()
})
@@ -383,7 +432,7 @@ func (t T) PageWaitRequestIdle() {
s.Route("/r4", "")
s.Route("/", ".html", ``)
- page := t.newPage(s.URL()).MustWaitLoad()
+ page := g.newPage(s.URL()).MustWaitLoad()
code := ` () => {
fetch('/r2').then(r => r.text())
@@ -392,7 +441,7 @@ func (t T) PageWaitRequestIdle() {
}`
waitReq := ""
- t.browser.Logger(utils.Log(func(msg ...interface{}) {
+ g.browser.Logger(utils.Log(func(msg ...interface{}) {
typ := msg[0].(rod.TraceType)
if typ == rod.TraceTypeWaitRequests {
list := msg[2].(map[string]string)
@@ -402,67 +451,77 @@ func (t T) PageWaitRequestIdle() {
}
}
}))
- defer t.browser.Logger(rod.DefaultLogger)
+ defer g.browser.Logger(rod.DefaultLogger)
- t.browser.Trace(true)
+ g.browser.Trace(true)
wait := page.MustWaitRequestIdle("/r1")
- t.browser.Trace(defaults.Trace)
+ g.browser.Trace(defaults.Trace)
page.MustEval(code)
start := time.Now()
wait()
- t.Gt(time.Since(start), sleep)
- t.Regex("/r2$", waitReq)
+ g.Gt(time.Since(start), sleep)
+ g.Regex("/r2$", waitReq)
wait = page.MustWaitRequestIdle("/r2")
page.MustEval(code)
start = time.Now()
wait()
- t.Lt(time.Since(start), sleep)
+ g.Lt(time.Since(start), sleep)
- t.Panic(func() {
+ g.Panic(func() {
wait()
})
}
-func (t T) PageWaitIdle() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestPageWaitIdle(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
p.MustElement("button").MustClick()
p.MustWaitIdle()
- t.True(p.MustHas("[a=ok]"))
+ g.True(p.MustHas("[a=ok]"))
}
-func (t T) PageEventSession() {
- s := t.Serve()
- p := t.newPage(s.URL())
+func TestPageEventSession(t *testing.T) {
+ g := setup(t)
+
+ s := g.Serve()
+ p := g.newPage(s.URL())
p.EnableDomain(proto.NetworkEnable{})
- go t.page.Context(t.Context()).EachEvent(func(e *proto.NetworkRequestWillBeSent) {
- t.Log("should not goes to here")
- t.Fail()
+ go g.page.Context(g.Context()).EachEvent(func(e *proto.NetworkRequestWillBeSent) {
+ g.Log("should not goes to here")
+ g.Fail()
})()
p.MustEval(`u => fetch(u)`, s.URL())
}
-func (t T) PageWaitEvent() {
- wait := t.page.WaitEvent(&proto.PageFrameNavigated{})
- t.page.MustNavigate(t.blank())
+func TestPageWaitEvent(t *testing.T) {
+ g := setup(t)
+
+ wait := g.page.WaitEvent(&proto.PageFrameNavigated{})
+ g.page.MustNavigate(g.blank())
wait()
}
-func (t T) PageWaitEventParseEventOnlyOnce() {
- nav1 := t.page.WaitEvent(&proto.PageFrameNavigated{})
- nav2 := t.page.WaitEvent(&proto.PageFrameNavigated{})
- t.page.MustNavigate(t.blank())
+func TestPageWaitEventParseEventOnlyOnce(t *testing.T) {
+ g := setup(t)
+
+ nav1 := g.page.WaitEvent(&proto.PageFrameNavigated{})
+ nav2 := g.page.WaitEvent(&proto.PageFrameNavigated{})
+ g.page.MustNavigate(g.blank())
nav1()
nav2()
}
-func (t T) PageEvent() {
- p := t.browser.MustPage()
- ctx := t.Context()
+func TestPageEvent(t *testing.T) {
+ g := setup(t)
+
+ p := g.browser.MustPage()
+ ctx := g.Context()
events := p.Context(ctx).Event()
- p.MustNavigate(t.blank())
+ p.MustNavigate(g.blank())
for msg := range events {
if msg.Load(proto.PageFrameStartedLoading{}) {
break
@@ -478,8 +537,10 @@ func (t T) PageEvent() {
p.MustClose()
}
-func (t T) PageStopEventAfterDetach() {
- p := t.browser.MustPage().Context(t.Context())
+func TestPageStopEventAfterDetach(t *testing.T) {
+ g := setup(t)
+
+ p := g.browser.MustPage().Context(g.Context())
go func() {
utils.Sleep(0.3)
p.MustClose()
@@ -488,20 +549,24 @@ func (t T) PageStopEventAfterDetach() {
}
}
-func (t T) Alert() {
- page := t.page.MustNavigate(t.srcFile("fixtures/alert.html"))
+func TestAlert(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.srcFile("fixtures/alert.html"))
wait, handle := page.MustHandleDialog()
go page.MustElement("button").MustClick()
e := wait()
- t.Eq(e.Message, "clicked")
+ g.Eq(e.Message, "clicked")
handle(true, "")
}
-func (t T) Mouse() {
- page := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestMouse(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
page.MustElement("button")
mouse := page.Mouse
@@ -510,28 +575,30 @@ func (t T) Mouse() {
mouse.MustDown("left")
mouse.MustUp("left")
- t.True(page.MustHas("[a=ok]"))
+ g.True(page.MustHas("[a=ok]"))
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputDispatchMouseEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputDispatchMouseEvent{})
mouse.MustScroll(0, 10)
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputDispatchMouseEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputDispatchMouseEvent{})
mouse.MustDown(proto.InputMouseButtonLeft)
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputDispatchMouseEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputDispatchMouseEvent{})
mouse.MustUp(proto.InputMouseButtonLeft)
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputDispatchMouseEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputDispatchMouseEvent{})
mouse.MustClick(proto.InputMouseButtonLeft)
})
}
-func (t T) MouseHoldMultiple() {
- p := t.page.MustNavigate(t.blank())
+func TestMouseHoldMultiple(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.blank())
p.Mouse.MustDown("left")
defer p.Mouse.MustUp("left")
@@ -539,33 +606,37 @@ func (t T) MouseHoldMultiple() {
defer p.Mouse.MustUp("right")
}
-func (t T) MouseClick() {
- t.browser.SlowMotion(1)
- defer func() { t.browser.SlowMotion(0) }()
+func TestMouseClick(t *testing.T) {
+ g := setup(t)
- page := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+ g.browser.SlowMotion(1)
+ defer func() { g.browser.SlowMotion(0) }()
+
+ page := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
page.MustElement("button")
mouse := page.Mouse
mouse.MustMove(140, 160)
mouse.MustClick("left")
- t.True(page.MustHas("[a=ok]"))
+ g.True(page.MustHas("[a=ok]"))
}
-func (t T) MouseDrag() {
- page := t.newPage().MustNavigate(t.srcFile("fixtures/drag.html")).MustWaitLoad()
+func TestMouseDrag(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage().MustNavigate(g.srcFile("fixtures/drag.html")).MustWaitLoad()
mouse := page.Mouse
mouse.MustMove(3, 3)
mouse.MustDown("left")
- t.E(mouse.Move(60, 80, 3))
+ g.E(mouse.Move(60, 80, 3))
mouse.MustUp("left")
utils.Sleep(0.3)
- t.Eq(page.MustEval(`() => dragTrack`).Str(), " move 3 3 down 3 3 move 22 28 move 41 54 move 60 80 up 60 80")
+ g.Eq(page.MustEval(`() => dragTrack`).Str(), " move 3 3 down 3 3 move 22 28 move 41 54 move 60 80 up 60 80")
}
-func (t T) NativeDrag(got.Skip) { // devtools doesn't support to use mouse event to simulate it for now
- page := t.page.MustNavigate(t.srcFile("fixtures/drag.html"))
+func (g G) NativeDrag(got.Skip) { // devtools doesn't support to use mouse event to simulate it for now
+ page := g.page.MustNavigate(g.srcFile("fixtures/drag.html"))
mouse := page.Mouse
pt := page.MustElement("#draggable").MustShape().OnePointInside()
@@ -576,18 +647,20 @@ func (t T) NativeDrag(got.Skip) { // devtools doesn't support to use mouse event
mouse.MustMove(pt.X, pt.Y)
mouse.MustDown("left")
- t.E(mouse.Move(pt.X, toY, 5))
+ g.E(mouse.Move(pt.X, toY, 5))
page.MustScreenshot("")
mouse.MustUp("left")
page.MustElement(".dropzone:nth-child(2) #draggable")
}
-func (t T) Touch() {
- page := t.newPage().MustEmulate(devices.IPad)
+func TestTouch(t *testing.T) {
+ g := setup(t)
+
+ page := g.newPage().MustEmulate(devices.IPad)
wait := page.WaitNavigation(proto.PageLifecycleEventNameLoad)
- page.MustNavigate(t.srcFile("fixtures/touch.html"))
+ page.MustNavigate(g.srcFile("fixtures/touch.html"))
wait()
touch := page.Touch
@@ -603,72 +676,80 @@ func (t T) Touch() {
page.MustWait(`() => touchTrack == ' start 10 20 end start 30 40 end start 30 40 move 50 60 cancel'`)
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputDispatchTouchEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputDispatchTouchEvent{})
touch.MustTap(1, 2)
})
}
-func (t T) PageScreenshot() {
- f := filepath.Join("tmp", "screenshots", t.Srand(16)+".png")
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestPageScreenshot(t *testing.T) {
+ g := setup(t)
+
+ f := filepath.Join("tmp", "screenshots", g.RandStr(16)+".png")
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
p.MustElement("button")
p.MustScreenshot()
data := p.MustScreenshot(f)
img, err := png.Decode(bytes.NewBuffer(data))
- t.E(err)
- t.Eq(1280, img.Bounds().Dx())
- t.Eq(800, img.Bounds().Dy())
- t.Nil(os.Stat(f))
+ g.E(err)
+ g.Eq(1280, img.Bounds().Dx())
+ g.Eq(800, img.Bounds().Dy())
+ g.Nil(os.Stat(f))
p.MustScreenshot("")
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageCaptureScreenshot{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageCaptureScreenshot{})
p.MustScreenshot()
})
}
-func (t T) ScreenshotFullPage() {
- p := t.page.MustNavigate(t.srcFile("fixtures/scroll.html"))
+func TestScreenshotFullPage(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/scroll.html"))
p.MustElement("button")
data := p.MustScreenshotFullPage()
img, err := png.Decode(bytes.NewBuffer(data))
- t.E(err)
+ g.E(err)
res := p.MustEval(`() => ({w: document.documentElement.scrollWidth, h: document.documentElement.scrollHeight})`)
- t.Eq(res.Get("w").Int(), img.Bounds().Dx())
- t.Eq(res.Get("h").Int(), img.Bounds().Dy())
+ g.Eq(res.Get("w").Int(), img.Bounds().Dx())
+ g.Eq(res.Get("h").Int(), img.Bounds().Dy())
// after the full page screenshot the window size should be the same as before
res = p.MustEval(`() => ({w: innerWidth, h: innerHeight})`)
- t.Eq(1280, res.Get("w").Int())
- t.Eq(800, res.Get("h").Int())
+ g.Eq(1280, res.Get("w").Int())
+ g.Eq(800, res.Get("h").Int())
p.MustScreenshotFullPage()
- noEmulation := t.newPage(t.blank())
- t.E(noEmulation.SetViewport(nil))
+ noEmulation := g.newPage(g.blank())
+ g.E(noEmulation.SetViewport(nil))
noEmulation.MustScreenshotFullPage()
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageGetLayoutMetrics{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageGetLayoutMetrics{})
p.MustScreenshotFullPage()
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.EmulationSetDeviceMetricsOverride{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.EmulationSetDeviceMetricsOverride{})
p.MustScreenshotFullPage()
})
}
-func (t T) ScreenshotFullPageInit() {
- p := t.newPage(t.srcFile("fixtures/scroll.html"))
+func TestScreenshotFullPageInit(t *testing.T) {
+ g := setup(t)
+
+ p := g.newPage(g.srcFile("fixtures/scroll.html"))
// should not panic
p.MustScreenshotFullPage()
}
-func (t T) PageInput() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestPageInput(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("input")
el.MustFocus()
@@ -676,82 +757,94 @@ func (t T) PageInput() {
p.Keyboard.MustInsertText(" Test")
p.Keyboard.MustPress(input.Tab)
- t.Eq("A Test", el.MustText())
+ g.Eq("A Test", el.MustText())
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputDispatchKeyEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputDispatchKeyEvent{})
p.Keyboard.MustDown('a')
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.InputDispatchKeyEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.InputDispatchKeyEvent{})
p.Keyboard.MustUp('a')
})
- t.Panic(func() {
- t.mc.stubErr(3, proto.InputDispatchKeyEvent{})
+ g.Panic(func() {
+ g.mc.stubErr(3, proto.InputDispatchKeyEvent{})
p.Keyboard.MustPress('a')
})
}
-func (t T) PageInputDate() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestPageInputDate(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
p.MustElement("[type=date]").MustInput("12")
}
-func (t T) PageScroll() {
- p := t.page.MustNavigate(t.srcFile("fixtures/scroll.html")).MustWaitLoad()
+func TestPageScroll(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/scroll.html")).MustWaitLoad()
p.Mouse.MustMove(30, 30)
p.Mouse.MustClick(proto.InputMouseButtonLeft)
p.Mouse.MustScroll(0, 10)
p.Mouse.MustScroll(100, 190)
- t.E(p.Mouse.Scroll(200, 300, 5))
+ g.E(p.Mouse.Scroll(200, 300, 5))
p.MustWait(`() => pageXOffset > 200 && pageYOffset > 300`)
}
-func (t T) PageConsoleLog() {
- p := t.newPage(t.blank()).MustWaitLoad()
+func TestPageConsoleLog(t *testing.T) {
+ g := setup(t)
+
+ p := g.newPage(g.blank()).MustWaitLoad()
e := &proto.RuntimeConsoleAPICalled{}
wait := p.WaitEvent(e)
p.MustEval(`() => console.log(1, {b: ['test']})`)
wait()
- t.Eq("test", p.MustObjectToJSON(e.Args[1]).Get("b.0").String())
- t.Eq(`1 map[b:[test]]`, p.MustObjectsToJSON(e.Args).Join(" "))
+ g.Eq("test", p.MustObjectToJSON(e.Args[1]).Get("b.0").String())
+ g.Eq(`1 map[b:[test]]`, p.MustObjectsToJSON(e.Args).Join(" "))
}
-func (t T) Fonts() {
+func TestFonts(t *testing.T) {
+ g := setup(t)
+
if !utils.InContainer { // No need to test font rendering on regular OS
- t.SkipNow()
+ g.SkipNow()
}
- p := t.page.MustNavigate(t.srcFile("fixtures/fonts.html")).MustWaitLoad()
+ p := g.page.MustNavigate(g.srcFile("fixtures/fonts.html")).MustWaitLoad()
p.MustPDF("tmp", "fonts.pdf") // download the file from Github Actions Artifacts
}
-func (t T) PagePDF() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestPagePDF(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
s, err := p.PDF(&proto.PagePrintToPDF{})
- t.E(err)
- t.Nil(s.Close())
+ g.E(err)
+ g.Nil(s.Close())
p.MustPDF("")
- t.Panic(func() {
- t.mc.stubErr(1, proto.PagePrintToPDF{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PagePrintToPDF{})
p.MustPDF()
})
}
-func (t T) PageNavigateErr() {
+func TestPageNavigateErr(t *testing.T) {
+ g := setup(t)
+
// dns error
- err := t.page.Navigate("http://" + t.Srand(16))
- t.Is(err, &rod.ErrNavigation{})
- t.Is(err.Error(), "navigation failed: net::ERR_NAME_NOT_RESOLVED")
+ err := g.page.Navigate("http://" + g.RandStr(16))
+ g.Is(err, &rod.ErrNavigation{})
+ g.Is(err.Error(), "navigation failed: net::ERR_NAME_NOT_RESOLVED")
- s := t.Serve()
+ s := g.Serve()
s.Mux.HandleFunc("/404", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404)
@@ -761,54 +854,60 @@ func (t T) PageNavigateErr() {
})
// will not panic
- t.page.MustNavigate(s.URL("/404"))
- t.page.MustNavigate(s.URL("/500"))
+ g.page.MustNavigate(s.URL("/404"))
+ g.page.MustNavigate(s.URL("/500"))
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageStopLoading{})
- t.page.MustNavigate(t.blank())
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageStopLoading{})
+ g.page.MustNavigate(g.blank())
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.PageNavigate{})
- t.page.MustNavigate(t.blank())
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.PageNavigate{})
+ g.page.MustNavigate(g.blank())
})
}
-func (t T) PageWaitLoadErr() {
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.page.MustWaitLoad()
+func TestPageWaitLoadErr(t *testing.T) {
+ g := setup(t)
+
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.page.MustWaitLoad()
})
}
-func (t T) PageNavigation() {
- p := t.newPage().MustReload()
+func TestPageNavigation(t *testing.T) {
+ g := setup(t)
+
+ p := g.newPage().MustReload()
wait := p.WaitNavigation(proto.PageLifecycleEventNameDOMContentLoaded)
- p.MustNavigate(t.srcFile("fixtures/click.html"))
+ p.MustNavigate(g.srcFile("fixtures/click.html"))
wait()
wait = p.WaitNavigation(proto.PageLifecycleEventNameDOMContentLoaded)
- p.MustNavigate(t.srcFile("fixtures/selector.html"))
+ p.MustNavigate(g.srcFile("fixtures/selector.html"))
wait()
wait = p.WaitNavigation(proto.PageLifecycleEventNameDOMContentLoaded)
p.MustNavigateBack()
wait()
- t.Regex("fixtures/click.html$", p.MustInfo().URL)
+ g.Regex("fixtures/click.html$", p.MustInfo().URL)
wait = p.WaitNavigation(proto.PageLifecycleEventNameDOMContentLoaded)
p.MustNavigateForward()
wait()
- t.Regex("fixtures/selector.html$", p.MustInfo().URL)
+ g.Regex("fixtures/selector.html$", p.MustInfo().URL)
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(p.Reload())
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(p.Reload())
}
-func (t T) PagePool() {
+func TestPagePool(t *testing.T) {
+ g := setup(t)
+
pool := rod.NewPagePool(3)
- create := func() *rod.Page { return t.browser.MustPage() }
+ create := func() *rod.Page { return g.browser.MustPage() }
p := pool.Get(create)
pool.Put(p)
pool.Cleanup(func(p *rod.Page) {
@@ -816,27 +915,31 @@ func (t T) PagePool() {
})
}
-func (t T) PageUseNonExistSession() {
+func TestPageUseNonExistSession(t *testing.T) {
+ g := setup(t)
+
// TODO: chrome bug that hangs for closing non-exist session id
// Related chrome ticket: https://bugs.chromium.org/p/chromium/issues/detail?id=1151822
- p := t.browser.PageFromSession("nonexist").Timeout(300 * time.Millisecond)
+ p := g.browser.PageFromSession("nonexist").Timeout(300 * time.Millisecond)
err := proto.PageClose{}.Call(p)
- t.Is(err, context.DeadlineExceeded)
+ g.Is(err, context.DeadlineExceeded)
}
-func (t T) PageElementFromObjectErr() {
- p := t.newPage()
+func TestPageElementFromObjectErr(t *testing.T) {
+ g := setup(t)
+
+ p := g.newPage()
wait := p.WaitNavigation(proto.PageLifecycleEventNameLoad)
- p.MustNavigate(t.srcFile("./fixtures/click.html"))
+ p.MustNavigate(g.srcFile("./fixtures/click.html"))
wait()
res, err := proto.DOMGetNodeForLocation{X: 10, Y: 10}.Call(p)
- t.E(err)
+ g.E(err)
obj, err := proto.DOMResolveNode{
BackendNodeID: res.BackendNodeID,
}.Call(p)
- t.E(err)
+ g.E(err)
- t.mc.stubErr(1, proto.RuntimeEvaluate{})
- t.Err(p.ElementFromObject(obj.Object))
+ g.mc.stubErr(1, proto.RuntimeEvaluate{})
+ g.Err(p.ElementFromObject(obj.Object))
}
diff --git a/query_test.go b/query_test.go
index ec0dcfb1..83f695bb 100644
--- a/query_test.go
+++ b/query_test.go
@@ -3,6 +3,7 @@ package rod_test
import (
"context"
"errors"
+ "testing"
"time"
"github.com/go-rod/rod"
@@ -13,82 +14,92 @@ import (
"github.com/ysmood/gson"
)
-func (t T) PageElements() {
- t.page.MustNavigate(t.srcFile("fixtures/input.html"))
- t.page.MustElement("input")
- list := t.page.MustElements("input")
- t.Eq("input", list.First().MustDescribe().LocalName)
- t.Eq("submit", list.Last().MustText())
+func TestPageElements(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/input.html"))
+ g.page.MustElement("input")
+ list := g.page.MustElements("input")
+ g.Eq("input", list.First().MustDescribe().LocalName)
+ g.Eq("submit", list.Last().MustText())
}
-func (t T) Pages() {
- t.page.MustNavigate(t.srcFile("fixtures/click.html")).MustWaitLoad()
- pages := t.browser.MustPages()
+func TestPages(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/click.html")).MustWaitLoad()
+ pages := g.browser.MustPages()
- t.True(pages.MustFind("button").MustHas("button"))
- t.Panic(func() { rod.Pages{}.MustFind("____") })
- t.True(pages.MustFindByURL("click.html").MustHas("button"))
- t.Panic(func() { rod.Pages{}.MustFindByURL("____") })
+ g.True(pages.MustFind("button").MustHas("button"))
+ g.Panic(func() { rod.Pages{}.MustFind("____") })
+ g.True(pages.MustFindByURL("click.html").MustHas("button"))
+ g.Panic(func() { rod.Pages{}.MustFindByURL("____") })
_, err := pages.Find("____")
- t.Err(err)
- t.Eq(err.Error(), "cannot find page")
- t.Panic(func() {
+ g.Err(err)
+ g.Eq(err.Error(), "cannot find page")
+ g.Panic(func() {
pages.MustFindByURL("____")
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
pages.MustFind("button")
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
pages.MustFindByURL("____")
})
}
-func (t T) PageHas() {
- t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
- t.page.MustElement("body")
- t.True(t.page.MustHas("span"))
- t.False(t.page.MustHas("a"))
- t.True(t.page.MustHasX("//span"))
- t.False(t.page.MustHasX("//a"))
- t.True(t.page.MustHasR("button", "03"))
- t.False(t.page.MustHasR("button", "11"))
-
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(t.page.HasX("//a"))
-
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(t.page.HasR("button", "03"))
+func TestPageHas(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
+ g.page.MustElement("body")
+ g.True(g.page.MustHas("span"))
+ g.False(g.page.MustHas("a"))
+ g.True(g.page.MustHasX("//span"))
+ g.False(g.page.MustHasX("//a"))
+ g.True(g.page.MustHasR("button", "03"))
+ g.False(g.page.MustHasR("button", "11"))
+
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(g.page.HasX("//a"))
+
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(g.page.HasR("button", "03"))
}
-func (t T) ElementHas() {
- t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
- b := t.page.MustElement("body")
- t.True(b.MustHas("span"))
- t.False(b.MustHas("a"))
- t.True(b.MustHasX("//span"))
- t.False(b.MustHasX("//a"))
- t.True(b.MustHasR("button", "03"))
- t.False(b.MustHasR("button", "11"))
+func TestElementHas(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
+ b := g.page.MustElement("body")
+ g.True(b.MustHas("span"))
+ g.False(b.MustHas("a"))
+ g.True(b.MustHasX("//span"))
+ g.False(b.MustHasX("//a"))
+ g.True(b.MustHasR("button", "03"))
+ g.False(b.MustHasR("button", "11"))
}
-func (t T) Search() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestSearch(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
el := p.MustSearch("click me")
- t.Eq("click me", el.MustText())
- t.True(el.MustClick().MustMatches("[a=ok]"))
+ g.Eq("click me", el.MustText())
+ g.True(el.MustClick().MustMatches("[a=ok]"))
_, err := p.Sleeper(rod.NotFoundSleeper).Search("not-exists")
- t.True(errors.Is(err, &rod.ErrElementNotFound{}))
- t.Eq(err.Error(), "cannot find element")
+ g.True(errors.Is(err, &rod.ErrElementNotFound{}))
+ g.Eq(err.Error(), "cannot find element")
// when search result is not ready
{
- t.mc.stub(1, proto.DOMGetSearchResults{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.DOMGetSearchResults{}, func(send StubSend) (gson.JSON, error) {
return gson.New(nil), cdp.ErrCtxNotFound
})
p.MustSearch("click me")
@@ -96,7 +107,7 @@ func (t T) Search() {
// when node id is zero
{
- t.mc.stub(1, proto.DOMGetSearchResults{}, func(send StubSend) (gson.JSON, error) {
+ g.mc.stub(1, proto.DOMGetSearchResults{}, func(send StubSend) (gson.JSON, error) {
return gson.New(proto.DOMGetSearchResultsResult{
NodeIds: []proto.DOMNodeID{0},
}), nil
@@ -104,93 +115,103 @@ func (t T) Search() {
p.MustSearch("click me")
}
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMPerformSearch{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMPerformSearch{})
p.MustSearch("click me")
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.DOMGetSearchResults{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.DOMGetSearchResults{})
p.MustSearch("click me")
})
- t.Panic(func() {
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Panic(func() {
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
p.MustSearch("click me")
})
}
-func (t T) SearchElements() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestSearchElements(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
{
res, err := p.Search("button")
- t.E(err)
+ g.E(err)
c, err := res.All()
- t.E(err)
+ g.E(err)
- t.Len(c, 4)
+ g.Len(c, 4)
- t.mc.stubErr(1, proto.DOMGetSearchResults{})
- t.Err(res.All())
+ g.mc.stubErr(1, proto.DOMGetSearchResults{})
+ g.Err(res.All())
- t.mc.stubErr(1, proto.DOMResolveNode{})
- t.Err(res.All())
+ g.mc.stubErr(1, proto.DOMResolveNode{})
+ g.Err(res.All())
}
{ // disable retry
sleeper := func() utils.Sleeper { return utils.CountSleeper(1) }
_, err := p.Sleeper(sleeper).Search("not-exists")
- t.Err(err)
+ g.Err(err)
}
}
-func (t T) SearchIframes() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click-iframes.html"))
+func TestSearchIframes(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click-iframes.html"))
el := p.MustSearch("button[onclick]")
- t.Eq("click me", el.MustText())
- t.True(el.MustClick().MustMatches("[a=ok]"))
+ g.Eq("click me", el.MustText())
+ g.True(el.MustClick().MustMatches("[a=ok]"))
}
-func (t T) SearchIframesAfterReload() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click-iframes.html"))
+func TestSearchIframesAfterReload(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click-iframes.html"))
frame := p.MustElement("iframe").MustFrame().MustElement("iframe").MustFrame()
frame.MustReload()
el := p.MustSearch("button[onclick]")
- t.Eq("click me", el.MustText())
- t.True(el.MustClick().MustMatches("[a=ok]"))
+ g.Eq("click me", el.MustText())
+ g.True(el.MustClick().MustMatches("[a=ok]"))
}
-func (t T) PageRace() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestPageRace(t *testing.T) {
+ g := setup(t)
- p.Race().Element("button").MustHandle(func(e *rod.Element) { t.Eq("01", e.MustText()) }).MustDo()
- t.Eq("01", p.Race().Element("button").MustDo().MustText())
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
- p.Race().ElementX("//button").MustHandle(func(e *rod.Element) { t.Eq("01", e.MustText()) }).MustDo()
- t.Eq("01", p.Race().ElementX("//button").MustDo().MustText())
+ p.Race().Element("button").MustHandle(func(e *rod.Element) { g.Eq("01", e.MustText()) }).MustDo()
+ g.Eq("01", p.Race().Element("button").MustDo().MustText())
- p.Race().ElementR("button", "02").MustHandle(func(e *rod.Element) { t.Eq("02", e.MustText()) }).MustDo()
- t.Eq("02", p.Race().ElementR("button", "02").MustDo().MustText())
+ p.Race().ElementX("//button").MustHandle(func(e *rod.Element) { g.Eq("01", e.MustText()) }).MustDo()
+ g.Eq("01", p.Race().ElementX("//button").MustDo().MustText())
+
+ p.Race().ElementR("button", "02").MustHandle(func(e *rod.Element) { g.Eq("02", e.MustText()) }).MustDo()
+ g.Eq("02", p.Race().ElementR("button", "02").MustDo().MustText())
p.Race().MustElementByJS("() => document.querySelector('button')", nil).
- MustHandle(func(e *rod.Element) { t.Eq("01", e.MustText()) }).MustDo()
- t.Eq("01", p.Race().MustElementByJS("() => document.querySelector('button')", nil).MustDo().MustText())
+ MustHandle(func(e *rod.Element) { g.Eq("01", e.MustText()) }).MustDo()
+ g.Eq("01", p.Race().MustElementByJS("() => document.querySelector('button')", nil).MustDo().MustText())
el, err := p.Sleeper(func() utils.Sleeper { return utils.CountSleeper(2) }).Race().
Element("not-exists").MustHandle(func(e *rod.Element) {}).
ElementX("//not-exists").
ElementR("not-exists", "test").MustHandle(func(e *rod.Element) {}).
Do()
- t.Err(err)
- t.Nil(el)
+ g.Err(err)
+ g.Nil(el)
el, err = p.Race().MustElementByJS(`() => notExists()`, nil).Do()
- t.Err(err)
- t.Nil(el)
+ g.Err(err)
+ g.Nil(el)
}
-func (t T) PageRaceRetryInHandle() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestPageRaceRetryInHandle(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
p.Race().Element("div").MustHandle(func(e *rod.Element) {
go func() {
utils.Sleep(0.5)
@@ -200,162 +221,196 @@ func (t T) PageRaceRetryInHandle() {
}).MustDo()
}
-func (t T) PageElementX() {
- t.page.MustNavigate(t.srcFile("fixtures/click.html"))
- t.page.MustElement("body")
- name := t.page.MustElementX("//*[contains(text(), 'click')]").MustDescribe().LocalName
- t.Eq("button", name)
+func TestPageElementX(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/click.html"))
+ g.page.MustElement("body")
+ name := g.page.MustElementX("//*[contains(text(), 'click')]").MustDescribe().LocalName
+ g.Eq("button", name)
}
-func (t T) PageElementsX() {
- t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
- t.page.MustElement("body")
- list := t.page.MustElementsX("//button")
- t.Len(list, 4)
+func TestPageElementsX(t *testing.T) {
+ g := setup(t)
+
+ g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
+ g.page.MustElement("body")
+ list := g.page.MustElementsX("//button")
+ g.Len(list, 4)
}
-func (t T) ElementR() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestElementR(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
el := p.MustElementR("button", `\d1`)
- t.Eq("01", el.MustText())
+ g.Eq("01", el.MustText())
el = p.MustElement("div").MustElementR("button", `03`)
- t.Eq("03", el.MustText())
+ g.Eq("03", el.MustText())
- p = t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+ p = g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el = p.MustElementR("input", `submit`)
- t.Eq("submit", el.MustText())
+ g.Eq("submit", el.MustText())
el = p.MustElementR("input", `placeholder`)
- t.Eq("blur", *el.MustAttribute("id"))
+ g.Eq("blur", *el.MustAttribute("id"))
el = p.MustElementR("option", `/cc/i`)
- t.Eq("CC", el.MustText())
+ g.Eq("CC", el.MustText())
}
-func (t T) ElementFromElement() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestElementFromElement(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
el := p.MustElement("div").MustElement("button")
- t.Eq("02", el.MustText())
+ g.Eq("02", el.MustText())
}
-func (t T) ElementsFromElement() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestElementsFromElement(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("form")
list := p.MustElement("form").MustElements("option")
- t.Len(list, 4)
- t.Eq("B", list[1].MustText())
+ g.Len(list, 4)
+ g.Eq("B", list[1].MustText())
- t.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
- t.Err(el.Elements("input"))
+ g.mc.stubErr(1, proto.RuntimeCallFunctionOn{})
+ g.Err(el.Elements("input"))
}
-func (t T) ElementParent() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
+func TestElementParent(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
el := p.MustElement("input").MustParent()
- t.Eq("FORM", el.MustEval(`() => this.tagName`).String())
+ g.Eq("FORM", el.MustEval(`() => this.tagName`).String())
}
-func (t T) ElementParents() {
- p := t.page.MustNavigate(t.srcFile("fixtures/input.html"))
- t.Len(p.MustElement("option").MustParents("*"), 4)
- t.Len(p.MustElement("option").MustParents("form"), 1)
+func TestElementParents(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/input.html"))
+ g.Len(p.MustElement("option").MustParents("*"), 4)
+ g.Len(p.MustElement("option").MustParents("form"), 1)
}
-func (t T) ElementSiblings() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestElementSiblings(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
el := p.MustElement("div")
a := el.MustPrevious()
b := el.MustNext()
- t.Eq(a.MustText(), "01")
- t.Eq(b.MustText(), "04")
+ g.Eq(a.MustText(), "01")
+ g.Eq(b.MustText(), "04")
}
-func (t T) ElementFromElementX() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestElementFromElementX(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
el := p.MustElement("div").MustElementX("./button")
- t.Eq("02", el.MustText())
+ g.Eq("02", el.MustText())
}
-func (t T) ElementsFromElementsX() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html"))
+func TestElementsFromElementsX(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html"))
list := p.MustElement("div").MustElementsX("./button")
- t.Len(list, 2)
+ g.Len(list, 2)
}
-func (t T) ElementTracing() {
- t.browser.Trace(true)
- t.browser.Logger(utils.LoggerQuiet)
+func TestElementTracing(t *testing.T) {
+ g := setup(t)
+
+ g.browser.Trace(true)
+ g.browser.Logger(utils.LoggerQuiet)
defer func() {
- t.browser.Trace(defaults.Trace)
- t.browser.Logger(rod.DefaultLogger)
+ g.browser.Trace(defaults.Trace)
+ g.browser.Logger(rod.DefaultLogger)
}()
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
- t.Eq(`rod.element("code") html`, p.MustElement("html").MustElement("code").MustText())
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
+ g.Eq(`rod.element("code") html`, p.MustElement("html").MustElement("code").MustText())
}
-func (t T) PageElementByJS() {
- p := t.page.MustNavigate(t.srcFile("fixtures/click.html"))
+func TestPageElementByJS(t *testing.T) {
+ g := setup(t)
+
+ p := g.page.MustNavigate(g.srcFile("fixtures/click.html"))
- t.Eq(p.MustElementByJS(`() => document.querySelector('button')`).MustText(), "click me")
+ g.Eq(p.MustElementByJS(`() => document.querySelector('button')`).MustText(), "click me")
_, err := p.ElementByJS(rod.Eval(`() => 1`))
- t.Is(err, &rod.ErrExpectElement{})
- t.Eq(err.Error(), "expect js to return an element, but got: {\"type\":\"number\",\"value\":1,\"description\":\"1\"}")
+ g.Is(err, &rod.ErrExpectElement{})
+ g.Eq(err.Error(), "expect js to return an element, but got: {\"type\":\"number\",\"value\":1,\"description\":\"1\"}")
}
-func (t T) PageElementsByJS() {
- p := t.page.MustNavigate(t.srcFile("fixtures/selector.html")).MustWaitLoad()
+func TestPageElementsByJS(t *testing.T) {
+ g := setup(t)
- t.Len(p.MustElementsByJS("() => document.querySelectorAll('button')"), 4)
+ p := g.page.MustNavigate(g.srcFile("fixtures/selector.html")).MustWaitLoad()
+
+ g.Len(p.MustElementsByJS("() => document.querySelectorAll('button')"), 4)
_, err := p.ElementsByJS(rod.Eval(`() => [1]`))
- t.Is(err, &rod.ErrExpectElements{})
- t.Eq(err.Error(), "expect js to return an array of elements, but got: {\"type\":\"number\",\"value\":1,\"description\":\"1\"}")
+ g.Is(err, &rod.ErrExpectElements{})
+ g.Eq(err.Error(), "expect js to return an array of elements, but got: {\"type\":\"number\",\"value\":1,\"description\":\"1\"}")
_, err = p.ElementsByJS(rod.Eval(`() => 1`))
- t.Eq(err.Error(), "expect js to return an array of elements, but got: {\"type\":\"number\",\"value\":1,\"description\":\"1\"}")
+ g.Eq(err.Error(), "expect js to return an array of elements, but got: {\"type\":\"number\",\"value\":1,\"description\":\"1\"}")
_, err = p.ElementsByJS(rod.Eval(`() => foo()`))
- t.Err(err)
+ g.Err(err)
- t.mc.stubErr(1, proto.RuntimeGetProperties{})
+ g.mc.stubErr(1, proto.RuntimeGetProperties{})
_, err = p.ElementsByJS(rod.Eval(`() => [document.body]`))
- t.Err(err)
+ g.Err(err)
- t.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
- t.Err(p.Elements("button"))
+ g.mc.stubErr(4, proto.RuntimeCallFunctionOn{})
+ g.Err(p.Elements("button"))
}
-func (t T) PageElementTimeout() {
- page := t.page.MustNavigate(t.blank())
+func TestPageElementTimeout(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.blank())
start := time.Now()
_, err := page.Timeout(300 * time.Millisecond).Element("not-exists")
- t.Is(err, context.DeadlineExceeded)
- t.Gte(time.Since(start), 300*time.Millisecond)
+ g.Is(err, context.DeadlineExceeded)
+ g.Gte(time.Since(start), 300*time.Millisecond)
}
-func (t T) PageElementMaxRetry() {
- page := t.page.MustNavigate(t.blank())
+func TestPageElementMaxRetry(t *testing.T) {
+ g := setup(t)
+
+ page := g.page.MustNavigate(g.blank())
s := func() utils.Sleeper { return utils.CountSleeper(5) }
_, err := page.Sleeper(s).Element("not-exists")
- t.Is(err, &utils.ErrMaxSleepCount{})
+ g.Is(err, &utils.ErrMaxSleepCount{})
}
-func (t T) ElementsOthers() {
+func TestElementsOthers(t *testing.T) {
+ g := setup(t)
+
list := rod.Elements{}
- t.Nil(list.First())
- t.Nil(list.Last())
+ g.Nil(list.First())
+ g.Nil(list.Last())
}
-func (t T) PagesOthers() {
+func TestPagesOthers(t *testing.T) {
+ g := setup(t)
+
list := rod.Pages{}
- t.Nil(list.First())
- t.Nil(list.Last())
+ g.Nil(list.First())
+ g.Nil(list.Last())
list = append(list, &rod.Page{})
- t.NotNil(list.First())
- t.NotNil(list.Last())
+ g.NotNil(list.First())
+ g.NotNil(list.Last())
}
diff --git a/setup_test.go b/setup_test.go
index 23fe0657..203bd1e7 100644
--- a/setup_test.go
+++ b/setup_test.go
@@ -22,7 +22,7 @@ import (
"github.com/go-rod/rod/lib/proto"
"github.com/go-rod/rod/lib/utils"
"github.com/ysmood/got"
- "github.com/ysmood/gotrace/pkg/testleak"
+ "github.com/ysmood/gotrace"
"github.com/ysmood/gson"
)
@@ -38,15 +38,29 @@ func init() {
launcher.NewBrowser().MustGet() // preload browser to local
}
-// entry point for all tests
-func Test(t *testing.T) {
- testleak.Check(t, 0)
+var testerPool TesterPool
- got.Each(t, newTesterPool(t).get)
+func TestMain(m *testing.M) {
+ testerPool = newTesterPool()
+
+ code := m.Run()
+ if code != 0 {
+ os.Exit(code)
+ }
+
+ testerPool.cleanup()
+
+ if err := gotrace.Check(0); err != nil {
+ log.Fatal(err)
+ }
}
-// T is a tester. Testers are thread-safe, they shouldn't race each other.
-type T struct {
+var setup = func(t *testing.T) G {
+ return testerPool.get(t)
+}
+
+// G is a tester. Testers are thread-safe, they shouldn't race each other.
+type G struct {
got.G
mc *MockClient
@@ -54,36 +68,32 @@ type T struct {
page *rod.Page
}
-type TesterPool chan *T
+type TesterPool struct {
+ pool chan *G
+ parallel int
+}
-func newTesterPool(t *testing.T) TesterPool {
+func newTesterPool() TesterPool {
parallel := got.Parallel()
if parallel == 0 {
parallel = runtime.GOMAXPROCS(0)
}
fmt.Println("parallel test", parallel)
- cp := TesterPool(make(chan *T, parallel))
-
- t.Cleanup(func() {
- go func() {
- for i := 0; i < parallel; i++ {
- if t := <-cp; t != nil {
- t.browser.MustClose()
- }
- }
- }()
- })
+ cp := TesterPool{
+ pool: make(chan *G, parallel),
+ parallel: parallel,
+ }
for i := 0; i < parallel; i++ {
- cp <- nil
+ cp.pool <- nil
}
return cp
}
// new tester
-func (cp TesterPool) new() *T {
+func (tp TesterPool) new() *G {
u := launcher.New().MustLaunch()
mc := newMockClient(u)
@@ -92,7 +102,7 @@ func (cp TesterPool) new() *T {
page := browser.MustPage()
- return &T{
+ return &G{
mc: mc,
browser: browser,
page: page,
@@ -100,17 +110,17 @@ func (cp TesterPool) new() *T {
}
// get a tester
-func (cp TesterPool) get(t *testing.T) T {
- parallel := got.Parallel() != 1
+func (tp TesterPool) get(t *testing.T) G {
+ parallel := tp.parallel > 1
if parallel {
t.Parallel()
}
- tester := <-cp
+ tester := <-tp.pool
if tester == nil {
- tester = cp.new()
+ tester = tp.new()
}
- t.Cleanup(func() { cp <- tester })
+ t.Cleanup(func() { tp.pool <- tester })
tester.G = got.New(t)
tester.mc.t = t
@@ -122,61 +132,69 @@ func (cp TesterPool) get(t *testing.T) T {
return *tester
}
-func (t T) enableCDPLog() {
- t.mc.principal.Logger(rod.DefaultLogger)
+func (tp TesterPool) cleanup() {
+ for i := 0; i < tp.parallel; i++ {
+ if t := <-testerPool.pool; t != nil {
+ t.browser.MustClose()
+ }
+ }
+}
+
+func (g G) enableCDPLog() {
+ g.mc.principal.Logger(rod.DefaultLogger)
}
-func (t T) dump(args ...interface{}) {
- t.Log(utils.Dump(args))
+func (g G) dump(args ...interface{}) {
+ g.Log(utils.Dump(args))
}
-func (t T) blank() string {
- return t.srcFile("./fixtures/blank.html")
+func (g G) blank() string {
+ return g.srcFile("./fixtures/blank.html")
}
// Get abs file path from fixtures folder, such as "file:///a/b/click.html".
// Usually the path can be used for html src attribute like:
//
-func (t T) srcFile(path string) string {
- t.Helper()
+func (g G) srcFile(path string) string {
+ g.Helper()
f, err := filepath.Abs(slash(path))
- t.E(err)
+ g.E(err)
return "file://" + f
}
-func (t T) newPage(u ...string) *rod.Page {
- t.Helper()
- p := t.browser.MustPage(u...)
- t.Cleanup(func() {
- if !t.Failed() {
+func (g G) newPage(u ...string) *rod.Page {
+ g.Helper()
+ p := g.browser.MustPage(u...)
+ g.Cleanup(func() {
+ if !g.Failed() {
p.MustClose()
}
})
return p
}
-func (t T) checkLeaking(checkGoroutine bool) {
+func (g G) checkLeaking(checkGoroutine bool) {
if checkGoroutine {
- testleak.Check(t.Testable.(*testing.T), 0)
+ gotrace.CheckTest(g.Testable, 0)
}
- t.Cleanup(func() {
- if t.Failed() {
+ g.Cleanup(func() {
+ if g.Failed() {
return
}
- res, err := proto.TargetGetTargets{}.Call(t.browser)
- t.E(err)
+ res, err := proto.TargetGetTargets{}.Call(g.browser)
+ g.E(err)
if len(res.TargetInfos) > 2 { // don't account the init about:blank
- t.Logf("leaking pages: %v", utils.Dump(res.TargetInfos))
+ g.Logf("leaking pages: %v", utils.Dump(res.TargetInfos))
}
- if t.browser.LoadState(t.page.SessionID, proto.FetchEnable{}) {
- t.Logf("leaking FetchEnable")
- t.FailNow()
+ if g.browser.LoadState(g.page.SessionID, proto.FetchEnable{}) {
+ g.Logf("leaking FetchEnable")
+ g.FailNow()
}
- t.mc.setCall(nil)
+ g.mc.setCall(nil)
})
}
@@ -338,9 +356,9 @@ func (mr *MockReader) Read(p []byte) (n int, err error) {
return 0, mr.err
}
-func (t T) LintIgnore(got.Skip) {
+func (g G) LintIgnore(got.Skip) {
_ = rod.Try(func() {
- tt := T{}
+ tt := G{}
tt.dump()
tt.enableCDPLog()