Class: Rundoc::CodeCommand::Website::Driver

Inherits:
Object
  • Object
show all
Defined in:
lib/rundoc/code_command/website/driver.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, url:, width: 1024, height: 720, visible: false, io: $stdout, read_timeout: 60) ⇒ Driver

Returns a new instance of Driver.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/rundoc/code_command/website/driver.rb', line 9

def initialize(name:, url:, width: 1024, height: 720, visible: false, io: $stdout, read_timeout: 60)
  @io = io
  browser_options = ::Selenium::WebDriver::Chrome::Options.new
  browser_options.args << "--headless" unless visible
  browser_options.args << "--disable-gpu" if Gem.win_platform?
  browser_options.args << "--hide-scrollbars"
  # browser_options.args << "--window-size=#{width},#{height}"
  @width = width
  @height = height

  client = Selenium::WebDriver::Remote::Http::Default.new
  client.read_timeout = read_timeout

  @driver = Capybara::Selenium::Driver.new(nil, browser: :chrome, options: browser_options, http_client: client)
  driver_name = :"rundoc_driver_#{name}"
  Capybara.register_driver(driver_name) do |app|
    @driver
  end

  @session = Capybara::Session.new(driver_name)
end

Class Attribute Details

.tasksObject (readonly)

Returns the value of attribute tasks.



64
65
66
# File 'lib/rundoc/code_command/website/driver.rb', line 64

def tasks
  @tasks
end

Instance Attribute Details

#sessionObject (readonly)

Returns the value of attribute session.



7
8
9
# File 'lib/rundoc/code_command/website/driver.rb', line 7

def session
  @session
end

Class Method Details

.add(name, value) ⇒ Object



113
114
115
116
# File 'lib/rundoc/code_command/website/driver.rb', line 113

def self.add(name, value)
  raise "Task named #{name.inspect} is already started, choose a different name" if @tasks[name]
  @tasks[name] = value
end

.find(name) ⇒ Object



118
119
120
121
# File 'lib/rundoc/code_command/website/driver.rb', line 118

def self.find(name)
  raise "Could not find task with name #{name.inspect}, known task names: #{@tasks.keys.inspect}" unless @tasks[name]
  @tasks[name]
end

.next_screenshot_nameObject



123
124
125
126
127
# File 'lib/rundoc/code_command/website/driver.rb', line 123

def self.next_screenshot_name
  @count ||= 0
  @count += 1
  "screenshot_#{@count}.png"
end

Instance Method Details

#current_urlObject



51
52
53
# File 'lib/rundoc/code_command/website/driver.rb', line 51

def current_url
  session.current_url
end

#safe_eval(code, env = {}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rundoc/code_command/website/driver.rb', line 67

def safe_eval(code, env = {})
  @driver.send(:eval, code)
rescue => e
  msg = +""
  msg << "Error running code #{code.inspect} at #{current_url.inspect}\n"
  msg << "saving a screenshot to: `tmp/error.png`"
  @io.puts msg
  error_path = env[:context].screenshots_dir.join("error.png")
  session.save_screenshot(error_path)
  raise e
end

#screenshot(screenshots_dir:, upload: false) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/rundoc/code_command/website/driver.rb', line 79

def screenshot(screenshots_dir:, upload: false)
  @driver.resize_window_to(@driver.current_window_handle, @width, @height)
  FileUtils.mkdir_p(screenshots_dir)
  file_name = self.class.next_screenshot_name
  file_path = screenshots_dir.join(file_name)
  session.save_screenshot(file_path)
  @io.puts "Screenshot saved to #{file_path}"

  return file_path unless upload

  case upload
  when "s3", "aws"
    @io.puts "Uploading screenshot to S3"
    require "aws-sdk-s3"
    ENV.fetch("AWS_ACCESS_KEY_ID")
    s3 = Aws::S3::Resource.new(region: ENV.fetch("AWS_REGION"))

    key = "#{timestamp}/#{file_name}"
    obj = s3.bucket(ENV.fetch("AWS_BUCKET_NAME")).object(key)
    obj.upload_file(file_path)

    obj.client.put_object_acl(
      acl: "public-read",
      bucket: ENV.fetch("AWS_BUCKET_NAME"),
      key: key
    )

    obj.public_url
  else
    raise "Upload #{upload.inspect} is not valid, use 's3' instead"
  end
end

#scroll(value = 100) ⇒ Object



55
56
57
# File 'lib/rundoc/code_command/website/driver.rb', line 55

def scroll(value = 100)
  session.execute_script "window.scrollBy(0,#{value})"
end

#teardownObject



59
60
61
# File 'lib/rundoc/code_command/website/driver.rb', line 59

def teardown
  session.reset_session!
end

#timestampObject



47
48
49
# File 'lib/rundoc/code_command/website/driver.rb', line 47

def timestamp
  Time.now.utc.strftime("%Y%m%d%H%M%S%L%N")
end

#visit(url, max_attempts: 3, delay: 1) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rundoc/code_command/website/driver.rb', line 31

def visit(url, max_attempts: 3, delay: 1)
  attempts = 0
  begin
    @session.visit(url)
  rescue ::Net::ReadTimeout => e
    attempts += 1
    if attempts > max_attempts
      raise e
    else
      @io.puts "Error visiting url (#{attempts}/#{max_attempts}) `#{url}`:\n#{e}"
      sleep delay
      retry
    end
  end
end