Files
ubicloud/bin/regen_screenshots
Jeremy Evans 2c962c78cf Add screenshots rake task
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.
2024-11-01 12:19:25 -07:00

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