Skip to content

Commit

Permalink
Merge pull request #4 from go-oss/add-tests
Browse files Browse the repository at this point in the history
Add tests
  • Loading branch information
ww24 authored Apr 29, 2020
2 parents a579b13 + dfd7a55 commit 8e42784
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 13 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# chromedp-helper
[godoc]: https://godoc.org/github.com/go-oss/chromedp-helper
[godoc-badge]: https://godoc.org/github.com/go-oss/chromedp-helper?status.svg
[github-actions-badge]: https://github.com/go-oss/chromedp-helper/workflows/Test%20on%20master/badge.svg

![](https://github.com/go-oss/chromedp-helper/workflows/Test%20on%20master/badge.svg)
# chromedp-helper ![][github-actions-badge] [![][godoc-badge]][godoc]

[chromedp](https://github.com/chromedp/chromedp) helper utilities.

Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@ go 1.14
require (
github.com/chromedp/cdproto v0.0.0-20200424080200-0de008e41fa0
github.com/chromedp/chromedp v0.5.3
github.com/gobwas/ws v1.0.3 // indirect
github.com/mailru/easyjson v0.7.1 // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
golang.org/x/sys v0.0.0-20200428200454-593003d681fa // indirect
golang.org/x/tools v0.0.0-20200428211428-0c9eba77bc32 // indirect
)
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,40 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/gobwas/ws v1.0.3 h1:ZOigqf7iBxkA4jdQ3am7ATzdlOFp9YzA6NmuvEEZc9g=
github.com/gobwas/ws v1.0.3/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08 h1:V0an7KRw92wmJysvFvtqtKMAPmvS5O0jtB0nYo6t+gs=
github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08/go.mod h1:dFWs1zEqDjFtnBXsd1vPOZaLsESovai349994nHx3e0=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200428200454-593003d681fa h1:yMbJOvnfYkO1dSAviTu/ZguZWLBTXx4xE3LYrxUCCiA=
golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200428211428-0c9eba77bc32 h1:Xvf3ZQTm5bjXPxhI7g+dwqsCqadK1rcNtwtszuatetk=
golang.org/x/tools v0.0.0-20200428211428-0c9eba77bc32/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
22 changes: 19 additions & 3 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ var (
)

// Screenshot is an action that takes a screenshot of the entire browser viewport and save as image file.
//
// Note: this will override the viewport emulation settings.
//
// This function is based on https://github.com/chromedp/examples
func Screenshot(filename string) chromedp.Action {
return chromedp.ActionFunc(func(ctx context.Context) error {
Expand Down Expand Up @@ -94,10 +96,20 @@ func Navigate(urlstr interface{}, timeout time.Duration) chromedp.NavigateAction
// IgnoreCacheReload is an action that reloads the current page without cache.
func IgnoreCacheReload(timeout time.Duration) chromedp.NavigateAction {
return chromedp.ActionFunc(func(ctx context.Context) error {
if err := page.Reload().WithIgnoreCache(true).Do(ctx); err != nil {
_, entries, err := page.GetNavigationHistory().Do(ctx)
if err != nil {
return err
}
return WaitLoaded(timeout).Do(ctx)
currentURL := entries[len(entries)-1].URL
log.Printf("IgnoreCacheReload: current=%s\n", currentURL)
return WaitResponse(currentURL, timeout,
chromedp.ActionFunc(func(ctx context.Context) error {
if err := page.Reload().WithIgnoreCache(true).Do(ctx); err != nil {
return err
}
return nil
}),
).Do(ctx)
})
}

Expand Down Expand Up @@ -195,6 +207,9 @@ func WaitResponse(urlstr interface{}, timeout time.Duration, acts ...chromedp.Ac
}
log.Printf("WaitResponse: timeout=%s\n", timeout)
timer := time.NewTimer(timeout)
defer timer.Stop()
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case err, open := <-ch:
Expand All @@ -203,7 +218,7 @@ func WaitResponse(urlstr interface{}, timeout time.Duration, acts ...chromedp.Ac
}
if open {
log.Println("WaitResponse: reload")
time.Sleep(time.Second)
<-timer.C
reload := page.Reload().WithIgnoreCache(true)
if err := reload.Do(ctx); err != nil {
return err
Expand Down Expand Up @@ -235,6 +250,7 @@ func WaitLoaded(timeout time.Duration) chromedp.Action {
})
log.Printf("WaitLoaded: timeout=%s\n", timeout)
timer := time.NewTimer(timeout)
defer timer.Stop()
select {
case <-ch:
return nil
Expand Down
229 changes: 221 additions & 8 deletions helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,246 @@ import (
"bytes"
"context"
"errors"
"fmt"
"image"
_ "image/png"
"io"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"os"
"path"
"path/filepath"
"sync"
"testing"
"time"

"github.com/chromedp/cdproto/network"
cdpruntime "github.com/chromedp/cdproto/runtime"
"github.com/chromedp/chromedp"
)

var (
allocOpts = append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.DisableGPU, chromedp.NoSandbox)
browserOpts []chromedp.ContextOption
allocateOnce sync.Once
startServerOnce sync.Once
allocCtx context.Context
browserCtx context.Context
testServer *httptest.Server
testdataDir string
testdataURL string
)

func init() {
wd, err := os.Getwd()
if err != nil {
panic(fmt.Sprintf("could not get working directory: %v", err))
}
testdataDir = filepath.Join(wd, "testdata")
testdataURL = "file://" + path.Join(wd, "testdata")
}

func TestMain(m *testing.M) {
var cancel context.CancelFunc
allocCtx, cancel = chromedp.NewExecAllocator(context.Background(), allocOpts...)

if debug := os.Getenv("DEBUG"); debug != "" && debug != "false" {
browserOpts = append(browserOpts, chromedp.WithDebugf(log.Printf))
}

code := m.Run()
cancel()

if testServer != nil {
testServer.Close()
}

os.Exit(code)
}

func testAllocate(tb testing.TB) (context.Context, context.CancelFunc) {
allocateOnce.Do(func() {
ctx, _ := chromedp.NewContext(allocCtx, browserOpts...)
if err := chromedp.Run(ctx); err != nil {
tb.Fatal(err)
}
chromedp.ListenBrowser(ctx, func(ev interface{}) {
switch ev := ev.(type) {
case *cdpruntime.EventExceptionThrown:
tb.Errorf("%+v\n", ev.ExceptionDetails)
}
})
browserCtx = ctx
})

if browserCtx == nil {
tb.FailNow()
}

// Create new tab of existing browser.
ctx, _ := chromedp.NewContext(browserCtx)
cancel := func() {
if err := chromedp.Cancel(ctx); err != nil {
tb.Error(err)
}
}
return ctx, cancel
}

func testStartServer(tb testing.TB) string {
startServerOnce.Do(func() {
mux := http.NewServeMux()
mux.HandleFunc("/image.png", func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second)
http.ServeFile(w, r, filepath.Join(testdataDir, "image.png"))
})
mux.Handle("/", http.FileServer(http.Dir(testdataDir)))
testServer = httptest.NewServer(mux)
})

if testServer == nil {
tb.FailNow()
}

return testServer.URL
}

func TestScreenshot(t *testing.T) {
t.Skip("TODO")
t.Parallel()
ctx, cancel := testAllocate(t)
defer cancel()

dir, err := ioutil.TempDir("", "chromedp-helper-test")
if err != nil {
t.Fatalf("failed to create temporary directory: %v", err)
}
sspath := filepath.Join(dir, "screenshot.png")
log.Println("sspath:", sspath)

tasks := chromedp.Tasks{
chromedp.Navigate(testdataURL + "/screenshot.html"),
Screenshot(sspath),
}
if err := chromedp.Run(ctx, tasks); err != nil {
t.Fatal(err)
}

f, err := os.Open(sspath)
if err != nil {
t.Fatalf("failed to open screenshot file: %v", err)
}
defer f.Close()

config, format, err := image.DecodeConfig(f)
if err != nil {
t.Fatalf("failed to decode image config: %v", err)
}

const wantFormat = "png"
const wantWidth = 1200
const wantHeight = 1234
if format != wantFormat {
t.Fatalf("expected format to be %q, got %q", wantFormat, format)
}
if config.Width != wantWidth || config.Height != wantHeight {
t.Fatalf("expected dimensions to be %d*%d, got %d*%d",
wantWidth, wantHeight, config.Width, config.Height)
}
}

func TestNavigate(t *testing.T) {
t.Skip("TODO")
t.Parallel()
ctx, cancel := testAllocate(t)
defer cancel()
endpoint := testStartServer(t)

var got string
tasks := chromedp.Tasks{
network.Enable(),
EnableLifeCycleEvents(),
Navigate(endpoint+"/navigate.html", 5*time.Second),
chromedp.Text("#text", &got),
}
if err := chromedp.Run(ctx, tasks); err != nil {
t.Fatal(err)
}
const want = "DOMContentLoaded"
if got != want {
t.Fatalf("expected text to be %q, got %q", want, got)
}
}

func TestIgnoreCacheReload(t *testing.T) {
t.Skip("TODO")
}
t.Parallel()
ctx, cancel := testAllocate(t)
defer cancel()
endpoint := testStartServer(t)

func TestEnableLifeCycleEvents(t *testing.T) {
t.Skip("TODO")
var got string
tasks := chromedp.Tasks{
network.Enable(),
EnableLifeCycleEvents(),
chromedp.Navigate(endpoint + "/navigate.html"),
IgnoreCacheReload(5 * time.Second),
chromedp.Text("#text", &got),
}
if err := chromedp.Run(ctx, tasks); err != nil {
t.Fatal(err)
}
const want = "DOMContentLoaded"
if got != want {
t.Fatalf("expected text to be %q, got %q", want, got)
}
}

func TestWaitResponse(t *testing.T) {
t.Skip("TODO")
t.Parallel()
ctx, cancel := testAllocate(t)
defer cancel()
endpoint := testStartServer(t)

var got string
tasks := chromedp.Tasks{
network.Enable(),
EnableLifeCycleEvents(),
chromedp.Navigate(endpoint + "/index.html"),
WaitResponse(endpoint+"/navigate.html", 5*time.Second,
chromedp.Click(`a[href="navigate.html"]`),
),
chromedp.Text("#text", &got),
}
if err := chromedp.Run(ctx, tasks); err != nil {
t.Fatal(err)
}
const want = "DOMContentLoaded"
if got != want {
t.Fatalf("expected text to be %q, got %q", want, got)
}
}

func TestWaitLoaded(t *testing.T) {
t.Skip("TODO")
t.Parallel()
ctx, cancel := testAllocate(t)
defer cancel()
endpoint := testStartServer(t)

var got string
tasks := chromedp.Tasks{
chromedp.Navigate(endpoint + "/index.html"),
chromedp.Click(`a[href="navigate.html"]`),
WaitLoaded(5 * time.Second),
chromedp.Text("#text", &got),
}
if err := chromedp.Run(ctx, tasks); err != nil {
t.Fatal(err)
}
const want = "loaded"
if got != want {
t.Fatalf("expected text to be %q, got %q", want, got)
}
}

func TestWaitInput(t *testing.T) {
Expand Down
Binary file added testdata/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions testdata/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document for the test</title>
</head>

<body>
<article>
<header style="background-color: turquoise;">Test</header>
<a href="navigate.html">navigate</a>
</article>
</body>

</html>
Loading

0 comments on commit 8e42784

Please sign in to comment.