diff --git a/README.md b/README.md index c5e1f620..3f089973 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,22 @@ class WebhooksController < ApplicationController end ``` +#### Accessing the webhook ID + +If you need to access the webhook ID for debugging purposes, you can use `parse_with_meta` instead: + +```ruby +result = GoCardlessPro::Webhook.parse_with_meta( + request_body: request.raw_post, + signature_header: request.headers['Webhook-Signature'], + webhook_endpoint_secret: webhook_endpoint_secret +) +events = result.events +webhook_id = result.webhook_id # e.g. "WB123" - useful for debugging +``` + +Note: The webhook ID is intended for debugging and logging purposes only. It should not be used for deduplication - instead, use the event IDs to deduplicate, as each event has a unique ID that remains consistent if the same event is sent multiple times. + For more details on working with webhooks, see our ["Getting started" guide](https://developer.gocardless.com/getting-started/api/introduction/?lang=ruby). ### Using the OAuth API diff --git a/lib/gocardless_pro.rb b/lib/gocardless_pro.rb index 4258c51e..a5194c88 100644 --- a/lib/gocardless_pro.rb +++ b/lib/gocardless_pro.rb @@ -123,6 +123,12 @@ module GoCardlessPro require_relative 'gocardless_pro/resources/outbound_payment' require_relative 'gocardless_pro/services/outbound_payments_service' +require_relative 'gocardless_pro/resources/outbound_payment_import' +require_relative 'gocardless_pro/services/outbound_payment_imports_service' + +require_relative 'gocardless_pro/resources/outbound_payment_import_entry' +require_relative 'gocardless_pro/services/outbound_payment_import_entries_service' + require_relative 'gocardless_pro/resources/payer_authorisation' require_relative 'gocardless_pro/services/payer_authorisations_service' diff --git a/lib/gocardless_pro/client.rb b/lib/gocardless_pro/client.rb index 6a1de3ab..2363a6a7 100644 --- a/lib/gocardless_pro/client.rb +++ b/lib/gocardless_pro/client.rb @@ -143,6 +143,16 @@ def outbound_payments @outbound_payments ||= Services::OutboundPaymentsService.new(@api_service) end + # Access to the service for outbound_payment_import to make API calls + def outbound_payment_imports + @outbound_payment_imports ||= Services::OutboundPaymentImportsService.new(@api_service) + end + + # Access to the service for outbound_payment_import_entry to make API calls + def outbound_payment_import_entries + @outbound_payment_import_entries ||= Services::OutboundPaymentImportEntriesService.new(@api_service) + end + # Access to the service for payer_authorisation to make API calls def payer_authorisations @payer_authorisations ||= Services::PayerAuthorisationsService.new(@api_service) @@ -273,7 +283,7 @@ def default_options 'User-Agent' => "#{user_agent}", 'Content-Type' => 'application/json', 'GoCardless-Client-Library' => 'gocardless-pro-ruby', - 'GoCardless-Client-Version' => '4.3.0', + 'GoCardless-Client-Version' => '4.4.0', }, } end diff --git a/lib/gocardless_pro/list_response.rb b/lib/gocardless_pro/list_response.rb index aae7d3d0..c76c0677 100644 --- a/lib/gocardless_pro/list_response.rb +++ b/lib/gocardless_pro/list_response.rb @@ -22,12 +22,12 @@ def api_response # return the before cursor for paginating def before - @response.body['meta']['cursors']['before'] + @response.body.dig('meta', 'cursors', 'before') end # return the after cursor for paginating def after - @response.body['meta']['cursors']['after'] + @response.body.dig('meta', 'cursors', 'after') end end end diff --git a/lib/gocardless_pro/resources/customer_bank_account.rb b/lib/gocardless_pro/resources/customer_bank_account.rb index 5f706aef..b4a3aee7 100644 --- a/lib/gocardless_pro/resources/customer_bank_account.rb +++ b/lib/gocardless_pro/resources/customer_bank_account.rb @@ -39,6 +39,7 @@ class CustomerBankAccount attr_reader :enabled attr_reader :id attr_reader :metadata + attr_reader :trusted_recipient # Initialize a customer_bank_account resource instance # @param object [Hash] an object returned from the API @@ -57,6 +58,7 @@ def initialize(object, response = nil) @id = object['id'] @links = object['links'] @metadata = object['metadata'] + @trusted_recipient = object['trusted_recipient'] @response = response end diff --git a/lib/gocardless_pro/resources/export.rb b/lib/gocardless_pro/resources/export.rb index d1f59ea9..3f2c3a48 100644 --- a/lib/gocardless_pro/resources/export.rb +++ b/lib/gocardless_pro/resources/export.rb @@ -15,6 +15,7 @@ class Export attr_reader :created_at attr_reader :currency attr_reader :download_url + attr_reader :error_message attr_reader :export_type attr_reader :id @@ -26,6 +27,7 @@ def initialize(object, response = nil) @created_at = object['created_at'] @currency = object['currency'] @download_url = object['download_url'] + @error_message = object['error_message'] @export_type = object['export_type'] @id = object['id'] @response = response diff --git a/lib/gocardless_pro/resources/mandate.rb b/lib/gocardless_pro/resources/mandate.rb index 5ff71f12..fccaad2c 100644 --- a/lib/gocardless_pro/resources/mandate.rb +++ b/lib/gocardless_pro/resources/mandate.rb @@ -22,6 +22,7 @@ class Mandate attr_reader :created_at attr_reader :funds_settlement attr_reader :id + attr_reader :mandate_type attr_reader :metadata attr_reader :next_possible_charge_date attr_reader :next_possible_standard_ach_charge_date @@ -43,6 +44,7 @@ def initialize(object, response = nil) @funds_settlement = object['funds_settlement'] @id = object['id'] @links = object['links'] + @mandate_type = object['mandate_type'] @metadata = object['metadata'] @next_possible_charge_date = object['next_possible_charge_date'] @next_possible_standard_ach_charge_date = object['next_possible_standard_ach_charge_date'] diff --git a/lib/gocardless_pro/resources/outbound_payment_import.rb b/lib/gocardless_pro/resources/outbound_payment_import.rb new file mode 100644 index 00000000..0d2f461b --- /dev/null +++ b/lib/gocardless_pro/resources/outbound_payment_import.rb @@ -0,0 +1,81 @@ +# +# This client is automatically generated from a template and JSON schema definition. +# See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. +# + +require 'uri' + +module GoCardlessPro + # A module containing classes for each of the resources in the GC Api + module Resources + # Represents an instance of a outbound_payment_import resource returned from the API + + # Outbound Payment Imports allow you to create multiple payments via a + # single API call. + # + # The Workflow: + # 1. Create the outbound payment import. + # 2. Retrieve an authorisation link from the response. + # 3. Redirect the user to the link to authorise the import. + # 4. Once the user authorises the import, the individual outbound payments + # are automatically submitted. + # + # Import entries are not processed as actual payments until they are + # reviewed and authorised in GoCardless Dashboard. + # Upon approval, a unique outbound payment is generated for every entry in + # the import. + # + #
Outbound Payment Imports are capped at 1000 entries. If + # you expect to exceed this limit, please create multiple smaller + # imports.
+ class OutboundPaymentImport + attr_reader :amount_sum + attr_reader :authorisation_url + attr_reader :created_at + attr_reader :currency + attr_reader :entry_counts + attr_reader :id + attr_reader :status + + # Initialize a outbound_payment_import resource instance + # @param object [Hash] an object returned from the API + def initialize(object, response = nil) + @object = object + + @amount_sum = object['amount_sum'] + @authorisation_url = object['authorisation_url'] + @created_at = object['created_at'] + @currency = object['currency'] + @entry_counts = object['entry_counts'] + @id = object['id'] + @links = object['links'] + @status = object['status'] + @response = response + end + + def api_response + ApiResponse.new(@response) + end + + # Return the links that the resource has + def links + @outbound_payment_import_links ||= Links.new(@links) + end + + # Provides the outbound_payment_import resource as a hash of all its readable attributes + def to_h + @object + end + + class Links + def initialize(links) + @links = links || {} + end + + def creditor + @links['creditor'] + end + end + end + end +end diff --git a/lib/gocardless_pro/resources/outbound_payment_import_entry.rb b/lib/gocardless_pro/resources/outbound_payment_import_entry.rb new file mode 100644 index 00000000..5b0f9c12 --- /dev/null +++ b/lib/gocardless_pro/resources/outbound_payment_import_entry.rb @@ -0,0 +1,77 @@ +# +# This client is automatically generated from a template and JSON schema definition. +# See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. +# + +require 'uri' + +module GoCardlessPro + # A module containing classes for each of the resources in the GC Api + module Resources + # Represents an instance of a outbound_payment_import_entry resource returned from the API + + # Import Entries are the individual rows of an outbound payment import, + # representing each payment to be created. + class OutboundPaymentImportEntry + attr_reader :amount + attr_reader :created_at + attr_reader :id + attr_reader :metadata + attr_reader :processed_at + attr_reader :reference + attr_reader :scheme + attr_reader :validation_errors + attr_reader :verification_result + + # Initialize a outbound_payment_import_entry resource instance + # @param object [Hash] an object returned from the API + def initialize(object, response = nil) + @object = object + + @amount = object['amount'] + @created_at = object['created_at'] + @id = object['id'] + @links = object['links'] + @metadata = object['metadata'] + @processed_at = object['processed_at'] + @reference = object['reference'] + @scheme = object['scheme'] + @validation_errors = object['validation_errors'] + @verification_result = object['verification_result'] + @response = response + end + + def api_response + ApiResponse.new(@response) + end + + # Return the links that the resource has + def links + @outbound_payment_import_entry_links ||= Links.new(@links) + end + + # Provides the outbound_payment_import_entry resource as a hash of all its readable attributes + def to_h + @object + end + + class Links + def initialize(links) + @links = links || {} + end + + def outbound_payment + @links['outbound_payment'] + end + + def outbound_payment_import + @links['outbound_payment_import'] + end + + def recipient_bank_account + @links['recipient_bank_account'] + end + end + end + end +end diff --git a/lib/gocardless_pro/services/billing_requests_service.rb b/lib/gocardless_pro/services/billing_requests_service.rb index 7f18017d..b5613376 100644 --- a/lib/gocardless_pro/services/billing_requests_service.rb +++ b/lib/gocardless_pro/services/billing_requests_service.rb @@ -329,8 +329,7 @@ def get(identity, options = {}) # it. # Currently, the customer can only be notified by email. # - # This endpoint is currently supported only for Instant Bank Pay Billing - # Requests. + # This endpoint is currently supported only for Pay by Bank Billing Requests. # Example URL: /billing_requests/:identity/actions/notify # # @param identity # Unique identifier, beginning with "BRQ". diff --git a/lib/gocardless_pro/services/mandate_pdfs_service.rb b/lib/gocardless_pro/services/mandate_pdfs_service.rb index 112507c5..0a4cd3bb 100644 --- a/lib/gocardless_pro/services/mandate_pdfs_service.rb +++ b/lib/gocardless_pro/services/mandate_pdfs_service.rb @@ -20,7 +20,7 @@ class MandatePdfsService < BaseService # # To generate a PDF mandate in another language, set the `Accept-Language` # header when creating the PDF mandate to the relevant [ISO - # 639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code + # 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code # supported for the scheme. # # | Scheme | Supported languages diff --git a/lib/gocardless_pro/services/outbound_payment_import_entries_service.rb b/lib/gocardless_pro/services/outbound_payment_import_entries_service.rb new file mode 100644 index 00000000..4d8072dc --- /dev/null +++ b/lib/gocardless_pro/services/outbound_payment_import_entries_service.rb @@ -0,0 +1,57 @@ +require_relative './base_service' + +# encoding: utf-8 +# +# This client is automatically generated from a template and JSON schema definition. +# See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. +# + +module GoCardlessPro + module Services + # Service for making requests to the OutboundPaymentImportEntry endpoints + class OutboundPaymentImportEntriesService < BaseService + # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of the entries + # for a given outbound payment import. + # Example URL: /outbound_payment_import_entries + # @param options [Hash] parameters as a hash, under a params key. + def list(options = {}) + path = '/outbound_payment_import_entries' + + options[:retry_failures] = true + + response = make_request(:get, path, options) + + ListResponse.new( + response: response, + unenveloped_body: unenvelope_body(response.body), + resource_class: Resources::OutboundPaymentImportEntry + ) + end + + # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. + # + # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. + # Otherwise they will be the body of the request. + def all(options = {}) + Paginator.new( + service: self, + options: options + ).enumerator + end + + private + + # Unenvelope the response of the body using the service's `envelope_key` + # + # @param body [Hash] + def unenvelope_body(body) + body[envelope_key] || body['data'] + end + + # return the key which API responses will envelope data under + def envelope_key + 'outbound_payment_import_entries' + end + end + end +end diff --git a/lib/gocardless_pro/services/outbound_payment_imports_service.rb b/lib/gocardless_pro/services/outbound_payment_imports_service.rb new file mode 100644 index 00000000..5ca708a6 --- /dev/null +++ b/lib/gocardless_pro/services/outbound_payment_imports_service.rb @@ -0,0 +1,111 @@ +require_relative './base_service' + +# encoding: utf-8 +# +# This client is automatically generated from a template and JSON schema definition. +# See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. +# + +module GoCardlessPro + module Services + # Service for making requests to the OutboundPaymentImport endpoints + class OutboundPaymentImportsService < BaseService + # + # Example URL: /outbound_payment_imports + # @param options [Hash] parameters as a hash, under a params key. + def create(options = {}) + path = '/outbound_payment_imports' + + params = options.delete(:params) || {} + options[:params] = {} + options[:params][envelope_key] = params + + options[:retry_failures] = true + + begin + response = make_request(:post, path, options) + + # Response doesn't raise any errors until #body is called + response.tap(&:body) + rescue InvalidStateError => e + if e.idempotent_creation_conflict? + case @api_service.on_idempotency_conflict + when :raise + raise IdempotencyConflict.new(e.error) + when :fetch + return get(e.conflicting_resource_id) + end + end + + raise e + end + + return if response.body.nil? + + Resources::OutboundPaymentImport.new(unenvelope_body(response.body), response) + end + + # Returns a single outbound payment import. + # Example URL: /outbound_payment_imports/:identity + # + # @param identity # Unique identifier, beginning with "IM". + # @param options [Hash] parameters as a hash, under a params key. + def get(identity, options = {}) + path = sub_url('/outbound_payment_imports/:identity', { + 'identity' => identity, + }) + + options[:retry_failures] = true + + response = make_request(:get, path, options) + + return if response.body.nil? + + Resources::OutboundPaymentImport.new(unenvelope_body(response.body), response) + end + + # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your + # outbound payment imports. + # Example URL: /outbound_payment_imports + # @param options [Hash] parameters as a hash, under a params key. + def list(options = {}) + path = '/outbound_payment_imports' + + options[:retry_failures] = true + + response = make_request(:get, path, options) + + ListResponse.new( + response: response, + unenveloped_body: unenvelope_body(response.body), + resource_class: Resources::OutboundPaymentImport + ) + end + + # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. + # + # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. + # Otherwise they will be the body of the request. + def all(options = {}) + Paginator.new( + service: self, + options: options + ).enumerator + end + + private + + # Unenvelope the response of the body using the service's `envelope_key` + # + # @param body [Hash] + def unenvelope_body(body) + body[envelope_key] || body['data'] + end + + # return the key which API responses will envelope data under + def envelope_key + 'outbound_payment_imports' + end + end + end +end diff --git a/lib/gocardless_pro/services/outbound_payments_service.rb b/lib/gocardless_pro/services/outbound_payments_service.rb index de4104f7..104ab683 100644 --- a/lib/gocardless_pro/services/outbound_payments_service.rb +++ b/lib/gocardless_pro/services/outbound_payments_service.rb @@ -124,7 +124,7 @@ def cancel(identity, options = {}) end # Approves an outbound payment. Only outbound payments with the - # “pending_approval” status can be approved. + # "pending_approval" status can be approved. # Example URL: /outbound_payments/:identity/actions/approve # # @param identity # Unique identifier of the outbound payment. diff --git a/lib/gocardless_pro/version.rb b/lib/gocardless_pro/version.rb index 12de3668..5de036e1 100644 --- a/lib/gocardless_pro/version.rb +++ b/lib/gocardless_pro/version.rb @@ -3,5 +3,5 @@ module GoCardlessPro module GoCardlessPro # Current version of the GC gem - VERSION = '4.3.0' + VERSION = '4.4.0' end diff --git a/lib/gocardless_pro/webhook.rb b/lib/gocardless_pro/webhook.rb index 9e44e5ca..93fc4331 100644 --- a/lib/gocardless_pro/webhook.rb +++ b/lib/gocardless_pro/webhook.rb @@ -1,6 +1,18 @@ require 'openssl' module GoCardlessPro + # Represents the result of parsing a webhook, containing both the events + # and the webhook metadata. + class WebhookParseResult + attr_reader :events + attr_reader :webhook_id + + def initialize(events, webhook_id) + @events = events + @webhook_id = webhook_id + end + end + class Webhook class InvalidSignatureError < StandardError; end @@ -38,6 +50,39 @@ def parse(options = {}) events.map { |event| Resources::Event.new(event) } end + # Validates that a webhook was genuinely sent by GoCardless using + # `.signature_valid?`, and then parses it into a WebhookParseResult containing + # both the events and the webhook ID from the meta field + # + # @option options [String] :request_body the request body + # @option options [String] :signature_header the signature included in the request, + # found in the `Webhook-Signature` header + # @option options [String] :webhook_endpoint_secret the webhook endpoint secret for + # your webhook endpoint, as configured in your GoCardless Dashboard + # @return [WebhookParseResult] containing the events and webhook ID + # @raise [InvalidSignatureError] if the signature header specified does not match + # the signature computed using the request body and webhook endpoint secret + # @raise [ArgumentError] if a required keyword argument is not provided or is not + # of the required type + def parse_with_meta(options = {}) + validate_options!(options) + + unless signature_valid?(request_body: options[:request_body], + signature_header: options[:signature_header], + webhook_endpoint_secret: options[:webhook_endpoint_secret]) + raise InvalidSignatureError, "This webhook doesn't appear to be a genuine " \ + 'webhook from GoCardless, because the signature ' \ + "header doesn't match the signature computed" \ + ' with your webhook endpoint secret.' + end + + parsed = JSON.parse(options[:request_body]) + events = parsed['events'].map { |event| Resources::Event.new(event) } + webhook_id = parsed.dig('meta', 'webhook_id') + + WebhookParseResult.new(events, webhook_id) + end + # Validates that a webhook was genuinely sent by GoCardless by computing its # signature using the body and your webhook endpoint secret, and comparing that with # the signature included in the `Webhook-Signature` header diff --git a/spec/code_samples/balances_code_samples_spec.rb b/spec/code_samples/balances_code_samples_spec.rb new file mode 100644 index 00000000..a7aabf96 --- /dev/null +++ b/spec/code_samples/balances_code_samples_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Balances Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/balances'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'balances' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.balances.list( + params: { + creditor: 'CR123', + } + ).records + end + end +end diff --git a/spec/code_samples/bank_account_details_code_samples_spec.rb b/spec/code_samples/bank_account_details_code_samples_spec.rb new file mode 100644 index 00000000..ce434619 --- /dev/null +++ b/spec/code_samples/bank_account_details_code_samples_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BankAccountDetails Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/bank_account_details/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'bank_account_details' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.bank_account_details.get('BA123', + headers: { 'Gc-Key-Id' => 'PK123' }) + end + end +end diff --git a/spec/code_samples/bank_account_holder_verifications_code_samples_spec.rb b/spec/code_samples/bank_account_holder_verifications_code_samples_spec.rb new file mode 100644 index 00000000..4b49977d --- /dev/null +++ b/spec/code_samples/bank_account_holder_verifications_code_samples_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BankAccountHolderVerifications Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/bank_account_holder_verifications'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'bank_account_holder_verifications' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.bank_account_holder_verifications.create( + params: { + type: 'confirmation_of_payee', + links: { + bank_account: 'BA123', + }, + } + ) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/bank_account_holder_verifications/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'bank_account_holder_verifications' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.bank_account_holder_verifications.get('BAHV123') + end + end +end diff --git a/spec/code_samples/bank_authorisations_code_samples_spec.rb b/spec/code_samples/bank_authorisations_code_samples_spec.rb new file mode 100644 index 00000000..40505615 --- /dev/null +++ b/spec/code_samples/bank_authorisations_code_samples_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BankAuthorisations Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/bank_authorisations'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'bank_authorisations' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.bank_authorisations.create( + params: { + redirect_uri: 'https://my-company.com/landing', + links: { + billing_request: 'BRQ123', + }, + } + ) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/bank_authorisations/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'bank_authorisations' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.bank_authorisations.get('BAU123') + end + end +end diff --git a/spec/code_samples/bank_details_lookups_code_samples_spec.rb b/spec/code_samples/bank_details_lookups_code_samples_spec.rb new file mode 100644 index 00000000..124e2c50 --- /dev/null +++ b/spec/code_samples/bank_details_lookups_code_samples_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BankDetailsLookups Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/bank_details_lookups'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'bank_details_lookups' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.bank_details_lookups.create( + params: { + country_code: 'GB', + account_number: '55779911', + branch_code: '200000', + } + ) + end + end +end diff --git a/spec/code_samples/billing_request_flows_code_samples_spec.rb b/spec/code_samples/billing_request_flows_code_samples_spec.rb new file mode 100644 index 00000000..81470a99 --- /dev/null +++ b/spec/code_samples/billing_request_flows_code_samples_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BillingRequestFlows Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_request_flows'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_request_flows' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_request_flows.create( + params: { + redirect_uri: 'https://my-company.com/landing', + exit_uri: 'https://my-company.com/exit', + prefilled_customer: { + given_name: 'Frank', + family_name: 'Osborne', + email: 'frank.osborne@acmeplc.com', + }, + links: { + billing_request: 'BRQ123', + }, + } + ) + end + end + + describe '#initialise code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_request_flows/:identity/actions/initialise'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_request_flows' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_request_flows.initialise('BRF123') + end + end +end diff --git a/spec/code_samples/billing_request_templates_code_samples_spec.rb b/spec/code_samples/billing_request_templates_code_samples_spec.rb new file mode 100644 index 00000000..1a64f289 --- /dev/null +++ b/spec/code_samples/billing_request_templates_code_samples_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BillingRequestTemplates Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_request_templates'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_request_templates' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_request_templates.list + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_request_templates/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_request_templates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_request_templates.get('BRT123') + end + end + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_request_templates'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_request_templates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_request_templates.create( + params: { + name: '12 Month Gold Plan', + payment_request_description: 'One-time joining fee', + mandate_request_description: 'Recurring fee', + payment_request_currency: 'GBP', + payment_request_amount: '69.99', + mandate_request_currency: 'GBP', + redirect_uri: 'https://my-company.com/landing', + } + ) + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_request_templates/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_request_templates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_request_templates.update('BRT123', params: { + name: '12 Month Silver Plan', + payment_request_amount: '49.99', + }) + end + end +end diff --git a/spec/code_samples/billing_request_with_actions_code_samples_spec.rb b/spec/code_samples/billing_request_with_actions_code_samples_spec.rb new file mode 100644 index 00000000..42f94d94 --- /dev/null +++ b/spec/code_samples/billing_request_with_actions_code_samples_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BillingRequestWithActions Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } +end diff --git a/spec/code_samples/billing_requests_code_samples_spec.rb b/spec/code_samples/billing_requests_code_samples_spec.rb new file mode 100644 index 00000000..be69a65a --- /dev/null +++ b/spec/code_samples/billing_requests_code_samples_spec.rb @@ -0,0 +1,243 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'BillingRequests Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.create( + params: { + payment_request: { + description: 'First Payment', + amount: '500', + currency: 'GBP', + }, + mandate_request: { + scheme: 'bacs', + }, + } + ) + end + end + + describe '#collect_customer_details code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/collect_customer_details'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.collect_customer_details('BR123', { + params: { + customer: { + email: 'alice@example.com', + given_name: 'Alice', + family_name: 'Smith', + }, + customer_billing_detail: { + address_line1: '1 Somewhere Lane', + }, + }, + }) + end + end + + describe '#collect_bank_account code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/collect_bank_account'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.collect_bank_account('BR123', { + params: { + account_number: '55779911', + branch_code: '200000', + account_holder_name: 'Frank Osborne', + country_code: 'GB', + }, + }) + end + end + + describe '#confirm_payer_details code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/confirm_payer_details'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.confirm_payer_details('BR123') + end + end + + describe '#fulfil code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/fulfil'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.fulfil('BR123') + end + end + + describe '#cancel code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/cancel'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.cancel('BR123') + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.list + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.get('BR123') + end + end + + describe '#notify code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/notify'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.notify('BR123', { + params: { + notification_type: 'email', + redirect_uri: 'https://my-company.com', + }, + }) + end + end + + describe '#fallback code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/fallback'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.fallback('BR123') + end + end + + describe '#choose_currency code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/actions/choose_currency'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'billing_requests' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.billing_requests.choose_currency('BR123', { + params: { + currency: 'GBP', + }, + }) + end + end +end diff --git a/spec/code_samples/blocks_code_samples_spec.rb b/spec/code_samples/blocks_code_samples_spec.rb new file mode 100644 index 00000000..fe363fb1 --- /dev/null +++ b/spec/code_samples/blocks_code_samples_spec.rb @@ -0,0 +1,136 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Blocks Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/blocks'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'blocks' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.blocks.create( + params: { + block_type: 'email', + reason_type: 'no_intent_to_pay', + resource_reference: 'example@example.com', + } + ) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/blocks/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'blocks' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.blocks.get('BLC456') + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/blocks'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'blocks' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.blocks.all.each do |block| + puts block.id + puts block.block_type + end + end + end + + describe '#disable code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/blocks/:identity/actions/disable'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'blocks' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.blocks.disable('BLC123') + end + end + + describe '#enable code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/blocks/:identity/actions/enable'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'blocks' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.blocks.enable('BLC123') + end + end + + describe '#block_by_ref code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/blocks/block_by_ref'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'blocks' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + resp = @client.blocks.block_by_ref( + params: { + reference_type: 'customer', + reference_value: 'CU123', + reason_type: 'no_intent_to_pay', + } + ) + resp.records + end + end +end diff --git a/spec/code_samples/creditor_bank_accounts_code_samples_spec.rb b/spec/code_samples/creditor_bank_accounts_code_samples_spec.rb new file mode 100644 index 00000000..6163268a --- /dev/null +++ b/spec/code_samples/creditor_bank_accounts_code_samples_spec.rb @@ -0,0 +1,98 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'CreditorBankAccounts Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditor_bank_accounts'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditor_bank_accounts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditor_bank_accounts.create( + params: { + account_holder_name: 'Example Ltd', + account_number: '55779911', + branch_code: '200000', + country_code: 'GB', + links: { + creditor: 'CR123', + }, + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditor_bank_accounts'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditor_bank_accounts' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditor_bank_accounts.list + + @client.creditor_bank_accounts.list(params: { enabled: true }) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditor_bank_accounts/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditor_bank_accounts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditor_bank_accounts.get('BA123') + end + end + + describe '#disable code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditor_bank_accounts/:identity/actions/disable'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditor_bank_accounts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditor_bank_accounts.disable('BA123') + end + end +end diff --git a/spec/code_samples/creditors_code_samples_spec.rb b/spec/code_samples/creditors_code_samples_spec.rb new file mode 100644 index 00000000..f78acfaa --- /dev/null +++ b/spec/code_samples/creditors_code_samples_spec.rb @@ -0,0 +1,100 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Creditors Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditors'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditors' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditors.create( + params: { + name: 'Acme', + country_code: 'GB', + creditor_type: 'company', + bank_reference_prefix: 'ACME', + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditors'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditors' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditors.list + + @client.creditors.list(params: { limit: 2 }) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditors/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditors' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditors.get('CR123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/creditors/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'creditors' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.creditors.update( + 'CR123', + params: { + links: { default_gbp_payout_account: 'BA789' }, + } + ) + end + end +end diff --git a/spec/code_samples/currency_exchange_rates_code_samples_spec.rb b/spec/code_samples/currency_exchange_rates_code_samples_spec.rb new file mode 100644 index 00000000..8373a924 --- /dev/null +++ b/spec/code_samples/currency_exchange_rates_code_samples_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'CurrencyExchangeRates Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/currency_exchange_rates'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'currency_exchange_rates' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.currency_exchange_rates.list(params: { source: 'EUR', target: 'GBP' }) + end + end +end diff --git a/spec/code_samples/customer_bank_accounts_code_samples_spec.rb b/spec/code_samples/customer_bank_accounts_code_samples_spec.rb new file mode 100644 index 00000000..243e9368 --- /dev/null +++ b/spec/code_samples/customer_bank_accounts_code_samples_spec.rb @@ -0,0 +1,125 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'CustomerBankAccounts Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customer_bank_accounts'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customer_bank_accounts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customer_bank_accounts.create( + params: { + account_holder_name: 'Fran Cosborne', + account_number: '55779911', + branch_code: '200000', + country_code: 'GB', + links: { + customer: 'CU123', + }, + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customer_bank_accounts'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customer_bank_accounts' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customer_bank_accounts.list + + @client.customer_bank_accounts.list( + params: { + customer: 'CU123', + enabled: true, + } + ) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customer_bank_accounts/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customer_bank_accounts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customer_bank_accounts.get('BA123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customer_bank_accounts/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customer_bank_accounts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customer_bank_accounts.update( + 'BA123', + params: { + metadata: { description: 'Business account' }, + } + ) + end + end + + describe '#disable code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customer_bank_accounts/:identity/actions/disable'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customer_bank_accounts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customer_bank_accounts.disable('BA123') + end + end +end diff --git a/spec/code_samples/customer_notifications_code_samples_spec.rb b/spec/code_samples/customer_notifications_code_samples_spec.rb new file mode 100644 index 00000000..4a8bf2d0 --- /dev/null +++ b/spec/code_samples/customer_notifications_code_samples_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'CustomerNotifications Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#handle code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customer_notifications/:identity/actions/handle'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customer_notifications' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customer_notifications.handle('PCN123') + end + end +end diff --git a/spec/code_samples/customers_code_samples_spec.rb b/spec/code_samples/customers_code_samples_spec.rb new file mode 100644 index 00000000..55a2219a --- /dev/null +++ b/spec/code_samples/customers_code_samples_spec.rb @@ -0,0 +1,123 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Customers Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customers'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customers' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customers.create( + params: { + email: 'user@example.com', + given_name: 'Jacob', + family_name: 'Pargin', + country_code: 'GB', + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customers'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customers' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customers.list + + @client.customers.list( + params: { + 'created_at[gt]' => '2016-08-06T09:30:00Z', + } + ) + + @client.customers.list.records.each { |customer| puts customer.inspect } + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customers/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customers' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customers.get('CU123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customers/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customers' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customers.update( + 'CU123', + params: { + metadata: { custom_reference: 'EXAMPLELTD01' }, + } + ) + end + end + + describe '#remove code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/customers/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:delete, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'customers' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.customers.remove('CU123') + end + end +end diff --git a/spec/code_samples/events_code_samples_spec.rb b/spec/code_samples/events_code_samples_spec.rb new file mode 100644 index 00000000..8a80675f --- /dev/null +++ b/spec/code_samples/events_code_samples_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Events Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/events'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'events' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.events.list + + @client.events.list(params: { resource_type: 'payments' }) + + @client.events.list.records.each { |event| puts event.inspect } + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/events/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'events' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.events.get('EV123') + end + end +end diff --git a/spec/code_samples/exports_code_samples_spec.rb b/spec/code_samples/exports_code_samples_spec.rb new file mode 100644 index 00000000..dbbce8b8 --- /dev/null +++ b/spec/code_samples/exports_code_samples_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Exports Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/exports/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'exports' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.exports.get('EX123') + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/exports'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'exports' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.exports.list + end + end +end diff --git a/spec/code_samples/funds_availabilities_code_samples_spec.rb b/spec/code_samples/funds_availabilities_code_samples_spec.rb new file mode 100644 index 00000000..312bafc9 --- /dev/null +++ b/spec/code_samples/funds_availabilities_code_samples_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'FundsAvailabilities Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#check code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/funds_availability/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'funds_availability' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.funds_availabilities.check('MD123', params: { amount: '1000' }) + end + end +end diff --git a/spec/code_samples/instalment_schedules_code_samples_spec.rb b/spec/code_samples/instalment_schedules_code_samples_spec.rb new file mode 100644 index 00000000..c46f6427 --- /dev/null +++ b/spec/code_samples/instalment_schedules_code_samples_spec.rb @@ -0,0 +1,189 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'InstalmentSchedules Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create_with_dates code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/instalment_schedules'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'instalment_schedules' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.instalment_schedules.create_with_dates( + params: { + name: 'ACME Invoice 103', + total_amount: 10_000, # 100 GBP in pence, collected from the customer + app_fee: 10, # Your 10 pence fee, applied to each instalment, + # to be paid out to you + currency: 'GBP', + instalments: [ + { + charge_date: '2019-08-20', + amount: 3_400, + }, + { + charge_date: '2019-09-03', + amount: 3_400, + }, + { + charge_date: '2019-09-17', + amount: 3_200, + }, + ], + links: { + mandate: 'MD0000XH9A3T4C', + }, + metadata: {}, + }, + headers: { + 'Idempotency-Key': 'random_instalment_schedule_specific_string', + } + ) + end + end + + describe '#create_with_schedule code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/instalment_schedules'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'instalment_schedules' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.instalment_schedules.create_with_schedule( + params: { + name: 'ACME Invoice 103', + total_amount: 10_000, # 100 GBP in pence, collected from the customer + app_fee: 10, # Your 10 pence fee, applied to each instalment, + # to be paid out to you + currency: 'GBP', + instalments: { + start_date: '2019-08-20', + interval_unit: 'weekly', + interval: 2, + amounts: [ + 3_400, + 3_400, + 3_200, + ], + }, + links: { + mandate: 'MD0000XH9A3T4C', + }, + metadata: {}, + }, + headers: { + 'Idempotency-Key': 'random_instalment_schedule_specific_string', + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/instalment_schedules'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'instalment_schedules' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.instalment_schedules.list + + @client.instalment_schedules.list( + params: { + 'created_at[gt]' => '2016-08-06T09:30:00Z', + } + ) + + @client.instalment_schedules.list.records.each do |instalment_schedule| + puts instalment_schedule.inspect + end + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/instalment_schedules/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'instalment_schedules' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.instalment_schedules.get('IS123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/instalment_schedules/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'instalment_schedules' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.instalment_schedules.update( + 'IS123', + params: { + metadata: { key: 'value' }, + } + ) + end + end + + describe '#cancel code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/instalment_schedules/:identity/actions/cancel'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'instalment_schedules' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.instalment_schedules.cancel('IS123') + end + end +end diff --git a/spec/code_samples/institutions_code_samples_spec.rb b/spec/code_samples/institutions_code_samples_spec.rb new file mode 100644 index 00000000..229b6dc8 --- /dev/null +++ b/spec/code_samples/institutions_code_samples_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Institutions Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/institutions'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'institutions' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.institutions.list(params: { country_code: 'GB' }) + end + end + + describe '#list_for_billing_request code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/billing_requests/:identity/institutions'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'institutions' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.institutions.list_for_billing_request('BR123', { + params: { country_code: 'GB' }, + }) + end + end +end diff --git a/spec/code_samples/logos_code_samples_spec.rb b/spec/code_samples/logos_code_samples_spec.rb new file mode 100644 index 00000000..57037cc1 --- /dev/null +++ b/spec/code_samples/logos_code_samples_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Logos Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create_for_creditor code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/branding/logos'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'logos' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.logos.create_for_creditor( + params: { + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA', + links: { + creditor: 'CR123', + }, + } + ) + end + end +end diff --git a/spec/code_samples/mandate_import_entries_code_samples_spec.rb b/spec/code_samples/mandate_import_entries_code_samples_spec.rb new file mode 100644 index 00000000..97775bb0 --- /dev/null +++ b/spec/code_samples/mandate_import_entries_code_samples_spec.rb @@ -0,0 +1,74 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'MandateImportEntries Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandate_import_entries'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandate_import_entries' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandate_import_entries.create(params: { + links: { + mandate_import: 'IM000010790WX1', + }, + record_identifier: 'bank-file.xml/line-1', + customer: { + company_name: "Jane's widgets", + email: 'jane@janeswidgets.fr', + }, + bank_account: { + account_holder_name: 'Jane Doe', + iban: 'FR14BARC20000055779911', + }, + amendment: { + original_mandate_reference: 'REFNMANDATE', + original_creditor_id: 'FR123OTHERBANK', + original_creditor_name: 'Existing DD Provider', + }, + }) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandate_import_entries'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandate_import_entries' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandate_import_entries.all( + params: { + 'mandate_import' => 'IM000010790WX1', + } + ).each { |entry| puts entry.record_identifier } + end + end +end diff --git a/spec/code_samples/mandate_imports_code_samples_spec.rb b/spec/code_samples/mandate_imports_code_samples_spec.rb new file mode 100644 index 00000000..8db04689 --- /dev/null +++ b/spec/code_samples/mandate_imports_code_samples_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'MandateImports Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandate_imports'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandate_imports' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandate_imports.create(params: { + scheme: 'bacs', + }) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandate_imports/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandate_imports' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandate_imports.get('IM123') + end + end + + describe '#submit code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandate_imports/:identity/actions/submit'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandate_imports' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandate_imports.submit('IM123') + end + end + + describe '#cancel code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandate_imports/:identity/actions/cancel'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandate_imports' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandate_imports.cancel('IM123') + end + end +end diff --git a/spec/code_samples/mandate_pdfs_code_samples_spec.rb b/spec/code_samples/mandate_pdfs_code_samples_spec.rb new file mode 100644 index 00000000..2dcde1bc --- /dev/null +++ b/spec/code_samples/mandate_pdfs_code_samples_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'MandatePdfs Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandate_pdfs'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandate_pdfs' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandate_pdfs.create( + params: { + links: { mandate: 'MD123' }, + } + ) + + @client.mandate_pdfs.create( + params: { + account_number: '55779911', + branch_code: '200000', + country_code: 'GB', + } + ) + + @client.mandate_pdfs.create( + params: { + iban: 'FR14BARC20000055779911', + }, + headers: { + 'Accept-Language' => 'fr', + } + ) + end + end +end diff --git a/spec/code_samples/mandates_code_samples_spec.rb b/spec/code_samples/mandates_code_samples_spec.rb new file mode 100644 index 00000000..36b84609 --- /dev/null +++ b/spec/code_samples/mandates_code_samples_spec.rb @@ -0,0 +1,136 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Mandates Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandates'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandates.create( + params: { + scheme: 'bacs', + links: { + customer_bank_account: 'BA123', + }, + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandates'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandates' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandates.list + + @client.mandates.list(params: { customer: 'CU123' }) + + @client.mandates.list.records.each { |mandate| puts mandate.inspect } + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandates/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandates.get('MD123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandates/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandates.update( + 'MD123', + params: { + metadata: { contract_id: 'ref_09011991' }, + } + ) + end + end + + describe '#cancel code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandates/:identity/actions/cancel'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandates.cancel('MD123') + end + end + + describe '#reinstate code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/mandates/:identity/actions/reinstate'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'mandates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.mandates.reinstate('MD123') + end + end +end diff --git a/spec/code_samples/negative_balance_limits_code_samples_spec.rb b/spec/code_samples/negative_balance_limits_code_samples_spec.rb new file mode 100644 index 00000000..ed6f0a7d --- /dev/null +++ b/spec/code_samples/negative_balance_limits_code_samples_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'NegativeBalanceLimits Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/negative_balance_limits'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'negative_balance_limits' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.negative_balance_limits.list( + params: { + currency: 'GBP', + creditor: 'CR123', + } + ).records + end + end +end diff --git a/spec/code_samples/outbound_payment_import_entries_code_samples_spec.rb b/spec/code_samples/outbound_payment_import_entries_code_samples_spec.rb new file mode 100644 index 00000000..2dcd26b9 --- /dev/null +++ b/spec/code_samples/outbound_payment_import_entries_code_samples_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'OutboundPaymentImportEntries Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payment_import_entries'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payment_import_entries' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payment_import_entries.list( + params: { + outbound_payment_import: 'IM123', + limit: 10, + } + ) + end + end +end diff --git a/spec/code_samples/outbound_payment_imports_code_samples_spec.rb b/spec/code_samples/outbound_payment_imports_code_samples_spec.rb new file mode 100644 index 00000000..0e8dc3c2 --- /dev/null +++ b/spec/code_samples/outbound_payment_imports_code_samples_spec.rb @@ -0,0 +1,92 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'OutboundPaymentImports Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payment_imports'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payment_imports' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payment_imports.create( + params: { + entry_items: [ + { + amount: 1000, + scheme: 'faster_payments', + reference: 'Invoice 123', + recipient_bank_account_id: 'BA123', + }, + { + amount: 2000, + scheme: 'faster_payments', + reference: 'Invoice 124', + recipient_bank_account_id: 'BA456', + metadata: { + order_id: 'ORD-789', + }, + }, + ], + links: { + creditor: 'CR123', + }, + } + ) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payment_imports/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payment_imports' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payment_imports.get('IM123') + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payment_imports'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payment_imports' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payment_imports.list(params: { limit: 10 }) + end + end +end diff --git a/spec/code_samples/outbound_payments_code_samples_spec.rb b/spec/code_samples/outbound_payments_code_samples_spec.rb new file mode 100644 index 00000000..2c5223b2 --- /dev/null +++ b/spec/code_samples/outbound_payments_code_samples_spec.rb @@ -0,0 +1,181 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'OutboundPayments Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.create( + params: { + amount: 1000, + scheme: 'faster_payments', + description: 'Reward Payment (August 2024)', + reference: 'Invoice 123', + links: { + creditor: 'CR123', + recipient_bank_account: 'BA123', + }, + } + ) + end + end + + describe '#withdraw code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments/withdrawal'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.withdraw( + params: { + amount: 5000, + scheme: 'faster_payments', + description: 'Withdraw funds to business account', + links: { + creditor: 'CR123', + }, + } + ) + end + end + + describe '#cancel code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments/:identity/actions/cancel'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.cancel('OUT123') + end + end + + describe '#approve code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments/:identity/actions/approve'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.approve('OUT123') + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.get('OUT123') + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.list(params: { limit: 10 }) + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.update( + 'OUT123', + params: { + metadata: { + invoice_id: 'INV-1234', + }, + } + ) + end + end + + describe '#stats code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/outbound_payments/stats'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'outbound_payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.outbound_payments.stats + end + end +end diff --git a/spec/code_samples/payer_authorisations_code_samples_spec.rb b/spec/code_samples/payer_authorisations_code_samples_spec.rb new file mode 100644 index 00000000..0e7409fd --- /dev/null +++ b/spec/code_samples/payer_authorisations_code_samples_spec.rb @@ -0,0 +1,144 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'PayerAuthorisations Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payer_authorisations/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payer_authorisations' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payer_authorisations.get('PAU123') + end + end + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payer_authorisations'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payer_authorisations' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payer_authorisations.create( + params: { + "customer": { + "email": 'mail@example.com', + "given_name": 'Name', + "family_name": 'Surname', + "metadata": { + "salesforce_id": 'EFGH5678', + }, + }, + "bank_account": { + "account_holder_name": 'Name Surname', + "branch_code": '200000', + "account_number": '55779911', + "metadata": {}, + }, + "mandate": { + "reference": 'XYZ789', + "metadata": {}, + }, + } + ) + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payer_authorisations/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payer_authorisations' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payer_authorisations.update( + 'PA123', + params: { + "customer": { + "email": 'mail@example.com', + "given_name": 'Name', + "family_name": 'Surname', + "metadata": { + "salesforce_id": 'EFGH5678', + }, + }, + "bank_account": { + "account_holder_name": 'Name Surname', + "branch_code": '200000', + "account_number": '55779911', + }, + "mandate": { + "reference": 'XYZ789', + }, + } + ) + end + end + + describe '#submit code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payer_authorisations/:identity/actions/submit'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payer_authorisations' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payer_authorisations.submit('PAU123') + end + end + + describe '#confirm code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payer_authorisations/:identity/actions/confirm'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payer_authorisations' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payer_authorisations.confirm('PAU123') + end + end +end diff --git a/spec/code_samples/payer_themes_code_samples_spec.rb b/spec/code_samples/payer_themes_code_samples_spec.rb new file mode 100644 index 00000000..1fe3d60f --- /dev/null +++ b/spec/code_samples/payer_themes_code_samples_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'PayerThemes Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create_for_creditor code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/branding/payer_themes'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payer_themes' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payer_themes.create_for_creditor( + params: { + "header_background_colour": '#BD10E0', + "link_text_colour": '#7ED321', + "button_background_colour": '#128DAA', + "content_box_border_colour": '#BD10E0', + "links": { + "creditor": 'CR123', + }, + } + ) + end + end +end diff --git a/spec/code_samples/payment_account_transactions_code_samples_spec.rb b/spec/code_samples/payment_account_transactions_code_samples_spec.rb new file mode 100644 index 00000000..c3bd010b --- /dev/null +++ b/spec/code_samples/payment_account_transactions_code_samples_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'PaymentAccountTransactions Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payment_account_transactions/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payment_account_transactions' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payment_account_transactions.get('PATR1234') + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payment_accounts/:identity/transactions'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payment_account_transactions' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payment_account_transactions.list( + 'BA12345', + params: { + value_date_from: '2024-01-01', + value_date_to: '2024-01-31', + } + ) + end + end +end diff --git a/spec/code_samples/payment_accounts_code_samples_spec.rb b/spec/code_samples/payment_accounts_code_samples_spec.rb new file mode 100644 index 00000000..625ed366 --- /dev/null +++ b/spec/code_samples/payment_accounts_code_samples_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'PaymentAccounts Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } +end diff --git a/spec/code_samples/payments_code_samples_spec.rb b/spec/code_samples/payments_code_samples_spec.rb new file mode 100644 index 00000000..f1e319c4 --- /dev/null +++ b/spec/code_samples/payments_code_samples_spec.rb @@ -0,0 +1,141 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Payments Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payments'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payments.create( + params: { + amount: 1000, + currency: 'GBP', + description: 'Club membership fee', + links: { + mandate: 'MD123', + }, + }, + headers: { + 'Idempotency-Key' => 'aaf50eb0-8ddb-4900-a97b-40ed794570a1', + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payments'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payments' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payments.list + + @client.payments.list(params: { customer: 'CU123' }) + + @client.payments.list.records.each { |payment| puts payment.inspect } + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payments/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payments.get('PM123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payments/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payments.update( + 'PM123', + params: { + metadata: { order_id: 'transaction-0HE9WQ0WDE' }, + } + ) + end + end + + describe '#cancel code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payments/:identity/actions/cancel'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payments.cancel('PM123') + end + end + + describe '#retry code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payments/:identity/actions/retry'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payments' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payments.retry('PM123') + end + end +end diff --git a/spec/code_samples/payout_items_code_samples_spec.rb b/spec/code_samples/payout_items_code_samples_spec.rb new file mode 100644 index 00000000..69bf27dc --- /dev/null +++ b/spec/code_samples/payout_items_code_samples_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'PayoutItems Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payout_items'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payout_items' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payout_items.list(params: { payout: 'PO123' }) + end + end +end diff --git a/spec/code_samples/payouts_code_samples_spec.rb b/spec/code_samples/payouts_code_samples_spec.rb new file mode 100644 index 00000000..3d2a1301 --- /dev/null +++ b/spec/code_samples/payouts_code_samples_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Payouts Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payouts'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payouts' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payouts.list + + @client.payouts.list(params: { creditor_bank_account: 'BA123' }) + + @client.payouts.list.records.each { |payout| puts payout.inspect } + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payouts/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payouts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payouts.get('PO123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/payouts/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'payouts' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.payouts.update( + 'PO123', + params: { + metadata: { key: 'value' }, + } + ) + end + end +end diff --git a/spec/code_samples/redirect_flows_code_samples_spec.rb b/spec/code_samples/redirect_flows_code_samples_spec.rb new file mode 100644 index 00000000..dd31c821 --- /dev/null +++ b/spec/code_samples/redirect_flows_code_samples_spec.rb @@ -0,0 +1,85 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'RedirectFlows Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/redirect_flows'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'redirect_flows' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.redirect_flows.create( + params: { + description: 'Team membership', + session_token: 'my_unique_tracking_id', + success_redirect_url: 'https://example.com/pay/confirm', + prefilled_customer: { + given_name: 'Frank', + family_name: 'Osborne', + email: 'frank.osborne@acmeplc.com', + }, + } + ) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/redirect_flows/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'redirect_flows' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.redirect_flows.get('RE123') + end + end + + describe '#complete code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/redirect_flows/:identity/actions/complete'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'redirect_flows' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.redirect_flows.complete( + 'RE123', + params: { + session_token: 'my_unique_tracking_id', + } + ) + end + end +end diff --git a/spec/code_samples/refunds_code_samples_spec.rb b/spec/code_samples/refunds_code_samples_spec.rb new file mode 100644 index 00000000..0800d933 --- /dev/null +++ b/spec/code_samples/refunds_code_samples_spec.rb @@ -0,0 +1,103 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Refunds Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/refunds'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'refunds' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.refunds.create( + params: { + amount: 100, + total_amount_confirmation: 150, + reference: 'Service refund', + metadata: { reason: 'Late delivery' }, + links: { payment: 'PM123' }, + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/refunds'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'refunds' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.refunds.list + + @client.refunds.list(params: { payment: 'PM123' }) + + @client.refunds.list.records.each { |refund| puts refund.inspect } + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/refunds/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'refunds' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.refunds.get('RF123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/refunds/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'refunds' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.refunds.update( + 'RF123', + params: { + metadata: { reason: 'Late delivery', internal_code: 'refund_1A' }, + } + ) + end + end +end diff --git a/spec/code_samples/scenario_simulators_code_samples_spec.rb b/spec/code_samples/scenario_simulators_code_samples_spec.rb new file mode 100644 index 00000000..ff8444ea --- /dev/null +++ b/spec/code_samples/scenario_simulators_code_samples_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'ScenarioSimulators Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#run code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/scenario_simulators/:identity/actions/run'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'scenario_simulators' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.scenario_simulators.run( + 'payment_failed', + params: { links: { resource: 'PM123' } } + ) + end + end +end diff --git a/spec/code_samples/scheme_identifiers_code_samples_spec.rb b/spec/code_samples/scheme_identifiers_code_samples_spec.rb new file mode 100644 index 00000000..ddf6c956 --- /dev/null +++ b/spec/code_samples/scheme_identifiers_code_samples_spec.rb @@ -0,0 +1,77 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'SchemeIdentifiers Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/scheme_identifiers'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'scheme_identifiers' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.scheme_identifiers.create( + params: { + scheme: 'bacs', + name: 'Example Ltd', + links: { + creditor: 'CR123', + }, + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/scheme_identifiers'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'scheme_identifiers' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.scheme_identifiers.list.records + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/scheme_identifiers/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'scheme_identifiers' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.scheme_identifiers.get('SU123') + end + end +end diff --git a/spec/code_samples/subscriptions_code_samples_spec.rb b/spec/code_samples/subscriptions_code_samples_spec.rb new file mode 100644 index 00000000..241d64e0 --- /dev/null +++ b/spec/code_samples/subscriptions_code_samples_spec.rb @@ -0,0 +1,157 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Subscriptions Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/subscriptions'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'subscriptions' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.subscriptions.create( + params: { + amount: 2500, + currency: 'GBP', + name: 'Monthly magazine', + interval_unit: 'monthly', + day_of_month: 1, + links: { + mandate: 'MD123', + }, + } + ) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/subscriptions'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'subscriptions' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.subscriptions.list + + @client.subscriptions.list(params: { customer: 'CU123' }) + + @client.subscriptions.list.records.each { |subscription| puts subscription.inspect } + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/subscriptions/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'subscriptions' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.subscriptions.get('SB123') + end + end + + describe '#update code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/subscriptions/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:put, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'subscriptions' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.subscriptions.update( + 'SB123', + params: { + metadata: { order_no: 'ABCD4321' }, + } + ) + end + end + + describe '#pause code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/subscriptions/:identity/actions/pause'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'subscriptions' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.subscriptions.pause('SB123') + end + end + + describe '#resume code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/subscriptions/:identity/actions/resume'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'subscriptions' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.subscriptions.resume('SB123') + end + end + + describe '#cancel code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/subscriptions/:identity/actions/cancel'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'subscriptions' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.subscriptions.cancel('SB123') + end + end +end diff --git a/spec/code_samples/tax_rates_code_samples_spec.rb b/spec/code_samples/tax_rates_code_samples_spec.rb new file mode 100644 index 00000000..67c3ae9e --- /dev/null +++ b/spec/code_samples/tax_rates_code_samples_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'TaxRates Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/tax_rates'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'tax_rates' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.tax_rates.list(params: { jurisdiction: 'GB' }) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/tax_rates/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'tax_rates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.tax_rates.get('GB_VAT_1') + end + end +end diff --git a/spec/code_samples/transferred_mandates_code_samples_spec.rb b/spec/code_samples/transferred_mandates_code_samples_spec.rb new file mode 100644 index 00000000..342f8bb1 --- /dev/null +++ b/spec/code_samples/transferred_mandates_code_samples_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'TransferredMandates Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#transferred_mandates code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/transferred_mandates/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'transferred_mandates' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.transferred_mandates.transferred_mandates('MD123') + end + end +end diff --git a/spec/code_samples/verification_details_code_samples_spec.rb b/spec/code_samples/verification_details_code_samples_spec.rb new file mode 100644 index 00000000..cbbbf842 --- /dev/null +++ b/spec/code_samples/verification_details_code_samples_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'VerificationDetails Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/verification_details'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'verification_details' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.verification_details.create(params: { + name: 'Acme', + company_number: '03768189', + address_line1: '12 Drury lane', + city: 'London', + description: 'wine and cheese seller', + postal_code: 'B4 7NJ', + directors: [{ + given_name: 'Gandalf', + family_name: 'Grey', + city: 'London', + date_of_birth: '1986-02-19', + street: 'Drury lane', + postal_code: 'B4 7NJ', + country_code: 'GB', + }], + links: { + creditor: 'CR123', + }, + }) + end + end + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/verification_details'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'verification_details' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.verification_details.list(params: { + creditor: 'CR123', + }).records + end + end +end diff --git a/spec/code_samples/webhooks_code_samples_spec.rb b/spec/code_samples/webhooks_code_samples_spec.rb new file mode 100644 index 00000000..a5723465 --- /dev/null +++ b/spec/code_samples/webhooks_code_samples_spec.rb @@ -0,0 +1,71 @@ +require 'spec_helper' + +# Code Sample Tests +# These tests verify that the documentation code samples are syntactically valid +# and can execute against a mocked API without errors. +# +# IMPORTANT: These tests do NOT verify business logic - they only verify that +# the code samples compile and execute without syntax errors. + +describe 'Webhooks Code Samples' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/webhooks'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'webhooks' => [{}], 'meta' => { 'cursors' => {}, 'limit' => 50 } }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.webhooks.list + + @client.webhooks.list(params: { successful: true }) + end + end + + describe '#get code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/webhooks/:identity'.gsub(/:\w+/, '[^/]+') + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'webhooks' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.webhooks.get('WB123') + end + end + + describe '#retry code sample' do + before do + # Convert :param placeholders to regex wildcards for flexible matching + stub_url = '/webhooks/:identity/actions/retry'.gsub(/:\w+/, '[^/]+') + stub_request(:post, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { 'webhooks' => {} }.to_json, + headers: response_headers + ) + end + + it 'executes without error' do + @client = client + @client.webhooks.retry('WB123') + end + end +end diff --git a/spec/resources/customer_bank_account_spec.rb b/spec/resources/customer_bank_account_spec.rb index a6aae314..a373324d 100644 --- a/spec/resources/customer_bank_account_spec.rb +++ b/spec/resources/customer_bank_account_spec.rb @@ -27,6 +27,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', } end @@ -48,6 +49,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, } ). @@ -69,6 +71,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, @@ -123,6 +126,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', } end @@ -167,6 +171,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -202,6 +207,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { cursors: { @@ -238,6 +244,8 @@ expect(get_list_response.records.first.id).to eq('id-input') expect(get_list_response.records.first.metadata).to eq('metadata-input') + + expect(get_list_response.records.first.trusted_recipient).to eq('trusted_recipient-input') end it 'exposes the cursors for before and after' do @@ -267,6 +275,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { cursors: { after: 'AB345' }, @@ -294,6 +303,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { limit: 2, @@ -337,6 +347,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -374,6 +385,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -433,6 +445,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -470,6 +483,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, @@ -513,6 +527,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers diff --git a/spec/resources/export_spec.rb b/spec/resources/export_spec.rb index 701e942f..93f1641d 100644 --- a/spec/resources/export_spec.rb +++ b/spec/resources/export_spec.rb @@ -26,6 +26,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }, @@ -56,6 +57,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }, @@ -104,6 +106,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -127,6 +130,8 @@ expect(get_list_response.records.first.download_url).to eq('download_url-input') + expect(get_list_response.records.first.error_message).to eq('error_message-input') + expect(get_list_response.records.first.export_type).to eq('export_type-input') expect(get_list_response.records.first.id).to eq('id-input') @@ -150,6 +155,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -170,6 +176,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], diff --git a/spec/resources/mandate_spec.rb b/spec/resources/mandate_spec.rb index bba878a2..6dccdc62 100644 --- a/spec/resources/mandate_spec.rb +++ b/spec/resources/mandate_spec.rb @@ -22,6 +22,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -46,6 +47,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -70,6 +72,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -127,6 +130,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -174,6 +178,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -212,6 +217,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -247,6 +253,8 @@ expect(get_list_response.records.first.id).to eq('id-input') + expect(get_list_response.records.first.mandate_type).to eq('mandate_type-input') + expect(get_list_response.records.first.metadata).to eq('metadata-input') expect(get_list_response.records.first.next_possible_charge_date).to eq('next_possible_charge_date-input') @@ -286,6 +294,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -316,6 +325,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -362,6 +372,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -402,6 +413,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -464,6 +476,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -504,6 +517,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -550,6 +564,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -585,6 +600,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -631,6 +647,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', diff --git a/spec/resources/outbound_payment_import_entry_spec.rb b/spec/resources/outbound_payment_import_entry_spec.rb new file mode 100644 index 00000000..2ff8d3dc --- /dev/null +++ b/spec/resources/outbound_payment_import_entry_spec.rb @@ -0,0 +1,131 @@ +require 'spec_helper' + +describe GoCardlessPro::Resources::OutboundPaymentImportEntry do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list' do + describe 'with no filters' do + subject(:get_list_response) { client.outbound_payment_import_entries.list } + + before do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries}).to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + cursors: { + before: nil, + after: 'ABC123', + }, + }, + }.to_json, + headers: response_headers + ) + end + + it 'wraps each item in the resource class' do + expect(get_list_response.records.map { |x| x.class }.uniq.first).to eq(GoCardlessPro::Resources::OutboundPaymentImportEntry) + + expect(get_list_response.records.first.amount).to eq('amount-input') + + expect(get_list_response.records.first.created_at).to eq('created_at-input') + + expect(get_list_response.records.first.id).to eq('id-input') + + expect(get_list_response.records.first.metadata).to eq('metadata-input') + + expect(get_list_response.records.first.processed_at).to eq('processed_at-input') + + expect(get_list_response.records.first.reference).to eq('reference-input') + + expect(get_list_response.records.first.scheme).to eq('scheme-input') + + expect(get_list_response.records.first.validation_errors).to eq('validation_errors-input') + + expect(get_list_response.records.first.verification_result).to eq('verification_result-input') + end + + it 'exposes the cursors for before and after' do + expect(get_list_response.before).to eq(nil) + expect(get_list_response.after).to eq('ABC123') + end + + specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } + end + end + + describe '#all' do + let!(:first_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries$}).to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + end + + let!(:second_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries\?after=AB345}).to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + end + + it 'automatically makes the extra requests' do + expect(client.outbound_payment_import_entries.all.to_a.length).to eq(2) + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested + end + end +end diff --git a/spec/resources/outbound_payment_import_spec.rb b/spec/resources/outbound_payment_import_spec.rb new file mode 100644 index 00000000..8003a59d --- /dev/null +++ b/spec/resources/outbound_payment_import_spec.rb @@ -0,0 +1,362 @@ +require 'spec_helper' + +describe GoCardlessPro::Resources::OutboundPaymentImport do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create' do + subject(:post_create_response) { client.outbound_payment_imports.create(params: new_resource) } + context 'with a valid request' do + let(:new_resource) do + { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + } + end + + before do + stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}). + with( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + } + ). + to_return( + body: { + 'outbound_payment_imports' => + + { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + + }.to_json, + headers: response_headers + ) + end + + it 'creates and returns the resource' do + expect(post_create_response).to be_a(GoCardlessPro::Resources::OutboundPaymentImport) + end + end + + context 'with a request that returns a validation error' do + let(:new_resource) { {} } + + before do + stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}).to_return( + body: { + error: { + type: 'validation_failed', + code: 422, + errors: [ + { message: 'test error message', field: 'test_field' }, + ], + }, + }.to_json, + headers: response_headers, + status: 422 + ) + end + + it 'throws the correct error' do + expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError) + end + end + + context 'with a request that returns an idempotent creation conflict error' do + let(:id) { 'ID123' } + + let(:new_resource) do + { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + } + end + + let!(:post_stub) do + stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}).to_return( + body: { + error: { + type: 'invalid_state', + code: 409, + errors: [ + { + message: 'A resource has already been created with this idempotency key', + reason: 'idempotent_creation_conflict', + links: { + conflicting_resource_id: id, + }, + }, + ], + }, + }.to_json, + headers: response_headers, + status: 409 + ) + end + + let!(:get_stub) do + stub_url = "/outbound_payment_imports/#{id}" + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + }.to_json, + headers: response_headers + ) + end + + it 'fetches the already-created resource' do + post_create_response + expect(post_stub).to have_been_requested + expect(get_stub).to have_been_requested + end + end + end + + describe '#get' do + let(:id) { 'ID123' } + + subject(:get_response) { client.outbound_payment_imports.get(id) } + + context 'passing in a custom header' do + let!(:stub) do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + with(headers: { 'Foo' => 'Bar' }). + to_return( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + }.to_json, + headers: response_headers + ) + end + + subject(:get_response) do + client.outbound_payment_imports.get(id, headers: { + 'Foo' => 'Bar', + }) + end + + it 'includes the header' do + get_response + expect(stub).to have_been_requested + end + end + + context 'when there is a outbound_payment_import to return' do + before do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + }.to_json, + headers: response_headers + ) + end + + it 'wraps the response in a resource' do + expect(get_response).to be_a(GoCardlessPro::Resources::OutboundPaymentImport) + end + end + + context 'when nothing is returned' do + before do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( + body: '', + headers: response_headers + ) + end + + it 'returns nil' do + expect(get_response).to be_nil + end + end + + context "when an ID is specified which can't be included in a valid URI" do + let(:id) { '`' } + + it "doesn't raise an error" do + expect { get_response }.to_not raise_error(/bad URI/) + end + end + end + + describe '#list' do + describe 'with no filters' do + subject(:get_list_response) { client.outbound_payment_imports.list } + + before do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports}).to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + cursors: { + before: nil, + after: 'ABC123', + }, + }, + }.to_json, + headers: response_headers + ) + end + + it 'wraps each item in the resource class' do + expect(get_list_response.records.map { |x| x.class }.uniq.first).to eq(GoCardlessPro::Resources::OutboundPaymentImport) + + expect(get_list_response.records.first.amount_sum).to eq('amount_sum-input') + + expect(get_list_response.records.first.authorisation_url).to eq('authorisation_url-input') + + expect(get_list_response.records.first.created_at).to eq('created_at-input') + + expect(get_list_response.records.first.currency).to eq('currency-input') + + expect(get_list_response.records.first.entry_counts).to eq('entry_counts-input') + + expect(get_list_response.records.first.id).to eq('id-input') + + expect(get_list_response.records.first.status).to eq('status-input') + end + + it 'exposes the cursors for before and after' do + expect(get_list_response.before).to eq(nil) + expect(get_list_response.after).to eq('ABC123') + end + + specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } + end + end + + describe '#all' do + let!(:first_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports$}).to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + end + + let!(:second_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports\?after=AB345}).to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + end + + it 'automatically makes the extra requests' do + expect(client.outbound_payment_imports.all.to_a.length).to eq(2) + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested + end + end +end diff --git a/spec/services/customer_bank_accounts_service_spec.rb b/spec/services/customer_bank_accounts_service_spec.rb index 71930687..d1509b7d 100644 --- a/spec/services/customer_bank_accounts_service_spec.rb +++ b/spec/services/customer_bank_accounts_service_spec.rb @@ -27,6 +27,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', } end @@ -48,6 +49,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, } ). @@ -69,6 +71,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, @@ -146,6 +149,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', } end @@ -190,6 +194,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -240,6 +245,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { cursors: { @@ -281,6 +287,8 @@ expect(get_list_response.records.first.id).to eq('id-input') expect(get_list_response.records.first.metadata).to eq('metadata-input') + + expect(get_list_response.records.first.trusted_recipient).to eq('trusted_recipient-input') end it 'exposes the cursors for before and after' do @@ -333,6 +341,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { cursors: { after: 'AB345' }, @@ -360,6 +369,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { limit: 2, @@ -396,6 +406,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { cursors: { after: 'AB345' }, @@ -423,6 +434,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { limit: 2, @@ -455,6 +467,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { cursors: { after: 'AB345' }, @@ -485,6 +498,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }], meta: { limit: 2, @@ -528,6 +542,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -565,6 +580,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -679,6 +695,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers @@ -741,6 +758,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, @@ -795,6 +813,7 @@ 'id' => 'id-input', 'links' => 'links-input', 'metadata' => 'metadata-input', + 'trusted_recipient' => 'trusted_recipient-input', }, }.to_json, headers: response_headers diff --git a/spec/services/exports_service_spec.rb b/spec/services/exports_service_spec.rb index 081b4aa4..6f7a7e44 100644 --- a/spec/services/exports_service_spec.rb +++ b/spec/services/exports_service_spec.rb @@ -26,6 +26,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }, @@ -56,6 +57,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }, @@ -158,6 +160,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -186,6 +189,8 @@ expect(get_list_response.records.first.download_url).to eq('download_url-input') + expect(get_list_response.records.first.error_message).to eq('error_message-input') + expect(get_list_response.records.first.export_type).to eq('export_type-input') expect(get_list_response.records.first.id).to eq('id-input') @@ -232,6 +237,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -252,6 +258,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -281,6 +288,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -301,6 +309,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -326,6 +335,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], @@ -349,6 +359,7 @@ 'created_at' => 'created_at-input', 'currency' => 'currency-input', 'download_url' => 'download_url-input', + 'error_message' => 'error_message-input', 'export_type' => 'export_type-input', 'id' => 'id-input', }], diff --git a/spec/services/mandates_service_spec.rb b/spec/services/mandates_service_spec.rb index 5120f1ab..7928f52e 100644 --- a/spec/services/mandates_service_spec.rb +++ b/spec/services/mandates_service_spec.rb @@ -22,6 +22,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -46,6 +47,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -70,6 +72,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -150,6 +153,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -197,6 +201,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -250,6 +255,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -290,6 +296,8 @@ expect(get_list_response.records.first.id).to eq('id-input') + expect(get_list_response.records.first.mandate_type).to eq('mandate_type-input') + expect(get_list_response.records.first.metadata).to eq('metadata-input') expect(get_list_response.records.first.next_possible_charge_date).to eq('next_possible_charge_date-input') @@ -352,6 +360,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -382,6 +391,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -421,6 +431,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -451,6 +462,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -486,6 +498,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -519,6 +532,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -565,6 +579,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -605,6 +620,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -722,6 +738,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -787,6 +804,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -844,6 +862,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -879,6 +898,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', @@ -936,6 +956,7 @@ 'funds_settlement' => 'funds_settlement-input', 'id' => 'id-input', 'links' => 'links-input', + 'mandate_type' => 'mandate_type-input', 'metadata' => 'metadata-input', 'next_possible_charge_date' => 'next_possible_charge_date-input', 'next_possible_standard_ach_charge_date' => 'next_possible_standard_ach_charge_date-input', diff --git a/spec/services/outbound_payment_import_entries_service_spec.rb b/spec/services/outbound_payment_import_entries_service_spec.rb new file mode 100644 index 00000000..1e193dcf --- /dev/null +++ b/spec/services/outbound_payment_import_entries_service_spec.rb @@ -0,0 +1,275 @@ +require 'spec_helper' + +describe GoCardlessPro::Services::OutboundPaymentImportEntriesService do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#list' do + describe 'with no filters' do + subject(:get_list_response) { client.outbound_payment_import_entries.list } + + let(:body) do + { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + cursors: { + before: nil, + after: 'ABC123', + }, + }, + }.to_json + end + + before do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries}).to_return( + body: body, + headers: response_headers + ) + end + + it 'wraps each item in the resource class' do + expect(get_list_response.records.map { |x| x.class }.uniq.first).to eq(GoCardlessPro::Resources::OutboundPaymentImportEntry) + + expect(get_list_response.records.first.amount).to eq('amount-input') + + expect(get_list_response.records.first.created_at).to eq('created_at-input') + + expect(get_list_response.records.first.id).to eq('id-input') + + expect(get_list_response.records.first.metadata).to eq('metadata-input') + + expect(get_list_response.records.first.processed_at).to eq('processed_at-input') + + expect(get_list_response.records.first.reference).to eq('reference-input') + + expect(get_list_response.records.first.scheme).to eq('scheme-input') + + expect(get_list_response.records.first.validation_errors).to eq('validation_errors-input') + + expect(get_list_response.records.first.verification_result).to eq('verification_result-input') + end + + it 'exposes the cursors for before and after' do + expect(get_list_response.before).to eq(nil) + expect(get_list_response.after).to eq('ABC123') + end + + specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } + + describe 'retry behaviour' do + before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) } + + it 'retries timeouts' do + stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries}). + to_timeout.then.to_return({ status: 200, headers: response_headers, body: body }) + + get_list_response + expect(stub).to have_been_requested.twice + end + + it 'retries 5XX errors' do + stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries}). + to_return({ status: 502, + headers: { 'Content-Type' => 'text/html' }, + body: 'Response from Cloudflare' }). + then.to_return({ status: 200, headers: response_headers, body: body }) + + get_list_response + expect(stub).to have_been_requested.twice + end + end + end + end + + describe '#all' do + let!(:first_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries$}).to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + end + + let!(:second_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries\?after=AB345}).to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + end + + it 'automatically makes the extra requests' do + expect(client.outbound_payment_import_entries.all.to_a.length).to eq(2) + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested + end + + describe 'retry behaviour' do + before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) } + + it 'retries timeouts' do + first_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries$}).to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + + second_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries\?after=AB345}). + to_timeout.then. + to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + + client.outbound_payment_import_entries.all.to_a + + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested.twice + end + + it 'retries 5XX errors' do + first_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries$}).to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + + second_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_import_entries\?after=AB345}). + to_return( + status: 502, + body: 'Response from Cloudflare', + headers: { 'Content-Type' => 'text/html' } + ).then.to_return( + body: { + 'outbound_payment_import_entries' => [{ + + 'amount' => 'amount-input', + 'created_at' => 'created_at-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'metadata' => 'metadata-input', + 'processed_at' => 'processed_at-input', + 'reference' => 'reference-input', + 'scheme' => 'scheme-input', + 'validation_errors' => 'validation_errors-input', + 'verification_result' => 'verification_result-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + + client.outbound_payment_import_entries.all.to_a + + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested.twice + end + end + end +end diff --git a/spec/services/outbound_payment_imports_service_spec.rb b/spec/services/outbound_payment_imports_service_spec.rb new file mode 100644 index 00000000..29a6df81 --- /dev/null +++ b/spec/services/outbound_payment_imports_service_spec.rb @@ -0,0 +1,592 @@ +require 'spec_helper' + +describe GoCardlessPro::Services::OutboundPaymentImportsService do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN' + ) + end + + let(:response_headers) { { 'Content-Type' => 'application/json' } } + + describe '#create' do + subject(:post_create_response) { client.outbound_payment_imports.create(params: new_resource) } + context 'with a valid request' do + let(:new_resource) do + { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + } + end + + before do + stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}). + with( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + } + ). + to_return( + body: { + 'outbound_payment_imports' => + + { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + + }.to_json, + headers: response_headers + ) + end + + it 'creates and returns the resource' do + expect(post_create_response).to be_a(GoCardlessPro::Resources::OutboundPaymentImport) + end + + describe 'retry behaviour' do + before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) } + + it 'retries timeouts' do + stub = stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}). + to_timeout.then.to_return({ status: 200, headers: response_headers }) + + post_create_response + expect(stub).to have_been_requested.twice + end + + it 'retries 5XX errors' do + stub = stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}). + to_return({ status: 502, + headers: { 'Content-Type' => 'text/html' }, + body: 'Response from Cloudflare' }). + then.to_return({ status: 200, headers: response_headers }) + + post_create_response + expect(stub).to have_been_requested.twice + end + end + end + + context 'with a request that returns a validation error' do + let(:new_resource) { {} } + + before do + stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}).to_return( + body: { + error: { + type: 'validation_failed', + code: 422, + errors: [ + { message: 'test error message', field: 'test_field' }, + ], + }, + }.to_json, + headers: response_headers, + status: 422 + ) + end + + it 'throws the correct error' do + expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError) + end + end + + context 'with a request that returns an idempotent creation conflict error' do + let(:id) { 'ID123' } + + let(:new_resource) do + { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + } + end + + let!(:post_stub) do + stub_request(:post, %r{.*api.gocardless.com/outbound_payment_imports}).to_return( + body: { + error: { + type: 'invalid_state', + code: 409, + errors: [ + { + message: 'A resource has already been created with this idempotency key', + reason: 'idempotent_creation_conflict', + links: { + conflicting_resource_id: id, + }, + }, + ], + }, + }.to_json, + headers: response_headers, + status: 409 + ) + end + + let!(:get_stub) do + stub_url = "/outbound_payment_imports/#{id}" + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + }.to_json, + headers: response_headers + ) + end + + context 'with default behaviour' do + it 'fetches the already-created resource' do + post_create_response + expect(post_stub).to have_been_requested + expect(get_stub).to have_been_requested + end + end + + context 'with on_idempotency_conflict: :raise' do + let(:client) do + GoCardlessPro::Client.new( + access_token: 'SECRET_TOKEN', + on_idempotency_conflict: :raise + ) + end + + it 'raises an IdempotencyConflict error' do + expect { post_create_response }. + to raise_error(GoCardlessPro::IdempotencyConflict) + end + end + end + end + + describe '#get' do + let(:id) { 'ID123' } + + subject(:get_response) { client.outbound_payment_imports.get(id) } + + context 'passing in a custom header' do + let!(:stub) do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + stub_request(:get, /.*api.gocardless.com#{stub_url}/). + with(headers: { 'Foo' => 'Bar' }). + to_return( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + }.to_json, + headers: response_headers + ) + end + + subject(:get_response) do + client.outbound_payment_imports.get(id, headers: { + 'Foo' => 'Bar', + }) + end + + it 'includes the header' do + get_response + expect(stub).to have_been_requested + end + end + + context 'when there is a outbound_payment_import to return' do + before do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( + body: { + 'outbound_payment_imports' => { + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }, + }.to_json, + headers: response_headers + ) + end + + it 'wraps the response in a resource' do + expect(get_response).to be_a(GoCardlessPro::Resources::OutboundPaymentImport) + end + end + + context 'when nothing is returned' do + before do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( + body: '', + headers: response_headers + ) + end + + it 'returns nil' do + expect(get_response).to be_nil + end + end + + context "when an ID is specified which can't be included in a valid URI" do + let(:id) { '`' } + + it "doesn't raise an error" do + expect { get_response }.to_not raise_error(/bad URI/) + end + end + + describe 'retry behaviour' do + before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) } + + it 'retries timeouts' do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + + stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_timeout.then.to_return({ status: 200, headers: response_headers }) + + get_response + expect(stub).to have_been_requested.twice + end + + it 'retries 5XX errors, other than 500s' do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + + stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return({ status: 502, + headers: { 'Content-Type' => 'text/html' }, + body: 'Response from Cloudflare' }). + then.to_return({ status: 200, headers: response_headers }) + + get_response + expect(stub).to have_been_requested.twice + end + + it 'retries 500 errors returned by the API' do + stub_url = '/outbound_payment_imports/:identity'.gsub(':identity', id) + + gocardless_error = { + 'error' => { + 'message' => 'Internal server error', + 'documentation_url' => 'https://developer.gocardless.com/#gocardless', + 'errors' => [{ + 'message' => 'Internal server error', + 'reason' => 'internal_server_error', + }], + 'type' => 'gocardless', + 'code' => 500, + 'request_id' => 'dummy_request_id', + 'id' => 'dummy_exception_id', + }, + } + + stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/). + to_return({ status: 500, + headers: response_headers, + body: gocardless_error.to_json }). + then.to_return({ status: 200, headers: response_headers }) + + get_response + expect(stub).to have_been_requested.twice + end + end + end + + describe '#list' do + describe 'with no filters' do + subject(:get_list_response) { client.outbound_payment_imports.list } + + let(:body) do + { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + cursors: { + before: nil, + after: 'ABC123', + }, + }, + }.to_json + end + + before do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports}).to_return( + body: body, + headers: response_headers + ) + end + + it 'wraps each item in the resource class' do + expect(get_list_response.records.map { |x| x.class }.uniq.first).to eq(GoCardlessPro::Resources::OutboundPaymentImport) + + expect(get_list_response.records.first.amount_sum).to eq('amount_sum-input') + + expect(get_list_response.records.first.authorisation_url).to eq('authorisation_url-input') + + expect(get_list_response.records.first.created_at).to eq('created_at-input') + + expect(get_list_response.records.first.currency).to eq('currency-input') + + expect(get_list_response.records.first.entry_counts).to eq('entry_counts-input') + + expect(get_list_response.records.first.id).to eq('id-input') + + expect(get_list_response.records.first.status).to eq('status-input') + end + + it 'exposes the cursors for before and after' do + expect(get_list_response.before).to eq(nil) + expect(get_list_response.after).to eq('ABC123') + end + + specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } + + describe 'retry behaviour' do + before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) } + + it 'retries timeouts' do + stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports}). + to_timeout.then.to_return({ status: 200, headers: response_headers, body: body }) + + get_list_response + expect(stub).to have_been_requested.twice + end + + it 'retries 5XX errors' do + stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports}). + to_return({ status: 502, + headers: { 'Content-Type' => 'text/html' }, + body: 'Response from Cloudflare' }). + then.to_return({ status: 200, headers: response_headers, body: body }) + + get_list_response + expect(stub).to have_been_requested.twice + end + end + end + end + + describe '#all' do + let!(:first_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports$}).to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + end + + let!(:second_response_stub) do + stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports\?after=AB345}).to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + end + + it 'automatically makes the extra requests' do + expect(client.outbound_payment_imports.all.to_a.length).to eq(2) + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested + end + + describe 'retry behaviour' do + before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) } + + it 'retries timeouts' do + first_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports$}).to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + + second_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports\?after=AB345}). + to_timeout.then. + to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + + client.outbound_payment_imports.all.to_a + + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested.twice + end + + it 'retries 5XX errors' do + first_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports$}).to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + cursors: { after: 'AB345' }, + limit: 1, + }, + }.to_json, + headers: response_headers + ) + + second_response_stub = stub_request(:get, %r{.*api.gocardless.com/outbound_payment_imports\?after=AB345}). + to_return( + status: 502, + body: 'Response from Cloudflare', + headers: { 'Content-Type' => 'text/html' } + ).then.to_return( + body: { + 'outbound_payment_imports' => [{ + + 'amount_sum' => 'amount_sum-input', + 'authorisation_url' => 'authorisation_url-input', + 'created_at' => 'created_at-input', + 'currency' => 'currency-input', + 'entry_counts' => 'entry_counts-input', + 'id' => 'id-input', + 'links' => 'links-input', + 'status' => 'status-input', + }], + meta: { + limit: 2, + cursors: {}, + }, + }.to_json, + headers: response_headers + ) + + client.outbound_payment_imports.all.to_a + + expect(first_response_stub).to have_been_requested + expect(second_response_stub).to have_been_requested.twice + end + end + end +end