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.



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

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.



66
67
68
# File 'lib/rundoc/code_command/website/driver.rb', line 66

def tasks
  @tasks
end

Instance Attribute Details

#sessionObject (readonly)

Returns the value of attribute session.



9
10
11
# File 'lib/rundoc/code_command/website/driver.rb', line 9

def session
  @session
end

Class Method Details

.add(name, value) ⇒ Object



115
116
117
118
# File 'lib/rundoc/code_command/website/driver.rb', line 115

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



120
121
122
123
# File 'lib/rundoc/code_command/website/driver.rb', line 120

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



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

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

Instance Method Details

#current_urlObject



53
54
55
# File 'lib/rundoc/code_command/website/driver.rb', line 53

def current_url
  session.current_url
end

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



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

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



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
111
112
# File 'lib/rundoc/code_command/website/driver.rb', line 81

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



57
58
59
# File 'lib/rundoc/code_command/website/driver.rb', line 57

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

#teardownObject



61
62
63
# File 'lib/rundoc/code_command/website/driver.rb', line 61

def teardown
  session.reset_session!
end

#timestampObject



49
50
51
# File 'lib/rundoc/code_command/website/driver.rb', line 49

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

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



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

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