skn_utils 5.6.0 → 5.7.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2822f2d8bb83e07b5b099fe277285948dc0e687f
4
- data.tar.gz: 28ae0ca8c94fbc7998ce696d3424345976588ff8
3
+ metadata.gz: '01339ef95f65037a1a9951185b69a8ee2fb9160c'
4
+ data.tar.gz: fd2bd2b6b3ae66f17b268f6f23abd2d1a8c0e69b
5
5
  SHA512:
6
- metadata.gz: 951ff479251217472626d4e8c4dca4bf8e40d59be6606ecefc7ee21b9eb5150f2ff080a9edb8e02b003d2d5cc59cca194cd63a57fc8b5c19dd36a6f4fe334671
7
- data.tar.gz: a7919693b23911d56a4c3411e5f8c89e62142921a507ecae61357d49e8f7a4eda5e1df65ecf0abf1516f4d3c47fead9820568d1fb2aeaf95972c83f3cfa58f36
6
+ metadata.gz: cb6089054a1e97e7e21d03df41c6622e253487fee45e9799217c8cff211dcb8ca63c39776e15c89876edd88e22a9a22c099a133328bb5786801a0d53ce682924
7
+ data.tar.gz: 288b6c71971afd3f0b84b5524d0c96ceec28b7db93a8183ea6c9e31e0a00a974b0eb11f8acbcda03f7b3d0b5160de6e244ec78b7fca13d43f75a63951765e72c
data/README.md CHANGED
@@ -8,6 +8,7 @@ dependencies, to augment the development of Ruby applications. Examples of thes
8
8
  utilities in action can be found in my related projects `SknServices`, `SknWebApp`,
9
9
  and `SknBase`.
10
10
 
11
+ * Most classes are standalone modules, or cleary documented, and can be copy/pasted into your project.
11
12
  * The exchange or handoff of values between objects is addressed via the `NestedResults`
12
13
  class which implements dot-notation and nesting over a concurrent hash: A ruby Hash can
13
14
  use any valid ruby object as a key or value.
@@ -31,7 +32,8 @@ classname, symbol, or string as needed
31
32
  * `ConcurrentJobs` is a feature implemented to allow concurrent/multi-threaded execution of jobs. The included
32
33
  companion classes focus on HTTP GET,PUT,POST, and DELETE jobs as an example of how to use the `ConcurrentJobs` feature.
33
34
 
34
- All classes and modules have RSpec test coverage (90+) of their originally intended use-cases.
35
+ All classes and modules have RSpec test coverage (90+) of their originally intended
36
+ use-cases.
35
37
 
36
38
 
37
39
  ### Available Classes
@@ -65,8 +67,19 @@ All classes and modules have RSpec test coverage (90+) of their originally inten
65
67
  * SknUtils.as_human_size()
66
68
  * SknUtils.duration(start_time=nil)
67
69
 
70
+ ### Available RSpec Helpers
71
+ * spec/support/xml_matchers.rb
72
+ * expect(bundle).to have_xpath('//witnesses/witness/role')
73
+ * expect(bundle).to have_nodes('//witnesses/witness/role', 3)
74
+ * expect(bundle).to match_xpath('//lossInformation/date', "2020-01-28")
75
+
68
76
 
69
77
  ## History
78
+ 2/3/2030 V5.7.0
79
+ Added
80
+ * RSpec XML_Matchers to spec/support folders
81
+ * Update ConcurrentJobs JobCommands to support HTTP Headers
82
+
70
83
  2/24/2019 V5.5.0
71
84
  Added
72
85
  * ConcurrentJobs feature set
@@ -15,6 +15,8 @@ module SknUtils
15
15
 
16
16
  def call
17
17
  @blk.call
18
+ rescue => ex
19
+ SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
18
20
  end
19
21
  end
20
22
 
@@ -25,6 +27,8 @@ module SknUtils
25
27
 
26
28
  def call
27
29
  @blk.value
30
+ rescue => ex
31
+ SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
28
32
  end
29
33
  end
30
34
 
@@ -50,7 +54,7 @@ module SknUtils
50
54
  def self.call(command, callable)
51
55
  callable.call(command)
52
56
  rescue => ex
53
- SknFailure.(ex.class.name, "#{ex.message}; #{ex.backtrace[0]}")
57
+ SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
54
58
  end
55
59
  end
56
60
 
@@ -85,7 +89,12 @@ module SknUtils
85
89
  def render_jobs
86
90
  stime = SknUtils.duration
87
91
  merged = @workers.each_with_object([]) do |worker, acc|
88
- acc.push( worker.call )
92
+ begin
93
+ res = worker.call
94
+ acc.push( res.nil? ? SknFailure.("Unknown", {cause: "Nil Return Value to render Jobs", backtrace: []}) : res )
95
+ rescue => ex
96
+ acc.push SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
97
+ end
89
98
  end
