This task runs bin/regen_screenshots, which automates the generation of screenshots used on the documentation site. The screenshot generation code is similar to the route testing code, but instead of using rack-test as the capybara driver, cuprite is used. Cuprite is a capybara driver that uses the ferrum Ruby library to automate Chrome using the Chrome DevTools Protocol, which is substantially more reliable than Selenium/WebDriver/ChromeDriver. Using an actual browser (Chrome) for the screenshot generation code requires using an actual server to handle the brower's requests. So this starts Puma as a separate thread in the screenshot generation process. To avoid permanent database modification, this uses a transaction around the screenshot generation code. As the server runs in a separate thread than the screenshot generation code, this uses the Sequel temporarily_release_connection extension to share a single connection between server and the main thread, so the main thread can open the transaction, all server actions use the same connection inside the transaction, and the main thread can rollback the transaction after generating all screenshots. For this to work correctly, it requires PR #7 in the documentation repository be merged, to rename the screenshot png files. The screenshots generated by this program have significant advantages over the existing screenshots: * Consistency: Uses "Demo" as the user, instead of different users depending on who generated the screenshot. It also consistently shows the layout (the layout was omitted in some existing screenshots), and shows the same options in the layout (existing screenshots showed Billing, Access Policy, or both). * Accuracy: Shows current layout, and makes it easy to stay up to date with layout changes. The existing screenshots have the following issues: * Show Provider in the title bar * Show different layout for the PostgreSQL page when no databases have been created. * Quickstart screenshot shows no existing accounts (how it will look for new users), unlike existing screenshot, which shows an existing account. * Show Full Page: Each screenshot shows the enter page, instead of cropping it. This makes the image larger, but should make it more pleasing to the user.
214 lines
5.8 KiB
Ruby
214 lines
5.8 KiB
Ruby
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
DOCUMENTATION_DIR = "../documentation/"
|
|
|
|
unless File.directory?(DOCUMENTATION_DIR)
|
|
warn "Documentation site must be checked out in ../documentation"
|
|
exit(1)
|
|
end
|
|
|
|
require "find"
|
|
require "capybara"
|
|
require "capybara/dsl"
|
|
require "capybara/cuprite"
|
|
require "puma/cli"
|
|
require "nio"
|
|
require "securerandom"
|
|
|
|
ENV["RACK_ENV"] = "test"
|
|
|
|
# Enable shared connections for Sequel DB, to allow server and screenshot code to share the same transaction
|
|
ENV["SHARED_CONNECTION"] = "1"
|
|
|
|
# Set fake stripe secret key in order to take screenshots of billing pages
|
|
ENV["STRIPE_SECRET_KEY"] = "1"
|
|
|
|
# Set fake GitHub app name in order to take screenshots of GitHub Runner pages
|
|
ENV["GITHUB_APP_NAME"] = "1"
|
|
|
|
require_relative "../loader"
|
|
|
|
PORT = 8383
|
|
db_name = DB.get { current_database.function }
|
|
raise "Doesn't look like a test database (#{db_name}), not generating screenshots" unless db_name.end_with?("test")
|
|
|
|
Capybara.exact = true
|
|
Capybara.default_selector = :css
|
|
Capybara.default_driver = :cuprite
|
|
Capybara.server_port = PORT
|
|
Capybara.register_driver(:cuprite) do |app|
|
|
Capybara::Cuprite::Driver.new(app, window_size: [1200, 800], browser_options: {timeout: 15}, base_url: "http://localhost:#{PORT}")
|
|
end
|
|
|
|
require "tilt/erubi"
|
|
require "tilt/string"
|
|
|
|
queue = Queue.new
|
|
server = Puma::CLI.new(["-s", "-e", "test", "-b", "tcp://localhost:#{PORT}", "-t", "1:1", "config.ru"])
|
|
server.launcher.events.on_booted { queue.push(nil) }
|
|
Thread.new do
|
|
server.launcher.run
|
|
end
|
|
queue.pop
|
|
|
|
::Mail.defaults do
|
|
delivery_method :test
|
|
end
|
|
|
|
class RegenScreenshots
|
|
include Capybara::DSL
|
|
|
|
SCREENSHOTS = {}
|
|
Find.find(DOCUMENTATION_DIR) do |file|
|
|
if File.file?(file) && file.end_with?("screenshot.png")
|
|
SCREENSHOTS[file.delete_prefix(DOCUMENTATION_DIR)] = file
|
|
end
|
|
end
|
|
|
|
def screenshot(filename)
|
|
unless (path = SCREENSHOTS.delete(filename))
|
|
raise "No existing screenshot for #{filename} in documentation site"
|
|
end
|
|
|
|
# rubocop:disable Lint/Debugger
|
|
save_screenshot(path:)
|
|
# rubocop:enable Lint/Debugger
|
|
|
|
puts "Saved screenshot: #{filename}"
|
|
end
|
|
|
|
def resize(height)
|
|
Capybara.current_session.driver.browser.resize(width: 1200, height:)
|
|
end
|
|
|
|
def call
|
|
visit "/"
|
|
click_link "Create a new account"
|
|
|
|
password = SecureRandom.base64(48)
|
|
fill_in "Full Name", with: "Demo"
|
|
fill_in "Email Address", with: "demo@example.com"
|
|
fill_in "Password", with: password
|
|
fill_in "Password Confirmation", with: password
|
|
click_button "Create Account"
|
|
|
|
mail = Mail::TestMailer.deliveries.shift
|
|
body = mail.parts[1].decoded
|
|
unless (match = %r{(/verify-account\?key=[^"]+)"}.match(body))
|
|
raise "no verify link in email"
|
|
end
|
|
visit match[1]
|
|
|
|
click_button "Verify Account"
|
|
|
|
visit "/"
|
|
screenshot "quickstart/managed-services-1-screenshot.png"
|
|
|
|
find("#billing-icon").hover
|
|
screenshot "github-actions-integration/quickstart-1-screenshot.png"
|
|
|
|
Project.define_method(:has_valid_payment_method?) { true }
|
|
click_link "GitHub Runners"
|
|
screenshot "github-actions-integration/quickstart-2-screenshot.png"
|
|
|
|
resize(650)
|
|
click_link "PostgreSQL"
|
|
screenshot "managed-postgresql/overview-1-screenshot.png"
|
|
|
|
resize(1400)
|
|
click_link "Create PostgreSQL Database"
|
|
screenshot "quickstart/using-kamal-with-ubicloud-3-screenshot.png"
|
|
|
|
project = Project.first
|
|
pg_resource = PostgresResource.create_with_id(
|
|
name: "postgresql-demo",
|
|
location: "hetzner-fsn1",
|
|
target_vm_size: "standard-2",
|
|
target_storage_size_gib: 10,
|
|
superuser_password: "1",
|
|
project_id: project.id
|
|
)
|
|
Project.define_method(:postgres_resources_dataset) do |*a|
|
|
super(*a).with_extend do
|
|
define_method(:all) { [pg_resource] }
|
|
define_method(:first) { pg_resource }
|
|
end
|
|
end
|
|
PostgresResource.define_method(:display_state) { "running" }
|
|
Authorization.define_singleton_method(:authorize) { |*| }
|
|
|
|
resize(800)
|
|
click_link "PostgreSQL"
|
|
click_link "postgresql-demo"
|
|
screenshot "managed-postgresql/overview-2-screenshot.png"
|
|
|
|
resize(1800)
|
|
click_link "Compute"
|
|
click_link "New Virtual Machine"
|
|
screenshot "quickstart/managed-services-2-screenshot.png"
|
|
|
|
click_link "Networking"
|
|
click_link "Load Balancers"
|
|
|
|
resize(1200)
|
|
private_subnet = PrivateSubnet.create_with_id(
|
|
net6: "fe80::/16",
|
|
net4: "10.0.0.0/8",
|
|
state: "available",
|
|
name: "blog-app1-subnet",
|
|
location: "hetzner-fsn1"
|
|
)
|
|
Project.define_method(:private_subnets_dataset) do |*a|
|
|
super(*a).with_extend do
|
|
define_method(:all) { [private_subnet] }
|
|
define_method(:first) { private_subnet }
|
|
end
|
|
end
|
|
|
|
click_link "New Load Balancer"
|
|
|
|
fill_in "Name", with: "my-blog"
|
|
select "blog-app1-subnet"
|
|
fill_in "Load Balancer Port", with: "443"
|
|
fill_in "Application Port", with: "443"
|
|
fill_in "HTTP Health Check Endpoint", with: "/up"
|
|
select "HTTPS"
|
|
screenshot "quickstart/using-kamal-with-ubicloud-1-screenshot.png"
|
|
|
|
vms = Array.new(2) do |i|
|
|
Vm.create_with_id(
|
|
name: "blog-app#{i + 1}",
|
|
unix_user: "a",
|
|
public_key: "a",
|
|
location: "hetzner-fsn1",
|
|
boot_image: "a",
|
|
family: "a",
|
|
cores: 2
|
|
)
|
|
end
|
|
PrivateSubnet.define_method(:vms_dataset) do |*a|
|
|
super(*a).with_extend do
|
|
define_method(:all) { vms }
|
|
end
|
|
end
|
|
Authorization.define_singleton_method(:has_permission?) { |*| true }
|
|
|
|
resize(1100)
|
|
click_button "Create"
|
|
find("#vm_id").click
|
|
screenshot "quickstart/using-kamal-with-ubicloud-2-screenshot.png"
|
|
end
|
|
end
|
|
|
|
DB.transaction(rollback: :always, auto_savepoint: true) do |conn|
|
|
DB.temporarily_release_connection(conn) do
|
|
RegenScreenshots.new.call
|
|
end
|
|
end
|
|
|
|
unless RegenScreenshots::SCREENSHOTS.empty?
|
|
warn "Missing screenshots:", RegenScreenshots::SCREENSHOTS.keys.sort
|
|
exit(1)
|
|
end
|