From 9186ff92117a3118bdbb9382c89867d869f0eac7 Mon Sep 17 00:00:00 2001 From: solebared Date: Fri, 28 Jul 2023 16:03:42 -0400 Subject: [PATCH 01/10] Begin system spec harness --- backend/Gemfile | 2 ++ backend/Gemfile.lock | 23 +++++++++++++++++++ backend/spec/system/signup_spec.rb | 8 +++++++ .../spec/system/support/capybara_config.rb | 13 +++++++++++ backend/spec/system/support/cuprite_config.rb | 22 ++++++++++++++++++ backend/spec/system_spec_helper.rb | 12 ++++++++++ 6 files changed, 80 insertions(+) create mode 100644 backend/spec/system/signup_spec.rb create mode 100644 backend/spec/system/support/capybara_config.rb create mode 100644 backend/spec/system/support/cuprite_config.rb create mode 100644 backend/spec/system_spec_helper.rb diff --git a/backend/Gemfile b/backend/Gemfile index cf488880..9886d03f 100644 --- a/backend/Gemfile +++ b/backend/Gemfile @@ -90,6 +90,8 @@ group :development do end group :test do + gem "capybara" + gem "cuprite" gem "mongoid-rspec" gem "shoulda-matchers" gem "vcr" diff --git a/backend/Gemfile.lock b/backend/Gemfile.lock index 77230109..1508a9f8 100644 --- a/backend/Gemfile.lock +++ b/backend/Gemfile.lock @@ -97,6 +97,15 @@ GEM cancancan (3.3.0) cancancan-mongoid (2.0.0) cancancan (>= 2.0, < 4) + capybara (3.39.2) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) coderay (1.1.3) coercible (1.0.0) descendants_tracker (~> 0.0.1) @@ -109,6 +118,9 @@ GEM crack (0.4.5) rexml crass (1.0.6) + cuprite (0.14.3) + capybara (~> 3.0) + ferrum (~> 0.13.0) database_cleaner (2.0.2) database_cleaner-active_record (>= 2, < 3) database_cleaner-active_record (2.1.0) @@ -170,6 +182,11 @@ GEM faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) faraday-rack (1.0.0) + ferrum (0.13) + addressable (~> 2.5) + concurrent-ruby (~> 1.1) + webrick (~> 1.7) + websocket-driver (>= 0.6, < 0.8) ffaker (2.21.0) ffi (1.15.5-java) forecast_io (2.0.2) @@ -213,6 +230,7 @@ GEM net-pop net-smtp marcel (1.0.2) + matrix (0.4.2) method_source (1.0.0) mini_mime (1.1.2) mini_portile2 (2.8.4) @@ -446,11 +464,14 @@ GEM addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) + webrick (1.8.1) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-driver (0.7.6-java) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) yard (0.9.34) zeitwerk (2.6.9) @@ -471,8 +492,10 @@ DEPENDENCIES byebug cancancan (~> 3.3.0) cancancan-mongoid (= 2.0.0) + capybara colored (~> 1.2) countries + cuprite database_cleaner database_cleaner-mongoid devise (= 4.8.0) diff --git a/backend/spec/system/signup_spec.rb b/backend/spec/system/signup_spec.rb new file mode 100644 index 00000000..59263f13 --- /dev/null +++ b/backend/spec/system/signup_spec.rb @@ -0,0 +1,8 @@ +require "system_spec_helper" + +RSpec.describe "signup flow" do + pending "works" do + visit "/" + expect(page.title).to eq "not this" + end +end diff --git a/backend/spec/system/support/capybara_config.rb b/backend/spec/system/support/capybara_config.rb new file mode 100644 index 00000000..7c7550c2 --- /dev/null +++ b/backend/spec/system/support/capybara_config.rb @@ -0,0 +1,13 @@ +# Usually, especially when using Selenium, developers tend to increase the max wait time. +# With Cuprite, there is no need for that. +# We use a Capybara default value here explicitly. +Capybara.default_max_wait_time = 2 + +# Normalize whitespaces when using `has_text?` and similar matchers, +# i.e., ignore newlines, trailing spaces, etc. +# That makes tests less dependent on slightly UI changes. +Capybara.default_normalize_ws = true + +# Where to store system tests artifacts (e.g. screenshots, downloaded files, etc.). +# It could be useful to be able to configure this path from the outside (e.g., on CI). +Capybara.save_path = ENV.fetch("CAPYBARA_ARTIFACTS", "./tmp/capybara") diff --git a/backend/spec/system/support/cuprite_config.rb b/backend/spec/system/support/cuprite_config.rb new file mode 100644 index 00000000..be2c5ea5 --- /dev/null +++ b/backend/spec/system/support/cuprite_config.rb @@ -0,0 +1,22 @@ +# First, load Cuprite Capybara integration +require "capybara/cuprite" + +# Then, we need to register our driver to be able to use it later +# with #driven_by method. +# NOTE: The name :cuprite is already registered by Rails. +# See https://github.com/rubycdp/cuprite/issues/180 +Capybara.register_driver(:better_cuprite) do |app| + Capybara::Cuprite::Driver.new( + app, + **{ # TODO: just inline? + window_size: [1200, 800], + browser_options: {}, + process_timeout: 10, + inspector: true, + headless: ENV["HEADLESS_CHROME"] != "false" + } + ) +end + +# Configure Capybara to use :better_cuprite driver by default +Capybara.default_driver = Capybara.javascript_driver = :better_cuprite diff --git a/backend/spec/system_spec_helper.rb b/backend/spec/system_spec_helper.rb new file mode 100644 index 00000000..cedeb491 --- /dev/null +++ b/backend/spec/system_spec_helper.rb @@ -0,0 +1,12 @@ +require "rails_helper" + +# Most of the system spec config was borrowed, with many thanks, from: +# https://evilmartians.com/chronicles/system-of-a-test-setting-up-end-to-end-rails-testing +require "system/support/capybara_config" +require "system/support/cuprite_config" + +RSpec.configure do |config| + config.prepend_before(:each, type: :system) do + driven_by Capybara.javascript_driver + end +end From 942dcdd381f76a0d150489d099da698531808f24 Mon Sep 17 00:00:00 2001 From: solebared Date: Sat, 29 Jul 2023 03:15:44 -0400 Subject: [PATCH 02/10] Wire up frontend to backend for system specs --- backend/env-example | 7 ++ backend/lib/tasks/spec.rake | 17 +++++ backend/spec/system/signup_spec.rb | 4 +- .../spec/system/support/capybara_config.rb | 6 ++ backend/spec/system/support/cuprite_config.rb | 12 ++- backend/spec/system/support/frontend_app.rb | 74 +++++++++++++++++++ backend/spec/system_spec_helper.rb | 11 ++- 7 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 backend/lib/tasks/spec.rake create mode 100644 backend/spec/system/support/frontend_app.rb diff --git a/backend/env-example b/backend/env-example index 96ab4a4b..dce94c15 100644 --- a/backend/env-example +++ b/backend/env-example @@ -55,3 +55,10 @@ FULLSTORY_ORG= # MongoDB MONGODB_HOST=localhost + +# System spec server ports +SYSTEM_SPEC_BACKEND_PORT=3003 +SYSTEM_SPEC_FRONTEND_PORT=4303 + +# Run system specs with a headless chrome instance +HEADLESS_CHROME=true diff --git a/backend/lib/tasks/spec.rake b/backend/lib/tasks/spec.rake new file mode 100644 index 00000000..2f93b347 --- /dev/null +++ b/backend/lib/tasks/spec.rake @@ -0,0 +1,17 @@ +require_relative "../../spec/system/support/frontend_app" + +namespace :spec do + namespace :system do + task :start_frontend do + frontend_app = SystemSpec::FrontendApp.instance + frontend_app.start $stdout + + trap "INT" do + frontend_app.stop + exit 1 + end + + frontend_app.wait_on + end + end +end diff --git a/backend/spec/system/signup_spec.rb b/backend/spec/system/signup_spec.rb index 59263f13..2829e661 100644 --- a/backend/spec/system/signup_spec.rb +++ b/backend/spec/system/signup_spec.rb @@ -1,8 +1,8 @@ require "system_spec_helper" RSpec.describe "signup flow" do - pending "works" do + it "loads the root page" do visit "/" - expect(page.title).to eq "not this" + expect(page.title).to eq "Flaredown" end end diff --git a/backend/spec/system/support/capybara_config.rb b/backend/spec/system/support/capybara_config.rb index 7c7550c2..7fb69242 100644 --- a/backend/spec/system/support/capybara_config.rb +++ b/backend/spec/system/support/capybara_config.rb @@ -11,3 +11,9 @@ # Where to store system tests artifacts (e.g. screenshots, downloaded files, etc.). # It could be useful to be able to configure this path from the outside (e.g., on CI). Capybara.save_path = ENV.fetch("CAPYBARA_ARTIFACTS", "./tmp/capybara") + +# Port on which to fire up the rails backend. +Capybara.server_port = ENV["SYSTEM_SPEC_BACKEND_PORT"] + +# Where to find frontend app; see ./frontend_app.rb +Capybara.app_host = "http://localhost:#{ENV['SYSTEM_SPEC_FRONTEND_PORT']}" diff --git a/backend/spec/system/support/cuprite_config.rb b/backend/spec/system/support/cuprite_config.rb index be2c5ea5..32d96a8e 100644 --- a/backend/spec/system/support/cuprite_config.rb +++ b/backend/spec/system/support/cuprite_config.rb @@ -8,13 +8,11 @@ Capybara.register_driver(:better_cuprite) do |app| Capybara::Cuprite::Driver.new( app, - **{ # TODO: just inline? - window_size: [1200, 800], - browser_options: {}, - process_timeout: 10, - inspector: true, - headless: ENV["HEADLESS_CHROME"] != "false" - } + window_size: [1200, 800], + browser_options: {}, + process_timeout: 10, + inspector: true, + headless: ENV["HEADLESS_CHROME"] != "false" ) end diff --git a/backend/spec/system/support/frontend_app.rb b/backend/spec/system/support/frontend_app.rb new file mode 100644 index 00000000..d2476685 --- /dev/null +++ b/backend/spec/system/support/frontend_app.rb @@ -0,0 +1,74 @@ +module SystemSpec + class FrontendApp + include Singleton + + def start(log = "/dev/null") + if test_connection_to_frontend_app + puts "Frontend app already running at #{frontend_app_url}" + return + end + + puts "Starting frontend app at #{frontend_app_url}" + @pid ||= Process.spawn( + frontend_app_cmd, + [:out, :err] => log, + chdir: "../frontend" + ) + + timeout = 15.seconds + unless test_connection_to_frontend_app(timeout) + fail "Frontend app did not start within #{timeout} seconds" + end + end + + def wait_on + return unless @pid + Process.wait @pid + end + + def stop + return unless @pid + Process.kill "QUIT", @pid + Process.wait @pid + end + + private + + def test_connection_to_frontend_app(timeout = 0) + system( + test_connection_cmd(timeout), + out: "/dev/null" + ) + end + + def test_connection_cmd(timeout) + [ + "curl --silent --head -X GET", + "--retry-connrefused", + "--retry", timeout.to_s, + "--retry-delay", "1", + frontend_app_url + ].join(" ") + end + + def frontend_app_cmd + [ + "./node_modules/.bin/ember", "serve", + "--port", frontend_port, + "--proxy", "http://localhost:#{backend_port}" + ].join(" ") + end + + def frontend_app_url + "http://localhost:#{frontend_port}" + end + + def frontend_port + ENV["SYSTEM_SPEC_FRONTEND_PORT"] + end + + def backend_port + ENV["SYSTEM_SPEC_BACKEND_PORT"] + end + end +end diff --git a/backend/spec/system_spec_helper.rb b/backend/spec/system_spec_helper.rb index cedeb491..93c0e4bf 100644 --- a/backend/spec/system_spec_helper.rb +++ b/backend/spec/system_spec_helper.rb @@ -2,11 +2,20 @@ # Most of the system spec config was borrowed, with many thanks, from: # https://evilmartians.com/chronicles/system-of-a-test-setting-up-end-to-end-rails-testing +require "system/support/frontend_app" require "system/support/capybara_config" require "system/support/cuprite_config" RSpec.configure do |config| - config.prepend_before(:each, type: :system) do + config.prepend_before(:each, type: :system) do driven_by Capybara.javascript_driver end + + config.before(:suite) do + SystemSpec::FrontendApp.instance.start + end + + config.after(:suite) do + SystemSpec::FrontendApp.instance.stop + end end From 03aa5a20a1b88e957a58034c979f029eb2068e8a Mon Sep 17 00:00:00 2001 From: solebared Date: Sat, 29 Jul 2023 10:52:33 -0400 Subject: [PATCH 03/10] Linting fixes --- backend/spec/system/support/capybara_config.rb | 2 +- backend/spec/system/support/cuprite_config.rb | 6 +++--- backend/spec/system/support/frontend_app.rb | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/spec/system/support/capybara_config.rb b/backend/spec/system/support/capybara_config.rb index 7fb69242..00a417bc 100644 --- a/backend/spec/system/support/capybara_config.rb +++ b/backend/spec/system/support/capybara_config.rb @@ -16,4 +16,4 @@ Capybara.server_port = ENV["SYSTEM_SPEC_BACKEND_PORT"] # Where to find frontend app; see ./frontend_app.rb -Capybara.app_host = "http://localhost:#{ENV['SYSTEM_SPEC_FRONTEND_PORT']}" +Capybara.app_host = "http://localhost:#{ENV["SYSTEM_SPEC_FRONTEND_PORT"]}" diff --git a/backend/spec/system/support/cuprite_config.rb b/backend/spec/system/support/cuprite_config.rb index 32d96a8e..3f4e5e03 100644 --- a/backend/spec/system/support/cuprite_config.rb +++ b/backend/spec/system/support/cuprite_config.rb @@ -8,11 +8,11 @@ Capybara.register_driver(:better_cuprite) do |app| Capybara::Cuprite::Driver.new( app, - window_size: [1200, 800], + window_size: [1200, 800], browser_options: {}, process_timeout: 10, - inspector: true, - headless: ENV["HEADLESS_CHROME"] != "false" + inspector: true, + headless: ENV["HEADLESS_CHROME"] != "false" ) end diff --git a/backend/spec/system/support/frontend_app.rb b/backend/spec/system/support/frontend_app.rb index d2476685..b1a5342a 100644 --- a/backend/spec/system/support/frontend_app.rb +++ b/backend/spec/system/support/frontend_app.rb @@ -12,7 +12,7 @@ def start(log = "/dev/null") @pid ||= Process.spawn( frontend_app_cmd, [:out, :err] => log, - chdir: "../frontend" + :chdir => "../frontend" ) timeout = 15.seconds @@ -32,10 +32,10 @@ def stop Process.wait @pid end - private + private def test_connection_to_frontend_app(timeout = 0) - system( + system( test_connection_cmd(timeout), out: "/dev/null" ) From 18f335dd81081c60c5716882d24d0274fffd8294 Mon Sep 17 00:00:00 2001 From: John Paul Ashenfelter Date: Sat, 29 Jul 2023 11:11:19 -0400 Subject: [PATCH 04/10] Add node --- .github/workflows/backend.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 8e21138f..c6777dd4 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -90,6 +90,7 @@ jobs: POSTGRES_PORT: 5432 INTERCOM_SECRET: secret BASE_URL: test.com + NODE_VERSION: 12.22.6 services: redis: @@ -111,6 +112,16 @@ jobs: steps: - uses: actions/checkout@v2.3.4 + - uses: actions/setup-node@v2 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + cache-dependency-path: frontend/package-lock.json + + - name: Setup node + run: | + npm install -g npm@7.0.0 + npm install - name: Install PostgreSQL client run: | From 4c683a9bc99d35a9709fd017f811be6cc52033c1 Mon Sep 17 00:00:00 2001 From: John Paul Ashenfelter Date: Sat, 29 Jul 2023 11:22:26 -0400 Subject: [PATCH 05/10] DEBUGGING: add some stuff --- backend/spec/system/support/frontend_app.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/spec/system/support/frontend_app.rb b/backend/spec/system/support/frontend_app.rb index b1a5342a..9d782000 100644 --- a/backend/spec/system/support/frontend_app.rb +++ b/backend/spec/system/support/frontend_app.rb @@ -9,6 +9,8 @@ def start(log = "/dev/null") end puts "Starting frontend app at #{frontend_app_url}" + puts "PWD: #{pwd}" + puts `ls` @pid ||= Process.spawn( frontend_app_cmd, [:out, :err] => log, From 0b33cdbf08419d770b5bdd5ce03c7f4dff9b21d7 Mon Sep 17 00:00:00 2001 From: John Paul Ashenfelter Date: Sat, 29 Jul 2023 11:25:58 -0400 Subject: [PATCH 06/10] duh --- backend/spec/system/support/frontend_app.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/spec/system/support/frontend_app.rb b/backend/spec/system/support/frontend_app.rb index 9d782000..0c0ecced 100644 --- a/backend/spec/system/support/frontend_app.rb +++ b/backend/spec/system/support/frontend_app.rb @@ -9,7 +9,7 @@ def start(log = "/dev/null") end puts "Starting frontend app at #{frontend_app_url}" - puts "PWD: #{pwd}" + puts `pwd` puts `ls` @pid ||= Process.spawn( frontend_app_cmd, From 50e71ab09cf84e42ec42d1e5e9cfdd745b8fdb41 Mon Sep 17 00:00:00 2001 From: John Paul Ashenfelter Date: Sat, 29 Jul 2023 11:29:57 -0400 Subject: [PATCH 07/10] morh debug --- backend/spec/system/support/frontend_app.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/spec/system/support/frontend_app.rb b/backend/spec/system/support/frontend_app.rb index 0c0ecced..ba2e6d87 100644 --- a/backend/spec/system/support/frontend_app.rb +++ b/backend/spec/system/support/frontend_app.rb @@ -10,7 +10,10 @@ def start(log = "/dev/null") puts "Starting frontend app at #{frontend_app_url}" puts `pwd` - puts `ls` + puts "ls .." + puts `ls ..` + puts "ls ../.." + puts `ls ../..` @pid ||= Process.spawn( frontend_app_cmd, [:out, :err] => log, From a5692f100c568a9ae571265e4ab2d84d0fc4fdcb Mon Sep 17 00:00:00 2001 From: John Paul Ashenfelter Date: Sat, 29 Jul 2023 11:42:17 -0400 Subject: [PATCH 08/10] More tries --- .github/workflows/backend.yml | 1 + backend/spec/system/support/frontend_app.rb | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index c6777dd4..84a43999 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -121,6 +121,7 @@ jobs: - name: Setup node run: | npm install -g npm@7.0.0 + working-directory: ./frontend npm install - name: Install PostgreSQL client diff --git a/backend/spec/system/support/frontend_app.rb b/backend/spec/system/support/frontend_app.rb index ba2e6d87..3d71431d 100644 --- a/backend/spec/system/support/frontend_app.rb +++ b/backend/spec/system/support/frontend_app.rb @@ -12,8 +12,8 @@ def start(log = "/dev/null") puts `pwd` puts "ls .." puts `ls ..` - puts "ls ../.." - puts `ls ../..` + puts "ls ../frontend" + puts `ls ../frontend` @pid ||= Process.spawn( frontend_app_cmd, [:out, :err] => log, From 0246ac534f33448ba290807638b8f28e288187c9 Mon Sep 17 00:00:00 2001 From: John Paul Ashenfelter Date: Sat, 29 Jul 2023 11:46:27 -0400 Subject: [PATCH 09/10] Fix nesting --- .github/workflows/backend.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 84a43999..98df1c0f 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -119,10 +119,9 @@ jobs: cache-dependency-path: frontend/package-lock.json - name: Setup node - run: | - npm install -g npm@7.0.0 - working-directory: ./frontend - npm install + run: npm install -g npm@7.0.0 + working-directory: ./frontend + - run: npm run test - name: Install PostgreSQL client run: | From 8d2f309e4816474a96002fa533af5f8768359cb2 Mon Sep 17 00:00:00 2001 From: John Paul Ashenfelter Date: Sat, 29 Jul 2023 11:48:14 -0400 Subject: [PATCH 10/10] ARGH --- .github/workflows/backend.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 98df1c0f..69621d00 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -121,7 +121,7 @@ jobs: - name: Setup node run: npm install -g npm@7.0.0 working-directory: ./frontend - - run: npm run test + - run: npm install - name: Install PostgreSQL client run: |