appydays 0.2.1 → 0.3.2

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
  SHA256:
3
- metadata.gz: 91b171c7afb39adf17de30701ad3047c6d5edb080e512e8a2a1596f88c1c8b2e
4
- data.tar.gz: 2020c7ec844d50ef4cbdfeb9a25bde44ac5d85d5d780e6736e6320af17a4771b
3
+ metadata.gz: 28e26d2090ae5a2026a2e0be984ef8eb9e9d0e77064805fd54e50579477e6b76
4
+ data.tar.gz: c42cd9bf6a052604a1a61b5188aef8ed052ff9312f0c737eae07825fb9ec0a7c
5
5
  SHA512:
6
- metadata.gz: f9f2f5dd7804b5a166451109432c253e8fd9c7fbaf2179a424b00d4448e0f0f3598029e0f5711d9c7cfed937e2f84f62e1850aae5c00866904b2acdd81be5c91
7
- data.tar.gz: 17a99175b776829772f1744cd740fb6ed396d171e7c8735f7c380c323d2cfc0dbab3cdf1fed890daf9b3bf371bfc26f982ceb5b5194a2ecb0980ae0fa0dad46c
6
+ metadata.gz: 69bb8e1c9f07c649c9e0d16a0b82ff50fc4a06810d122a49d78a312244dd62d2c5296c158a2fc3317dee90c1ab1c7ff0f8f25bbad5b5e35ffdd0e4cc99d61269
7
+ data.tar.gz: 92bd69f37dfdd3b28b6626a5203b53c1dc353587a784d77cd32cb0a316272575403063adf2e6f0fbb47529a73c4cbae925018047c7354ebf69b278e2e4631cc3
@@ -17,7 +17,11 @@ class Sequel::Database
17
17
  log_each(
18
18
  :info,
19
19
  proc { args ? "#{message}; #{args.inspect}" : message },
20
- proc { ["sequel_log", {message: message, args: args}] },
20
+ proc do
21
+ o = {message: message}
22
+ o[:args] = args unless args.nil?
23
+ ["sequel_log", o]
24
+ end,
21
25
  )
22
26
  end
23
27
 
@@ -28,7 +32,7 @@ class Sequel::Database
28
32
  log_each(
29
33
  lwd && (duration >= lwd) ? :warn : sql_log_level,
30
34
  proc { "(#{'%0.6fs' % duration}) #{message}" },
31
- proc { ["sequel_query", {duration: duration, query: message}] },
35
+ proc { ["sequel_query", {duration: duration * 1000, query: message}] },
32
36
  )
33
37
  end
34
38
 
@@ -43,10 +43,10 @@ class Appydays::Loggable::SidekiqJobLogger < Sidekiq::JobLogger
43
43
  yield
44
44
  duration = self.elapsed(start)
45
45
  log_method = duration >= self.slow_job_seconds ? :warn : :info
46
- self.logger.send(log_method, "job_done", duration: duration)
46
+ self.logger.send(log_method, "job_done", duration: duration * 1000)
47
47
  rescue StandardError
48
48
  # Do not log the error since it is probably a sidekiq retry error
49
- self.logger.error("job_fail", duration: self.elapsed(start))
49
+ self.logger.error("job_fail", duration: self.elapsed(start) * 1000)
50
50
  raise
51
51
  end
52
52
 
@@ -19,12 +19,15 @@ module Appydays::SpecHelpers
19
19
  #
20
20
 
21
21
  class HaveALineMatching
22
+ include RSpec::Matchers::Composable
23
+
22
24
  def initialize(regexp)
23
25
  @regexp = regexp
24
26
  end
25
27
 
26
28
  def matches?(target)
27
29
  @target = target
30
+ @target = @target.lines if @target.is_a?(String)
28
31
  return @target.find do |obj|
29
32
  obj.to_s.match(@regexp)
30
33
  end
@@ -43,9 +46,9 @@ module Appydays::SpecHelpers
43
46
  alias failure_message_for_should_not failure_message_when_negated
44
47
  end
45
48
 
46
- ### RSpec matcher -- set up the expectation that the lefthand side
47
- ### is Enumerable, and that at least one of the objects yielded
48
- ### while iterating matches +regexp+ when converted to a String.
49
+ # RSpec matcher -- set up the expectation that the lefthand side
50
+ # is Enumerable, and that at least one of the objects yielded
51
+ # while iterating matches +regexp+ when converted to a String.
49
52
  module_function def have_a_line_matching(regexp)
50
53
  return HaveALineMatching.new(regexp)
51
54
  end
@@ -54,39 +57,73 @@ module Appydays::SpecHelpers
54
57
  return RSpec::Matchers::BuiltIn::HaveAttributes.new(length: x)
55
58
  end
56
59
 
57
- # Matcher that will compare a string or time expected against a string or time actual,
58
- # within a tolerance (default to 1 millisecond).
59
- #
60
- # expect(last_response).to have_json_body.that_includes(
61
- # closes_at: match_time('2025-12-01T00:00:00.000+00:00').within(1.second))
62
- #
63
- RSpec::Matchers.define(:match_time) do |expected|
64
- match do |actual|
65
- @tolerance ||= 0.001
66
- RSpec::Matchers::BuiltIn::BeWithin.new(@tolerance).of(self.time(expected)).matches?(self.time(actual))
60
+ class MatchTime
61
+ include RSpec::Matchers::Composable
62
+
63
+ def initialize(expected)
64
+ @expected = expected
65
+ if expected == :now
66
+ @expected_t = Time.now
67
+ @tolerance = 5
68
+ else
69
+ @expected_t = self.time(expected)
70
+ @tolerance = 0.001
71
+ end
67
72
  end
