From f71e1c9318c820e6ec6e2345f3286fb4ac3f08e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Tue, 26 Nov 2019 11:54:17 +0100 Subject: [PATCH 01/12] First full endpoint implemented in the wrapper: Flanks::Token.create --- .rspec | 2 + .ruby-version | 1 + Gemfile.lock | 12 ++-- README.md | 7 ++ flanks.gemspec | 6 +- lib/flanks.rb | 5 ++ lib/flanks/base.rb | 52 ++++++++++++++ lib/flanks/configuration.rb | 1 + lib/flanks/error.rb | 9 +++ lib/flanks/resource.rb | 101 ++++++++++++++++++++++++++++ lib/flanks/resources/token.rb | 22 ++++++ spec/flanks/resources/token_spec.rb | 31 +++++++++ spec/flanks/version_spec.rb | 9 +++ spec/flanks_spec.rb | 7 -- spec/responses/token/create.json | 7 ++ spec/spec_helper.rb | 11 +-- 16 files changed, 263 insertions(+), 20 deletions(-) create mode 100644 .rspec create mode 100644 .ruby-version create mode 100644 lib/flanks/base.rb create mode 100644 lib/flanks/error.rb create mode 100644 lib/flanks/resource.rb create mode 100644 lib/flanks/resources/token.rb create mode 100644 spec/flanks/resources/token_spec.rb create mode 100644 spec/flanks/version_spec.rb delete mode 100644 spec/flanks_spec.rb create mode 100644 spec/responses/token/create.json diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..8c18f1a --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--format documentation +--color diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..005119b --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.4.1 diff --git a/Gemfile.lock b/Gemfile.lock index 735b54d..197585d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -44,10 +44,10 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.6) - webmock (2.3.2) + webmock (3.7.6) addressable (>= 2.3.6) crack (>= 0.3.2) - hashdiff + hashdiff (>= 0.4.0, < 2.0.0) PLATFORMS ruby @@ -55,9 +55,9 @@ PLATFORMS DEPENDENCIES bundler flanks-api-ruby! - rake (~> 10.0) - rspec (~> 3.0) - webmock (~> 2.3.1) + rake + rspec + webmock BUNDLED WITH - 1.16.1 + 1.17.3 diff --git a/README.md b/README.md index 174cb8e..6f78a0c 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,10 @@ Changelog --------- * v.0.1.0 TBD + +About Flanks +------------ + +* [Public site](https://www.flanks.io/) +* [Documentation](https://docs.flanks.io/) +* [Platform](https://platform.flanks.io/) diff --git a/flanks.gemspec b/flanks.gemspec index 7f08297..cf63299 100644 --- a/flanks.gemspec +++ b/flanks.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |spec| spec.add_dependency "rest-client", "~> 2.0.2" spec.add_development_dependency "bundler" - spec.add_development_dependency "rake", "~> 10.0" - spec.add_development_dependency "rspec", "~> 3.0" - spec.add_development_dependency "webmock", "~> 2.3.1" + spec.add_development_dependency "rake" + spec.add_development_dependency "rspec" + spec.add_development_dependency "webmock" end diff --git a/lib/flanks.rb b/lib/flanks.rb index cc59870..d43ac8a 100644 --- a/lib/flanks.rb +++ b/lib/flanks.rb @@ -1,2 +1,7 @@ require 'flanks/version' require 'flanks/configuration' +require 'flanks/base' +require 'flanks/error' +require 'flanks/resource' + +require 'flanks/resources/token' diff --git a/lib/flanks/base.rb b/lib/flanks/base.rb new file mode 100644 index 0000000..6fdfe37 --- /dev/null +++ b/lib/flanks/base.rb @@ -0,0 +1,52 @@ +require 'rest-client' +require 'json' + +module Flanks + BASE_URL = 'https://api.flanks.io' + + class << self + attr_accessor :configuration + + def configuration + @configuration ||= Configuration.new + end + + def configure + yield(configuration) + end + + def api_call(method:, path:, params: {}, token: nil) + url = Flanks.const_get(:BASE_URL) + path + + headers = if token.nil? + { 'Content-Type' => 'application/json' } + else + # TODO + end + + if method == :post + payload = params.to_json + else + headers.merge!(params: params) + end + + request_params = { + method: method, + url: url, + headers: headers, + payload: payload + } + + begin + response = RestClient::Request.execute(request_params) + return {} if response.empty? + + JSON.parse(response) + rescue StandardError => error + # TODO handle properly + response = JSON.parse(error.response) + raise Error.new(response['error']) + end + end + end +end diff --git a/lib/flanks/configuration.rb b/lib/flanks/configuration.rb index 99954c0..08d9f55 100644 --- a/lib/flanks/configuration.rb +++ b/lib/flanks/configuration.rb @@ -1,4 +1,5 @@ module Flanks class Configuration + attr_accessor :client_id, :client_secret, :username, :password end end diff --git a/lib/flanks/error.rb b/lib/flanks/error.rb new file mode 100644 index 0000000..3d62a70 --- /dev/null +++ b/lib/flanks/error.rb @@ -0,0 +1,9 @@ +module Flanks + class Error < StandardError + attr_reader :message + + def initialize(message) + @message = message + end + end +end diff --git a/lib/flanks/resource.rb b/lib/flanks/resource.rb new file mode 100644 index 0000000..3a82b3c --- /dev/null +++ b/lib/flanks/resource.rb @@ -0,0 +1,101 @@ +module Flanks + class Resource + def initialize(data, token = nil) + @token = token + generate_attr_readers + set_data(data) + end + + def fields + self.class.fields + end + + def resources + self.class.resources + end + + def collections + self.class.collections + end + + private + + def generate_attr_readers + fields.each do |field| + define_singleton_method(field) do + load_data! if instance_variable_get("@#{field}").nil? + instance_variable_get("@#{field}") + end + end + + (resources + collections).each do |resource| + define_singleton_method(resource[:name]) do + load_data! if instance_variable_get("@#{resource[:name]}").nil? + instance_variable_get("@#{resource[:name]}") + end + end + end + + def set_data(data) + fields.each do |field| + next unless data.key?(field.to_s) + instance_variable_set("@#{field}", data[field.to_s]) + end + + resources.each do |resource| + next unless data.key?(resource[:name].to_s) + klass = Object.const_get("Flanks::#{resource[:klass]}") + instance_variable_set("@#{resource[:name]}", klass.new(data[resource[:name].to_s], @token)) + end + + collections.each do |collection| + next unless data[collection[:name].to_s] + klass = Object.const_get("Flanks::#{collection[:klass]}") + arr = data[collection[:name].to_s].map { |item | klass.new(item, @token) } + instance_variable_set("@#{collection[:name]}", arr) + instance_variable_set("@#{collection[:name]}_ids", arr.map(&:id)) + end + end + + def load_data! + return if @loaded + response = Flanks.api_call(method: :get, path: @resource_uri, token: @token) + set_data(response) + @loaded = true + end + + class << self + def fields + @fields || [:resource_type, :resource_uri] + end + + def resources + @resources || [] + end + + def collections + @collections || [] + end + + def auth_delegate(name, options) + define_method(name) do |*args| + klass = Object.const_get("Flanks::#{options[:class]}") + klass.send(options[:method], self.token, *args) + end + end + + def has_fields(*new_fields) + @fields = (fields + new_fields).uniq + end + + def has_resource(name, klass) + @resources = resources << { name: name, klass: klass } + end + + def has_collection(name, klass) + @collections = collections << { name: name, klass: klass } + attr_reader :"#{name}_ids" + end + end + end +end diff --git a/lib/flanks/resources/token.rb b/lib/flanks/resources/token.rb new file mode 100644 index 0000000..3e5ab96 --- /dev/null +++ b/lib/flanks/resources/token.rb @@ -0,0 +1,22 @@ +module Flanks + class Token < Resource + RESOURCE_PATH = '/v0/token' + + has_fields :access_token, :expires_in, :token_type, :scope, :refresh_token + + def self.create + response = Flanks.api_call( + method: :post, + path: RESOURCE_PATH, + params: { + client_id: Flanks.configuration.client_id, + client_secret: Flanks.configuration.client_secret, + username: Flanks.configuration.username, + password: Flanks.configuration.password, + grant_type: 'password' + } + ) + new(response) + end + end +end diff --git a/spec/flanks/resources/token_spec.rb b/spec/flanks/resources/token_spec.rb new file mode 100644 index 0000000..8efc5dc --- /dev/null +++ b/spec/flanks/resources/token_spec.rb @@ -0,0 +1,31 @@ +require "spec_helper" + +module Flanks + describe Token do + before do + configure_flanks + end + + describe "#create" do + before do + stub_request(:post, "https://api.flanks.io/v0/token"). + with( + body: '{"client_id":"a_client_id","client_secret":"the_super_secret_stuff","username":"an_email","password":"le_password","grant_type":"password"}', + headers: { 'Content-Type' => 'application/json' } + ). + to_return(status: 200, body: response_json(resource: 'token', action: 'create')) + end + + it "works" do + token = Flanks::Token.create + + expect(token.class).to eq(Flanks::Token) + expect(token.access_token).to eq("aPscYAeKMbvLpWYgNYvtHUtsMOHxMT") + expect(token.expires_in).to eq(36000) + expect(token.token_type).to eq("Bearer") + expect(token.scope).to eq("read write aggregation payment") + expect(token.refresh_token).to eq("VwkqYDisjvIWNKJGjbFuOcyEacQchT") + end + end + end +end diff --git a/spec/flanks/version_spec.rb b/spec/flanks/version_spec.rb new file mode 100644 index 0000000..ce0a841 --- /dev/null +++ b/spec/flanks/version_spec.rb @@ -0,0 +1,9 @@ +require "spec_helper" + +module Flanks + describe "Flanks::VERSION" do + it "is the proper one" do + expect(Flanks::VERSION).to eq("0.1.0") + end + end +end diff --git a/spec/flanks_spec.rb b/spec/flanks_spec.rb deleted file mode 100644 index c31d012..0000000 --- a/spec/flanks_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "spec_helper" - -describe Flanks do - it "has a version number" do - expect(Flanks::VERSION).to eq("0.1.0") - end -end diff --git a/spec/responses/token/create.json b/spec/responses/token/create.json new file mode 100644 index 0000000..a0aa5f0 --- /dev/null +++ b/spec/responses/token/create.json @@ -0,0 +1,7 @@ +{ + "access_token": "aPscYAeKMbvLpWYgNYvtHUtsMOHxMT", + "expires_in": 36000, + "token_type": "Bearer", + "scope": "read write aggregation payment", + "refresh_token": "VwkqYDisjvIWNKJGjbFuOcyEacQchT" +} diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 19bc2e7..c2c00e2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,13 +2,16 @@ require 'webmock/rspec' require "flanks" -def response_json(filename) - path = File.join('spec', 'responses', "#{filename}.json") +def response_json(resource:, action:) + path = File.join('spec', 'responses', resource, "#{action}.json") File.read(path) end -def configure_bankin +def configure_flanks Flanks.configure do |config| - # TODO + config.client_id = 'a_client_id' + config.client_secret = 'the_super_secret_stuff' + config.username = 'an_email' + config.password = 'le_password' end end From 775d0fc9667c39c4bda64a7e87baade6fb1a82f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Wed, 27 Nov 2019 12:50:00 +0100 Subject: [PATCH 02/12] Flanks::Account.get added --- lib/flanks.rb | 1 + lib/flanks/base.rb | 11 +++---- lib/flanks/resources/account.rb | 20 ++++++++++++ spec/flanks/resources/account_spec.rb | 45 +++++++++++++++++++++++++++ spec/responses/account/get.json | 14 +++++++++ 5 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 lib/flanks/resources/account.rb create mode 100644 spec/flanks/resources/account_spec.rb create mode 100644 spec/responses/account/get.json diff --git a/lib/flanks.rb b/lib/flanks.rb index d43ac8a..d595897 100644 --- a/lib/flanks.rb +++ b/lib/flanks.rb @@ -4,4 +4,5 @@ require 'flanks/error' require 'flanks/resource' +require 'flanks/resources/account' require 'flanks/resources/token' diff --git a/lib/flanks/base.rb b/lib/flanks/base.rb index 6fdfe37..35d1341 100644 --- a/lib/flanks/base.rb +++ b/lib/flanks/base.rb @@ -18,16 +18,15 @@ def configure def api_call(method:, path:, params: {}, token: nil) url = Flanks.const_get(:BASE_URL) + path - headers = if token.nil? - { 'Content-Type' => 'application/json' } - else - # TODO - end + headers = { 'Content-Type' => 'application/json' } if method == :post payload = params.to_json else - headers.merge!(params: params) + headers.merge!( + Authorization: "Bearer #{token}", + params: params + ) end request_params = { diff --git a/lib/flanks/resources/account.rb b/lib/flanks/resources/account.rb new file mode 100644 index 0000000..e80c560 --- /dev/null +++ b/lib/flanks/resources/account.rb @@ -0,0 +1,20 @@ +module Flanks + class Account < Resource + RESOURCE_PATH = '/v0/bank/credentials/account' + + has_fields :iban, :entity, :alias, :balance, :currency, :description, + :isOwner, :numOwners, :owners, :_id + + def self.get(token:, credentials_token:) + response = Flanks.api_call( + method: :get, + path: RESOURCE_PATH, + token: token, + params: { + credentials_token: credentials_token + } + ) + new(response) + end + end +end diff --git a/spec/flanks/resources/account_spec.rb b/spec/flanks/resources/account_spec.rb new file mode 100644 index 0000000..353c712 --- /dev/null +++ b/spec/flanks/resources/account_spec.rb @@ -0,0 +1,45 @@ +require "spec_helper" + +module Flanks + describe Account do + before do + configure_flanks + end + + describe "#get" do + before do + stub_request(:get, "https://api.flanks.io/v0/bank/credentials/account?credentials_token=THE_TOKCREDENTIALS"). + with( + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' + } + ). + to_return(status: 200, body: response_json(resource: 'account', action: 'get')) + end + + it "works" do + account = Flanks::Account.get( + token: 'THIS_IS_EL_BUEN_TOKEN', + credentials_token: 'THE_TOKCREDENTIALS' + ) + + expect(account.class).to eq(Flanks::Account) + expect(account.iban).to eq("ES4501822763517295596839") + expect(account.entity).to eq("Banco Random") + expect(account.alias).to eq("Cuenta Random de Ahorros") + expect(account.balance).to eq(1034.19) + expect(account.currency).to eq("EUR") + expect(account.description).to eq("La boena descrepsión") + expect(account.isOwner).to be_truthy + expect(account.numOwners).to eq(3) + expect(account.owners).to eq( + [ + "Juanita admin", "Pepito colaborador", "Florencia gestora" + ] + ) + expect(account._id).to eq("abc12340a0011234fda") + end + end + end +end diff --git a/spec/responses/account/get.json b/spec/responses/account/get.json new file mode 100644 index 0000000..2d4809f --- /dev/null +++ b/spec/responses/account/get.json @@ -0,0 +1,14 @@ +{ + "iban": "ES4501822763517295596839", + "entity": "Banco Random", + "alias": "Cuenta Random de Ahorros", + "balance": 1034.19, + "currency": "EUR", + "description": "La boena descrepsión", + "isOwner": true, + "numOwners": 3, + "owners": [ + "Juanita admin", "Pepito colaborador", "Florencia gestora" + ], + "_id": "abc12340a0011234fda" +} From f5a5ca53f231f7464d5169c5bc4dc246cfa3aa10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Wed, 27 Nov 2019 13:28:14 +0100 Subject: [PATCH 03/12] Add logging --- lib/flanks/base.rb | 46 ++++++++++++++++++ lib/flanks/configuration.rb | 2 +- spec/flanks/base_spec.rb | 62 ++++++++++++++++++++++++ spec/flanks/resources/account_spec.rb | 70 +++++++++++++-------------- spec/flanks/resources/token_spec.rb | 42 ++++++++-------- spec/flanks/version_spec.rb | 8 ++- 6 files changed, 166 insertions(+), 64 deletions(-) create mode 100644 spec/flanks/base_spec.rb diff --git a/lib/flanks/base.rb b/lib/flanks/base.rb index 35d1341..e28b828 100644 --- a/lib/flanks/base.rb +++ b/lib/flanks/base.rb @@ -3,6 +3,8 @@ module Flanks BASE_URL = 'https://api.flanks.io' + SENSIBLE_HEADERS = %w{Authorization} + SENSIBLE_PARAMS = %w{client_secret password credentials_token} class << self attr_accessor :configuration @@ -29,6 +31,8 @@ def api_call(method:, path:, params: {}, token: nil) ) end + log_request(method, url, headers, params) + request_params = { method: method, url: url, @@ -47,5 +51,47 @@ def api_call(method:, path:, params: {}, token: nil) raise Error.new(response['error']) end end + + def log_request(method, url, headers, params) + log_message("") + log_message("=> #{method.upcase} #{url}") + + log_message("* Headers") + headers.each do |key, value| + next if key == :params + + safe_value = if SENSIBLE_HEADERS.include?(key.to_s) + "" + else + value + end + + log_message("#{key}: #{safe_value}") + end + + if params.any? + log_message("* Params") + params.each do |key, value| + safe_value = if SENSIBLE_PARAMS.include?(key.to_s) + "" + else + value + end + + log_message("#{key}: #{safe_value}") + end + else + log_message("* No params") + end + end + + def log_message(message) + return if message.nil? + + logger = Flanks.configuration.logger + return if logger.nil? + + logger.info(message) + end end end diff --git a/lib/flanks/configuration.rb b/lib/flanks/configuration.rb index 08d9f55..a26876e 100644 --- a/lib/flanks/configuration.rb +++ b/lib/flanks/configuration.rb @@ -1,5 +1,5 @@ module Flanks class Configuration - attr_accessor :client_id, :client_secret, :username, :password + attr_accessor :client_id, :client_secret, :username, :password, :logger end end diff --git a/spec/flanks/base_spec.rb b/spec/flanks/base_spec.rb new file mode 100644 index 0000000..b336852 --- /dev/null +++ b/spec/flanks/base_spec.rb @@ -0,0 +1,62 @@ +require "spec_helper" + +describe Flanks do + describe "#configuration" do + # TODO + end + + describe "#configure" do + # TODO + end + + describe "#api_call" do + # TODO + end + + describe "#log_request" do + # TODO + end + + describe "#log_message" do + context "without a message" do + it "does not call the logger" do + expect(Logger).not_to receive(:new) + + subject.log_message(nil) + end + end + + context "with a non-empty message" do + context "with a nil Flanks.configuration.logger" do + before do + allow(Flanks).to receive_message_chain(:configuration, :logger) { + nil + } + end + + it "does not call the logger" do + expect(Flanks.configuration.logger).not_to receive(:info) + + subject.log_message("cucamonga") + end + end + + context "with a set-up logger" do + before do + logger = double(Logger) + allow(logger).to receive(:info) { } + + allow(Flanks).to receive_message_chain(:configuration, :logger) { + logger + } + end + + it "calls the logger properly" do + expect(Flanks.configuration.logger).to receive(:info).with("cucamonga").once + + subject.log_message("cucamonga") + end + end + end + end +end diff --git a/spec/flanks/resources/account_spec.rb b/spec/flanks/resources/account_spec.rb index 353c712..dbecd9e 100644 --- a/spec/flanks/resources/account_spec.rb +++ b/spec/flanks/resources/account_spec.rb @@ -1,45 +1,43 @@ require "spec_helper" -module Flanks - describe Account do +describe Flanks::Account do + before do + configure_flanks + end + + describe "#get" do before do - configure_flanks + stub_request(:get, "https://api.flanks.io/v0/bank/credentials/account?credentials_token=THE_TOKCREDENTIALS"). + with( + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' + } + ). + to_return(status: 200, body: response_json(resource: 'account', action: 'get')) end - describe "#get" do - before do - stub_request(:get, "https://api.flanks.io/v0/bank/credentials/account?credentials_token=THE_TOKCREDENTIALS"). - with( - headers: { - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' - } - ). - to_return(status: 200, body: response_json(resource: 'account', action: 'get')) - end - - it "works" do - account = Flanks::Account.get( - token: 'THIS_IS_EL_BUEN_TOKEN', - credentials_token: 'THE_TOKCREDENTIALS' - ) + it "works" do + account = Flanks::Account.get( + token: 'THIS_IS_EL_BUEN_TOKEN', + credentials_token: 'THE_TOKCREDENTIALS' + ) - expect(account.class).to eq(Flanks::Account) - expect(account.iban).to eq("ES4501822763517295596839") - expect(account.entity).to eq("Banco Random") - expect(account.alias).to eq("Cuenta Random de Ahorros") - expect(account.balance).to eq(1034.19) - expect(account.currency).to eq("EUR") - expect(account.description).to eq("La boena descrepsión") - expect(account.isOwner).to be_truthy - expect(account.numOwners).to eq(3) - expect(account.owners).to eq( - [ - "Juanita admin", "Pepito colaborador", "Florencia gestora" - ] - ) - expect(account._id).to eq("abc12340a0011234fda") - end + expect(account.class).to eq(Flanks::Account) + expect(account.iban).to eq("ES4501822763517295596839") + expect(account.entity).to eq("Banco Random") + expect(account.alias).to eq("Cuenta Random de Ahorros") + expect(account.balance).to eq(1034.19) + expect(account.currency).to eq("EUR") + expect(account.description).to eq("La boena descrepsión") + expect(account.isOwner).to be_truthy + expect(account.numOwners).to eq(3) + expect(account.owners).to eq( + [ + "Juanita admin", "Pepito colaborador", "Florencia gestora" + ] + ) + expect(account._id).to eq("abc12340a0011234fda") end end end diff --git a/spec/flanks/resources/token_spec.rb b/spec/flanks/resources/token_spec.rb index 8efc5dc..109d560 100644 --- a/spec/flanks/resources/token_spec.rb +++ b/spec/flanks/resources/token_spec.rb @@ -1,31 +1,29 @@ require "spec_helper" -module Flanks - describe Token do +describe Flanks::Token do + before do + configure_flanks + end + + describe "#create" do before do - configure_flanks + stub_request(:post, "https://api.flanks.io/v0/token"). + with( + body: '{"client_id":"a_client_id","client_secret":"the_super_secret_stuff","username":"an_email","password":"le_password","grant_type":"password"}', + headers: { 'Content-Type' => 'application/json' } + ). + to_return(status: 200, body: response_json(resource: 'token', action: 'create')) end - describe "#create" do - before do - stub_request(:post, "https://api.flanks.io/v0/token"). - with( - body: '{"client_id":"a_client_id","client_secret":"the_super_secret_stuff","username":"an_email","password":"le_password","grant_type":"password"}', - headers: { 'Content-Type' => 'application/json' } - ). - to_return(status: 200, body: response_json(resource: 'token', action: 'create')) - end - - it "works" do - token = Flanks::Token.create + it "works" do + token = Flanks::Token.create - expect(token.class).to eq(Flanks::Token) - expect(token.access_token).to eq("aPscYAeKMbvLpWYgNYvtHUtsMOHxMT") - expect(token.expires_in).to eq(36000) - expect(token.token_type).to eq("Bearer") - expect(token.scope).to eq("read write aggregation payment") - expect(token.refresh_token).to eq("VwkqYDisjvIWNKJGjbFuOcyEacQchT") - end + expect(token.class).to eq(Flanks::Token) + expect(token.access_token).to eq("aPscYAeKMbvLpWYgNYvtHUtsMOHxMT") + expect(token.expires_in).to eq(36000) + expect(token.token_type).to eq("Bearer") + expect(token.scope).to eq("read write aggregation payment") + expect(token.refresh_token).to eq("VwkqYDisjvIWNKJGjbFuOcyEacQchT") end end end diff --git a/spec/flanks/version_spec.rb b/spec/flanks/version_spec.rb index ce0a841..4a51e23 100644 --- a/spec/flanks/version_spec.rb +++ b/spec/flanks/version_spec.rb @@ -1,9 +1,7 @@ require "spec_helper" -module Flanks - describe "Flanks::VERSION" do - it "is the proper one" do - expect(Flanks::VERSION).to eq("0.1.0") - end +describe "Flanks::VERSION" do + it "is the proper one" do + expect(Flanks::VERSION).to eq("0.1.0") end end From e09886ce42932d004002e4871a37cc8325b5370e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Wed, 27 Nov 2019 15:31:26 +0100 Subject: [PATCH 04/12] Flanks::Bank.list added --- lib/flanks.rb | 2 ++ lib/flanks/collection.rb | 55 ++++++++++++++++++++++++++++++ lib/flanks/resources/bank.rb | 16 +++++++++ spec/flanks/resources/bank_spec.rb | 41 ++++++++++++++++++++++ spec/responses/bank/list.json | 14 ++++++++ 5 files changed, 128 insertions(+) create mode 100644 lib/flanks/collection.rb create mode 100644 lib/flanks/resources/bank.rb create mode 100644 spec/flanks/resources/bank_spec.rb create mode 100644 spec/responses/bank/list.json diff --git a/lib/flanks.rb b/lib/flanks.rb index d595897..b61dbd0 100644 --- a/lib/flanks.rb +++ b/lib/flanks.rb @@ -3,6 +3,8 @@ require 'flanks/base' require 'flanks/error' require 'flanks/resource' +require 'flanks/collection' require 'flanks/resources/account' +require 'flanks/resources/bank' require 'flanks/resources/token' diff --git a/lib/flanks/collection.rb b/lib/flanks/collection.rb new file mode 100644 index 0000000..286bd83 --- /dev/null +++ b/lib/flanks/collection.rb @@ -0,0 +1,55 @@ +module Flanks + class Collection < Array + def initialize(response, item_class, token = nil) + @item_class = item_class + @token = token + populate!(response, item_class) + end + + def next_page? + !@next_page_uri.nil? + end + + def previous_page? + !@previous_page_uri.nil? + end + + def next_page! + return unless next_page? + + uri = URI.parse(@next_page_uri) + params = if uri.query + Hash[URI::decode_www_form(uri.query)] + else + {} + end + + response = Bankin.api_call(:get, uri.path, params, @token) + populate!(response, @item_class) + self + end + + def load_all! + while next_page? do + next_page! + end + self + end + + private + + def populate!(response, item_klass) + response.each do |item| + self << item_klass.new(item, @token) + end + + # TODO review + # set_pagination(response['pagination']) + end + + def set_pagination(pagination_data) + @next_page_uri = pagination_data['next_uri'] + @previous_page_uri = pagination_data['previous_uri'] + end + end +end diff --git a/lib/flanks/resources/bank.rb b/lib/flanks/resources/bank.rb new file mode 100644 index 0000000..06509bf --- /dev/null +++ b/lib/flanks/resources/bank.rb @@ -0,0 +1,16 @@ +module Flanks + class Bank < Resource + RESOURCE_PATH = '/v0/bank/available' + + has_fields :id, :name + + def self.list(token:) + response = Flanks.api_call( + method: :get, + path: RESOURCE_PATH, + token: token + ) + Collection.new(response, self) + end + end +end diff --git a/spec/flanks/resources/bank_spec.rb b/spec/flanks/resources/bank_spec.rb new file mode 100644 index 0000000..1167bac --- /dev/null +++ b/spec/flanks/resources/bank_spec.rb @@ -0,0 +1,41 @@ +require "spec_helper" + +describe Flanks::Bank do + before do + configure_flanks + end + + describe "#list" do + before do + stub_request(:get, "https://api.flanks.io/v0/bank/available"). + with( + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' + } + ). + to_return(status: 200, body: response_json(resource: 'bank', action: 'list')) + end + + it "works" do + banks = Flanks::Bank.list(token: 'THIS_IS_EL_BUEN_TOKEN') + + expect(banks.class).to eq(Flanks::Collection) + expect(banks.size).to eq(3) + + bank1, bank2, bank3 = banks + + expect(bank1.class).to eq(Flanks::Bank) + expect(bank1.id).to eq("12") + expect(bank1.name).to eq("Banc 1") + + expect(bank2.class).to eq(Flanks::Bank) + expect(bank2.id).to eq("13") + expect(bank2.name).to eq("Banc 2") + + expect(bank3.class).to eq(Flanks::Bank) + expect(bank3.id).to eq("14") + expect(bank3.name).to eq("Banc 3") + end + end +end diff --git a/spec/responses/bank/list.json b/spec/responses/bank/list.json new file mode 100644 index 0000000..c687457 --- /dev/null +++ b/spec/responses/bank/list.json @@ -0,0 +1,14 @@ +[ + { + "id": "12", + "name": "Banc 1" + }, + { + "id": "13", + "name": "Banc 2" + }, + { + "id": "14", + "name": "Banc 3" + } +] From 1a627659f5966d053d266909feab749d0c8d9441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Wed, 27 Nov 2019 17:57:56 +0100 Subject: [PATCH 05/12] Getting an account's information is a post request, motherflanker --- lib/flanks/base.rb | 9 +++++---- lib/flanks/resources/account.rb | 2 +- spec/flanks/resources/account_spec.rb | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/flanks/base.rb b/lib/flanks/base.rb index e28b828..ea8ad24 100644 --- a/lib/flanks/base.rb +++ b/lib/flanks/base.rb @@ -25,10 +25,11 @@ def api_call(method:, path:, params: {}, token: nil) if method == :post payload = params.to_json else - headers.merge!( - Authorization: "Bearer #{token}", - params: params - ) + headers.merge!(params: params) + end + + unless token.nil? + headers.merge!(Authorization: "Bearer #{token}") end log_request(method, url, headers, params) diff --git a/lib/flanks/resources/account.rb b/lib/flanks/resources/account.rb index e80c560..4b16227 100644 --- a/lib/flanks/resources/account.rb +++ b/lib/flanks/resources/account.rb @@ -7,7 +7,7 @@ class Account < Resource def self.get(token:, credentials_token:) response = Flanks.api_call( - method: :get, + method: :post, path: RESOURCE_PATH, token: token, params: { diff --git a/spec/flanks/resources/account_spec.rb b/spec/flanks/resources/account_spec.rb index dbecd9e..c4665a3 100644 --- a/spec/flanks/resources/account_spec.rb +++ b/spec/flanks/resources/account_spec.rb @@ -7,12 +7,13 @@ describe "#get" do before do - stub_request(:get, "https://api.flanks.io/v0/bank/credentials/account?credentials_token=THE_TOKCREDENTIALS"). + stub_request(:post, "https://api.flanks.io/v0/bank/credentials/account"). with( headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' - } + }, + body: "{\"credentials_token\":\"THE_TOKCREDENTIALS\"}" ). to_return(status: 200, body: response_json(resource: 'account', action: 'get')) end From 9f0eb1a9922a5e96319a017d51caa677c7d74407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Thu, 28 Nov 2019 11:46:05 +0100 Subject: [PATCH 06/12] Flanks::Link.create added --- lib/flanks.rb | 1 + lib/flanks/resources/link.rb | 19 +++++++++++++++++ spec/flanks/resources/link_spec.rb | 33 ++++++++++++++++++++++++++++++ spec/responses/link/create.json | 8 ++++++++ 4 files changed, 61 insertions(+) create mode 100644 lib/flanks/resources/link.rb create mode 100644 spec/flanks/resources/link_spec.rb create mode 100644 spec/responses/link/create.json diff --git a/lib/flanks.rb b/lib/flanks.rb index b61dbd0..73a5bdf 100644 --- a/lib/flanks.rb +++ b/lib/flanks.rb @@ -7,4 +7,5 @@ require 'flanks/resources/account' require 'flanks/resources/bank' +require 'flanks/resources/link' require 'flanks/resources/token' diff --git a/lib/flanks/resources/link.rb b/lib/flanks/resources/link.rb new file mode 100644 index 0000000..1a4d05f --- /dev/null +++ b/lib/flanks/resources/link.rb @@ -0,0 +1,19 @@ +module Flanks + class Link < Resource + RESOURCE_PATH = '/v0/platform/link' + + has_fields :message, :credentials_token, :extra + + def self.create(token:, code:) + response = Flanks.api_call( + method: :post, + path: RESOURCE_PATH, + token: token, + params: { + code: code + } + ) + new(response) + end + end +end diff --git a/spec/flanks/resources/link_spec.rb b/spec/flanks/resources/link_spec.rb new file mode 100644 index 0000000..d31c084 --- /dev/null +++ b/spec/flanks/resources/link_spec.rb @@ -0,0 +1,33 @@ +require "spec_helper" + +describe Flanks::Link do + before do + configure_flanks + end + + describe "#create" do + before do + stub_request(:post, "https://api.flanks.io/v0/platform/link"). + with( + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' + }, + body: "{\"code\":\"EL_LINK_CODIO\"}" + ). + to_return(status: 200, body: response_json(resource: 'link', action: 'create')) + end + + it "works" do + link = Flanks::Link.create(token: 'THIS_IS_EL_BUEN_TOKEN', code: 'EL_LINK_CODIO') + + expect(link.class).to eq(Flanks::Link) + expect(link.message).to eq("Successfully retrieved") + expect(link.credentials_token).to eq("THE_CREDENTIALS_TOKEN_FOR_YOU") + expect(link.extra.class).to eq(Hash) + expect(link.extra.keys).to eq(%w{a_key b_key}) + expect(link.extra['a_key']).to eq("a_content") + expect(link.extra['b_key']).to eq("b_content") + end + end +end diff --git a/spec/responses/link/create.json b/spec/responses/link/create.json new file mode 100644 index 0000000..435a975 --- /dev/null +++ b/spec/responses/link/create.json @@ -0,0 +1,8 @@ +{ + "message": "Successfully retrieved", + "credentials_token": "THE_CREDENTIALS_TOKEN_FOR_YOU", + "extra": { + "a_key": "a_content", + "b_key": "b_content" + } +} From 069d7432990db7641c8d29ef7ac1d8361abbb124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Thu, 28 Nov 2019 12:19:48 +0100 Subject: [PATCH 07/12] Flanks::LinkCode.pending added --- lib/flanks.rb | 1 + lib/flanks/resources/link_code.rb | 19 ++++++++++++++ spec/flanks/resources/link_code_spec.rb | 33 +++++++++++++++++++++++++ spec/responses/link_code/pending.json | 11 +++++++++ 4 files changed, 64 insertions(+) create mode 100644 lib/flanks/resources/link_code.rb create mode 100644 spec/flanks/resources/link_code_spec.rb create mode 100644 spec/responses/link_code/pending.json diff --git a/lib/flanks.rb b/lib/flanks.rb index 73a5bdf..56c8f78 100644 --- a/lib/flanks.rb +++ b/lib/flanks.rb @@ -8,4 +8,5 @@ require 'flanks/resources/account' require 'flanks/resources/bank' require 'flanks/resources/link' +require 'flanks/resources/link_code' require 'flanks/resources/token' diff --git a/lib/flanks/resources/link_code.rb b/lib/flanks/resources/link_code.rb new file mode 100644 index 0000000..857f83b --- /dev/null +++ b/lib/flanks/resources/link_code.rb @@ -0,0 +1,19 @@ +module Flanks + class LinkCode < Resource + RESOURCE_PATH = '/v0/platform/link' + + has_fields :code + + def self.pending(token:) + response = Flanks.api_call( + method: :get, + path: RESOURCE_PATH, + token: token, + params: { + client_id: Flanks.configuration.client_id + } + ) + Collection.new(response, self) + end + end +end diff --git a/spec/flanks/resources/link_code_spec.rb b/spec/flanks/resources/link_code_spec.rb new file mode 100644 index 0000000..1ef6299 --- /dev/null +++ b/spec/flanks/resources/link_code_spec.rb @@ -0,0 +1,33 @@ +require "spec_helper" + +describe Flanks::LinkCode do + before do + configure_flanks + end + + describe "#pending" do + before do + stub_request(:get, "https://api.flanks.io/v0/platform/link?client_id=a_client_id"). + with( + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' + } + ). + to_return(status: 200, body: response_json(resource: 'link_code', action: 'pending')) + end + + it "works" do + link_codes = Flanks::LinkCode.pending(token: 'THIS_IS_EL_BUEN_TOKEN') + + expect(link_codes.class).to eq(Flanks::Collection) + expect(link_codes.size).to eq(3) + expect(link_codes[0].class).to eq(Flanks::LinkCode) + expect(link_codes[0].code).to eq("a_first_codego") + expect(link_codes[1].class).to eq(Flanks::LinkCode) + expect(link_codes[1].code).to eq("el_codi_numbru_2") + expect(link_codes[2].class).to eq(Flanks::LinkCode) + expect(link_codes[2].code).to eq("cuca_code_3") + end + end +end diff --git a/spec/responses/link_code/pending.json b/spec/responses/link_code/pending.json new file mode 100644 index 0000000..aa8e871 --- /dev/null +++ b/spec/responses/link_code/pending.json @@ -0,0 +1,11 @@ +[ + { + "code": "a_first_codego" + }, + { + "code": "el_codi_numbru_2" + }, + { + "code": "cuca_code_3" + } +] From cc2f5d952779faadabae245a152d36162bb2f2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Thu, 28 Nov 2019 12:54:31 +0100 Subject: [PATCH 08/12] Code is a sensible parameter as well --- lib/flanks/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flanks/base.rb b/lib/flanks/base.rb index ea8ad24..db34b0a 100644 --- a/lib/flanks/base.rb +++ b/lib/flanks/base.rb @@ -4,7 +4,7 @@ module Flanks BASE_URL = 'https://api.flanks.io' SENSIBLE_HEADERS = %w{Authorization} - SENSIBLE_PARAMS = %w{client_secret password credentials_token} + SENSIBLE_PARAMS = %w{client_secret password credentials_token code} class << self attr_accessor :configuration From e9144c443a75f80415c38b685881b6c304ce1c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Thu, 28 Nov 2019 13:29:15 +0100 Subject: [PATCH 09/12] Flanks::Transaction.list added --- lib/flanks.rb | 1 + lib/flanks/resources/transaction.rb | 24 ++++++ spec/flanks/resources/transaction_spec.rb | 94 +++++++++++++++++++++++ spec/responses/transaction/list.json | 62 +++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 lib/flanks/resources/transaction.rb create mode 100644 spec/flanks/resources/transaction_spec.rb create mode 100644 spec/responses/transaction/list.json diff --git a/lib/flanks.rb b/lib/flanks.rb index 56c8f78..5ddd4e8 100644 --- a/lib/flanks.rb +++ b/lib/flanks.rb @@ -10,3 +10,4 @@ require 'flanks/resources/link' require 'flanks/resources/link_code' require 'flanks/resources/token' +require 'flanks/resources/transaction' diff --git a/lib/flanks/resources/transaction.rb b/lib/flanks/resources/transaction.rb new file mode 100644 index 0000000..6304f5f --- /dev/null +++ b/lib/flanks/resources/transaction.rb @@ -0,0 +1,24 @@ +module Flanks + class Transaction < Resource + RESOURCE_PATH = '/v0/bank/credentials/data' + + has_fields :_id, :account_id, :amount, :balance, :entity, :cardNumber, + :category, :currency, :operationDate, :valueDate, + :description, :productDescription, :transfer + + def self.list(token:, credentials_token:, account_id:) + response = Flanks.api_call( + method: :post, + path: RESOURCE_PATH, + token: token, + params: { + credentials_token: credentials_token, + query: { + "account_id" => [account_id] + } + } + ) + Collection.new(response, self) + end + end +end diff --git a/spec/flanks/resources/transaction_spec.rb b/spec/flanks/resources/transaction_spec.rb new file mode 100644 index 0000000..e59b98f --- /dev/null +++ b/spec/flanks/resources/transaction_spec.rb @@ -0,0 +1,94 @@ +require "spec_helper" + +describe Flanks::Bank do + before do + configure_flanks + end + + describe "#list" do + before do + stub_request(:post, "https://api.flanks.io/v0/bank/credentials/data"). + with( + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer THIS_IS_EL_BUEN_TOKEN' + }, + body: "{\"credentials_token\":\"THE_TOKCREDENTIALS\",\"query\":{\"account_id\":[\"A91515\"]}}" + ). + to_return(status: 200, body: response_json(resource: 'transaction', action: 'list')) + end + + it "works" do + transactions = Flanks::Transaction.list( + token: 'THIS_IS_EL_BUEN_TOKEN', + credentials_token: 'THE_TOKCREDENTIALS', + account_id: 'A91515' + ) + + expect(transactions.class).to eq(Flanks::Collection) + expect(transactions.size).to eq(3) + + transaction1, transaction2, transaction3 = transactions + + expect(transaction1.class).to eq(Flanks::Transaction) + expect(transaction1._id).to eq("T1230045") + expect(transaction1.account_id).to eq("A91515") + expect(transaction1.amount).to eq(-12.34) + expect(transaction1.balance).to eq(913.33) + expect(transaction1.entity).to eq("whatthebank") + expect(transaction1.cardNumber).to eq("abc") + expect(transaction1.category).to eq("Sport") + expect(transaction1.currency).to eq("EUR") + expect(transaction1.operationDate).to eq("2019-10-11") + expect(transaction1.valueDate).to eq("2019-10-12") + expect(transaction1.description).to eq("A description") + expect(transaction1.productDescription).to eq("A product description") + expect(transaction1.transfer).to eq({ + "beneficiary" => "John Benefits", + "ibanBeneficiary" => "ES5700752532614289557739", + "ibanPayer" => "ES5904877762281252243113", + "payer" => "Max Payer", + }) + + expect(transaction2.class).to eq(Flanks::Transaction) + expect(transaction2._id).to eq("T1230046") + expect(transaction2.account_id).to eq("A91515") + expect(transaction2.amount).to eq(3.11) + expect(transaction2.balance).to eq(916.44) + expect(transaction2.entity).to eq("whatthebank") + expect(transaction2.cardNumber).to eq("def") + expect(transaction2.category).to eq("Leisure") + expect(transaction2.currency).to eq("EUR") + expect(transaction2.operationDate).to eq("2019-10-13") + expect(transaction2.valueDate).to eq("2019-10-14") + expect(transaction2.description).to eq("Another description") + expect(transaction2.productDescription).to eq("Another product description") + expect(transaction2.transfer).to eq({ + "beneficiary" => "Max Payer", + "ibanBeneficiary" => "ES5904877762281252243113", + "ibanPayer" => "ES2731905381475958758479", + "payer" => "The Dude", + }) + + expect(transaction3.class).to eq(Flanks::Transaction) + expect(transaction3._id).to eq("T1230047") + expect(transaction3.account_id).to eq("A91515") + expect(transaction3.amount).to eq(4.99) + expect(transaction3.balance).to eq(921.43) + expect(transaction3.entity).to eq("whatthebank") + expect(transaction3.cardNumber).to eq("ghi") + expect(transaction3.category).to eq("Finance") + expect(transaction3.currency).to eq("EUR") + expect(transaction3.operationDate).to eq("2019-10-15") + expect(transaction3.valueDate).to eq("2019-10-16") + expect(transaction3.description).to eq("The final description") + expect(transaction3.productDescription).to eq("The final product description") + expect(transaction3.transfer).to eq({ + "beneficiary" => "Max Payer", + "ibanBeneficiary" => "ES5904877762281252243113", + "ibanPayer" => "ES6801287657415495297851", + "payer" => "Random Guy", + }) + end + end +end diff --git a/spec/responses/transaction/list.json b/spec/responses/transaction/list.json new file mode 100644 index 0000000..e04d280 --- /dev/null +++ b/spec/responses/transaction/list.json @@ -0,0 +1,62 @@ +[ + { + "_id": "T1230045", + "account_id": "A91515", + "amount": -12.34, + "balance": 913.33, + "entity": "whatthebank", + "cardNumber": "abc", + "category": "Sport", + "currency": "EUR", + "operationDate": "2019-10-11", + "valueDate": "2019-10-12", + "description": "A description", + "productDescription": "A product description", + "transfer": { + "beneficiary": "John Benefits", + "ibanBeneficiary": "ES5700752532614289557739", + "ibanPayer": "ES5904877762281252243113", + "payer": "Max Payer" + } + }, + { + "_id": "T1230046", + "account_id": "A91515", + "amount": 3.11, + "balance": 916.44, + "entity": "whatthebank", + "cardNumber": "def", + "category": "Leisure", + "currency": "EUR", + "operationDate": "2019-10-13", + "valueDate": "2019-10-14", + "description": "Another description", + "productDescription": "Another product description", + "transfer": { + "beneficiary": "Max Payer", + "ibanBeneficiary": "ES5904877762281252243113", + "ibanPayer": "ES2731905381475958758479", + "payer": "The Dude" + } + }, + { + "_id": "T1230047", + "account_id": "A91515", + "amount": 4.99, + "balance": 921.43, + "entity": "whatthebank", + "cardNumber": "ghi", + "category": "Finance", + "currency": "EUR", + "operationDate": "2019-10-15", + "valueDate": "2019-10-16", + "description": "The final description", + "productDescription": "The final product description", + "transfer": { + "beneficiary": "Max Payer", + "ibanBeneficiary": "ES5904877762281252243113", + "ibanPayer": "ES6801287657415495297851", + "payer": "Random Guy" + } + } +] From 94f69655dbbdce2f1673ad077000371424fec6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Thu, 28 Nov 2019 13:45:37 +0100 Subject: [PATCH 10/12] Complete coverage for flanks/base.rb --- lib/flanks/base.rb | 22 +-- spec/flanks/base_spec.rb | 189 +++++++++++++++++++++- spec/flanks/resources/account_spec.rb | 4 +- spec/flanks/resources/bank_spec.rb | 4 +- spec/flanks/resources/link_code_spec.rb | 4 +- spec/flanks/resources/link_spec.rb | 4 +- spec/flanks/resources/token_spec.rb | 4 +- spec/flanks/resources/transaction_spec.rb | 4 +- 8 files changed, 199 insertions(+), 36 deletions(-) diff --git a/lib/flanks/base.rb b/lib/flanks/base.rb index db34b0a..6ef7e4a 100644 --- a/lib/flanks/base.rb +++ b/lib/flanks/base.rb @@ -22,24 +22,20 @@ def api_call(method:, path:, params: {}, token: nil) headers = { 'Content-Type' => 'application/json' } - if method == :post - payload = params.to_json - else - headers.merge!(params: params) - end - unless token.nil? headers.merge!(Authorization: "Bearer #{token}") end log_request(method, url, headers, params) - request_params = { - method: method, - url: url, - headers: headers, - payload: payload - } + if method == :post + payload = params.to_json + else + headers.merge!(params: params) + end + + request_params = { method: method, url: url, headers: headers } + request_params.merge!(payload: payload) unless payload.nil? begin response = RestClient::Request.execute(request_params) @@ -59,8 +55,6 @@ def log_request(method, url, headers, params) log_message("* Headers") headers.each do |key, value| - next if key == :params - safe_value = if SENSIBLE_HEADERS.include?(key.to_s) "" else diff --git a/spec/flanks/base_spec.rb b/spec/flanks/base_spec.rb index b336852..85c7ba1 100644 --- a/spec/flanks/base_spec.rb +++ b/spec/flanks/base_spec.rb @@ -1,20 +1,201 @@ require "spec_helper" describe Flanks do + before { configure_flanks } + describe "#configuration" do - # TODO + it "returns a Configuration instance" do + expect(subject.configuration).to be_a(Flanks::Configuration) + end end describe "#configure" do - # TODO + it "returns the credentials properly" do + expect(subject.configuration.client_id).to eq('a_client_id') + expect(subject.configuration.client_secret).to eq('the_super_secret_stuff') + expect(subject.configuration.username).to eq('an_email') + expect(subject.configuration.password).to eq('le_password') + end end describe "#api_call" do - # TODO + let(:path) { '/v0/some/endpoint' } + let(:params) { { a: :b, c: :d, e: :f } } + let(:api_call) { + subject.api_call(method: method, path: path, params: params, token: token) + } + + before do + allow(RestClient::Request).to receive(:execute) { {} } + end + + context "for a GET request" do + let(:method) { :get } + + context "with a bearer token" do + let(:token) { 'tok123456789' } + + it "works" do + expect(subject) + .to receive(:log_request) + .with( + :get, + "https://api.flanks.io/v0/some/endpoint", + { + 'Content-Type' => 'application/json', + Authorization: 'Bearer tok123456789' + }, + { a: :b, c: :d, e: :f } + ) + + expect(RestClient::Request) + .to receive(:execute) + .with( + method: :get, + url: "https://api.flanks.io/v0/some/endpoint", + headers: { + 'Content-Type' => 'application/json', + Authorization: 'Bearer tok123456789', + params: { a: :b, c: :d, e: :f } + } + ) + + api_call + end + end + end + + context "for a POST request" do + let(:method) { :post } + + context "with a bearer token" do + let(:token) { 'tok123456789' } + + it "works" do + expect(subject) + .to receive(:log_request) + .with( + :post, + "https://api.flanks.io/v0/some/endpoint", + { + 'Content-Type' => 'application/json', + Authorization: 'Bearer tok123456789' + }, + { a: :b, c: :d, e: :f } + ) + + expect(RestClient::Request) + .to receive(:execute) + .with( + method: :post, + url: "https://api.flanks.io/v0/some/endpoint", + headers: { + 'Content-Type' => 'application/json', + Authorization: 'Bearer tok123456789' + }, + payload: "{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"}" + ) + + api_call + end + end + + context "with client credentials" do + let(:token) { nil } + + it "works" do + expect(subject) + .to receive(:log_request) + .with( + :post, + "https://api.flanks.io/v0/some/endpoint", + { + 'Content-Type' => 'application/json' + }, + { a: :b, c: :d, e: :f } + ) + + expect(RestClient::Request) + .to receive(:execute) + .with( + method: :post, + url: "https://api.flanks.io/v0/some/endpoint", + headers: { + 'Content-Type' => 'application/json' + }, + payload: "{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"}" + ) + + api_call + end + end + end end describe "#log_request" do - # TODO + let(:method) { :cuca } + let(:url) { "https://some.where/over/the/rainbow" } + let(:headers) { + { Authorization: "Bearer 123142515", cuca: :monga, a: :b } + } + let(:log_request) { + subject.log_request(method, url, headers, params) + } + + context "without params" do + let(:params) { {} } + + it "works" do + [ + "", + "=> CUCA https://some.where/over/the/rainbow", + "* Headers", + "Authorization: ", + "cuca: monga", + "a: b", + "* No params" + ].each do |unique_message| + expect(subject).to receive(:log_message).with(unique_message).once + end + + log_request + end + end + + context "with some params" do + let(:params) { + { + client_secret: "the_super_secret_stuff", + password: 'mipassword', + b: :c, + credentials_token: 'eltokencito', + code: 'ruby', + d: :e + } + } + + it "works" do + [ + "", + "=> CUCA https://some.where/over/the/rainbow", + "* Headers", + "Authorization: ", + "cuca: monga", + "a: b", + "* Params", + "client_secret: ", + "password: ", + "b: c", + "credentials_token: ", + "code: ", + "d: e", + ].each do |unique_message| + expect(subject).to receive(:log_message).with(unique_message).once + end + + log_request + end + end end describe "#log_message" do diff --git a/spec/flanks/resources/account_spec.rb b/spec/flanks/resources/account_spec.rb index c4665a3..1b962c3 100644 --- a/spec/flanks/resources/account_spec.rb +++ b/spec/flanks/resources/account_spec.rb @@ -1,9 +1,7 @@ require "spec_helper" describe Flanks::Account do - before do - configure_flanks - end + before { configure_flanks } describe "#get" do before do diff --git a/spec/flanks/resources/bank_spec.rb b/spec/flanks/resources/bank_spec.rb index 1167bac..280fa35 100644 --- a/spec/flanks/resources/bank_spec.rb +++ b/spec/flanks/resources/bank_spec.rb @@ -1,9 +1,7 @@ require "spec_helper" describe Flanks::Bank do - before do - configure_flanks - end + before { configure_flanks } describe "#list" do before do diff --git a/spec/flanks/resources/link_code_spec.rb b/spec/flanks/resources/link_code_spec.rb index 1ef6299..24908df 100644 --- a/spec/flanks/resources/link_code_spec.rb +++ b/spec/flanks/resources/link_code_spec.rb @@ -1,9 +1,7 @@ require "spec_helper" describe Flanks::LinkCode do - before do - configure_flanks - end + before { configure_flanks } describe "#pending" do before do diff --git a/spec/flanks/resources/link_spec.rb b/spec/flanks/resources/link_spec.rb index d31c084..301c9f5 100644 --- a/spec/flanks/resources/link_spec.rb +++ b/spec/flanks/resources/link_spec.rb @@ -1,9 +1,7 @@ require "spec_helper" describe Flanks::Link do - before do - configure_flanks - end + before { configure_flanks } describe "#create" do before do diff --git a/spec/flanks/resources/token_spec.rb b/spec/flanks/resources/token_spec.rb index 109d560..a26b6ec 100644 --- a/spec/flanks/resources/token_spec.rb +++ b/spec/flanks/resources/token_spec.rb @@ -1,9 +1,7 @@ require "spec_helper" describe Flanks::Token do - before do - configure_flanks - end + before { configure_flanks } describe "#create" do before do diff --git a/spec/flanks/resources/transaction_spec.rb b/spec/flanks/resources/transaction_spec.rb index e59b98f..672f074 100644 --- a/spec/flanks/resources/transaction_spec.rb +++ b/spec/flanks/resources/transaction_spec.rb @@ -1,9 +1,7 @@ require "spec_helper" describe Flanks::Bank do - before do - configure_flanks - end + before { configure_flanks } describe "#list" do before do From cc2ec575ba8d3640add6a294eefe07d577796984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Thu, 28 Nov 2019 14:31:23 +0100 Subject: [PATCH 11/12] The accounts endpoint is * cardinality, not 1 --- lib/flanks/resources/account.rb | 4 +-- spec/flanks/resources/account_spec.rb | 51 ++++++++++++++++++--------- spec/responses/account/get.json | 14 -------- spec/responses/account/list.json | 30 ++++++++++++++++ 4 files changed, 66 insertions(+), 33 deletions(-) delete mode 100644 spec/responses/account/get.json create mode 100644 spec/responses/account/list.json diff --git a/lib/flanks/resources/account.rb b/lib/flanks/resources/account.rb index 4b16227..0bdc495 100644 --- a/lib/flanks/resources/account.rb +++ b/lib/flanks/resources/account.rb @@ -5,7 +5,7 @@ class Account < Resource has_fields :iban, :entity, :alias, :balance, :currency, :description, :isOwner, :numOwners, :owners, :_id - def self.get(token:, credentials_token:) + def self.list(token:, credentials_token:) response = Flanks.api_call( method: :post, path: RESOURCE_PATH, @@ -14,7 +14,7 @@ def self.get(token:, credentials_token:) credentials_token: credentials_token } ) - new(response) + Collection.new(response, self) end end end diff --git a/spec/flanks/resources/account_spec.rb b/spec/flanks/resources/account_spec.rb index 1b962c3..47ff54d 100644 --- a/spec/flanks/resources/account_spec.rb +++ b/spec/flanks/resources/account_spec.rb @@ -3,7 +3,7 @@ describe Flanks::Account do before { configure_flanks } - describe "#get" do + describe "#list" do before do stub_request(:post, "https://api.flanks.io/v0/bank/credentials/account"). with( @@ -13,30 +13,47 @@ }, body: "{\"credentials_token\":\"THE_TOKCREDENTIALS\"}" ). - to_return(status: 200, body: response_json(resource: 'account', action: 'get')) + to_return(status: 200, body: response_json(resource: 'account', action: 'list')) end it "works" do - account = Flanks::Account.get( + accounts = Flanks::Account.list( token: 'THIS_IS_EL_BUEN_TOKEN', credentials_token: 'THE_TOKCREDENTIALS' ) - expect(account.class).to eq(Flanks::Account) - expect(account.iban).to eq("ES4501822763517295596839") - expect(account.entity).to eq("Banco Random") - expect(account.alias).to eq("Cuenta Random de Ahorros") - expect(account.balance).to eq(1034.19) - expect(account.currency).to eq("EUR") - expect(account.description).to eq("La boena descrepsión") - expect(account.isOwner).to be_truthy - expect(account.numOwners).to eq(3) - expect(account.owners).to eq( - [ - "Juanita admin", "Pepito colaborador", "Florencia gestora" - ] + expect(accounts.class).to eq(Flanks::Collection) + expect(accounts.size).to eq(2) + + account1, account2 = accounts + + expect(account1.class).to eq(Flanks::Account) + expect(account1.iban).to eq("ES4501822763517295596839") + expect(account1.entity).to eq("whatthebank") + expect(account1.alias).to eq("Cuenta Random de Ahorros") + expect(account1.balance).to eq(1034.19) + expect(account1.currency).to eq("EUR") + expect(account1.description).to eq("La boena descrepsión") + expect(account1.isOwner).to be_truthy + expect(account1.numOwners).to eq(3) + expect(account1.owners).to eq( + ["Juanita admin", "Pepito colaborador", "Florencia gestora"] + ) + expect(account1._id).to eq("abc12340a0011234fda") + + expect(account2.class).to eq(Flanks::Account) + expect(account2.iban).to eq("ES8620956428346945419764") + expect(account2.entity).to eq("whatthebank") + expect(account2.alias).to eq("Cuenta Random de Inversiones") + expect(account2.balance).to eq(180_291.55) + expect(account2.currency).to eq("EUR") + expect(account2.description).to eq("Long term money") + expect(account2.isOwner).to be_truthy + expect(account2.numOwners).to eq(1) + expect(account2.owners).to eq( + ["Juanita admin"] ) - expect(account._id).to eq("abc12340a0011234fda") + expect(account2._id).to eq("def78940a0011234fda") end end end diff --git a/spec/responses/account/get.json b/spec/responses/account/get.json deleted file mode 100644 index 2d4809f..0000000 --- a/spec/responses/account/get.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "iban": "ES4501822763517295596839", - "entity": "Banco Random", - "alias": "Cuenta Random de Ahorros", - "balance": 1034.19, - "currency": "EUR", - "description": "La boena descrepsión", - "isOwner": true, - "numOwners": 3, - "owners": [ - "Juanita admin", "Pepito colaborador", "Florencia gestora" - ], - "_id": "abc12340a0011234fda" -} diff --git a/spec/responses/account/list.json b/spec/responses/account/list.json new file mode 100644 index 0000000..166a208 --- /dev/null +++ b/spec/responses/account/list.json @@ -0,0 +1,30 @@ +[ + { + "iban": "ES4501822763517295596839", + "entity": "whatthebank", + "alias": "Cuenta Random de Ahorros", + "balance": 1034.19, + "currency": "EUR", + "description": "La boena descrepsión", + "isOwner": true, + "numOwners": 3, + "owners": [ + "Juanita admin", "Pepito colaborador", "Florencia gestora" + ], + "_id": "abc12340a0011234fda" + }, + { + "iban": "ES8620956428346945419764", + "entity": "whatthebank", + "alias": "Cuenta Random de Inversiones", + "balance": 180291.55, + "currency": "EUR", + "description": "Long term money", + "isOwner": true, + "numOwners": 1, + "owners": [ + "Juanita admin" + ], + "_id": "def78940a0011234fda" + } +] From 05977d77835a3deb40341e1d99162f2e9003cf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Bellonch=20Llargu=C3=A9s?= Date: Thu, 28 Nov 2019 14:33:01 +0100 Subject: [PATCH 12/12] Improve a specific test --- spec/flanks/base_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/flanks/base_spec.rb b/spec/flanks/base_spec.rb index 85c7ba1..8df96f0 100644 --- a/spec/flanks/base_spec.rb +++ b/spec/flanks/base_spec.rb @@ -216,7 +216,7 @@ end it "does not call the logger" do - expect(Flanks.configuration.logger).not_to receive(:info) + expect_any_instance_of(Logger).not_to receive(:info) subject.log_message("cucamonga") end