Skip to content

Commit

Permalink
screenshot: replace the unit test for Screenshot
Browse files Browse the repository at this point in the history
This unit test is copied from puppeteer.

The Screenshot action is updated to handle fractional dimensions
properly too.
  • Loading branch information
ZekeLu committed Jul 12, 2021
1 parent f0cd5d5 commit a3b306a
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 32 deletions.
8 changes: 8 additions & 0 deletions screenshot.go
Expand Up @@ -3,6 +3,7 @@ package chromedp
import (
"context"
"fmt"
"math"

"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/cdproto/page"
Expand Down Expand Up @@ -43,6 +44,13 @@ func Screenshot(sel interface{}, picbuf *[]byte, opts ...QueryOption) QueryActio
return err
}

// The "Capture node screenshot" command does not handle fractional dimensions properly.
// Let's align with puppeteer:
// https://github.com/puppeteer/puppeteer/blob/bba3f41286908ced8f03faf98242d4c3359a5efc/src/common/Page.ts#L2002-L2011
x, y := math.Round(clip.X), math.Round(clip.Y)
clip.Width, clip.Height = math.Round(clip.Width+clip.X-x), math.Round(clip.Height+clip.Y-y)
clip.X, clip.Y = x, y

// The next comment is copied from the original code.
// This seems to be necessary? Seems to do the right thing regardless of DPI.
clip.Scale = 1
Expand Down
87 changes: 55 additions & 32 deletions screenshot_test.go
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"image"
_ "image/jpeg"
"image/png"
_ "image/png"
"os"
"path"
"testing"
Expand All @@ -16,43 +16,66 @@ import (
func TestScreenshot(t *testing.T) {
t.Parallel()

ctx, cancel := testAllocate(t, "image2.html")
defer cancel()

tests := []struct {
name string
sel string
by QueryOption
size int
want string
}{
{`/html/body/img`, BySearch, 239},
{`img`, ByQueryAll, 239},
{`#icon-github`, ByID, 120},
{`document.querySelector('#imagething').shadowRoot.querySelector('.container')`, ByJSPath, 190},
{
name: "padding border",
sel: "#padding-border",
want: "element-padding-border.png",
},
{
name: "larger than viewport",
sel: "#larger-than-viewport",
want: "element-larger-than-viewport.png",
},
{
name: "outside viewport",
sel: "#outside-viewport",
want: "element-scrolled-into-view.png",
},
{
name: "rotate element",
sel: "#rotated",
want: "element-rotate.png",
},
{
name: "fractional dimensions",
sel: "#fractional-dimensions",
want: "element-fractional.png",
},
{
name: "fractional offset",
sel: "#fractional-offset",
want: "element-fractional-offset.png",
},
}

// a smaller viewport speeds up this test
if err := Run(ctx, EmulateViewport(600, 400)); err != nil {
t.Fatal(err)
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
ctx, cancel := testAllocate(t, "screenshot.html")
defer cancel()

for i, test := range tests {
var buf []byte
if err := Run(ctx, Screenshot(test.sel, &buf, test.by)); err != nil {
t.Fatalf("test %d got error: %v", i, err)
}

if len(buf) == 0 {
t.Fatalf("test %d failed to capture screenshot", i)
}
img, err := png.Decode(bytes.NewReader(buf))
if err != nil {
t.Fatal(err)
}
size := img.Bounds().Size()
if size.X != test.size || size.Y != test.size {
t.Errorf("expected dimensions to be %d*%d, got %d*%d",
test.size, test.size, size.X, size.Y)
}
var buf []byte
if err := Run(ctx,
EmulateViewport(500, 500),
EvaluateAsDevTools("document.documentElement.scrollTo(20, 30)", nil),
Screenshot(test.sel, &buf, ByQuery),
); err != nil {
t.Fatal(err)
}
diff, err := matchPixel(buf, test.want)
if err != nil {
t.Fatal(err)
}
if diff != 0 {
t.Fatalf("screenshot does not match. diff: %v", diff)
}
})
}
}

Expand Down
73 changes: 73 additions & 0 deletions testdata/screenshot.html
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>screenshot</title>
<style>
#padding-border {
border: 2px solid blue;
background: green;
width: 50px;
height: 50px;
}

#larger-than-viewport {
border: 1px solid blue;
width: 600px;
height: 600px;
margin-left: 50px;
}

#above {
border: 2px solid blue;
background: red;
height: 1500px;
}

#outside-viewport {
border: 2px solid blue;
background: green;
width: 50px;
height: 50px;
}

#rotated {
position: absolute;
top: 100px;
right: 100px;
width: 100px;
height: 100px;
background: green;
transform: rotateZ(200deg);
}

#fractional-dimensions {
width: 48.51px;
height: 19.8px;
border: 1px solid black;
}

#fractional-offset {
position: absolute;
top: 10.3px;
left: 200.4px;
width: 50.3px;
height: 20.2px;
border: 1px solid black;
}

::-webkit-scrollbar {
display: none;
}
</style>
</head>
<body>
<div id="padding-border"></div>
<div id="larger-than-viewport"></div>
<div id="above"></div>
<div id="outside-viewport"></div>
<div id="rotated"></div>
<div id="fractional-dimensions"></div>
<div id="fractional-offset" ></div>
</body>
</html>
Binary file added testdata/screenshots/element-fractional-offset.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testdata/screenshots/element-fractional.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testdata/screenshots/element-padding-border.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testdata/screenshots/element-rotate.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testdata/screenshots/element-scrolled-into-view.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a3b306a

Please sign in to comment.