68
73
 
69
- failure_message do |actual|
70
- "expected ids %s to be within %s of %s" % [self.time(actual), @tolerance, self.time(expected)]
74
+ def time(s)
75
+ return nil if s.nil?
76
+ return Time.parse(s) if s.is_a?(String)
77
+ return Time.at(s) if s.is_a?(Numeric)
78
+ return s.to_time
79
+ end
80
+
81
+ def matches?(actual)
82
+ @actual_t = self.time(actual)
83
+ @actual_t = self.change_tz(@actual_t, @expected_t.zone) if @actual_t
84
+ return RSpec::Matchers::BuiltIn::BeWithin.new(@tolerance).of(@expected_t).matches?(@actual_t)
85
+ end
86
+
87
+ protected def change_tz(t, zone)
88
+ return t.change(zone: zone) if t.respond_to?(:change)
89
+ prev_tz = ENV.fetch("TZ", nil)
90
+ begin
91
+ ENV["TZ"] = zone
92
+ return Time.at(t.to_f)
93
+ ensure
94
+ ENV["TZ"] = prev_tz
95
+ end
71
96
  end
72
97
 
73
- chain :within do |tolerance|
98
+ def within(tolerance)
74
99
  @tolerance = tolerance
100
+ return self
75
101
  end
76
102
 
77
- def time(s)
78
- return Time.parse(s) if s.is_a?(String)
79
- return s.to_time
103
+ def failure_message
104
+ return "expected %s to be within %s of %s" % [@actual_t, @tolerance, @expected_t]
80
105
  end
81
106
  end
82
107
 
108
+ # Matcher that will compare a string or time expected against a string or time actual,
109
+ # within a tolerance (default to 1 millisecond).
110
+ #
111
+ # Use match_time(:now) to automatically `match_time(Time.now).within(5.seconds)`.
112
+ #
113
+ # expect(last_response).to have_json_body.that_includes(
114
+ # closes_at: match_time('2025-12-01T00:00:00.000+00:00').within(1.second))
115
+ #
116
+ def match_time(expected)
117
+ return MatchTime.new(expected)
118
+ end
119
+
83
120
  # Matcher that will compare a string or Money expected against a string or Money actual.
84
121
  #
85
122
  # expect(order.total).to cost('$25')
86
123
  #
87
- RSpec::Matchers.define(:cost) do |expected|
124
+ RSpec::Matchers.define(:cost) do |expected, currency|
88
125
  match do |actual|
89
- @base = RSpec::Matchers::BuiltIn::Eq.new(self.money(expected))
126
+ @base = RSpec::Matchers::BuiltIn::Eq.new(self.money(expected, currency))
90
127
  @base.matches?(self.money(actual))
91
128
  end
92
129
 
@@ -94,12 +131,37 @@ module Appydays::SpecHelpers
94
131
  @base.failure_message
95
132
  end
96
133
 
97
- def money(s)
98
- return Monetize.parse(s) if s.is_a?(String)
134
+ def money(s, currency=nil)
135
+ if (m = self.tryparse(s, currency))
136
+ return m
137
+ end
99
138
  return s if s.is_a?(Money)
100
- return Money.new(s) if s.is_a?(Integer)
139
+ return Money.new(s, currency) if s.is_a?(Integer)
101
140
  return Money.new(s[:cents], s[:currency]) if s.respond_to?(:key?) && s.key?(:cents) && s.key?(:currency)
102
141
  raise "#{s} type #{s.class.name} not convertable to Money (add support or use supported type)"
103
142
  end
143
+
144
+ def tryparse(s, currency)
145
+ # We need to capture some global settings while we parse, and set them back after.
146
+ orig_default = Money.instance_variable_get(:@default_currency)
147
+ orig_assume = Monetize.assume_from_symbol
148
+ return nil unless s.is_a?(String)
149
+ # See https://github.com/RubyMoney/monetize/issues/161
150
+ # To get around this, need to use a valid custom currency
151
+ begin
152
+ Money::Currency.new("APPYDAYS")
153
+ rescue Money::Currency::UnknownCurrency
154
+ Money::Currency.register(iso_code: "APPYDAYS", subunit_to_unit: 1)
155
+ end
156
+ Money.default_currency = currency || orig_default || "APPYDAYS"
157
+ Monetize.assume_from_symbol = true
158
+ m = Monetize.parse!(s)
159
+ return m unless m.currency == "APPYDAYS"
160
+ raise Money::Currency::UnknownCurrency,
161
+ "Could not parse currency from '#{s}'. It needs a symbol, or set default_currency."
162
+ ensure
163
+ Money.default_currency = orig_default
164
+ Monetize.assume_from_symbol = orig_assume
165
+ end
104
166
  end
105
167
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appydays
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appydays
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lithic Tech
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-01 00:00:00.000000000 Z
11
+ date: 2022-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '4.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: monetize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.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'
55
+ - !ruby/object:Gem::Dependency
56
+ name: money
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '6.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '6.0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rack
43
71
  requirement: !ruby/object:Gem::Requirement