appydays 0.3.0 → 0.4.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 +4 -4
- data/lib/appydays/configurable.rb +4 -1
- data/lib/appydays/loggable/sequel_logger.rb +2 -1
- data/lib/appydays/spec_helpers.rb +86 -24
- data/lib/appydays/version.rb +1 -1
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa853f6dccbb995b590e7a13204f7e02f7c8bb992630fa19344a15e751149bcf
|
4
|
+
data.tar.gz: 235896b58a7e3a1fac6fa742cf01dfd8d129a54182d09ae1dfb65ad31b60448c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 931e7d037f44b697864b519f3efe6577a02f9923e814c2201f4c1ab1aea9430416f3cfc6dd63b26f116916b32ba08d608b03919cb7be52f173b11514e73d860a
|
7
|
+
data.tar.gz: 161d5c8a250623e558426ee6be2dae1135717c6599de90d4ff38e2276f2d5b2b65de729eaf16443ae18e92f6bb923771762d9c92ab8c2bec33731c7ed154645d
|
@@ -86,6 +86,8 @@ module Appydays::Configurable
|
|
86
86
|
# If convert is passed, that is used as the converter so the default value can be any type.
|
87
87
|
# key: The key to lookup the config value from the environment.
|
88
88
|
# If nil, use an auto-generated combo of the configuration key and method name.
|
89
|
+
# If key is an array, look up each (string) value as a key.
|
90
|
+
# The first non-nil (ie, `ENV.fetch(x, nil)`) value will be used.
|
89
91
|
# convert: If provided, call it with the string value so it can be parsed.
|
90
92
|
# For example, you can parse a string JSON value here.
|
91
93
|
# Convert will not be called with the default value.
|
@@ -106,7 +108,8 @@ module Appydays::Configurable
|
|
106
108
|
end
|
107
109
|
|
108
110
|
key ||= "#{@group_key}_#{name}".upcase
|
109
|
-
|
111
|
+
keys = Array(key)
|
112
|
+
env_value = keys.filter_map { |k| ENV.fetch(k, nil) }.first
|
110
113
|
converter = self._converter(default, convert)
|
111
114
|
value = env_value.nil? ? default : converter[env_value]
|
112
115
|
value = installer._set_value(name, value, side_effect)
|
@@ -5,8 +5,9 @@ require "sequel/database/logging"
|
|
5
5
|
|
6
6
|
class Sequel::Database
|
7
7
|
def log_exception(exception, message)
|
8
|
+
level = message.match?(/^SELECT NULL AS "?nil"? FROM .* LIMIT 1$/i) ? :debug : :error
|
8
9
|
log_each(
|
9
|
-
|
10
|
+
level,
|
10
11
|
proc { "#{exception.class}: #{exception.message.strip if exception.message}: #{message}" },
|
11
12
|
proc { ["sequel_exception", {sequel_message: message}, exception] },
|
12
13
|
)
|
@@ -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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
70
|
-
|
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
|
-
|
98
|
+
def within(tolerance)
|
74
99
|
@tolerance = tolerance
|
100
|
+
return self
|
75
101
|
end
|
76
102
|
|
77
|
-
def
|
78
|
-
return
|
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
|
-
|
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
|
data/lib/appydays/version.rb
CHANGED
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.
|
4
|
+
version: 0.4.0
|
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-
|
11
|
+
date: 2022-08-19 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
|