isomorfeus-puppetmaster 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +191 -0
  3. data/lib/isomorfeus-puppetmaster.rb +43 -0
  4. data/lib/isomorfeus/puppetmaster.rb +62 -0
  5. data/lib/isomorfeus/puppetmaster/console_message.rb +19 -0
  6. data/lib/isomorfeus/puppetmaster/cookie.rb +46 -0
  7. data/lib/isomorfeus/puppetmaster/document.rb +160 -0
  8. data/lib/isomorfeus/puppetmaster/driver/jsdom.rb +370 -0
  9. data/lib/isomorfeus/puppetmaster/driver/jsdom_document.rb +908 -0
  10. data/lib/isomorfeus/puppetmaster/driver/jsdom_node.rb +836 -0
  11. data/lib/isomorfeus/puppetmaster/driver/puppeteer.rb +401 -0
  12. data/lib/isomorfeus/puppetmaster/driver/puppeteer_document.rb +944 -0
  13. data/lib/isomorfeus/puppetmaster/driver/puppeteer_node.rb +866 -0
  14. data/lib/isomorfeus/puppetmaster/driver_registration.rb +19 -0
  15. data/lib/isomorfeus/puppetmaster/dsl.rb +40 -0
  16. data/lib/isomorfeus/puppetmaster/errors.rb +90 -0
  17. data/lib/isomorfeus/puppetmaster/iframe.rb +17 -0
  18. data/lib/isomorfeus/puppetmaster/node.rb +241 -0
  19. data/lib/isomorfeus/puppetmaster/node/checkbox.rb +17 -0
  20. data/lib/isomorfeus/puppetmaster/node/content_editable.rb +18 -0
  21. data/lib/isomorfeus/puppetmaster/node/filechooser.rb +9 -0
  22. data/lib/isomorfeus/puppetmaster/node/input.rb +21 -0
  23. data/lib/isomorfeus/puppetmaster/node/radiobutton.rb +13 -0
  24. data/lib/isomorfeus/puppetmaster/node/select.rb +36 -0
  25. data/lib/isomorfeus/puppetmaster/node/textarea.rb +7 -0
  26. data/lib/isomorfeus/puppetmaster/request.rb +17 -0
  27. data/lib/isomorfeus/puppetmaster/response.rb +26 -0
  28. data/lib/isomorfeus/puppetmaster/rspec/features.rb +23 -0
  29. data/lib/isomorfeus/puppetmaster/rspec/matcher_proxies.rb +80 -0
  30. data/lib/isomorfeus/puppetmaster/rspec/matchers.rb +164 -0
  31. data/lib/isomorfeus/puppetmaster/rspec/matchers/base.rb +98 -0
  32. data/lib/isomorfeus/puppetmaster/rspec/matchers/become_closed.rb +33 -0
  33. data/lib/isomorfeus/puppetmaster/rspec/matchers/compound.rb +88 -0
  34. data/lib/isomorfeus/puppetmaster/rspec/matchers/have_current_path.rb +29 -0
  35. data/lib/isomorfeus/puppetmaster/rspec/matchers/have_selector.rb +69 -0
  36. data/lib/isomorfeus/puppetmaster/rspec/matchers/have_text.rb +33 -0
  37. data/lib/isomorfeus/puppetmaster/rspec/matchers/have_title.rb +29 -0
  38. data/lib/isomorfeus/puppetmaster/rspec/matchers/match_selector.rb +27 -0
  39. data/lib/isomorfeus/puppetmaster/rspec/matchers/match_style.rb +38 -0
  40. data/lib/isomorfeus/puppetmaster/self_forwardable.rb +31 -0
  41. data/lib/isomorfeus/puppetmaster/server.rb +128 -0
  42. data/lib/isomorfeus/puppetmaster/server/checker.rb +40 -0
  43. data/lib/isomorfeus/puppetmaster/server/middleware.rb +60 -0
  44. data/lib/isomorfeus/puppetmaster/server_registration.rb +37 -0
  45. data/lib/isomorfeus/puppetmaster/version.rb +3 -0
  46. metadata +282 -0
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capybara
4
+ module RSpecMatchers
5
+ module Matchers
6
+ class BecomeClosed
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def matches?(window)
12
+ @window = window
13
+ @wait_time = Capybara::Queries::BaseQuery.wait(@options, window.session.config.default_max_wait_time)
14
+ timer = Capybara::Helpers.timer(expire_in: @wait_time)
15
+ while window.exists?
16
+ return false if timer.expired?
17
+
18
+ sleep 0.01
19
+ end
20
+ true
21
+ end
22
+
23
+ def failure_message
24
+ "expected #{@window.inspect} to become closed after #{@wait_time} seconds"
25
+ end
26
+
27
+ def failure_message_when_negated
28
+ "expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(::RSpec::Expectations::Version)
4
+ module Capybara
5
+ module RSpecMatchers
6
+ module Matchers
7
+ module Compound
8
+ include ::RSpec::Matchers::Composable
9
+
10
+ def and(matcher)
11
+ And.new(self, matcher)
12
+ end
13
+
14
+ def and_then(matcher)
15
+ ::RSpec::Matchers::BuiltIn::Compound::And.new(self, matcher)
16
+ end
17
+
18
+ def or(matcher)
19
+ Or.new(self, matcher)
20
+ end
21
+
22
+ class CapybaraEvaluator
23
+ def initialize(actual)
24
+ @actual = actual
25
+ @match_results = Hash.new { |hsh, matcher| hsh[matcher] = matcher.matches?(@actual) }
26
+ end
27
+
28
+ def matcher_matches?(matcher)
29
+ @match_results[matcher]
30
+ end
31
+
32
+ def reset
33
+ @match_results.clear
34
+ end
35
+ end
36
+
37
+ # @api private
38
+ module Synchronizer
39
+ def match(_expected, actual)
40
+ @evaluator = CapybaraEvaluator.new(actual)
41
+ syncer = sync_element(actual)
42
+ begin
43
+ syncer.synchronize do
44
+ @evaluator.reset
45
+ raise ::Capybara::ElementNotFound unless synchronized_match?
46
+
47
+ true
48
+ end
49
+ rescue StandardError
50
+ false
51
+ end
52
+ end
53
+
54
+ def sync_element(el)
55
+ if el.respond_to? :synchronize
56
+ el
57
+ elsif el.respond_to? :current_scope
58
+ el.current_scope
59
+ else
60
+ Capybara.string(el)
61
+ end
62
+ end
63
+ end
64
+
65
+ class And < ::RSpec::Matchers::BuiltIn::Compound::And
66
+ include Synchronizer
67
+
68
+ private
69
+
70
+ def synchronized_match?
71
+ [matcher_1_matches?, matcher_2_matches?].all?
72
+ end
73
+ end
74
+
75
+ class Or < ::RSpec::Matchers::BuiltIn::Compound::Or
76
+ include Synchronizer
77
+
78
+ private
79
+
80
+ def synchronized_match?
81
+ [matcher_1_matches?, matcher_2_matches?].any?
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveCurrentPath < WrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_current_path(*@args)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_current_path(*@args)
15
+ end
16
+
17
+ def description
18
+ "have current path #{current_path.inspect}"
19
+ end
20
+
21
+ private
22
+
23
+ def current_path
24
+ @args.first
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveSelector < WrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_selector(*@args, &@filter_block)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_selector(*@args, &@filter_block)
15
+ end
16
+
17
+ def description
18
+ "have #{query.description}"
19
+ end
20
+
21
+ def query
22
+ @query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, &@filter_block)
23
+ end
24
+ end
25
+
26
+ class HaveAllSelectors < WrappedElementMatcher
27
+ def element_matches?(el)
28
+ el.assert_all_of_selectors(*@args, &@filter_block)
29
+ end
30
+
31
+ def does_not_match?(_actual)
32
+ raise ArgumentError, 'The have_all_selectors matcher does not support use with not_to/should_not'
33
+ end
34
+
35
+ def description
36
+ 'have all selectors'
37
+ end
38
+ end
39
+
40
+ class HaveNoSelectors < WrappedElementMatcher
41
+ def element_matches?(el)
42
+ el.assert_none_of_selectors(*@args, &@filter_block)
43
+ end
44
+
45
+ def does_not_match?(_actual)
46
+ raise ArgumentError, 'The have_none_of_selectors matcher does not support use with not_to/should_not'
47
+ end
48
+
49
+ def description
50
+ 'have no selectors'
51
+ end
52
+ end
53
+
54
+ class HaveAnySelectors < WrappedElementMatcher
55
+ def element_matches?(el)
56
+ el.assert_any_of_selectors(*@args, &@filter_block)
57
+ end
58
+
59
+ def does_not_match?(_actual)
60
+ el.assert_none_of_selectors(*@args, &@filter_block)
61
+ end
62
+
63
+ def description
64
+ 'have any selectors'
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveText < WrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_text(*@args)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_text(*@args)
15
+ end
16
+
17
+ def description
18
+ "text #{format(text)}"
19
+ end
20
+
21
+ def format(content)
22
+ content.inspect
23
+ end
24
+
25
+ private
26
+
27
+ def text
28
+ @args[0].is_a?(Symbol) ? @args[1] : @args[0]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveTitle < WrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_title(*@args)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_title(*@args)
15
+ end
16
+
17
+ def description
18
+ "have title #{title.inspect}"
19
+ end
20
+
21
+ private
22
+
23
+ def title
24
+ @args.first
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/have_selector'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class MatchSelector < HaveSelector
9
+ def element_matches?(el)
10
+ el.assert_matches_selector(*@args, &@filter_block)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_not_matches_selector(*@args, &@filter_block)
15
+ end
16
+
17
+ def description
18
+ "match #{query.description}"
19
+ end
20
+
21
+ def query
22
+ @query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class MatchStyle < WrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_matches_style(*@args)
11
+ end
12
+
13
+ def does_not_match?(_actual)
14
+ raise ArgumentError, 'The match_style matcher does not support use with not_to/should_not'
15
+ end
16
+
17
+ def description
18
+ 'match style'
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ module Capybara
26
+ module RSpecMatchers
27
+ module Matchers
28
+ ##
29
+ # @deprecated
30
+ class HaveStyle < MatchStyle
31
+ def initialize(*args, &filter_block)
32
+ warn 'HaveStyle matcher is deprecated, please use the MatchStyle matcher instead'
33
+ super
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ module Isomorfeus
2
+ module Puppetmaster
3
+ module SelfForwardable
4
+ def self.extended(base)
5
+ base.define_singleton_method(:document_forward) do |methods|
6
+ methods.each do |method|
7
+ define_method(method) do |*args, &block|
8
+ @driver.send("document_#{method}", self, *args, &block)
9
+ end
10
+ end
11
+ end
12
+
13
+ base.define_singleton_method(:frame_forward) do |methods|
14
+ methods.each do |method|
15
+ define_method(method) do |*args|
16
+ @driver.send("frame_#{method}", self, *args)
17
+ end
18
+ end
19
+ end
20
+
21
+ base.define_singleton_method(:node_forward) do |methods|
22
+ methods.each do |method|
23
+ define_method(method) do |*args|
24
+ @driver.send("node_#{method}", self, *args)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,128 @@
1
+ module Isomorfeus
2
+ module Puppetmaster
3
+ class Server
4
+ class Timer
5
+ def initialize(expire_in:)
6
+ @start = current
7
+ @expire_in = expire_in
8
+ end
9
+
10
+ def expired?
11
+ raise Isomorfeus::Puppetmaster::FrozenInTime, 'Time appears to be frozen. Puppetmaster does not work with libraries which freeze time, consider using time travelling instead' if stalled?
12
+
13
+ current - @start >= @expire_in
14
+ end
15
+
16
+ def stalled?
17
+ @start == current
18
+ end
19
+
20
+ private
21
+
22
+ if defined?(Process::CLOCK_MONOTONIC)
23
+ def current; Process.clock_gettime Process::CLOCK_MONOTONIC; end
24
+ else
25
+ def current; Time.now.to_f; end
26
+ end
27
+ end
28
+
29
+ class << self
30
+ def ports
31
+ @ports ||= {}
32
+ end
33
+ end
34
+
35
+ attr_reader :app, :port, :host
36
+
37
+ def initialize(app,
38
+ port: Isomorfeus::Puppetmaster.server_port,
39
+ host: Isomorfeus::Puppetmaster.server_host,
40
+ extra_middleware: [])
41
+ @app = app
42
+ @extra_middleware = extra_middleware
43
+ @server_thread = nil # suppress warnings
44
+ @host = host
45
+ @port = port
46
+ @port ||= Isomorfeus::Puppetmaster::Server.ports[port_key]
47
+ @port ||= find_available_port(host)
48
+ @checker = Isomorfeus::Puppetmaster::Server::Checker.new(@host, @port)
49
+ end
50
+
51
+ def reset_error!
52
+ middleware.clear_error
53
+ end
54
+
55
+ def error
56
+ middleware.error
57
+ end
58
+
59
+ def using_ssl?
60
+ @checker.ssl?
61
+ end
62
+
63
+ def scheme
64
+ using_ssl? ? 'https' : 'http'
65
+ end
66
+
67
+ def responsive?
68
+ return false if @server_thread&.join(0)
69
+
70
+ res = @checker.request { |http| http.get('/__identify__') }
71
+
72
+ return res.body == app.object_id.to_s if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
73
+ rescue SystemCallError, Net::ReadTimeout, OpenSSL::SSL::SSLError
74
+ false
75
+ end
76
+
77
+ def wait_for_pending_requests
78
+ timer = Isomorfeus::Puppetmaster::Server::Timer.new(expire_in: 60)
79
+ while pending_requests?
80
+ raise 'Requests did not finish in 60 seconds' if timer.expired?
81
+
82
+ sleep 0.01
83
+ end
84
+ end
85
+
86
+ def boot
87
+ unless responsive?
88
+ Isomorfeus::Puppetmaster::Server.ports[port_key] = port
89
+
90
+ @server_thread = Thread.new do
91
+ Isomorfeus::Puppetmaster.server.call(middleware, port, host)
92
+ end
93
+
94
+ timer = Isomorfeus::Puppetmaster::Server::Timer.new(expire_in: 60)
95
+ until responsive?
96
+ raise 'Rack application timed out during boot' if timer.expired?
97
+
98
+ @server_thread.join(0.1)
99
+ end
100
+ end
101
+
102
+ self
103
+ end
104
+
105
+ private
106
+
107
+ def middleware
108
+ @middleware ||= ::Isomorfeus::Puppetmaster::Server::Middleware.new(app, @extra_middleware)
109
+ end
110
+
111
+ def port_key
112
+ app.object_id
113
+ end
114
+
115
+ def pending_requests?
116
+ middleware.pending_requests?
117
+ end
118
+
119
+ def find_available_port(host)
120
+ server = TCPServer.new(host, 0)
121
+ server.addr[1]
122
+ ensure
123
+ server&.close
124
+ end
125
+ end
126
+ end
127
+ end
128
+