diff --git a/config/ci.rb b/config/ci.rb index bc96a3831..5ded71515 100644 --- a/config/ci.rb +++ b/config/ci.rb @@ -5,12 +5,13 @@ CI.run do step "Style: Ruby", "bin/rubocop" - step "Security: Gem audit", "bin/bundler-audit check --update" - step "Security: Importmap vulnerability audit", "bin/importmap audit" - step "Security: Brakeman code analysis", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error" + step "Security: Gem audit", "bin/bundler-audit check --update" + step "Security: Importmap audit", "bin/importmap audit" + step "Security: Brakeman audit", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error" - step "Tests: Rails", "bin/rails test" - step "Tests: 37id", "bin/rails 37id:test:units" + step "Tests: Rails", "bin/rails test" + step "Tests: 37id", "bin/rails 37id:test:units" + step "Tests: System", "bin/rails test:system" if success? step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff" diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index d7e6bba8a..01bcbabeb 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -1,5 +1,31 @@ require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase - driven_by :selenium, using: :chrome, screen_size: [ 1400, 1400 ] + browser_options = Selenium::WebDriver::Chrome::Options.new.tap do |opts| + opts.add_argument("--window-size=1200,800") + opts.add_argument("--disable-extensions") + # Disable non-foreground tabs from getting a lower process priority + opts.add_argument("--disable-renderer-backgrounding") + # Normally, Chrome will treat a 'foreground' tab instead as backgrounded if the surrounding + # window is occluded (aka visually covered) by another window. This flag disables that. + opts.add_argument("--disable-backgrounding-occluded-windows") + # Suppress all permission prompts by automatically denying them. + opts.add_argument("--deny-permission-prompts") + opts.add_argument("--enable-automation") + end + + Capybara.register_driver :chrome_headless do |app| + browser_options.add_argument("--headless") + Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options) + end + + Capybara.register_driver :chrome do |app| + Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options) + end + + if ENV["SYSTEM_TESTS_BROWSER"] + driven_by :chrome, screen_size: [ 1200, 1000 ] + else + driven_by :chrome_headless, screen_size: [ 1200, 1000 ] + end end diff --git a/test/system/smoke_test.rb b/test/system/smoke_test.rb new file mode 100644 index 000000000..be15df0cc --- /dev/null +++ b/test/system/smoke_test.rb @@ -0,0 +1,67 @@ +require "application_system_test_case" + +class SmokeTest < ApplicationSystemTestCase + test "create a card" do + sign_in_as(users(:david)) + + visit cards_url(collection_ids: [ collections(:writebook).id ]) + click_on "Add a card" + fill_in "card_title", with: "Hello, world!" + fill_in_lexxy with: "I am editing this thing" + click_on "Create card" + + assert_selector "h1", text: "Hello, world!" + end + + test "active storage attachments" do + sign_in_as(users(:david)) + + visit card_url(cards(:layout)) + fill_in_lexxy with: "Here is a comment" + attach_file file_fixture("moon.jpg") do + click_on "Upload file" + end + + assert_image_figure_attachment content_type: "image/jpeg", caption: "moon.jpg" + + click_on "Post this comment" + + assert_image_figure_attachment content_type: "image/jpeg", caption: "moon.jpg" + end + + test "dismissing notifications" do + sign_in_as(users(:david)) + + notif = notifications(:logo_card_david_mention_by_jz) + + assert_selector "div##{dom_id(notif)}" + + within_window(open_new_window) { visit card_url(notif.card) } + + assert_no_selector "div##{dom_id(notif)}" + end + + private + def sign_in_as(user) + visit session_transfer_url(user.transfer_id) + assert_selector "h1", text: "Activity" + end + + def fill_in_lexxy(selector = "lexxy-editor", with:) + editor_element = find(selector) + editor_element.set with + page.execute_script("arguments[0].value = '#{with}'", editor_element) + end + + def assert_figure_attachment(content_type:, &block) + figure = find("figure.attachment[data-content-type='#{content_type}']") + within(figure, &block) if block_given? + end + + def assert_image_figure_attachment(content_type: "image/png", caption:) + assert_figure_attachment(content_type: content_type) do + assert_selector("img[src*='/rails/active_storage']") + assert_selector "figcaption input[placeholder='#{caption}']" + end + end +end