eml 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +10 -0
  3. data/.env.example +6 -0
  4. data/.gitignore +5 -0
  5. data/.rspec +5 -0
  6. data/.rubocop.yml +90 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE +21 -0
  9. data/README.md +87 -0
  10. data/eml.gemspec +37 -0
  11. data/lib/eml.rb +22 -0
  12. data/lib/eml/config.rb +49 -0
  13. data/lib/eml/data/countries.rb +260 -0
  14. data/lib/eml/data/currencies.rb +176 -0
  15. data/lib/eml/data/states.rb +4055 -0
  16. data/lib/eml/environment.rb +54 -0
  17. data/lib/eml/error.rb +25 -0
  18. data/lib/eml/error/rest.rb +42 -0
  19. data/lib/eml/error/rest/authentication.rb +21 -0
  20. data/lib/eml/error/rest/bad_request.rb +20 -0
  21. data/lib/eml/error/rest/daily_funding_limit.rb +19 -0
  22. data/lib/eml/error/rest/forbidden.rb +20 -0
  23. data/lib/eml/error/rest/internal_server.rb +9 -0
  24. data/lib/eml/error/rest/not_found.rb +20 -0
  25. data/lib/eml/error/rest/unprocessable_entity.rb +20 -0
  26. data/lib/eml/lib/endpoint_class.rb +42 -0
  27. data/lib/eml/parameters.rb +153 -0
  28. data/lib/eml/payload.rb +137 -0
  29. data/lib/eml/response.rb +103 -0
  30. data/lib/eml/uk.rb +51 -0
  31. data/lib/eml/uk/api_resource.rb +94 -0
  32. data/lib/eml/uk/config.rb +52 -0
  33. data/lib/eml/uk/lib/endpoint_class.rb +19 -0
  34. data/lib/eml/uk/lib/parse_date.rb +35 -0
  35. data/lib/eml/uk/model/transaction.rb +56 -0
  36. data/lib/eml/uk/parameters.rb +99 -0
  37. data/lib/eml/uk/parameters/agreement/show.rb +22 -0
  38. data/lib/eml/uk/parameters/card/activation.rb +24 -0
  39. data/lib/eml/uk/parameters/card/lock.rb +26 -0
  40. data/lib/eml/uk/parameters/card/register.rb +24 -0
  41. data/lib/eml/uk/parameters/card/reload.rb +24 -0
  42. data/lib/eml/uk/parameters/card/show.rb +102 -0
  43. data/lib/eml/uk/parameters/card/transaction.rb +59 -0
  44. data/lib/eml/uk/parameters/card/unload.rb +26 -0
  45. data/lib/eml/uk/parameters/card/unlock.rb +26 -0
  46. data/lib/eml/uk/parameters/card/void.rb +26 -0
  47. data/lib/eml/uk/payload.rb +94 -0
  48. data/lib/eml/uk/payload/agreement/show.rb +46 -0
  49. data/lib/eml/uk/payload/card/activation.rb +73 -0
  50. data/lib/eml/uk/payload/card/lock.rb +34 -0
  51. data/lib/eml/uk/payload/card/register.rb +70 -0
  52. data/lib/eml/uk/payload/card/reload.rb +38 -0
  53. data/lib/eml/uk/payload/card/show.rb +12 -0
  54. data/lib/eml/uk/payload/card/transaction.rb +12 -0
  55. data/lib/eml/uk/payload/card/unload.rb +38 -0
  56. data/lib/eml/uk/payload/card/unlock.rb +23 -0
  57. data/lib/eml/uk/payload/card/void.rb +23 -0
  58. data/lib/eml/uk/payload/contactentity.rb +64 -0
  59. data/lib/eml/uk/payload/iso.rb +48 -0
  60. data/lib/eml/uk/payload/location.rb +30 -0
  61. data/lib/eml/uk/resources/agreement.rb +32 -0
  62. data/lib/eml/uk/resources/card.rb +181 -0
  63. data/lib/eml/uk/response.rb +29 -0
  64. data/lib/eml/uk/responses/agreement/show.rb +16 -0
  65. data/lib/eml/uk/responses/card/reload.rb +19 -0
  66. data/lib/eml/uk/responses/card/show.rb +53 -0
  67. data/lib/eml/uk/responses/card/transaction.rb +24 -0
  68. data/lib/eml/version.rb +6 -0
  69. data/sorbet/config +2 -0
  70. data/sorbet/rbi/gems/addressable.rbi +198 -0
  71. data/sorbet/rbi/gems/ast.rbi +47 -0
  72. data/sorbet/rbi/gems/concurrent-ruby.rbi +218 -0
  73. data/sorbet/rbi/gems/crack.rbi +47 -0
  74. data/sorbet/rbi/gems/docile.rbi +31 -0
  75. data/sorbet/rbi/gems/domain_name.rbi +51 -0
  76. data/sorbet/rbi/gems/dotenv.rbi +67 -0
  77. data/sorbet/rbi/gems/faker.rbi +1350 -0
  78. data/sorbet/rbi/gems/hashdiff.rbi +65 -0
  79. data/sorbet/rbi/gems/http-cookie.rbi +92 -0
  80. data/sorbet/rbi/gems/http-form_data.rbi +73 -0
  81. data/sorbet/rbi/gems/http.rbi +609 -0
  82. data/sorbet/rbi/gems/http_parser.rb.rbi +36 -0
  83. data/sorbet/rbi/gems/i18n.rbi +191 -0
  84. data/sorbet/rbi/gems/jaro_winkler.rbi +14 -0
  85. data/sorbet/rbi/gems/parallel.rbi +81 -0
  86. data/sorbet/rbi/gems/parser.rbi +835 -0
  87. data/sorbet/rbi/gems/public_suffix.rbi +103 -0
  88. data/sorbet/rbi/gems/rainbow.rbi +117 -0
  89. data/sorbet/rbi/gems/rspec-core.rbi +1655 -0
  90. data/sorbet/rbi/gems/rspec-support.rbi +126 -0
  91. data/sorbet/rbi/gems/rspec.rbi +14 -0
  92. data/sorbet/rbi/gems/rubocop-performance.rbi +276 -0
  93. data/sorbet/rbi/gems/rubocop-rspec.rbi +860 -0
  94. data/sorbet/rbi/gems/rubocop.rbi +6943 -0
  95. data/sorbet/rbi/gems/ruby-progressbar.rbi +304 -0
  96. data/sorbet/rbi/gems/simplecov-html.rbi +30 -0
  97. data/sorbet/rbi/gems/simplecov.rbi +225 -0
  98. data/sorbet/rbi/gems/unf.rbi +18 -0
  99. data/sorbet/rbi/gems/unicode-display_width.rbi +16 -0
  100. data/sorbet/rbi/gems/vcr.rbi +503 -0
  101. data/sorbet/rbi/gems/webmock.rbi +521 -0
  102. data/sorbet/rbi/hidden-definitions/errors.txt +4802 -0
  103. data/sorbet/rbi/hidden-definitions/hidden.rbi +10700 -0
  104. data/sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi +8682 -0
  105. data/sorbet/rbi/sorbet-typed/lib/ruby/all/gem.rbi +4222 -0
  106. data/sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi +111 -0
  107. data/sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi +543 -0
  108. data/sorbet/rbi/todo.rbi +24 -0
  109. data/spec/config_spec.rb +26 -0
  110. data/spec/helpers/config_helper.rb +21 -0
  111. data/spec/helpers/vcr_helper.rb +19 -0
  112. data/spec/spec_helper.rb +120 -0
  113. data/spec/uk/api_resource_spec.rb +39 -0
  114. data/spec/uk/resources/agreement_spec.rb +23 -0
  115. data/spec/uk/resources/card_spec.rb +197 -0
  116. metadata +339 -0
