Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
Code optimization and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mgrachev committed Jan 23, 2016
1 parent 9113f25 commit a3656c5
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 37 deletions.
5 changes: 5 additions & 0 deletions lib/gastly.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
require 'phantomjs'
require 'mini_magick'
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/object/blank'

require_relative 'gastly/image'
require_relative 'gastly/screenshot'
require_relative 'gastly/exceptions'
Expand Down
1 change: 1 addition & 0 deletions lib/gastly/exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ def initialize(url)
end

PhantomJSError = Class.new(RuntimeError)
UnknownError = Class.new(RuntimeError)
end
26 changes: 11 additions & 15 deletions lib/gastly/image.rb
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
require 'mini_magick'

module Gastly
class Image
attr_reader :file
attr_reader :image

# @param tempfile [Tempfile] Screenshot
def initialize(tempfile)
@file = MiniMagick::Image.open(tempfile.path)
tempfile.unlink
# @param image [MiniMagick::Image] Instance of MiniMagick::Image
def initialize(image)
@image = image
end

# @param [Hash]
# @option width [Fixnum] Image width
# @option height [Fixnum] Image height
# @param width [Fixnum] Image width
# @param height [Fixnum] Image height
def resize(width:, height:)
dimensions = "#{width}x#{height}"
@file.resize(dimensions)
image.resize(dimensions)
end

# @param ext [String] Image extension
# @return [MiniMagick::Image] Instance
def format(ext)
@file.format(ext)
image.format(ext)
end

# @param output [String] Full path to file
# @return [String] Full path to file
# @param output [String] Full path to image
# @return [String] Full path to image
def save(output)
@file.write(output)
image.write(output)
output
end
end
Expand Down
35 changes: 15 additions & 20 deletions lib/gastly/screenshot.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
require 'phantomjs'
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/object/blank'

module Gastly
class Screenshot
SCRIPT_PATH = File.expand_path('../script.js', __FILE__)
DEFAULT_TIMEOUT = 0
DEFAULT_BROWSER_WIDTH = 1440
DEFAULT_BROWSER_HEIGHT = 900
DEFAULT_FILE_NAME = 'output'.freeze
DEFAULT_FILE_FORMAT = '.png'.freeze

attr_reader :tempfile
attr_reader :image
attr_writer :timeout, :browser_width, :browser_height
attr_accessor :url, :selector, :cookies, :proxy_host, :proxy_port

Expand All @@ -22,12 +17,11 @@ def initialize(url, **kwargs)
@url = url
@cookies = kwargs.delete(:cookies)

@tempfile = Tempfile.new([DEFAULT_FILE_NAME, DEFAULT_FILE_FORMAT]) # TODO: Use MiniMagick::Image.create instead
@image = MiniMagick::Image.create(DEFAULT_FILE_FORMAT, false) # Disable validation

kwargs.each { |key, value| instance_variable_set(:"@#{key}", value) }
end

#
# Capture image via PhantomJS and save to output file
#
# @return [Gastly::Image] Instance of Gastly::Image
Expand All @@ -37,10 +31,9 @@ def capture
Phantomjs.proxy_port = proxy_port if proxy_port

output = Phantomjs.run(proxy_options, SCRIPT_PATH.to_s, *prepared_params)
handle_output(output)

handle_exception(output) if output.present? # TODO: Add test

Gastly::Image.new(tempfile) # TODO: Add test
Gastly::Image.new(image)
end

%w(timeout browser_width browser_height).each do |name|
Expand All @@ -63,26 +56,28 @@ def prepared_params
timeout: timeout,
width: browser_width,
height: browser_height,
output: tempfile.path
output: image.path
}

params[:selector] = selector if selector.present?
params[:cookies] = hash_to_array(cookies).join(',') if cookies.present?
params[:cookies] = parameterize(cookies).join(',') if cookies.present?

hash_to_array(params)
parameterize(params)
end

# TODO: Rename method to parameterize
def hash_to_array(data)
data.map { |key, value| "#{key}=#{value}" }
# @param hash [Hash]
# @return [Array] Array of parameterized strings
def parameterize(hash)
hash.map { |key, value| "#{key}=#{value}" }
end

