Skip to content

Commit

Permalink
Merge pull request #171 from janbiedermann/element_handle_screenshot
Browse files Browse the repository at this point in the history
ElementHandle#screenshot
  • Loading branch information
Yusuke Iwaki committed Dec 1, 2021
2 parents e22585e + db777ac commit d3481e5
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 158 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@
/.rakeTasks

diff-*.png
*.github.pdf
.envrc
18 changes: 10 additions & 8 deletions lib/puppeteer/element_handle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def box_model
end
end

def screenshot(options = {})
def screenshot(type: nil, path: nil, full_page: nil, clip: nil, quality: nil, omit_background: nil, encoding: nil)
needs_viewport_reset = false

box = bounding_box
Expand Down Expand Up @@ -358,14 +358,16 @@ def screenshot(options = {})
page_x = layout_metrics["layoutViewport"]["pageX"]
page_y = layout_metrics["layoutViewport"]["pageY"]

clip = {
x: page_x + box.x,
y: page_y + box.y,
width: box.width,
height: box.height,
}
if clip.nil?
clip = {
x: page_x + box.x,
y: page_y + box.y,
width: box.width,
height: box.height,
}
end

@page.screenshot({ clip: clip }.merge(options))
@page.screenshot(type: type, path: path, full_page: full_page, clip: clip, quality: quality, omit_background: omit_background, encoding: encoding)
ensure
if needs_viewport_reset
@page.viewport = viewport
Expand Down
264 changes: 114 additions & 150 deletions spec/integration/screenshot_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,154 +172,118 @@
end
end

# describe('ElementHandle.screenshot', function () {
# it('should work', async () => {
# const { page, server } = getTestState();

# await page.setViewport({ width: 500, height: 500 });
# await page.goto(server.PREFIX + '/grid.html');
# await page.evaluate(() => window.scrollBy(50, 100));
# const elementHandle = await page.$('.box:nth-of-type(3)');
# const screenshot = await elementHandle.screenshot();
# expect(screenshot).toBeGolden('screenshot-element-bounding-box.png');
# });
# it('should take into account padding and border', async () => {
# const { page } = getTestState();

# await page.setViewport({ width: 500, height: 500 });
# await page.setContent(`
# something above
# <style>div {
# border: 2px solid blue;
# background: green;
# width: 50px;
# height: 50px;
# }
# </style>
# <div></div>
# `);
# const elementHandle = await page.$('div');
# const screenshot = await elementHandle.screenshot();
# expect(screenshot).toBeGolden('screenshot-element-padding-border.png');
# });
# it('should capture full element when larger than viewport', async () => {
# const { page } = getTestState();

# await page.setViewport({ width: 500, height: 500 });

# await page.setContent(`
# something above
# <style>
# div.to-screenshot {
# border: 1px solid blue;
# width: 600px;
# height: 600px;
# margin-left: 50px;
# }
# ::-webkit-scrollbar{
# display: none;
# }
# </style>
# <div class="to-screenshot"></div>
# `);
# const elementHandle = await page.$('div.to-screenshot');
# const screenshot = await elementHandle.screenshot();
# expect(screenshot).toBeGolden(
# 'screenshot-element-larger-than-viewport.png'
# );

# expect(
# await page.evaluate(() => ({
# w: window.innerWidth,
# h: window.innerHeight,
# }))
# ).toEqual({ w: 500, h: 500 });
# });
# it('should scroll element into view', async () => {
# const { page } = getTestState();

# await page.setViewport({ width: 500, height: 500 });
# await page.setContent(`
# something above
# <style>div.above {
# border: 2px solid blue;
# background: red;
# height: 1500px;
# }
# div.to-screenshot {
# border: 2px solid blue;
# background: green;
# width: 50px;
# height: 50px;
# }
# </style>
# <div class="above"></div>
# <div class="to-screenshot"></div>
# `);
# const elementHandle = await page.$('div.to-screenshot');
# const screenshot = await elementHandle.screenshot();
# expect(screenshot).toBeGolden(
# 'screenshot-element-scrolled-into-view.png'
# );
# });
# itFailsFirefox('should work with a rotated element', async () => {
# const { page } = getTestState();

# await page.setViewport({ width: 500, height: 500 });
# await page.setContent(`<div style="position:absolute;
# top: 100px;
# left: 100px;
# width: 100px;
# height: 100px;
# background: green;
# transform: rotateZ(200deg);">&nbsp;</div>`);
# const elementHandle = await page.$('div');
# const screenshot = await elementHandle.screenshot();
# expect(screenshot).toBeGolden('screenshot-element-rotate.png');
# });
# itFailsFirefox('should fail to screenshot a detached element', async () => {
# const { page } = getTestState();

