diff --git a/screenshot.go b/screenshot.go index 8cbd4390..367c1f48 100644 --- a/screenshot.go +++ b/screenshot.go @@ -3,6 +3,7 @@ package chromedp import ( "context" "fmt" + "math" "github.com/chromedp/cdproto/cdp" "github.com/chromedp/cdproto/page" @@ -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 diff --git a/screenshot_test.go b/screenshot_test.go index 34ec83cd..a2e1dbb3 100644 --- a/screenshot_test.go +++ b/screenshot_test.go @@ -5,7 +5,7 @@ import ( "fmt" "image" _ "image/jpeg" - "image/png" + _ "image/png" "os" "path" "testing" @@ -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) + } + }) } } diff --git a/testdata/screenshot.html b/testdata/screenshot.html new file mode 100644 index 00000000..b9ddacad --- /dev/null +++ b/testdata/screenshot.html @@ -0,0 +1,73 @@ + + + + + screenshot + + + +
+
+
+
+
+
+
+ + diff --git a/testdata/screenshots/element-fractional-offset.png b/testdata/screenshots/element-fractional-offset.png new file mode 100644 index 00000000..cc8669d5 Binary files /dev/null and b/testdata/screenshots/element-fractional-offset.png differ diff --git a/testdata/screenshots/element-fractional.png b/testdata/screenshots/element-fractional.png new file mode 100644 index 00000000..35c53377 Binary files /dev/null and b/testdata/screenshots/element-fractional.png differ diff --git a/testdata/screenshots/element-larger-than-viewport.png b/testdata/screenshots/element-larger-than-viewport.png new file mode 100644 index 00000000..5fcdb923 Binary files /dev/null and b/testdata/screenshots/element-larger-than-viewport.png differ diff --git a/testdata/screenshots/element-padding-border.png b/testdata/screenshots/element-padding-border.png new file mode 100644 index 00000000..917dd481 Binary files /dev/null and b/testdata/screenshots/element-padding-border.png differ diff --git a/testdata/screenshots/element-rotate.png b/testdata/screenshots/element-rotate.png new file mode 100644 index 00000000..52e2a0f6 Binary files /dev/null and b/testdata/screenshots/element-rotate.png differ diff --git a/testdata/screenshots/element-scrolled-into-view.png b/testdata/screenshots/element-scrolled-into-view.png new file mode 100644 index 00000000..917dd481 Binary files /dev/null and b/testdata/screenshots/element-scrolled-into-view.png differ