# TODO: Rename to handle_output
def handle_exception(output)
def handle_output(output)
return unless output.present?

error = case output
when /^FetchError:(.+)/ then Gastly::FetchError
when /^RuntimeError:(.+)/m then Gastly::PhantomJSError
# TODO: Return unknown error
else UnknownError
end

fail error, Regexp.last_match(1)
Expand Down
32 changes: 32 additions & 0 deletions spec/gastly/image_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
require 'spec_helper'

RSpec.describe Gastly::Image do
let(:image) { MiniMagick::Image.new('test.png') }
subject { Gastly::Image.new(image) }

context '#resize' do
it 'invokes method #resize with arguments' do
width, height = 100, 100
expect_any_instance_of(MiniMagick::Image).to receive(:resize).with("#{width}x#{height}")
subject.resize(width: 100, height: 100)
end
end

context '#format' do
it 'invokes method #format' do
ext = 'png'
expect_any_instance_of(MiniMagick::Image).to receive(:format).with(ext)
subject.format(ext)
end
end

context '#save' do
let(:output) { 'output.png' }
before do
expect_any_instance_of(MiniMagick::Image).to receive(:write).with(output)
end

it 'invokes method #write' do
subject.save(output)
end

it 'returns a string' do
expect(subject.save(output)).to eq output
end
end
end
26 changes: 24 additions & 2 deletions spec/gastly/screenshot_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
it { expect(Gastly::Screenshot::DEFAULT_TIMEOUT).to eq 0 }
it { expect(Gastly::Screenshot::DEFAULT_BROWSER_WIDTH).to eq 1440 }
it { expect(Gastly::Screenshot::DEFAULT_BROWSER_HEIGHT).to eq 900 }
it { expect(Gastly::Screenshot::DEFAULT_FILE_NAME).to eq 'output' }
it { expect(Gastly::Screenshot::DEFAULT_FILE_FORMAT).to eq '.png' }

context '#initialize' do
Expand Down Expand Up @@ -57,14 +56,37 @@
"timeout=#{params[:timeout]}",
"width=#{params[:browser_width]}",
"height=#{params[:browser_height]}",
"output=#{screenshot.tempfile.path}",
"output=#{screenshot.image.path}",
"selector=#{params[:selector]}",
"cookies=#{cookies}"
]

expect(Phantomjs).to receive(:run).with(*args)
screenshot.capture
end

it 'raises an exception if fetch error' do
url = 'h11p://google.com'
screenshot = Gastly::Screenshot.new(url)
expect { screenshot.capture }.to raise_error(Gastly::FetchError, "Unable to load #{url}")
end

it 'raises an exception if runtime error' do
expect(Phantomjs).to receive(:run).and_return('RuntimeError:test runtime error')
screenshot = Gastly::Screenshot.new(url)
expect { screenshot.capture }.to raise_error(Gastly::PhantomJSError, 'test runtime error')
end

it 'raises an exception if unknown error' do
expect(Phantomjs).to receive(:run).and_return('unknown error')
screenshot = Gastly::Screenshot.new(url)
expect { screenshot.capture }.to raise_error(Gastly::UnknownError)
end

it 'returns an instance of Gastly::Image' do
screenshot = Gastly::Screenshot.new(url)
expect(screenshot.capture).to be_instance_of Gastly::Image
end
end

context '#timeout' do
Expand Down
18 changes: 18 additions & 0 deletions spec/gastly_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
require 'spec_helper'

describe Gastly do
let(:url) { 'http://google.com' }

context '#screenshot' do
it 'returns an instance of Gastly::Screenshot' do
expect(Gastly.screenshot(url, timeout: 1000)).to be_instance_of Gastly::Screenshot
end
end

context '#capture' do
it 'creates a screenshot' do
tmp = 'spec/support/tmp'
path = "#{tmp}/output.png"
expect(Dir.glob("#{tmp}/*").length).to eq 0
Gastly.capture(url, path)
expect(Dir.glob("#{tmp}/*").length).to eq 1
FileUtils.rm Dir.glob("#{tmp}/*")
end
end
end

0 comments on commit a3656c5

Please sign in to comment.