# await page.setContent('<h1>remove this</h1>');
# const elementHandle = await page.$('h1');
# await page.evaluate(
# (element: HTMLElement) => element.remove(),
# elementHandle
# );
# const screenshotError = await elementHandle
# .screenshot()
# .catch((error) => error);
# expect(screenshotError.message).toBe(
# 'Node is either not visible or not an HTMLElement'
# );
# });
# it('should not hang with zero width/height element', async () => {
# const { page } = getTestState();

# await page.setContent('<div style="width: 50px; height: 0"></div>');
# const div = await page.$('div');
# const error = await div.screenshot().catch((error_) => error_);
# expect(error.message).toBe('Node has 0 height.');
# });
# it('should work for an element with fractional dimensions', async () => {
# const { page } = getTestState();

# await page.setContent(
# '<div style="width:48.51px;height:19.8px;border:1px solid black;"></div>'
# );
# const elementHandle = await page.$('div');
# const screenshot = await elementHandle.screenshot();
# expect(screenshot).toBeGolden('screenshot-element-fractional.png');
# });
# itFailsFirefox('should work for an element with an offset', async () => {
# const { page } = getTestState();

# await page.setContent(
# '<div style="position:absolute; top: 10.3px; left: 20.4px;width:50.3px;height:20.2px;border:1px solid black;"></div>'
# );
# const elementHandle = await page.$('div');
# const screenshot = await elementHandle.screenshot();
# expect(screenshot).toBeGolden('screenshot-element-fractional-offset.png');
# });
# });
describe 'ElementHandle#screenshot', skip: ENV['CI'], sinatra: true do
before {
page.viewport = Puppeteer::Viewport.new(width: 500, height: 500)
page.goto("#{server_prefix}/grid.html")
}

it 'should work' do
page.evaluate('() => window.scrollBy(50, 100)')
element_handle = page.S('.box:nth-of-type(3)')
expect(element_handle.screenshot).to be_golden('screenshot-element-bounding-box.png')
end

it 'should take into account padding and border' do
page.set_content <<-CONTENT
something above
<style>div {
border: 2px solid blue;
background: green;
width: 50px;
height: 50px;
}
</style>
<div></div>
CONTENT

elementHandle = page.S('div')
expect(elementHandle.screenshot).to be_golden('screenshot-element-padding-border.png')
end

it 'should capture full element when larger than viewport' do
page.set_content <<-CONTENT
something above
<style>
div.to-screenshot {
border: 1px solid blue;
width: 600px;
height: 600px;
margin-left: 50px;
}
::-webkit-scrollbar{
display: none;
}
</style>
<div class="to-screenshot"></div>
CONTENT

element_handle = page.S('div.to-screenshot')
expect(element_handle.screenshot).to be_golden('screenshot-element-larger-than-viewport.png')

expect(
page.evaluate('() => ({ w: window.innerWidth, h: window.innerHeight}))')
).to eq({ w: 500, h: 500 })
end

it 'should scroll element into view' do
page.set_content <<-CONTENT
something above
<style>div.above {
border: 2px solid blue;
background: red;
height: 1500px;
}
div.to-screenshot {
border: 2px solid blue;
background: green;
width: 50px;
height: 50px;
}
</style>
<div class="above"></div>
<div class="to-screenshot"></div>
CONTENT
element_handle = page.S('div.to-screenshot')
expect(element_handle.screenshot).to be_golden('screenshot-element-scrolled-into-view.png')
end

it_fails_firefox 'should work with a rotated element' do
page.set_content <<-CONTENT
<div style="position:absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background: green;
transform: rotateZ(200deg);">&nbsp;</div>
CONTENT
element_handle = page.S('div')
expect(element_handle.screenshot).to be_golden('screenshot-element-rotate.png');
end

it_fails_firefox 'should fail to screenshot a detached element' do
page.set_content('<h1>remove this</h1>')
element_handle = page.S('h1')
page.evaluate('(element) => element.remove()', element_handle)
begin
element_handle.screenshot
rescue => error
screenshot_error = error
end
expect(screenshot_error.message).to eq('Node is either not visible or not an HTMLElement')
end

it 'should work for an element with fractional dimensions' do
page.set_content '<div style="width:48.51px;height:19.8px;border:1px solid black;"></div>'
element_handle = page.S('div')
expect(element_handle.screenshot).to be_golden('screenshot-element-fractional.png')
end

it_fails_firefox 'should work for an element with an offset' do
page.set_content '<div style="position:absolute; top: 10.3px; left: 20.4px;width:50.3px;height:20.2px;border:1px solid black;"></div>'
element_handle = page.S('div')
expect(element_handle.screenshot).to be_golden('screenshot-element-fractional-offset.png')
end
end
end

0 comments on commit d3481e5

Please sign in to comment.