evil_systems 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []