evil_systems 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6c39ae0b47c7d330afb6daa3ef1c8137d190f861905a4a3cdc45305740927ec1
4
+ data.tar.gz: e3c40f2764522b1796d11053aecd530267704d87f0ce6732b7d58374a2c030e9
5
+ SHA512:
6
+ metadata.gz: fed0a5eebfba465c8d2d36228e7b05e6da431a464ee540b34f867c34e64d6263e7cc52d7e9612b679c198514f81ae1fbaff833dc8430600a561e89617ad8a407
7
+ data.tar.gz: 992f7b9646ecf70c5c07c032f40af6422e52785897ef7cc29c56cc45b08f875e684fec1a5a9b90c81687a1a67b660159fb3bde20490f7f8e9d2226aea59101f5
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 0.0.1
2
+
3
+ Initial release!
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 ParamagicDev
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # EvilSystemTests
2
+
3
+ Why does this exist?
4
+
5
+ I wanted a quick, easy, reusable way to use the settings put forth in
6
+ [EvilMartians System of a Test blog post] (https://evilmartians.com/chronicles/system-of-a-test-setting-up-end-to-end-rails-testing)
7
+ for Minitest. System of a test is currently written for RSpec.
8
+
9
+ Full API documentation can be found here:
10
+
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'evil_system_tests'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ ```bash
23
+ bundle
24
+ ```
25
+
26
+ ## Setup
27
+
28
+ ### Minitest
29
+
30
+ Navigate to `test/application_system_test_case.rb` in your Rails app.
31
+
32
+ Setup your file like so:
33
+
34
+ ```rb
35
+ # test/application_system_test_case.rb
36
+
37
+ require 'test_helper'
38
+
39
+ + # 'capybara' and 'capybara/cuprite' need to be defined for EvilSystems to
40
+ work properly.
41
+ + require 'capybara'
42
+ + require 'capybara/cuprite'
43
+
44
+ + require 'evil_systems'
45
+
46
+ + EvilSystems.initial_setup
47
+
48
+ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
49
+ - driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
50
+ + driven_by :cuprite
51
+
52
+ + include EvilSystems::Helpers
53
+ end
54
+ ```
55
+
56
+ ### RSpec
57
+
58
+ *Maybe in the future?*
59
+
60
+ ## Whats included?
61
+
62
+ ## Usage
63
+
64
+ `EvilSystems.initial_setup` takes two keyword arguments, `:task`, and
65
+ `silent`.
66
+
67
+ Both arguments have to do with precompiling assets.
68
+ `:silent` by default is set to `true` and will only tell you when assets
69
+ are compiling, and how long it took.
70
+ `:task` defaults to `assets:precompile`, System of a test uses
71
+ `webpacker:compile`.
72
+
73
+ ### Settings
74
+
75
+ [x] - Automatically registers a `:cuprite` driver if `Capybara::Cuprite`
76
+ is defined.
77
+ [x] - Automatically sets Capybara's default and javascript driver to
78
+ `:cuprite`
79
+ [x] - Automatically sets `Capybara.app_host`
80
+
81
+ <details>
82
+ <summary>How `app_host` is set</summary>
83
+
84
+ `app_host` will first use `ENV["APP_HOST"]` then falls back to the systems
85
+ `hostname` if the `APP_HOST` ENV var is not defined.
86
+ If neither are defined, it will then default to `"0.0.0.0"`
87
+
88
+ </details>
89
+
90
+ [x] - `Capybara.server_host = "0.0.0.0"`
91
+ [x] - `Capybara.default_max_wait_time = 2`
92
+ [x] - `Capybara.default_normalize_ws = true` normalizes whitespace in
93
+ `has_text?` and similar matchers.
94
+ [x] - Sets the `Capybara.save_path` Uses `ENV["CAPYBARA_ARTIFACTS"]` and
95
+ falls back to `"./tmp/capybara"`
96
+ [x] - Sets a `REMOTE_CHROME` instance if a `ENV["CHROME_URL"]` is found
97
+ [x] - Prepends a `last_used_session` attribute accessor to Capybara.
98
+
99
+ ### Helpers
100
+
101
+ `EvilSystems::Helpers`
102
+
103
+ Automatically includes `ActionView::RecordIdentifier` if Rails is
104
+ defined.
105
+
106
+ Also includes:
107
+
108
+ ```rb
109
+ EvilSystems::CupriteHelpers
110
+ EvilSystems::SessionHelpers
111
+ ```
112
+
113
+ #### Regular Helpers
114
+
115
+ ```rb
116
+ # The full path to be prepended to a screen shot
117
+ absolute_image_path
118
+
119
+ # The relative path to be prepended to a screenshot message to make it clickable
120
+ image_path
121
+
122
+ # Make failure screenshots compatible with multi-session setup
123
+ take_screenshot
124
+
125
+ # Prepends a '#' to the +dom_id+ method provided by Rails
126
+ dom_id(*args)
127
+ ```
128
+
129
+ #### SessionHelpers
130
+
131
+ ```rb
132
+ # Small wrapper around Capybara.using_session thats easy to call from an
133
+ instance
134
+ within_session(name_or_session, &block)
135
+
136
+ # Remove all cookie banners
137
+ mark_all_banners_as_read!
138
+ ```
139
+
140
+ #### Cuprite Helpers
141
+
142
+ ```rb
143
+ # pauses the page
144
+ pause
145
+
146
+ # Opens a Pry or IRB repl. Will use Pry if Pry is defined, fallsback
147
+ to debugging with IRB
148
+ debug
149
+ ```
150
+
151
+ ### Env Variables
152
+
153
+ ```rb
154
+ ENV["APP_HOST"] # used for Capybara.app_host
155
+ ENV["CAPYBARA_ARTIFACTS"] # used for Capybara.save_path
156
+ ENV["CHROME_URL"] # used for setting a remote chrome instance for
157
+ Cuprite
158
+ ```
159
+
160
+ ENV variables used by this gem.
161
+
162
+ ## I don't want to use Cuprite.
163
+
164
+ Thats fine! I totally get it. Selenium is battle tested. Simply remove
165
+ the `require "capybara/cuprite"` line and `EvilSystems` will detect that
166
+ Cuprite is not defined and not setup a driver for you and not include
167
+ Cuprite helpers.
168
+
169
+ ## Omissions and differences
170
+
171
+ - Will use `assets:precompile` instead of `webpacker:compile` before
172
+ systems tests (configurable)
173
+
174
+ - Does not set the `Rails.application.default_url_options[:host]` due to
175
+ parallelization issues found while testing the dummy app.
176
+
177
+ ## License
178
+
179
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler/setup"
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require "rake/testtask"
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << "test"
9
+ t.pattern = "test/**/*_test.rb"
10
+ t.verbose = false
11
+ end
12
+
13
+ task default: :test
@@ -0,0 +1,21 @@
1
+ require "zeitwerk"
2
+ loader = Zeitwerk::Loader.for_gem
3
+ loader.setup
4
+
5
+ # EvilMartians like setup for Minitest
6
+ module EvilSystems
7
+ # To be called before module +ApplicationSystemTest+
8
+ # @param task [String, nil] ("assets:precompile") - the precompile task to run
9
+ # @param silent [Boolean] (true) - silence build output and only show asset compilation and time spent compiling.
10
+ # @return void
11
+ # @see Settings#initial_setup
12
+ # @see RegisterCuprite#initial_setup
13
+ # @see PrecompileAssets#initial_setup
14
+ def self.initial_setup(task: "assets:precompile", silent: true)
15
+ Settings.initial_setup
16
+ RegisterCuprite.initial_setup
17
+ PrecompileAssets.initial_setup(task: task, silent: silent)
18
+ end
19
+ end
20
+
21
+ require "evil_systems/engine" if defined?(Rails)
@@ -0,0 +1,22 @@
1
+ # Add shortcuts for cuprite-specific debugging helpers
2
+ module EvilSystems
3
+ module CupriteHelpers
4
+ # Pauses the current driver
5
+ # @return [nil]
6
+ def pause
7
+ page.driver.pause
8
+ end
9
+
10
+ # Opens a debug session via Pry if defined, else uses Irb.
11
+ def debug(binding = nil)
12
+ $stdout.puts "🔎 Open Chrome inspector at http://localhost:3333"
13
+ if binding
14
+ return binding.pry if defined?(Pry)
15
+
16
+ return binding.irb
17
+ end
18
+
19
+ page.driver.pause
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ # require "rails/railtie"
2
+ # Dont think this is needed, perhaps for older rails?
3
+ # Leaving this here in case an issue is reported.
4
+
5
+ module EvilSystems
6
+ class Engine < ::Rails::Engine
7
+ end
8
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilSystems
4
+ # Helpers to make life easier
5
+ module Helpers
6
+ include ActionView::RecordIdentifier if defined? ::Rails
7
+ include CupriteHelpers if defined? ::Capybara::Cuprite
8
+ include SessionHelpers
9
+
10
+ # Use our `Capybara.save_path` to store screenshots with other capybara artifacts
11
+ # (Rails screenshots path is not configurable https://github.com/rails/rails/blob/49baf092439fc74fc3377b12e3334c3dd9d0752f/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L79)
12
+ # @return [String]
13
+ def absolute_image_path
14
+ return ::Rails.root.join("#{::Capybara.save_path}/screenshots/#{image_name}.png") if defined? ::Rails
15
+
16
+ File.join("#{::Capybara.save_path}/screenshots/#{image_name}.png")
17
+ end
18
+
19
+ # Use relative path in screenshot message to make it clickable in VS Code when running in Docker
20
+ # @return [String]
21
+ def image_path
22
+ return absolute_image_path.relative_path_from(::Rails.root).to_s if defined? ::Rails
23
+
24
+ absolute_image_path.relative_path_from(Dir.pwd)
25
+ end
26
+
27
+ # Make failure screenshots compatible with multi-session setup
28
+ # @return void
29
+ def take_screenshot
30
+ return super unless ::Capybara.last_used_session
31
+
32
+ ::Capybara.using_session(::Capybara.last_used_session) { super }
33
+ end
34
+
35
+ # Convert dom_id to a selector.
36
+ # @example
37
+ # dom_id(Facility.first)
38
+ # # => "#facility-1"
39
+ # @return [String]
40
+ def dom_id(*args)
41
+ "##{super}"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilSystems
4
+ module PrecompileAssets
5
+ # Precompile assets before running tests to avoid timeouts.
6
+ # Do not precompile if webpack-dev-server is running (NOTE: MUST be launched with RAILS_ENV=test)
7
+ # @param task [String, nil] ("assets:precompile") - the precompile task to run
8
+ # @param silent [Boolean] (true) - silence build output and only show asset compilation and time spent compiling.
9
+ def self.initial_setup(task: "assets:precompile", silent: true)
10
+ $stdout.puts "\n🐢 Precompiling assets.\n"
11
+ original_stdout = $stdout.clone
12
+ start = Time.current
13
+ begin
14
+ # Silence output
15
+ $stdout.reopen(File.new("/dev/null", "w")) if silent == true
16
+ # next 3 lines to compile assets before running our test suite
17
+ require "rake"
18
+ Rails.application.load_tasks
19
+ Rake::Task[task].invoke if task
20
+ ensure
21
+ $stdout.reopen(original_stdout) if silent == true
22
+ $stdout.puts "Finished in #{(Time.current - start).round(2)} seconds"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilSystems
4
+ # Cuprite is a modern Capybara driver which uses Chrome CDP API
5
+ # instead of Selenium & co.
6
+ # See https://github.com/rubycdp/cuprite
7
+ module RegisterCuprite
8
+ # Registers the Cuprite driver. Can be used via:
9
+ # driven_by :cuprite, using: :chrome, screen_size: [1400, 1400]
10
+ # The initial setup prior to the class ApplicationSystemTestCase, runs before the entire test suite.
11
+ # @return [void]
12
+ def self.initial_setup
13
+ return unless defined? Capybara::Cuprite
14
+
15
+ remote_options = RemoteChrome.options
16
+ ::Capybara.register_driver(:cuprite) do |app|
17
+ ::Capybara::Cuprite::Driver.new(
18
+ app,
19
+ **{
20
+ window_size: [1200, 800],
21
+ browser_options: {"no-sandbox" => nil},
22
+ inspector: true
23
+ }.merge(remote_options)
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ Capybara.default_driver = Capybara.javascript_driver = :cuprite
@@ -0,0 +1,42 @@
1
+ module EvilSystems
2
+ module RemoteChrome
3
+ # @return [String, nil]
4
+ def self.url
5
+ ENV["CHROME_URL"]
6
+ end
7
+
8
+ # Current port
9
+ # @return Integer
10
+ def self.port
11
+ URI.parse(url).yield_self { |uri| uri.port }
12
+ end
13
+
14
+ # Current host
15
+ # @return [String, nil]
16
+ def self.host
17
+ URI.parse(url).yield_self { |uri| uri.host } if url
18
+ end
19
+
20
+ # Returns a hash with a :url key / value if a remote chrome url is found.
21
+ # @return [Hash{:url => String, nil}]
22
+ #
23
+ def self.options
24
+ # Check whether the remote chrome is running and configure the Capybara
25
+ # driver for it.
26
+ remote_chrome ? {url: url} : {}
27
+ end
28
+
29
+ # Whether or not the socket could be connected
30
+ # @return [Boolean]
31
+ def self.remote_chrome
32
+ if url.nil?
33
+ false
34
+ else
35
+ Socket.tcp(host, port, connect_timeout: 1).close
36
+ true
37
+ end
38
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
39
+ false
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ module EvilSystems
2
+ # Capybara Sessions are limited, lets add some extra helpers.
3
+ module SessionHelpers
4
+ # Convencience method for session names.
5
+ def within_session(name_or_session, &block)
6
+ ::Capybara.using_session(name_or_session, &block)
7
+ end
8
+
9
+ # Remove all banners
10
+ def mark_all_banners_as_read!
11
+ page.driver.set_cookie "show_banners", "N"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvilSystems
4
+ # Capybara settings (not covered by Rails system tests)
5
+ module Settings
6
+ # Finds the current app host via ENV["APP_HOST"], `hostname`, or defaults to "0.0.0.0"
7
+ # @return [String]
8
+ def self.app_host
9
+ "http://#{ENV.fetch("APP_HOST", `hostname`&.strip&.downcase || "0.0.0.0")}"
10
+ end
11
+
12
+ # Finds the current cookie domain
13
+ # @return [String]
14
+ def self.cookie_domain
15
+ URI.parse(app_host).host.then do |host|
16
+ # If host is a top-level domain
17
+ next host unless host.include?(".")
18
+
19
+ ".#{host}"
20
+ end
21
+ end
22
+
23
+ # The setup to be run prior to the test suite
24
+ def self.initial_setup
25
+ prepend_session_to_capybara
26
+
27
+ ::Capybara.app_host = app_host
28
+
29
+ # Make server listening on all hosts
30
+ ::Capybara.server_host = "0.0.0.0"
31
+
32
+ # Don't wait too long in `have_xyz` matchers
33
+ ::Capybara.default_max_wait_time = 2
34
+
35
+ # Normalizes whitespaces when using `has_text?` and similar matchers
36
+ ::Capybara.default_normalize_ws = true
37
+
38
+ # Where to store artifacts (e.g. screenshots, downloaded files, etc.)
39
+ ::Capybara.save_path = ENV.fetch("CAPYBARA_ARTIFACTS", "./tmp/capybara")
40
+ end
41
+
42
+ private_class_method def self.prepend_session_to_capybara
43
+ ::Capybara.singleton_class.prepend(Module.new do
44
+ attr_accessor :last_used_session
45
+
46
+ def using_session(name, &block)
47
+ self.last_used_session = name
48
+ super
49
+ ensure
50
+ self.last_used_session = nil
51
+ end
52
+ end)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module EvilSystems
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evil_systems
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - ParamagicDev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: zeitwerk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: capybara
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: standardrb
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ description:
56
+ email:
57
+ - konnor5456@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - CHANGELOG.md
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - lib/evil_systems.rb
67
+ - lib/evil_systems/cuprite_helpers.rb
68
+ - lib/evil_systems/engine.rb
69
+ - lib/evil_systems/helpers.rb
70
+ - lib/evil_systems/precompile_assets.rb
71
+ - lib/evil_systems/register_cuprite.rb
72
+ - lib/evil_systems/remote_chrome.rb
73
+ - lib/evil_systems/session_helpers.rb
74
+ - lib/evil_systems/settings.rb
75
+ - lib/evil_systems/version.rb
76
+ homepage: https://github.com/paramagicdev/evil_systems
77
+ licenses:
78
+ - MIT
79
+ metadata:
80
+ homepage_uri: https://github.com/paramagicdev/evil_systems
81
+ source_code_uri: https://github.com/paramagicdev/evil_systems
82
+ changelog_uri: https://github.com/paramagicdev/evil_systems/CHANGELOG.md
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubygems_version: 3.1.4
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Fully integrated setup based on EvilMartians system of a test
102
+ test_files: []