90
99
  @elapsed_time_string = SknUtils.duration(stime)
91
100
  Result.new(merged)
@@ -59,6 +59,10 @@ module SknUtils
59
59
  # - env = string value from RACK_ENV
60
60
  # - registry = SknRegistry instance
61
61
  # - logger = Assigned Logger instance
62
+ # - romDB = var for Rom-DB if used or Any Platform Database
63
+ # - metadata = platform metadata container
64
+ # - userdata = user area
65
+ # - metrics = platform metrics container
62
66
  # #with(*user_attrs, enable_root: true|false) - defaults to enable of Main Class Attrs
63
67
  # ##
64
68
  # User-Defined Attrs
@@ -131,6 +135,38 @@ module SknUtils
131
135
  def logger=(obj)
132
136
  @__logger = obj
133
137
  end
138
+
139
+ # Any Platform Database
140
+ def romDB
141
+ @__db ||= nil
142
+ end
143
+ def romDB(obj)
144
+ @__db = obj
145
+ end
146
+
147
+ # Maybe Platform Metadata
148
+ def metadata
149
+ @__metadata ||= nil
150
+ end
151
+ def metadata=(obj)
152
+ @__metadata = obj
153
+ end
154
+
155
+ # Userdata container for any use
156
+ def userdata
157
+ @__userdata ||= nil
158
+ end
159
+ def userdata=(obj)
160
+ @__userdata = obj
161
+ end
162
+
163
+ # Metrics container for any use
164
+ def metrics
165
+ @__metrics ||= nil
166
+ end
167
+ def metrics=(obj)
168
+ @__metrics = obj
169
+ end
134
170
  end
135
171
  end
136
172
 
@@ -7,7 +7,7 @@ module SknUtils
7
7
  # #################################################
8
8
  #
9
9
  class CommandJSONPost
10
- def self.call(options) # {full_url:,username:,userpass:,payload:}
10
+ def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
11
11
  new(options)
12
12
  end
13
13
 
@@ -20,7 +20,7 @@ module SknUtils
20
20
  end
21
21
 
22
22
  def request
23
- req = Net::HTTP::Post.new(uri.path) # Generate HTTPRequest object
23
+ req = @_headers.nil? ? Net::HTTP::Post.new(uri.path) : Net::HTTP::Post.new(uri.path, @_headers) # Generate HTTPRequest object
24
24
  req.basic_auth(@_username, @_userpass) if credentials?
25
25
  req.content_type = 'application/json'
26
26
  req.body = formatted_data
@@ -32,6 +32,7 @@ module SknUtils
32
32
  def initialize(opts={})
33
33
  @_username = opts[:username]
34
34
  @_userpass = opts[:userpass]
35
+ @_headers = opts[:headers]
35
36
  @_uri = URI.parse( opts[:full_url])
36
37
  @_data = opts[:payload]
37
38
  end
@@ -49,7 +50,7 @@ module SknUtils
49
50
  # #################################################
50
51
  #
51
52
  class CommandFORMPost
52
- def self.call(options) # {full_url:,username:,userpass:,payload:}
53
+ def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
53
54
  new(options)
54
55
  end
55
56
 
@@ -62,7 +63,7 @@ module SknUtils
62
63
  end
63
64
 
64
65
  def request
65
- req = Net::HTTP::Post.new(uri.path) # Generate HTTPRequest object
66
+ req = @_headers.nil? ? Net::HTTP::Post.new(uri.path) : Net::HTTP::Post.new(uri.path, @_headers) # Generate HTTPRequest object
66
67
  req.basic_auth(@_username, @_userpass) if credentials?
67
68
  req.content_type = 'application/x-www-form-urlencoded'
68
69
  req.set_form_data(formatted_data)
@@ -74,6 +75,7 @@ module SknUtils
74
75
  def initialize(opts={})
75
76
  @_username = opts[:username]
76
77
  @_userpass = opts[:userpass]
78
+ @_headers = opts[:headers]
77
79
  @_uri = URI.parse( opts[:full_url])
78
80
  @_data = opts[:payload]
79
81
  end
@@ -91,7 +93,7 @@ module SknUtils
91
93
  # #################################################
92
94
  #
93
95
  class CommandJSONGet
94
- def self.call(options) # {full_url:,username:,userpass:}
96
+ def self.call(options) # {full_url:,username:,userpass:,headers:}
95
97
  new(options)
96
98
  end
97
99
 
@@ -104,7 +106,7 @@ module SknUtils
104
106
  end
105
107
 
106
108
  def request
107
- req = Net::HTTP::Get.new(uri.request_uri)
109
+ req = @_headers.nil? ? Net::HTTP::Get.new(uri.request_uri) : Net::HTTP::Get.new(uri.request_uri, @_headers) # Generate HTTPRequest object
108
110
  req.basic_auth(@_username, @_userpass) if credentials?