@@ -0,0 +1,24 @@
1
+ # This file is autogenerated. Do not edit it by hand. Regenerate it with:
2
+ # srb rbi todo
3
+
4
+ # typed: strong
5
+ module ::Anonymous_Delegator_4; end
6
+ module ::Anonymous_Delegator_5; end
7
+ module ::Anonymous_Delegator_9; end
8
+ module T::Private::Methods::MethodHooks; end
9
+ module T::Private::Methods::MethodHooks; end
10
+ module T::Private::Methods::MethodHooks; end
11
+ module T::Private::Methods::MethodHooks; end
12
+ module T::Private::Methods::MethodHooks; end
13
+ module T::Private::Methods::MethodHooks; end
14
+ module T::Private::Methods::MethodHooks; end
15
+ module T::Private::Methods::MethodHooks; end
16
+ module T::Private::Methods::SingletonMethodHooks; end
17
+ module T::Private::Methods::SingletonMethodHooks; end
18
+ module T::Private::Methods::SingletonMethodHooks; end
19
+ module T::Private::Methods::SingletonMethodHooks; end
20
+ module T::Private::Methods::SingletonMethodHooks; end
21
+ module T::Private::Methods::SingletonMethodHooks; end
22
+ module T::Private::Methods::SingletonMethodHooks; end
23
+ module T::Private::Methods::SingletonMethodHooks; end
24
+ module T::Private::Methods::SingletonMethodHooks; end
@@ -0,0 +1,26 @@
1
+ # typed: ignore
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe EML::Config do
5
+ let(:config) { described_class.new }
6
+
7
+ describe "#environment=" do
8
+ after { config.environment = :test }
9
+
10
+ it "sets the environment" do
11
+ expect { config.environment = :production }.to(
12
+ change(config.environment, :production?).from(false).to(true)
13
+ )
14
+ end
15
+
16
+ context "when in invalid environment is supplied" do
17
+ specify do
18
+ expect { config.environment = :invalid }.to raise_error(ArgumentError)
19
+ end
20
+
21
+ specify do
22
+ expect { config.environment = "production" }.to raise_error(TypeError)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module EML
5
+ module Helpers
6
+ module Config
7
+ extend T::Sig
8
+
9
+ sig { void }
10
+ def configure_uk
11
+ EML::UK.configure do |config|
12
+ config.username = ENV["UK_REST_API_USERNAME"]
13
+ config.password = ENV["UK_REST_API_PASSWORD"]
14
+ config.merchant_group = ENV["UK_REST_API_MERCHANT_GROUP"]
15
+ config.program = ENV["UK_REST_API_PROGRAM"]
16
+ config.search_parameter = ENV["UK_REST_API_SEARCH_PARAMETER"]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module EML
5
+ module Helpers
6
+ module VCR
7
+ extend T::Sig
8
+
9
+ RE_RECORD_INTERVAL = T.let(86_400, Integer)
10
+
11
+ sig { params(path: String).void }
12
+ def self.with_cassette(path)
13
+ ::VCR.use_cassette(path, re_record_interval: RE_RECORD_INTERVAL) do
14
+ yield
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,120 @@
1
+ # typed: ignore
2
+ # frozen_string_literal: true
3
+
4
+ # This file was generated by the `rspec --init` command. Conventionally, all
5
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
6
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
7
+ # this file to always be loaded, without a need to explicitly require it in any
8
+ # files.
9
+ #
10
+ # Given that it is always loaded, you are encouraged to keep this file as
11
+ # light-weight as possible. Requiring heavyweight dependencies from this file
12
+ # will add to the boot time of your test suite on EVERY test run, even for an
13
+ # individual file that may not need all of that loaded. Instead, consider making
14
+ # a separate helper file that requires the additional dependencies and performs
15
+ # the additional setup, and require it from the spec files that actually need
16
+ # it.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+
20
+ ENV["ENV"] = "test"
21
+
22
+ require "simplecov"
23
+ SimpleCov.start do
24
+ add_filter "/spec/"
25
+
26
+ add_group(
27
+ "API Operations", %w[lib/eml/api_operations.rb lib/eml/api_operation/]
28
+ )
29
+ add_group "UK", %w[lib/eml/uk.rb lib/eml/uk/]
30
+ end
31
+
32
+ require "date"
33
+ require "dotenv/load"
34
+ require "eml"
35
+ require "faker"
36
+ require "webmock/rspec"
37
+
38
+ RSpec.configure do |config|
39
+ # rspec-expectations config goes here. You can use an alternate
40
+ # assertion/expectation library such as wrong or the stdlib/minitest
41
+ # assertions if you prefer.
42
+ config.expect_with :rspec do |expectations|
43
+ # This option will default to `true` in RSpec 4. It makes the `description`
44
+ # and `failure_message` of custom matchers include text for helper methods
45
+ # defined using `chain`, e.g.:
46
+ # be_bigger_than(2).and_smaller_than(4).description
47
+ # # => "be bigger than 2 and smaller than 4"
48
+ # ...rather than:
49
+ # # => "be bigger than 2"
50
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
51
+ end
52
+
53
+ # rspec-mocks config goes here. You can use an alternate test double
54
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
55
+ config.mock_with :rspec do |mocks|
56
+ # Prevents you from mocking or stubbing a method that does not exist on
57
+ # a real object. This is generally recommended, and will default to
58
+ # `true` in RSpec 4.
59
+ mocks.verify_partial_doubles = true
60
+ end
61
+
62
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
63
+ # have no way to turn it off -- the option exists only for backwards
64
+ # compatibility in RSpec 3). It causes shared context metadata to be
65
+ # inherited by the metadata hash of host groups and examples, rather than
66
+ # triggering implicit auto-inclusion in groups with matching metadata.
67
+ config.shared_context_metadata_behavior = :apply_to_host_groups
68
+
69
+ # This allows you to limit a spec run to individual examples or groups
70
+ # you care about by tagging them with `:focus` metadata. When nothing
71
+ # is tagged with `:focus`, all examples get run. RSpec also provides
72
+ # aliases for `it`, `describe`, and `context` that include `:focus`
73
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
74
+ config.filter_run_when_matching :focus
75
+
76
+ # Allows RSpec to persist some state between runs in order to support
77
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
78
+ # you configure your source control system to ignore this file.
79
+ config.example_status_persistence_file_path = "spec/examples.txt"
80
+
81
+ # Limits the available syntax to the non-monkey patched syntax that is
82
+ # recommended. For more details, see:
83
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
84
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
85
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
86
+ config.disable_monkey_patching!
87
+
88
+ # This setting enables warnings. It's recommended, but in some cases may
89
+ # be too noisy due to issues in dependencies.
90
+ config.warnings = true
91
+
92
+ # Many RSpec users commonly either run the entire suite or an individual
93
+ # file, and it's useful to allow more verbose output when running an
94
+ # individual spec file.
95
+ if config.files_to_run.one?
96
+ # Use the documentation formatter for detailed output,
97
+ # unless a formatter has already been configured
98
+ # (e.g. via a command-line flag).
99
+ config.default_formatter = "doc"
100
+ end
101
+
102
+ # Print the 10 slowest examples and example groups at the
103
+ # end of the spec run, to help surface which specs are running
104
+ # particularly slow.
105
+ config.profile_examples = 10
106
+
107
+ # Some of the tests need to be run in order, for example activating and
108
+ # voiding a card can not be performed out of order
109
+ config.order = :defined
110
+ end
111
+
112
+ %w[helpers shared_examples].each do |directory|
113
+ Dir[File.dirname(__FILE__) + "/#{directory}/**/*.rb"].each { |f| require f }
114
+ end
115
+
116
+ require "vcr"
117
+ VCR.configure do |config|
118
+ config.cassette_library_dir = "spec/vcr_cassettes"
119
+ config.hook_into :webmock
120
+ end
@@ -0,0 +1,39 @@
1
+ # typed: ignore
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe EML::UK::APIResource do
5
+ extend EML::Helpers::Config
6
+ configure_uk
7
+
8
+ describe ".request" do
9
+ context "when the credentials are wrong" do
10
+ before do
11
+ EML::UK.configure do |config|
12
+ config.username = "username"
13
+ config.password = "password"
14
+ end
15
+
16
+ allow(described_class).to receive(:const_get).with(:ENDPOINT_BASE).
17
+ and_return("cards")
18
+ allow(EML::UK::Payload).to receive(:convert).and_return({})
19
+ allow(EML::UK::Parameters).to receive(:convert).and_return({})
20
+ end
21
+
22
+ after do
23
+ EML::UK.configure do |config|
24
+ config.username = ENV["UK_REST_API_USERNAME"]
25
+ config.password = ENV["UK_REST_API_PASSWORD"]
26
+ end
27
+ end
28
+
29
+ let(:cassette) { "uk/api_resource/authentiction_error" }
30
+
31
+ it "raises an AuthenticationError" do
32
+ EML::Helpers::VCR.with_cassette(cassette) do
33
+ expect { described_class.new.request(:get, "") }.
34
+ to raise_error(EML::REST::AuthenticationError)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ # typed: ignore
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe EML::UK::Agreement do
5
+ extend EML::Helpers::Config
6
+ configure_uk
7
+
8
+ describe ".show" do
9
+ it "gives an ok response" do
10
+ EML::Helpers::VCR.with_cassette("uk/agreement/show") do
11
+ response = described_class.show
12
+ expect(response.success?).to be true
13
+ end
14
+ end
15
+
16
+ it "retreives a URL" do
17
+ EML::Helpers::VCR.with_cassette("uk/agreement/show") do
18
+ response = described_class.show
19
+ expect(response.pdf_url.match?(%r{https://.+\.pdf})).to be true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,197 @@
1
+ # typed: ignore
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe EML::UK::Card do
5
+ extend EML::Helpers::Config
6
+ configure_uk
7
+
8
+ let(:card_id) { ENV["UK_CARD_EXTERNAL_ID"] }
9
+ let(:location) do
10
+ {
11
+ name: "Number 10",
12
+ address1: "10 Downing St",
13
+ city: "Westminster",
14
+ province: "LND",
15
+ postal_code: "SW1A 2AA",
16
+ country: "GBR",
17
+ }
18
+ end
19
+
20
+ describe ".activate" do
21
+ let(:payload) do
22
+ {
23
+ amount: 0,
24
+ location: location,
25
+ client_order_date: DateTime.now,
26
+ sales_channel: "Online",
27
+ }
28
+ end
29
+
30
+ # it "activates the card" do
31
+ # EML::Helpers::VCR.with_cassette("uk/card/activation") do
32
+ # response = described_class.activate(card_id, payload)
33
+ # expect(response.success?).to be true
34
+ # end
35
+ # end
36
+
37
+ context "when the card is already active" do
38
+ it "raises an UnprocessableEntityError" do
39
+ cassette = "uk/card/activation/unprocessable"
40
+ EML::Helpers::VCR.with_cassette(cassette) do
41
+ expect { described_class.activate(id: card_id, payload: payload) }.
42
+ to raise_error(EML::REST::UnprocessableEntityError)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ describe ".register" do
49
+ let(:payload) do
50
+ location.delete(:name)
51
+ {
52
+ first_name: "Adam",
53
+ last_name: "Quitzon",
54
+ email: "not.an@ddress.fake",
55
+ }.merge(location)
56
+ end
57
+
58
+ it "registers the card" do
59
+ EML::Helpers::VCR.with_cassette("uk/card/register") do
60
+ response = described_class.register(id: card_id, payload: payload)
61
+ expect(response.success?).to be true
62
+ end
63
+ end
64
+
65
+ context "when the DOB is in the wrong format" do
66
+ it "raises an ArgumentError" do
67
+ payload[:dob] = "31012000"
68
+ cassette = "uk/card/register/dob"
69
+ EML::Helpers::VCR.with_cassette(cassette) do
70
+ expect { described_class.register(id: card_id, payload: payload) }.
71
+ to raise_error(ArgumentError)
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ describe ".reload" do
78
+ let(:payload) do
79
+ {
80
+ amount: 1.00,
81
+ location: location,
82
+ }
83
+ end
84
+
85
+ it "loads funds onto the card" do
86
+ EML::Helpers::VCR.with_cassette("uk/card/reload") do
87
+ response = described_class.reload(id: card_id, payload: payload)
88
+ expect(response.body["adjusted_balance"]).to eq(1)
89
+ end
90
+ end
91
+ end
92
+
93
+ describe ".show" do
94
+ it "gives an ok response" do
95
+ EML::Helpers::VCR.with_cassette("uk/card/show") do
96
+ response = described_class.show(id: card_id)
97
+ expect(response.success?).to be true
98
+ end
99
+ end
100
+
101
+ it "returns the information about the card" do
102
+ EML::Helpers::VCR.with_cassette("uk/card/show") do
103
+ response = described_class.show(id: card_id)
104
+ expect(response.body["actual_balance"]).to eq(1)
105
+ end
106
+ end
107
+ end
108
+
109
+ describe ".transactions" do
110
+ it "gives an ok response" do
111
+ EML::Helpers::VCR.with_cassette("uk/card/transactions") do
112
+ response = described_class.transactions(id: card_id)
113
+ expect(response.success?).to be true
114
+ end
115
+ end
116
+
117
+ it "get the transactions" do
118
+ EML::Helpers::VCR.with_cassette("uk/card/transactions") do
119
+ response = described_class.transactions(id: card_id)
120
+ expect(response.transactions.length).to be > 0
121
+ end
122
+ end
123
+ end
124
+
125
+ describe ".unload" do
126
+ let(:payload) do
127
+ {
128
+ amount: 1.00,
129
+ location: location,
130
+ note: "Unloading test",
131
+ }
132
+ end
133
+
134
+ it "removes funds from the card" do
135
+ EML::Helpers::VCR.with_cassette("uk/card/unload") do
136
+ response = described_class.unload(id: card_id, payload: payload)
137
+ expect(response.body["adjusted_balance"]).to eq(0)
138
+ end
139
+ end
140
+ end
141
+
142
+ describe ".lock" do
143
+ let(:payload) do
144
+ {
145
+ note: "Test suite",
146
+ reason: "Stolen",
147
+ }
148
+ end
149
+
150
+ it "locks the card" do
151
+ EML::Helpers::VCR.with_cassette("uk/card/lock") do
152
+ response = described_class.lock(id: card_id, payload: payload)
153
+ expect(response.success?).to be true
154
+ end
155
+ end
156
+
157
+ context "when the reason is invalid" do
158
+ before { payload[:reason] = "InvalidReason" }
159
+
160
+ it "raises an Argument error" do
161
+ expect { described_class.lock(id: card_id, payload: payload) }.
162
+ to raise_error(ArgumentError)
163
+ end
164
+ end
165
+
166
+ context "when the card is already locked" do
167
+ it "raises an UnprocessableEntityError" do
168
+ EML::Helpers::VCR.with_cassette("uk/card/lock/unprocessable") do
169
+ expect { described_class.lock(id: card_id, payload: payload) }.
170
+ to raise_error(EML::REST::UnprocessableEntityError)
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ describe ".unlock" do
177
+ let(:payload) do
178
+ { note: "Test suite" }
179
+ end
180
+
181
+ it "unlocks the card" do
182
+ EML::Helpers::VCR.with_cassette("uk/card/unlock") do
183
+ response = described_class.unlock(id: card_id, payload: payload)
184
+ expect(response.success?).to be true
185
+ end
186
+ end
187
+
188
+ context "when the card is already unlocked" do
189
+ it "raises an UnprocessableEntityError" do
190
+ EML::Helpers::VCR.with_cassette("uk/card/unlock/unprocessable") do
191
+ expect { described_class.unlock(id: card_id, payload: payload) }.
192
+ to raise_error(EML::REST::UnprocessableEntityError)
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end