appydays 0.2.1 → 0.3.2

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: 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