109
111
  req
110
112
  end
@@ -114,6 +116,7 @@ module SknUtils
114
116
  def initialize(opts={})
115
117
  @_username = opts[:username]
116
118
  @_userpass = opts[:userpass]
119
+ @_headers = opts[:headers]
117
120
  @_uri = URI.parse( opts[:full_url])
118
121
  end
119
122
 
@@ -126,7 +129,7 @@ module SknUtils
126
129
  # #################################################
127
130
  #
128
131
  class CommandJSONPut
129
- def self.call(options) # {full_url:,username:,userpass:,payload:}
132
+ def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
130
133
  new(options)
131
134
  end
132
135
 
@@ -139,7 +142,7 @@ module SknUtils
139
142
  end
140
143
 
141
144
  def request
142
- req = Net::HTTP::Put.new(uri.path) # Generate HTTPRequest object
145
+ req = @_headers.nil? ? Net::HTTP::Put.new(uri.path) : Net::HTTP::Put.new(uri.path, @_headers) # Generate HTTPRequest object
143
146
  req.basic_auth(@_username, @_userpass) if credentials?
144
147
  req.content_type = 'application/json'
145
148
  req.body = formatted_data
@@ -151,6 +154,7 @@ module SknUtils
151
154
  def initialize(opts={})
152
155
  @_username = opts[:username]
153
156
  @_userpass = opts[:userpass]
157
+ @_headers = opts[:headers]
154
158
  @_uri = URI.parse( opts[:full_url])
155
159
  @_data = opts[:payload]
156
160
  end
@@ -181,7 +185,7 @@ module SknUtils
181
185
  end
182
186
 
183
187
  def request
184
- req = Net::HTTP::Delete.new(uri.request_uri)
188
+ req = @_headers.nil? ? Net::HTTP::Delete.new(uri.request_uri) : Net::HTTP::Delete.new(uri.request_uri, @_headers) # Generate HTTPRequest object
185
189
  req.basic_auth(@_username, @_userpass) if credentials?
186
190
  req
187
191
  end
@@ -191,6 +195,7 @@ module SknUtils
191
195
  def initialize(opts={})
192
196
  @_username = opts[:username]
193
197
  @_userpass = opts[:userpass]
198
+ @_headers = opts[:headers]
194
199
  @_uri = URI.parse( opts[:full_url])
195
200
  end
196
201
 
@@ -4,7 +4,7 @@
4
4
  module SknUtils
5
5
  class Version
6
6
  MAJOR = 5
7
- MINOR = 6
7
+ MINOR = 7
8
8
  PATCH = 0
9
9
 
10
10
  def self.to_s
@@ -7,7 +7,7 @@ describe SknUtils::ConcurrentJobs, 'Run Multiple Jobs' do
7
7
 
