with_clues 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e8a1a2ede55c2de31c9a7a7e53a576b4a52dd08001b87a9406e8b9a16fa5495
4
- data.tar.gz: 7e75e12ebe1d192c74813521f4800d2e70dd2641e1c8e70f5cda563fea700100
3
+ metadata.gz: 270e2b6f2af29d8d7871cba1103db16ec84efd97380acb4592b094729adfb994
4
+ data.tar.gz: 22de0039993571e0a491cbe9ec5d1b53021d184793d99bfc47ffb34d64ca833a
5
5
  SHA512:
6
- metadata.gz: 2c3722af382010534c4020a70b17ff7c6907c101fc0f6159758193a8152b30850a0b208dcfd6a94d1128275b8026c524bad9a2e4cac55bd292cb4c4bc9dc0645
7
- data.tar.gz: c90b2558520118f6617db83b2a3a48317ee51a03bfd01fc3eec9a726f6e4b5aea34fccc03cae5d74c03aed117eefdf8b39942084f59eed2ecadcb3784954907a
6
+ metadata.gz: f019bd0a5354f762b4a7304d88509054fe53078528c188e8186aa8af134ff40d99042b0c3556ea2c2497317e0d899e764a6649e78f22ed1aea53e5301ee83c6f
7
+ data.tar.gz: d106562538a1cd625d422e1e500aa34564c5f1c97bfeea30fa6083c7e7f1b99d4addf59f7046c29575122f0b43a15c61b7efefc6fba16ef8a0aeec0107b15148
data/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ See [https://github.com/sustainable-rails/with\_clues/releases](https://github.com/sustainable-rails/with_clues/releases)
data/README.md CHANGED
@@ -107,13 +107,15 @@ There are three clues included:
107
107
  `with_clues` is intended as a diagnostic tool you can develop and enhance over time. As your team writes more code or develops
108
108
  more conventions, you can develop diagnostics as well.
109
109
 
110
- To add one, create a class that implements `dump(notifier, context:)`:
110
+ To add one, create a class that implements `dump(notifier, context:)` or `dump(notifier, context:, page:)`:
111
111
 
112
112
  * `notifier` is a `WithClues::Notifier` that you should use to produce output:
113
113
  * `notify` - output text, preceded with `[ with_clues ]` (this is so you can tell output from your code vs from `with_clues`)
114
114
  * `blank_line` - a blank line (no prefix)
115
115
  * `notify_raw` - output text without a prefix, useful for removing ambiguity about what is being output
116
116
  * `context:` the context passed into `with_clues` (nil if it was omitted)
117
+ * `page:` If `dump` requires this keyword, your clue will only be used in a browser context when the Capybara `page` object is available.
118
+ In that case, that is what is passed in.
117
119
 
118
120
  For example, suppose you want to output information about an Active Record like so:
119
121
 
@@ -153,6 +155,9 @@ WithClues::Method.use_custom_clue ActiveRecordClues
153
155
 
154
156
  You can use multiple clues by repeatedly calling `use_custom_clue`
155
157
 
158
+ Note that if your clue implements the three-arg version of `dump` ( `dump(notifier, context:, page:)` ), it will *only* be used when in
159
+ a context where Capybara's `page` element in in play.
160
+
156
161
  ## Developing
157
162
 
158
163
  * Get set up with `bin/setup`
@@ -6,24 +6,35 @@ module WithClues
6
6
  return
7
7
  end
8
8
  if page.driver.respond_to?(:browser)
9
- if page.driver.browser.respond_to?(:manage)
10
- if page.driver.browser.manage.respond_to?(:logs)
11
- logs = page.driver.browser.manage.logs
12
- browser_logs = logs.get(:browser)
13
- notifier.notify "BROWSER LOGS {"
14
- browser_logs.each do |log|
15
- notifier.notify_raw log.message
16
- end
17
- notifier.notify "} END BROWSER LOGS"
18
- else
19
- notifier.notify "NO BROWSER LOGS: page.driver.browser.manage #{page.driver.browser.manage.class} does not respond to #logs"
9
+ logs = locate_logs(page.driver.browser, notifier: notifier)
10
+ if !logs.nil?
11
+ browser_logs = logs.get(:browser)
12
+ notifier.notify "BROWSER LOGS {"
13
+ browser_logs.each do |log|
14
+ notifier.notify_raw log.message
20
15
  end
21
- else
22
- notifier.notify "NO BROWSER LOGS: page.driver.browser #{page.driver.browser.class} does not respond to #manage"
16
+ notifier.notify "} END BROWSER LOGS"
23
17
  end
24
18
  else
25
- notifier.notify "NO BROWSER LOGS: page.driver #{page.driver.class} does not respond to #browser"
19
+ notifier.notify "[with_clues: #{self.class}] NO BROWSER LOGS: page.driver #{page.driver.class} does not respond to #browser"
26
20
  end
27
21
  end
22
+
23
+ private
24
+
25
+ def locate_logs(browser, notifier:)
26
+ if browser.respond_to?(:logs)
27
+ return browser.logs
28
+ elsif browser.respond_to?(:manage)
29
+ if browser.manage.respond_to?(:logs)
30
+ return browser.manage.logs
31
+ end
32
+ notifier.notify "[with_clues: #{self.class}] NO BROWSER LOGS: page.driver.browser.manage #{browser.manage.class} does not respond to #logs"
33
+ else
34
+ notifier.notify "[with_clues: #{self.class}] NO BROWSER LOGS: page.driver.browser #{browser.class} does not respond to #manage or #logs"
35
+ end
36
+ nil
37
+ end
38
+
28
39
  end
29
40
  end
@@ -1,6 +1,7 @@
1
1
  require_relative "html"
2
2
  require_relative "browser_logs"
3
3
  require_relative "notifier"
4
+ require_relative "private/custom_clue_method_analysis"
4
5
 
5
6
  module WithClues
6
7
  module Method
@@ -23,18 +24,25 @@ module WithClues
23
24
  @@clue_classes[:custom].each do |klass|
24
25
  klass.new.dump(notifier, context: context)
25
26
  end
26
- if !defined?(page)
27
- raise ex
28
- end
29
- notifier.notify "Test failed: #{ex.message}"
30
- @@clue_classes[:require_page].each do |klass|
31
- klass.new.dump(notifier, context: context, page: page)
27
+ if defined?(page)
28
+ notifier.notify "Test failed: #{ex.message}"
29
+ @@clue_classes[:require_page].each do |klass|
30
+ klass.new.dump(notifier, context: context, page: page)
31
+ end
32
32
  end
33
33
  raise ex
34
34
  end
35
35
 
36
36
  def self.use_custom_clue(klass)
37
- @@clue_classes[:custom] << klass
37
+ dump_method = klass.instance_method(:dump)
38
+ analysis = WithClues::Private::CustomClueMethodAnalysis.from_method(dump_method)
39
+ if analysis.standard_implementation?
40
+ @@clue_classes[:custom] << klass
41
+ elsif analysis.requires_page_object?
42
+ @@clue_classes[:require_page] << klass
43
+ else
44
+ analysis.raise_exception!
45
+ end
38
46
  end
39
47
  end
40
48
  end
@@ -0,0 +1,139 @@
1
+ module WithClues
2
+ module Private
3
+ class CustomClueMethodAnalysis
4
+
5
+ def self.from_method(unbound_method)
6
+
7
+ params = unbound_method.parameters.map { |param_array| Param.new(param_array) }
8
+
9
+ if params.size == 2
10
+ two_arg_method = TwoArgMethod.new(params)
11
+ if two_arg_method.valid?
12
+ return StandardImplementation.new
13
+ end
14
+
15
+ return BadParams.new(two_arg_method.errors)
16
+
17
+ elsif params.size == 3
18
+ three_arg_method = ThreeArgMethod.new(params)
19
+ if three_arg_method.valid?
20
+ return RequiresPageObject.new
21
+ end
22
+ return BadParams.new(three_arg_method.errors)
23
+ end
24
+
25
+ BadParams.new([])
26
+ end
27
+
28
+ def standard_implementation?
29
+ false
30
+ end
31
+
32
+ def requires_page_object?
33
+ false
34
+ end
35
+
36
+ def raise_exception!
37
+ raise StandardError.new("Unimplemented condition found inside #from_method")
38
+ end
39
+
40
+ class Param
41
+
42
+ def initialize(method_param_array)
43
+ @type = method_param_array[0]
44
+ @name = method_param_array[1]
45
+
46
+ end
47
+
48
+ def required?
49
+ @type == :req
50
+ end
51
+ def keyword_required?
52
+ @type == :keyreq
53
+ end
54
+
55
+ def named?(*allowed_names)
56
+ allowed_names.include?(@name)
57
+ end
58
+ def name
59
+ if self.keyword_required?
60
+ "#{@name}:"
61
+ else
62
+ @name
63
+ end
64
+ end
65
+ end
66
+
67
+ class TwoArgMethod
68
+ attr_reader :errors
69
+ def initialize(params)
70
+ @errors = []
71
+ if !params[0].required?
72
+ @errors << "Param 1, #{params[0].name}, is not required"
73
+ end
74
+ require_keyword(2,params[1])
75
+ end
76
+
77
+ def valid?
78
+ @errors.empty?
79
+ end
80
+ private
81
+
82
+ def require_keyword(param_number, param)
83
+ if !param.keyword_required?
84
+ @errors << "Param #{param_number}, #{param.name}, is not a required keyword param"
85
+ end
86
+ if !param.named?(*allowed_names)
87
+ @errors << "Param #{param_number}, #{param.name}, should be named context:"
88
+ end
89
+ end
90
+
91
+ def allowed_names
92
+ [ :context ]
93
+ end
94
+ end
95
+
96
+ class ThreeArgMethod < TwoArgMethod
97
+ def initialize(params)
98
+ super(params)
99
+ require_keyword(3,params[2])
100
+ end
101
+ private
102
+ def allowed_names
103
+ [ :context, :page ]
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ class GoodParams < CustomClueMethodAnalysis
110
+ def raise_exception!
111
+ raise StandardError.new("You should not have called .exception on a #{self.class.name}")
112
+ end
113
+ end
114
+
115
+ class RequiresPageObject < CustomClueMethodAnalysis
116
+ def requires_page_object?
117
+ true
118
+ end
119
+ end
120
+
121
+ class StandardImplementation < CustomClueMethodAnalysis
122
+ def standard_implementation?
123
+ true
124
+ end
125
+ end
126
+
127
+ class BadParams < CustomClueMethodAnalysis
128
+ def initialize(errors)
129
+ @message = errors.empty? ? DEFAULT_ERROR : errors.join(", ")
130
+ end
131
+
132
+ DEFAULT_ERROR = "dump must take one required param, one keyword param named context: and an optional keyword param named page:"
133
+
134
+ def raise_exception!
135
+ raise NameError.new(@message)
136
+ end
137
+ end
138
+ end
139
+ end
@@ -1,3 +1,3 @@
1
1
  module WithClues
2
- VERSION="1.1.0"
2
+ VERSION="1.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: with_clues
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Copeland
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-04 00:00:00.000000000 Z
11
+ date: 2022-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -77,6 +77,7 @@ files:
77
77
  - ".gitignore"
78
78
  - ".rspec"
79
79
  - ".tool-versions"
80
+ - CHANGELOG.md
80
81
  - CODE_OF_CONDUCT.md
81
82
  - CONTRIBUTING.md
82
83
  - Gemfile
@@ -95,6 +96,7 @@ files:
95
96
  - lib/with_clues/html.rb
96
97
  - lib/with_clues/method.rb
97
98
  - lib/with_clues/notifier.rb
99
+ - lib/with_clues/private/custom_clue_method_analysis.rb
98
100
  - lib/with_clues/version.rb
99
101
  - with_clues.gemspec
100
102
  homepage: https://sustainable-rails.com