8
8
  let(:commands) {
9
9
  [
10
- SknUtils::CommandJSONPost.call(full_url: "http://example.com/posts", payload: {one: 1}),
10
+ SknUtils::CommandJSONPost.call(full_url: "http://example.com/posts", payload: {one: 1}, headers: {'my-header'=> "header-value"}),
11
11
  SknUtils::CommandFORMPost.call(full_url: "http://example.com/posts", payload: {one: 1}),
12
12
  SknUtils::CommandJSONGet.call(full_url: "http://example.com/posts/1"),
13
13
  SknUtils::CommandJSONPut.call(full_url: "http://example.com/posts", payload: {one: 1}),
@@ -199,10 +199,12 @@ describe SknUtils::ConcurrentJobs, 'Run Multiple Jobs' do
199
199
  expect(result).to be_a(SknUtils::Result)
200
200
  expect(result.success?).to be false
201
201
  expect(result.values.size).to eq(commands.size)
202
+ expect(result.values.last).to be_a(SknSuccess)
202
203
  expect(result.values[3].value).to eq("NameError")
203
- expect(result.values[3]).to be_a(SknFailure)
204
- expect(result.values[3]).to be_a(SknFailure)
205
- expect(result.values[0]).to be nil
204
+ expect(result.values[2]).to be_a(SknFailure)
205
+ expect(result.values[1]).to be_a(SknFailure)
206
+ expect(result.values[0]).to be_a(SknFailure)
207
+ expect(result.values[0].value).to eq("Unknown")
206
208
  end
207
209
  end
208
210
 
@@ -16,6 +16,7 @@ require 'skn_utils'
16
16
  require 'rspec'
17
17
 
18
18
  require 'webmock/rspec'
19
+ require 'support/xml_matchers'
19
20
 
20
21
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
22
  RSpec.configure do |config|
@@ -0,0 +1,121 @@
1
+ # ##
2
+ # File: <spec>/xml_matchers.rb
3
+ #
4
+ # Refs: https://github.com/sparklemotion/nokogiri/wiki/Cheat-sheet
5
+ # https://arjanvandergaag.nl/blog/rspec-matchers.html
6
+ # http://blog.wolfman.com/articles/2008/1/2/xpath-matchers-for-rspec
7
+ # https://semaphoreci.com/community/tutorials/how-to-use-custom-rspec-matchers-to-specify-behaviour
8
+ #
9
+
10
+ # Useage
11
+ # ----------------------------------------------------------------------
12
+ # expect(bundle).to have_xpath('//witnesses/witness/role')
13
+ # expect(bundle).to have_nodes('//witnesses/witness/role', 3)
14
+ # expect(bundle).to match_xpath('//lossInformation/date', "2020-01-28")
15
+
16
+ # check if the xpath exists one or more times
17
+ class HaveXpath
18
+ def initialize(xpath)
19
+ @xpath = xpath
20
+ end
21
+
22
+ def matches?(str)
23
+ @str = str
24
+ xml_document.xpath(@xpath).any?
25
+ end
26
+
27
+ def failure_message
28
+ "Expected xpath #{@xpath.inspect} to match in:\n" + pretty_printed_xml
29
+ end
30
+
31
+ def failure_message_when_negated
32
+ "Expected xpath #{@xpath.inspect} not to match in:\n" + pretty_printed_xml
33
+ end
34
+
35
+ private
36
+
37
+ def pretty_printed_xml
38
+ xml_document.to_xml(indent: 2)
39
+ end
40
+
41
+ def xml_document
42
+ @xml_document ||= Nokogiri::XML(@str)
43
+ end
44
+ end
45
+
46
+ def have_xpath(*xpath)
47
+ HaveXpath.new(*xpath)
48
+ end
49
+
50
+ # check if the xpath has the specified value
51
+ # value is a string and there must be a single result to match its
52
+ # equality against
53
+ class MatchXpath
54
+ def initialize(xpath, val)
55
+ @xpath = xpath
56
+ @val= val
57
+ end
58
+
59
+ def matches?(response)
60
+ @response = response
61
+ doc = response.is_a?(Nokogiri::XML::Document) ? response : Nokogiri::XML(@response)
62
+ ok= true
63
+ doc.xpath(@xpath).each do |e|
64
+ @actual_val= case e
65
+ when Nokogiri::XML::Attr
66
+ e.to_s
67
+ when Nokogiri::XML::Element
68
+ e.text
69
+ else
70
+ e.to_s
71
+ end
72
+ return false unless @val == @actual_val
73
+ end
74
+ return ok
75
+ end
76
+
77
+ def failure_message
78
+ "The xpath #{@xpath} did not have the value '#{@val}' \n It was '#{@actual_val}'"
79
+ end
80
+
81
+ def failure_message_when_negated
82
+ "The xpath #{@xpath} has the value '#{@val}' \n Was expected not to match '#{@actual_val}'"
83
+ end
84
+
85
+ def description
86
+ "match the xpath expression #{@xpath} with #{@val}"
87
+ end
88
+ end
89
+
90
+ def match_xpath(xpath, val)
91
+ MatchXpath.new(xpath, val)
92
+ end
93
+
94
+ # checks if the given xpath occurs num times
95
+ class HaveNodes #:nodoc:
96
+ def initialize(xpath, num)
97
+ @xpath= xpath
98
+ @num = num
99
+ end
100
+
101
+ def matches?(response)
102
+ @response = response
103
+ doc = response.is_a?(Nokogiri::XML::Document) ? response : Nokogiri::XML(@response)
104
+ matches = doc.xpath(@xpath)
105
+ @num_found= matches.size
106
+ @num_found == @num
107
+ end
108
+
109
+ def failure_message
110
+ "Did not find expected number of nodes #{@num} in xpath #{@xpath} \n Found #{@num_found}"
111
+ end
112
+
113
+ def description
114
+ "match the number of nodes #{@num}"
115
+ end
116
+ end
117
+
118
+ def have_nodes(xpath, num)
119
+ HaveNodes.new(xpath, num)
120
+ end
121
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skn_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.0
4
+ version: 5.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Scott Jr
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-02 00:00:00.000000000 Z
11
+ date: 2020-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -242,6 +242,7 @@ files:
242
242
  - spec/lib/skn_utils/wrappers_spec.rb
243
243
  - spec/spec_helper.rb
244
244
  - spec/support/configurables.rb
245
+ - spec/support/xml_matchers.rb
245
246
  homepage: https://github.com/skoona/skn_utils
246
247
  licenses:
247
248
  - MIT
@@ -293,3 +294,4 @@ test_files:
293
294
  - spec/lib/skn_utils/wrappers_spec.rb
294
295
  - spec/spec_helper.rb
295
296
  - spec/support/configurables.rb
297
+ - spec/support/xml_matchers.rb