├── .github └── workflows │ └── test.yml ├── .gitignore ├── .rspec ├── 2.0-Upgrade.md ├── 4.0-Upgrade.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── changelog.md ├── chartmogul-ruby.gemspec ├── lib ├── chartmogul.rb └── chartmogul │ ├── account.rb │ ├── api │ └── actions │ │ ├── all.rb │ │ ├── create.rb │ │ ├── custom.rb │ │ ├── destroy.rb │ │ ├── destroy_with_params.rb │ │ ├── retrieve.rb │ │ └── update.rb │ ├── api_resource.rb │ ├── concerns │ ├── entries.rb │ ├── pageable.rb │ ├── pageable2.rb │ ├── pageable_with_anchor.rb │ ├── pageable_with_cursor.rb │ ├── summary.rb │ └── summary_all.rb │ ├── config_attributes.rb │ ├── configuration.rb │ ├── contact.rb │ ├── customer.rb │ ├── customer_invoices.rb │ ├── data_source.rb │ ├── enrichment │ └── customer.rb │ ├── errors │ ├── chartmogul_error.rb │ ├── configuration_error.rb │ ├── deprecated_parameter_error.rb │ ├── forbidden_error.rb │ ├── not_found_error.rb │ ├── resource_invalid_error.rb │ ├── schema_invalid_error.rb │ ├── server_error.rb │ └── unauthorized_error.rb │ ├── invoice.rb │ ├── line_items │ ├── one_time.rb │ └── subscription.rb │ ├── metrics │ ├── activities_export.rb │ ├── activity.rb │ ├── all_key_metrics.rb │ ├── arpa.rb │ ├── arr.rb │ ├── asp.rb │ ├── base.rb │ ├── customer_churn_rate.rb │ ├── customer_count.rb │ ├── customers │ │ ├── activity.rb │ │ └── subscription.rb │ ├── ltv.rb │ ├── mrr.rb │ └── mrr_churn_rate.rb │ ├── note.rb │ ├── object.rb │ ├── opportunity.rb │ ├── ping.rb │ ├── plan.rb │ ├── plan_group.rb │ ├── plan_groups │ └── plans.rb │ ├── resource_path.rb │ ├── subscription.rb │ ├── subscription_event.rb │ ├── summary.rb │ ├── summary_all.rb │ ├── task.rb │ ├── transactions │ ├── payment.rb │ └── refund.rb │ ├── utils │ ├── hash_snake_caser.rb │ └── json_parser.rb │ └── version.rb ├── pre-commit.example └── spec ├── .DS_Store ├── chartmogul ├── account_spec.rb ├── api_resource_spec.rb ├── configuration_spec.rb ├── connection_cache_spec.rb ├── contact_spec.rb ├── customer_invoices_spec.rb ├── customer_spec.rb ├── data_source_spec.rb ├── errors │ └── chartmogul_error_spec.rb ├── invoice_spec.rb ├── line_items │ ├── one_time_spec.rb │ └── subscription_spec.rb ├── metrics │ ├── activities_export_spec.rb │ ├── activities_spec.rb │ ├── all_key_metrics_spec.rb │ ├── customers │ │ ├── activities_spec.rb │ │ └── subscriptions_spec.rb │ ├── metrics_spec.rb │ ├── mrr_spec.rb │ └── shared │ │ ├── metrics_resource.rb │ │ ├── pageable.rb │ │ ├── pageable_with_anchor.rb │ │ └── summary.rb ├── note_spec.rb ├── opportunity_spec.rb ├── ping_spec.rb ├── plan_group_spec.rb ├── plan_groups │ └── plans_spec.rb ├── plan_spec.rb ├── resource_path_spec.rb ├── retry_spec.rb ├── ruby_spec.rb ├── subscription_event_spec.rb ├── subscription_spec.rb ├── task_spec.rb ├── transactions │ ├── payment_spec.rb │ └── refund_spec.rb └── utils │ ├── hash_snake_caser_spec.rb │ └── json_parser_spec.rb ├── fixtures └── vcr_cassettes │ ├── ChartMogul_APIResource │ └── connection │ │ ├── works_in_a_threaded_environment.yml │ │ └── works_when_credentials_are_updated.yml │ ├── ChartMogul_Account │ └── returns_details_of_current_account.yml │ ├── ChartMogul_Contact │ └── API_Actions │ │ ├── creates_the_contact_correctly.yml │ │ ├── destroys_the_contact_correctly.yml │ │ ├── merges_contacts_correctly.yml │ │ ├── retrieves_the_contact_correctly.yml │ │ ├── updates_the_contact_correctly_with_the_class_method.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_Customer │ ├── API_Actions │ │ ├── Customer_Notes │ │ │ ├── creates_a_note_belonging_to_the_customer_correctly.yml │ │ │ └── lists_the_notes_belonging_to_the_customer_correctly.yml │ │ ├── adds_custom_attributes_correctly.yml │ │ ├── adds_tags_correctly.yml │ │ ├── creates_a_contact_belonging_to_the_customer_correctly.yml │ │ ├── creates_a_note_belonging_to_the_customer_correctly.yml │ │ ├── creates_a_opportunity_belonging_to_the_customer_correctly.yml │ │ ├── creates_a_task_belonging_to_the_customer_correctly.yml │ │ ├── creates_the_customer_correctly.yml │ │ ├── destroys_the_customer_correctly.yml │ │ ├── lists_the_contacts_belonging_to_the_customer_correctly.yml │ │ ├── lists_the_invoices_belonging_to_the_customer_correctly.yml │ │ ├── lists_the_notes_belonging_to_the_customer_correctly.yml │ │ ├── lists_the_opportunities_belonging_to_the_customer_correctly.yml │ │ ├── lists_the_subscriptions_belonging_to_the_customer_correctly.yml │ │ ├── lists_the_tasks_belonging_to_the_customer_correctly.yml │ │ ├── merges_customers_correctly_with_the_class_method.yml │ │ ├── merges_customers_correctly_with_the_instance_method.yml │ │ ├── raises_a_HTTP_404_if_searching_for_customers_does_not_find_any.yml │ │ ├── removes_custom_attributes_correctly.yml │ │ ├── removes_tags_correctly.yml │ │ ├── retrieves_the_customer_correctly.yml │ │ ├── searches_for_customers_correctly.yml │ │ ├── unmerges_correctly_with_the_class_method.yml │ │ ├── unmerges_correctly_with_the_instance_method.yml │ │ ├── updates_custom_attributes_correctly.yml │ │ ├── updates_customer_correctly_with_the_class_method.yml │ │ ├── updates_the_customer_correctly_with_the_instance_method.yml │ │ └── with_pagination │ │ │ ├── paginates_correctly.yml │ │ │ └── paginates_the_ │ │ │ └── search_endpoint_correctly.yml │ └── _find_by_external_id │ │ ├── returns_matching_user_if_exists.yml │ │ └── returns_nil_if_customer_does_not_exist.yml │ ├── ChartMogul_CustomerInvoices │ └── API_Actions │ │ ├── creates_the_customer_invoice_correctly.yml │ │ ├── destroys_all_customer_invoices_correctly.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_DataSource │ └── API_Interactions │ │ ├── correctly_interracts_with_the_API.yml │ │ ├── correctly_raises_errors_on_404.yml │ │ ├── correctly_raises_errors_on_422.yml │ │ └── retrieves_existing_data_source_matching_uuid.yml │ ├── ChartMogul_Invoice │ └── API_Actions │ │ ├── destroys_the_invoice_correctly.yml │ │ ├── destroys_the_invoice_correctly_with_instance_method.yml │ │ ├── retrieves_the_invoice_correctly.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_Metrics_ARPA │ └── behaves_like_Metrics_API_resource │ │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ │ └── should_have_entries.yml │ ├── ChartMogul_Metrics_ARR │ └── behaves_like_Metrics_API_resource │ │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ │ └── should_have_entries.yml │ ├── ChartMogul_Metrics_ASP │ └── behaves_like_Metrics_API_resource │ │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ │ └── should_have_entries.yml │ ├── ChartMogul_Metrics_ActivitiesExport │ ├── get_activities_export.yml │ └── post_activities_export.yml │ ├── ChartMogul_Metrics_Activity.yml │ ├── ChartMogul_Metrics_Activity │ ├── behaves_like_PageableWithAnchor │ │ └── should_be_pageable.yml │ ├── should_have_Activity_entries.yml │ └── should_paginate_using_cursor_when_called_with_next.yml │ ├── ChartMogul_Metrics_AllKeyMetric │ ├── should_have_entries.yml │ └── should_have_summary.yml │ ├── ChartMogul_Metrics_CustomerChurnRate │ └── behaves_like_Metrics_API_resource │ │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ │ └── should_have_entries.yml │ ├── ChartMogul_Metrics_CustomerCount │ └── behaves_like_Metrics_API_resource │ │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ │ └── should_have_entries.yml │ ├── ChartMogul_Metrics_Customers_Activity │ ├── behaves_like_Pageable │ │ └── should_be_pageable.yml │ ├── should_have_Activity_entries.yml │ └── should_paginate_using_cursor_when_called_with_next.yml │ ├── ChartMogul_Metrics_Customers_Subscription │ ├── behaves_like_Pageable │ │ └── should_be_pageable.yml │ ├── should_have_Subscription_entries.yml │ └── should_paginate_using_cursor_when_called_with_next.yml │ ├── ChartMogul_Metrics_LTV │ └── behaves_like_Metrics_API_resource │ │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ │ └── should_have_entries.yml │ ├── ChartMogul_Metrics_MRR │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ └── should_have_entries.yml │ ├── ChartMogul_Metrics_MRRChurnRate │ └── behaves_like_Metrics_API_resource │ │ ├── behaves_like_Summary │ │ └── should_have_summary.yml │ │ └── should_have_entries.yml │ ├── ChartMogul_Note │ └── API_Actions │ │ ├── creates_a_note_correctly.yml │ │ ├── destroys_the_note_correctly.yml │ │ ├── retrieves_a_note_correctly.yml │ │ ├── retrieves_all_notes_correctly.yml │ │ ├── retrieves_the_note_correctly.yml │ │ ├── updates_the_note_correctly_with_the_class_method.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_Opportunity │ └── API_Actions │ │ ├── creates_a_opportunity_correctly.yml │ │ ├── destroys_the_opportunity_correctly.yml │ │ ├── retrieves_a_opportunity_correctly.yml │ │ ├── retrieves_all_opportunities_correctly.yml │ │ ├── updates_the_opportunity_correctly_with_the_class_method.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_Ping │ └── pings │ │ ├── and_fails_on_incorrect_credentials.yml │ │ ├── and_fails_with_500_internal_server_error.yml │ │ ├── and_fails_with_504_gateway_timeout_error.yml │ │ └── when_credentials_correct.yml │ ├── ChartMogul_Plan │ └── API_Actions │ │ ├── creates_the_plan_correctly.yml │ │ ├── destroys_the_plan_correctly.yml │ │ ├── retrieves_the_plan_correctly.yml │ │ ├── updates_the_plan_correctly_with_the_class_method.yml │ │ ├── updates_the_plan_correctly_with_the_instance_method.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_PlanGroup │ └── API_Actions │ │ ├── correctly_handles_a_422_error.yml │ │ ├── creates_a_plan_group_correctly.yml │ │ ├── destroys_a_plan_group_correctly.yml │ │ ├── retrieves_the_plan_group_correctly.yml │ │ ├── updates_a_plan_group_plans.yml │ │ ├── updates_the_plan_group_correctly_with_the_class_method.yml │ │ ├── updates_the_plan_group_correctly_with_the_instance_method.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_PlanGroups_Plans │ └── API_Actions │ │ └── with_pagination │ │ └── paginates_correctly.yml │ ├── ChartMogul_Subscription │ ├── API_Interactions │ │ ├── connects_subscriptions.yml │ │ ├── correctly_interracts_with_the_API.yml │ │ ├── disconnects_subscriptions.yml │ │ ├── has_multiple_aliases.yml │ │ └── should_paginate_using_cursor_when_called_with_next.yml │ └── _update_cancellation_dates │ │ ├── when_array_has_time_objects │ │ └── is_setting_the_cancellation_dates_of_the_subscription.yml │ │ ├── when_array_includes_invalid_entries │ │ └── raises_an_exception.yml │ │ ├── when_array_includes_valid_entries │ │ └── is_setting_the_cancellation_dates_of_the_subscription.yml │ │ └── when_array_is_empty │ │ └── makes_an_API_call_and_removes_the_cancellation_dates.yml │ ├── ChartMogul_SubscriptionEvent │ └── API_interactions │ │ ├── creates_a_new_subscription_event.yml │ │ ├── creates_a_new_subscription_event_through_initialization.yml │ │ ├── deletes_the_subscription_event.yml │ │ ├── lists_all_subscription_events.yml │ │ ├── should_paginate_using_cursor_when_called_with_next.yml │ │ └── updates_the_subscription_event.yml │ ├── ChartMogul_Task │ └── API_Actions │ │ ├── creates_a_task_correctly.yml │ │ ├── destroys_the_task_correctly.yml │ │ ├── retrieves_a_task_correctly.yml │ │ ├── retrieves_all_tasks_correctly.yml │ │ ├── updates_the_task_correctly_with_the_class_method.yml │ │ └── with_pagination │ │ └── paginates_correctly.yml │ └── ChartMogul_Transactions_Payment │ └── API_Interactions │ └── correctly_interracts_with_the_API.yml ├── spec_helper.rb └── support └── shared_example_raises_deprecated_param_error.rb /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Run specs and generate Code Climate report 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | ruby-version: [2.7, 3.0, 3.1, 3.2, 3.3, head] 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Set up Ruby ${{ matrix.ruby-version }} 16 | uses: ruby/setup-ruby@v1 17 | with: 18 | ruby-version: ${{ matrix.ruby-version }} 19 | bundler-cache: true 20 | - name: Install dependencies 21 | run: bundle install 22 | - name: Set ENV for codeclimate (pull_request) 23 | run: | 24 | git fetch --no-tags --prune --depth=1 origin +refs/heads/$GITHUB_HEAD_REF:refs/remotes/origin/$GITHUB_HEAD_REF 25 | echo "GIT_BRANCH=$GITHUB_HEAD_REF" >> $GITHUB_ENV 26 | echo "GIT_COMMIT_SHA=$(git rev-parse origin/$GITHUB_HEAD_REF)" >> $GITHUB_ENV 27 | if: github.event_name == 'pull_request' 28 | - name: Set ENV for codeclimate (push) 29 | run: | 30 | echo "GIT_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV 31 | echo "GIT_COMMIT_SHA=$GITHUB_SHA" >> $GITHUB_ENV 32 | if: github.event_name == 'push' 33 | - name: Install Code Climate test report 34 | run: | 35 | curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter 36 | chmod +x ./cc-test-reporter 37 | ./cc-test-reporter before-build 38 | - name: Run tests 39 | env: 40 | CC_TEST_REPORTER_ID: 'enable JSON output for SimpleCov' 41 | run: bundle exec rake 42 | - name: Send Report to Code Climate 43 | env: 44 | CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} 45 | if: ${{ success() }} 46 | run: ./cc-test-reporter after-build 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.swp 11 | vendor/bundle 12 | /.idea 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /2.0-Upgrade.md: -------------------------------------------------------------------------------- 1 | # Upgrading to chartmogul-ruby 2.0.0 2 | 3 | The gem upgrade brings breaking changes to the Metrics API. All other APIs remain unaffected. Please note the following changes: 4 | 5 | * If you used the Metrics API to get a customer's activities or subscriptions, make the following changes in the namespace 6 | - `ChartMogul::Metrics::Activity.all('cus_58c7d166-3bd1-4c10-948e-e68bb0fa2478')` should be replaced with `ChartMogul::Metrics::Customers::Activity.all('cus_58c7d166-3bd1-4c10-948e-e68bb0fa2478')` 7 | - `ChartMogul::Metrics::Subscription.all('cus_3f6f53d3-bca7-4fcd-ad47-345180ef329b')` should be replace with `ChartMogul::Metrics::Customers::Subscription.all('cus_3f6f53d3-bca7-4fcd-ad47-345180ef329b')` 8 | 9 | 10 | -------------------------------------------------------------------------------- /4.0-Upgrade.md: -------------------------------------------------------------------------------- 1 | # Upgrading to chartmogul-ruby 4.0.0 2 | 3 | This new version replaces the existing pagination for the `.all()` endpoints that used a combination 4 | of `page` and `per_page` parameters, and instead uses a `cursor` based pagination. So to list 5 | (as an example) Plans you now can: 6 | 7 | ```ruby 8 | ChartMogul.api_key = '' 9 | 10 | # Getting the first page 11 | plans = ChartMogul::Plan.all(per_page: 12) 12 | ``` 13 | 14 | This will return an array of plans (if available), and a cursor + has_more fields: 15 | 16 | ```json 17 | { 18 | "plans": [ 19 | { 20 | "uuid": "some_uuid", 21 | "data_source_uuid": "some_uuid", 22 | "name": "Master Plan" 23 | } 24 | ], 25 | "has_more": true, 26 | "cursor": "MjAyMy0wNy0yOFQwODowOToyMi4xNTQyMDMwMDBaJjk0NDQ0Mg==" 27 | } 28 | ``` 29 | 30 | ```ruby 31 | # You can get the following pages by passing a cursor to .all 32 | if plans.has_more 33 | more_plans = ChartMogul::Plan.all(per_page: 12, cursor: plans.cursor) 34 | end 35 | 36 | # Or by calling .next on the result 37 | if plans.has_more 38 | more_plans = plans.next(per_page: 3) 39 | end 40 | ``` 41 | 42 | If you have existing code that relies on the `page` parameter, those requests will now throw an error 43 | alerting you of their deprecation. 44 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | # Specify your gem's dependencies in chartmogul-ruby.gemspec 6 | gemspec 7 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 ChartMogul Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'rspec/core/rake_task' 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | task default: :spec 9 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'bundler/setup' 5 | require 'chartmogul' 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | # (If you use this, don't forget to add pry to your Gemfile!) 11 | # require "pry" 12 | # Pry.start 13 | 14 | require 'irb' 15 | IRB.start 16 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | gem install bundler 7 | bundle install 8 | 9 | # Do any other automated setup that you need to do here 10 | -------------------------------------------------------------------------------- /chartmogul-ruby.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'chartmogul/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = 'chartmogul-ruby' 9 | spec.version = ChartMogul::VERSION 10 | spec.authors = ['Petr Kopac'] 11 | spec.email = ['petr@chartmogul.com'] 12 | 13 | spec.summary = 'Chartmogul API Ruby Client' 14 | spec.description = 'Official Ruby client for ChartMogul\'s API' 15 | spec.homepage = 'https://github.com/chartmogul/chartmogul-ruby' 16 | spec.license = 'MIT' 17 | spec.required_ruby_version = '>= 2.7' 18 | 19 | spec.post_install_message = %q{ 20 | Starting October 29 2021, we are updating our developer libraries to support the enhanced API Access Management. Please use the same API Key for both API Token and Secret Key. 21 | [Deprecation] - account_token/secret_key combo is deprecated. Please use API key for both fields. 22 | Version 3.x will introduce a breaking change in authentication configuration. For more details, please visit: https://dev.chartmogul.com/docs/authentication 23 | } 24 | 25 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 26 | spec.bindir = 'exe' 27 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 28 | spec.require_paths = ['lib'] 29 | 30 | spec.add_dependency 'faraday', '~> 2.8' 31 | spec.add_dependency 'faraday-retry', '~> 2.2' 32 | 33 | # Higher versions break ruby 2.7 support. 34 | spec.add_development_dependency 'bundler', '~> 2' 35 | spec.add_development_dependency 'pry' 36 | spec.add_development_dependency 'rake' 37 | spec.add_development_dependency 'rspec' 38 | spec.add_development_dependency 'rubocop', '= 1.56.3' 39 | spec.add_development_dependency 'rubocop-rspec', '~> 2.9' 40 | spec.add_development_dependency 'rubocop-thread_safety', '~> 0.5.1' 41 | spec.add_development_dependency 'simplecov', '~> 0.21' 42 | spec.add_development_dependency 'vcr' 43 | spec.add_development_dependency 'webmock' 44 | end 45 | -------------------------------------------------------------------------------- /lib/chartmogul/account.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class Account < APIResource 5 | set_resource_name 'Account' 6 | set_resource_path '/v1/account' 7 | 8 | readonly_attr :name 9 | readonly_attr :currency 10 | readonly_attr :time_zone 11 | readonly_attr :week_start_on 12 | 13 | include API::Actions::Custom 14 | 15 | def self.retrieve 16 | custom!(:get, '/v1/account') 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/chartmogul/api/actions/all.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module API 5 | module Actions 6 | module All 7 | def self.included(base) 8 | base.extend ClassMethods 9 | end 10 | 11 | module ClassMethods 12 | def all(options = {}) 13 | resp = handling_errors do 14 | connection.get(resource_path.apply_with_get_params(options)) do |req| 15 | req.headers['Content-Type'] = 'application/json' 16 | end 17 | end 18 | 19 | json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys) 20 | new_from_json(json) 21 | end 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/chartmogul/api/actions/create.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module API 5 | module Actions 6 | module Create 7 | def self.included(base) 8 | base.extend ClassMethods 9 | end 10 | 11 | def create! 12 | resp = handling_errors do 13 | connection.post(resource_path.apply(instance_attributes)) do |req| 14 | req.headers['Content-Type'] = 'application/json' 15 | req.body = JSON.dump(serialize_for_write) 16 | end 17 | end 18 | json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: self.class.immutable_keys) 19 | 20 | assign_all_attributes(json) 21 | end 22 | 23 | module ClassMethods 24 | def create!(attributes = {}) 25 | resource = new(attributes) 26 | 27 | resp = handling_errors do 28 | connection.post(resource_path.apply(attributes)) do |req| 29 | req.headers['Content-Type'] = 'application/json' 30 | req.body = JSON.dump(resource.serialize_for_write) 31 | end 32 | end 33 | json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys) 34 | 35 | new_from_json(json) 36 | end 37 | end 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/chartmogul/api/actions/custom.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module API 5 | module Actions 6 | module Custom 7 | def self.included(base) 8 | base.extend ClassMethods 9 | end 10 | 11 | def custom_without_assign!(http_method, http_path, body_data = {}) 12 | self.class.custom_without_assign!(http_method, http_path, body_data) 13 | end 14 | 15 | def custom!(http_method, http_path, body_data = {}) 16 | json = custom_without_assign!(http_method, http_path, body_data) 17 | assign_all_attributes(json) 18 | end 19 | 20 | module ClassMethods 21 | def custom_without_assign!(http_method, http_path, body_data = {}) 22 | resp = handling_errors do 23 | connection.send(http_method, http_path) do |req| 24 | req.headers['Content-Type'] = 'application/json' 25 | req.body = JSON.dump(body_data) 26 | end 27 | end 28 | parsed_body = resp.body.empty? ? '{}' : resp.body 29 | ChartMogul::Utils::JSONParser.parse(parsed_body, immutable_keys: immutable_keys) 30 | end 31 | 32 | def custom!(http_method, http_path, body_data = {}) 33 | json = custom_without_assign!(http_method, http_path, body_data) 34 | new_from_json(json) 35 | end 36 | end 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/chartmogul/api/actions/destroy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module API 5 | module Actions 6 | module Destroy 7 | def self.included(base) 8 | base.extend ClassMethods 9 | end 10 | 11 | def destroy! 12 | handling_errors do 13 | connection.delete("#{resource_path.apply(instance_attributes)}/#{uuid}") 14 | end 15 | true 16 | end 17 | 18 | module ClassMethods 19 | def destroy!(options = {}) 20 | handling_errors do 21 | connection.delete("#{resource_path.apply(options)}/#{options[:uuid]}") 22 | end 23 | true 24 | end 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/chartmogul/api/actions/destroy_with_params.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module API 5 | module Actions 6 | module DestroyWithParams 7 | def self.included(base) 8 | base.extend ClassMethods 9 | end 10 | 11 | def destroy_with_params! 12 | handling_errors do 13 | connection.delete(resource_path.path, instance_attributes) 14 | end 15 | true 16 | end 17 | 18 | module ClassMethods 19 | def destroy_with_params!(options = {}) 20 | handling_errors do 21 | connection.delete(resource_path.path, options) 22 | end 23 | true 24 | end 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/chartmogul/api/actions/retrieve.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module API 5 | module Actions 6 | module Retrieve 7 | def self.included(base) 8 | base.extend ClassMethods 9 | end 10 | 11 | module ClassMethods 12 | def retrieve(uuid, options = {}) 13 | resp = handling_errors do 14 | connection.get("#{resource_path.apply(options)}/#{uuid}") do |req| 15 | req.headers['Content-Type'] = 'application/json' 16 | end 17 | end 18 | 19 | json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys) 20 | new_from_json(json) 21 | end 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/chartmogul/api/actions/update.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module API 5 | module Actions 6 | module Update 7 | def self.included(base) 8 | base.extend ClassMethods 9 | end 10 | 11 | def update! 12 | resp = handling_errors do 13 | connection.patch("#{resource_path.apply(instance_attributes)}/#{uuid}") do |req| 14 | req.headers['Content-Type'] = 'application/json' 15 | req.body = JSON.dump(serialize_for_write) 16 | end 17 | end 18 | 19 | json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: self.class.immutable_keys) 20 | 21 | assign_all_attributes(json) 22 | end 23 | 24 | module ClassMethods 25 | def update!(uuid, attributes = {}) 26 | resource = new(attributes) 27 | 28 | resp = handling_errors do 29 | connection.patch("#{resource_path.apply(attributes)}/#{uuid}") do |req| 30 | req.headers['Content-Type'] = 'application/json' 31 | req.body = JSON.dump(resource.serialize_for_write) 32 | end 33 | end 34 | json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys) 35 | 36 | new_from_json(json) 37 | end 38 | end 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/chartmogul/concerns/entries.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Concerns 5 | module Entries 6 | def self.included(base) 7 | base.extend ClassMethods 8 | 9 | base.instance_eval do 10 | @resource_root_key = :entries if @resource_root_key.nil? 11 | readonly_attr @resource_root_key, default: [] 12 | 13 | include API::Actions::All 14 | 15 | include Enumerable 16 | def_delegators @resource_root_key, :each, :[], :<<, :size, :length, :empty?, :first, :last 17 | 18 | resource_root_key = @resource_root_key.to_s 19 | base.send :define_method, 'set_' + resource_root_key do |entries| 20 | objects = entries.map do |entity| 21 | self.class.get_entry_class.new_from_json(entity) 22 | end 23 | instance_variable_set "@#{resource_root_key}", objects 24 | end 25 | end 26 | end 27 | 28 | module ClassMethods 29 | def set_entry_class(klass) 30 | instance_variable_set('@entry_class', klass) 31 | end 32 | 33 | def get_entry_class 34 | instance_variable_get('@entry_class') 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/chartmogul/concerns/pageable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Concerns 5 | module Pageable 6 | def self.included(base) 7 | base.instance_eval do 8 | readonly_attr :has_more 9 | readonly_attr :per_page 10 | readonly_attr :page 11 | end 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/chartmogul/concerns/pageable2.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Concerns 5 | module Pageable2 6 | def self.included(base) 7 | base.instance_eval do 8 | readonly_attr :current_page 9 | readonly_attr :total_pages 10 | end 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/chartmogul/concerns/pageable_with_anchor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Concerns 5 | module PageableWithAnchor 6 | def self.included(base) 7 | base.instance_eval do 8 | readonly_attr :has_more 9 | readonly_attr :per_page 10 | end 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/chartmogul/concerns/pageable_with_cursor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Concerns 5 | module PageableWithCursor 6 | def self.included(base) 7 | base.instance_eval do 8 | readonly_attr :has_more 9 | readonly_attr :cursor 10 | end 11 | end 12 | 13 | def next(options = {}) 14 | self.class.all(options.merge(cursor: cursor)) 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/chartmogul/concerns/summary.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Concerns 5 | module Summary 6 | def self.included(base) 7 | base.send :prepend, InstanceMethods 8 | 9 | base.instance_eval do 10 | readonly_attr :summary 11 | end 12 | end 13 | 14 | module InstanceMethods 15 | def set_summary(summary_attributes) 16 | @summary = ChartMogul::Summary.new_from_json(summary_attributes) 17 | end 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/concerns/summary_all.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Concerns 5 | module SummaryAll 6 | def self.included(base) 7 | base.send :prepend, InstanceMethods 8 | 9 | base.instance_eval do 10 | readonly_attr :summary 11 | end 12 | end 13 | 14 | module InstanceMethods 15 | def set_summary(summary_attributes) 16 | @summary = ChartMogul::SummaryAll.new_from_json(summary_attributes) 17 | end 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/config_attributes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module ConfigAttributes 5 | def config_accessor(attribute, default_value = nil) 6 | define_method(attribute) do 7 | attr = config.send(attribute) || global_config.send(attribute) || default_value 8 | if attr.nil? 9 | raise ConfigurationError, "Configuration for #{attribute} not set" 10 | end 11 | 12 | attr 13 | end 14 | 15 | define_method("global_#{attribute}") do 16 | attr = global_config.send(attribute) || default_value 17 | if attr.nil? 18 | raise ConfigurationError, "Global configuration for #{attribute} not set" 19 | end 20 | 21 | attr 22 | end 23 | 24 | define_method("#{attribute}=") do |val| 25 | config.send("#{attribute}=", val) 26 | Thread.current[ChartMogul::APIResource::THREAD_CONNECTION_KEY] = nil 27 | val 28 | end 29 | 30 | define_method("global_#{attribute}=") do |val| 31 | global_config.send("#{attribute}=", val) 32 | Thread.current[ChartMogul::APIResource::THREAD_CONNECTION_KEY] = nil 33 | val 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/chartmogul/configuration.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class Configuration 5 | attr_accessor :api_key 6 | attr_accessor :max_retries 7 | attr_accessor :api_base 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/chartmogul/contact.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class Contact < APIResource 5 | set_resource_name 'Contact' 6 | set_resource_path '/v1/contacts' 7 | set_immutable_keys([:custom]) 8 | 9 | readonly_attr :uuid 10 | 11 | writeable_attr :customer_uuid 12 | writeable_attr :data_source_uuid 13 | writeable_attr :customer_external_id 14 | writeable_attr :position 15 | writeable_attr :first_name 16 | writeable_attr :last_name 17 | writeable_attr :title 18 | writeable_attr :email 19 | writeable_attr :phone 20 | writeable_attr :linked_in 21 | writeable_attr :twitter 22 | writeable_attr :notes 23 | writeable_attr :custom 24 | 25 | include API::Actions::Create 26 | include API::Actions::Custom 27 | include API::Actions::Destroy 28 | include API::Actions::Retrieve 29 | include API::Actions::Update 30 | 31 | def self.all(options = {}) 32 | Contacts.all(options) 33 | end 34 | 35 | def self.merge!(into_uuid:, from_uuid:) 36 | custom!(:post, "/v1/contacts/#{into_uuid}/merge/#{from_uuid}") 37 | true 38 | end 39 | 40 | def serialize_for_write 41 | super.tap do |attributes| 42 | attributes.clone.each do |attribute_name, attribute_value| 43 | if attribute_name == :custom && attribute_value.is_a?(Hash) 44 | payload = attribute_value.each_with_object([]) do |custom_value, arr| 45 | key, value = custom_value 46 | arr << { key: key, value: value } 47 | end 48 | attributes[:custom] = payload 49 | else 50 | attributes[attribute_name] = attribute_value 51 | end 52 | end 53 | end 54 | end 55 | end 56 | 57 | class Contacts < APIResource 58 | set_resource_name 'Contacts' 59 | set_resource_path '/v1/contacts' 60 | 61 | include Concerns::Entries 62 | include Concerns::PageableWithCursor 63 | 64 | set_entry_class Contact 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/chartmogul/customer_invoices.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'forwardable' 4 | 5 | module ChartMogul 6 | class CustomerInvoices < APIResource 7 | extend Forwardable 8 | include Enumerable 9 | 10 | set_resource_name 'Invoices' 11 | set_resource_path '/v1/import/customers/:customer_uuid/invoices' 12 | 13 | writeable_attr :invoices, default: [] 14 | 15 | writeable_attr :customer_uuid 16 | 17 | include API::Actions::All 18 | include API::Actions::Create 19 | include Concerns::Pageable2 20 | include Concerns::PageableWithCursor 21 | 22 | def serialize_invoices 23 | map(&:serialize_for_write) 24 | end 25 | 26 | def self.all(customer_uuid, options = {}) 27 | super(options.merge(customer_uuid: customer_uuid)) 28 | end 29 | 30 | def next(options = {}) 31 | CustomerInvoices.all(customer_uuid, options.merge(cursor: cursor)) 32 | end 33 | 34 | def self.destroy_all!(data_source_uuid, customer_uuid) 35 | path = ChartMogul::ResourcePath.new('v1/data_sources/:data_source_uuid/customers/:customer_uuid/invoices') 36 | handling_errors do 37 | connection.delete(path.apply(data_source_uuid: data_source_uuid, customer_uuid: customer_uuid)) 38 | end 39 | true 40 | end 41 | 42 | def_delegators :invoices, :each, :[], :<<, :size, :length, :empty?, :first 43 | 44 | private 45 | 46 | # TODO: replace with Entries concern? 47 | def set_invoices(invoices_attributes) 48 | @invoices = invoices_attributes.map.with_index do |invoice_attributes, index| 49 | existing_invoice = invoices[index] 50 | 51 | if existing_invoice 52 | existing_invoice.assign_all_attributes(invoice_attributes) 53 | else 54 | Invoice.new_from_json(invoice_attributes) 55 | end 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/chartmogul/data_source.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class DataSource < APIResource 5 | set_resource_name 'Data Source' 6 | set_resource_path '/v1/data_sources' 7 | 8 | readonly_attr :uuid 9 | readonly_attr :status 10 | readonly_attr :system 11 | readonly_attr :created_at, type: :time 12 | 13 | writeable_attr :name 14 | 15 | include API::Actions::All 16 | include API::Actions::Create 17 | include API::Actions::Custom 18 | include API::Actions::Destroy 19 | include API::Actions::Retrieve 20 | 21 | def self.all(options = {}) 22 | DataSources.all(options) 23 | end 24 | end 25 | 26 | class DataSources < APIResource 27 | set_resource_name 'Data Sources' 28 | set_resource_path '/v1/data_sources' 29 | 30 | set_resource_root_key :data_sources 31 | 32 | include Concerns::Entries 33 | 34 | set_entry_class DataSource 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/chartmogul_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class ChartMogulError < StandardError 5 | attr_reader :error_message, :response, :http_status 6 | 7 | def initialize(error_message, http_status: nil, response: nil) 8 | @error_message = error_message 9 | @http_status = http_status 10 | @response = response 11 | 12 | super(build_message) 13 | end 14 | 15 | def build_message 16 | status = http_status ? " (HTTP Status: #{http_status})" : '' 17 | resp = response ? "\nResponse: #{response}" : '' 18 | "#{error_message}#{status}#{resp}" 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/configuration_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class ConfigurationError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/deprecated_parameter_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class DeprecatedParameterError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/forbidden_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class ForbiddenError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/not_found_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class NotFoundError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/resource_invalid_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class ResourceInvalidError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/schema_invalid_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class SchemaInvalidError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/server_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class ServerError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/errors/unauthorized_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class UnauthorizedError < ChartMogulError 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/chartmogul/line_items/one_time.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module LineItems 5 | class OneTime < ChartMogul::Object 6 | readonly_attr :uuid 7 | 8 | writeable_attr :type, default: 'one_time' 9 | writeable_attr :amount_in_cents 10 | writeable_attr :description 11 | writeable_attr :quantity 12 | writeable_attr :discount_amount_in_cents 13 | writeable_attr :discount_code 14 | writeable_attr :tax_amount_in_cents 15 | writeable_attr :transaction_fees_in_cents 16 | writeable_attr :external_id 17 | writeable_attr :transaction_fees_currency 18 | writeable_attr :discount_description 19 | writeable_attr :event_order 20 | 21 | writeable_attr :plan_uuid 22 | writeable_attr :invoice_uuid 23 | 24 | def initialize(attributes = {}) 25 | super(attributes) 26 | @type = 'one_time' 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/chartmogul/line_items/subscription.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module LineItems 5 | class Subscription < ChartMogul::Object 6 | readonly_attr :uuid 7 | 8 | writeable_attr :type, default: 'subscription' 9 | writeable_attr :subscription_external_id 10 | writeable_attr :service_period_start, type: :time 11 | writeable_attr :service_period_end, type: :time 12 | writeable_attr :amount_in_cents 13 | writeable_attr :cancelled_at, type: :time 14 | writeable_attr :prorated 15 | writeable_attr :proration_type 16 | writeable_attr :quantity 17 | writeable_attr :discount_amount_in_cents 18 | writeable_attr :discount_code 19 | writeable_attr :tax_amount_in_cents 20 | writeable_attr :transaction_fees_in_cents 21 | writeable_attr :external_id 22 | writeable_attr :subscription_set_external_id 23 | writeable_attr :transaction_fees_currency 24 | writeable_attr :discount_description 25 | writeable_attr :event_order 26 | 27 | readonly_attr :subscription_uuid 28 | writeable_attr :invoice_uuid 29 | writeable_attr :plan_uuid 30 | 31 | def initialize(attributes = {}) 32 | super(attributes) 33 | @type = 'subscription' 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/activities_export.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class ActivitiesExport < APIResource 6 | set_resource_name 'ActivitiesExport' 7 | set_resource_path '/v1/activities_export' 8 | 9 | readonly_attr :id 10 | readonly_attr :status 11 | readonly_attr :file_url 12 | readonly_attr :params 13 | readonly_attr :expires_at 14 | readonly_attr :created_at 15 | 16 | writeable_attr :start_date 17 | writeable_attr :end_date 18 | writeable_attr :type 19 | 20 | include API::Actions::Retrieve 21 | include API::Actions::Create 22 | 23 | def serialize_for_write 24 | super.tap do |attributes| 25 | attributes.clone.each do |k, v| 26 | attributes[preprocess_attributes(k)] = attributes.delete(k) 27 | end 28 | end 29 | end 30 | 31 | def preprocess_attributes(attribute) 32 | return attribute unless %i[start_date end_date].include?(attribute) 33 | 34 | attribute.to_s.tr('_', '-') 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/activity.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class Activity < ChartMogul::Object 6 | readonly_attr :description 7 | readonly_attr :type 8 | readonly_attr :date, type: :time 9 | readonly_attr :activity_arr 10 | readonly_attr :activity_mrr 11 | readonly_attr :activity_mrr_movement 12 | readonly_attr :currency 13 | readonly_attr :subscription_external_id 14 | readonly_attr :plan_external_id 15 | readonly_attr :customer_name 16 | readonly_attr :customer_uuid 17 | readonly_attr :customer_external_id 18 | readonly_attr :billing_connector_uuid 19 | readonly_attr :uuid 20 | 21 | def self.all(options = {}) 22 | ChartMogul::Metrics::Activities.all(options) 23 | end 24 | end 25 | 26 | class Activities < APIResource 27 | set_resource_name 'Activities' 28 | set_resource_path '/v1/activities' 29 | 30 | include Concerns::Entries 31 | include Concerns::PageableWithAnchor 32 | include Concerns::PageableWithCursor 33 | 34 | set_entry_class Activity 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/all_key_metrics.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class AllKeyMetric < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :arpa 8 | readonly_attr :arr 9 | readonly_attr :asp 10 | readonly_attr :customer_churn_rate 11 | readonly_attr :customers 12 | readonly_attr :ltv 13 | readonly_attr :mrr 14 | readonly_attr :mrr_churn_rate 15 | readonly_attr :arpa_percentage_change 16 | readonly_attr :arr_percentage_change 17 | readonly_attr :asp_percentage_change 18 | readonly_attr :customer_churn_rate_percentage_change 19 | readonly_attr :customers_percentage_change 20 | readonly_attr :ltv_percentage_change 21 | readonly_attr :mrr_percentage_change 22 | readonly_attr :mrr_churn_rate_percentage_change 23 | end 24 | 25 | class AllKeyMetrics < APIResource 26 | set_resource_name 'All Key Metrics' 27 | set_resource_path '/v1/metrics/all' 28 | 29 | include Concerns::Entries 30 | include Concerns::SummaryAll 31 | 32 | set_entry_class AllKeyMetric 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/arpa.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class ARPA < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :arpa 8 | readonly_attr :percentage_change 9 | end 10 | 11 | class ARPAs < APIResource 12 | set_resource_name 'ARPAs' 13 | set_resource_path '/v1/metrics/arpa' 14 | 15 | include Concerns::Entries 16 | include Concerns::Summary 17 | 18 | set_entry_class ARPA 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/arr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class ARR < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :arr 8 | readonly_attr :percentage_change 9 | end 10 | 11 | class ARRs < APIResource 12 | set_resource_name 'ARRs' 13 | set_resource_path '/v1/metrics/arr' 14 | 15 | include Concerns::Entries 16 | include Concerns::Summary 17 | 18 | set_entry_class ARR 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/asp.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class ASP < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :asp 8 | readonly_attr :percentage_change 9 | end 10 | 11 | class ASPs < APIResource 12 | set_resource_name 'ASPs' 13 | set_resource_path '/v1/metrics/asp' 14 | 15 | include Concerns::Entries 16 | include Concerns::Summary 17 | 18 | set_entry_class ASP 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | def self.all(options = {}) 6 | ChartMogul::Metrics::AllKeyMetrics.all(preprocess_params(options)) 7 | end 8 | 9 | def self.arpa(options = {}) 10 | ChartMogul::Metrics::ARPAs.all(preprocess_params(options)) 11 | end 12 | 13 | def self.arr(options = {}) 14 | ChartMogul::Metrics::ARRs.all(preprocess_params(options)) 15 | end 16 | 17 | def self.asp(options = {}) 18 | ChartMogul::Metrics::ASPs.all(preprocess_params(options)) 19 | end 20 | 21 | def self.customer_churn_rate(options = {}) 22 | ChartMogul::Metrics::CustomerChurnRates.all(preprocess_params(options)) 23 | end 24 | 25 | def self.customer_count(options = {}) 26 | ChartMogul::Metrics::CustomerCounts.all(preprocess_params(options)) 27 | end 28 | 29 | def self.mrr(options = {}) 30 | ChartMogul::Metrics::MRRs.all(preprocess_params(options)) 31 | end 32 | 33 | def self.ltv(options = {}) 34 | ChartMogul::Metrics::LTVs.all(preprocess_params(options)) 35 | end 36 | 37 | def self.mrr_churn_rate(options = {}) 38 | ChartMogul::Metrics::MRRChurnRates.all(preprocess_params(options)) 39 | end 40 | 41 | private 42 | 43 | def self.preprocess_params(options) 44 | %i[start_date end_date].each do |param_name| 45 | if options[param_name] 46 | options[param_name.to_s.tr('_', '-')] = options.delete(param_name) 47 | end 48 | end 49 | 50 | %i[geo plans].each do |param_name| 51 | if options[param_name]&.is_a?(Array) 52 | options[param_name] = options[param_name].join(',') 53 | end 54 | end 55 | options 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/customer_churn_rate.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class CustomerChurnRate < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :customer_churn_rate 8 | readonly_attr :percentage_change 9 | end 10 | 11 | class CustomerChurnRates < APIResource 12 | set_resource_name 'Customer Churn Rates' 13 | set_resource_path '/v1/metrics/customer-churn-rate' 14 | 15 | include Concerns::Entries 16 | include Concerns::Summary 17 | 18 | set_entry_class CustomerChurnRate 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/customer_count.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class CustomerCount < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :customers 8 | readonly_attr :percentage_change 9 | end 10 | 11 | class CustomerCounts < APIResource 12 | set_resource_name 'Customer Counts' 13 | set_resource_path '/v1/metrics/customer-count' 14 | 15 | include Concerns::Entries 16 | include Concerns::Summary 17 | 18 | set_entry_class CustomerCount 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/customers/activity.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | module Customers 6 | class Activity < ChartMogul::Object 7 | readonly_attr :id 8 | readonly_attr :description 9 | readonly_attr :type 10 | readonly_attr :date, type: :time 11 | readonly_attr :activity_arr 12 | readonly_attr :activity_mrr 13 | readonly_attr :activity_mrr_movement 14 | readonly_attr :currency 15 | readonly_attr :currency_sign 16 | readonly_attr :subscription_external_id 17 | 18 | def self.all(customer_uuid, options = {}) 19 | ChartMogul::Metrics::Customers::Activities.all(customer_uuid, options) 20 | end 21 | end 22 | 23 | class Activities < APIResource 24 | set_resource_name 'Activities' 25 | set_resource_path '/v1/customers/:customer_uuid/activities' 26 | 27 | include Concerns::Entries 28 | include Concerns::Pageable 29 | include Concerns::PageableWithCursor 30 | 31 | set_entry_class Activity 32 | 33 | def self.all(customer_uuid, options = {}) 34 | super(options.merge(customer_uuid: customer_uuid)) 35 | end 36 | 37 | def next(customer_uuid, options = {}) 38 | Activities.all(customer_uuid, options.merge(cursor: cursor)) 39 | end 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/customers/subscription.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | module Customers 6 | class Subscription < ChartMogul::Object 7 | readonly_attr :id 8 | readonly_attr :uuid 9 | readonly_attr :external_id 10 | readonly_attr :plan 11 | readonly_attr :quantity 12 | readonly_attr :mrr 13 | readonly_attr :arr 14 | readonly_attr :status 15 | readonly_attr :billing_cycle 16 | readonly_attr :billing_cycle_count 17 | readonly_attr :start_date, type: :time 18 | readonly_attr :end_date, type: :time 19 | readonly_attr :currency 20 | readonly_attr :currency_sign 21 | 22 | def self.all(customer_uuid, options = {}) 23 | ChartMogul::Metrics::Customers::Subscriptions.all(customer_uuid, options) 24 | end 25 | end 26 | 27 | class Subscriptions < APIResource 28 | set_resource_name 'Subscriptions' 29 | set_resource_path '/v1/customers/:customer_uuid/subscriptions' 30 | 31 | include Concerns::Entries 32 | include Concerns::Pageable 33 | include Concerns::PageableWithCursor 34 | 35 | set_entry_class Subscription 36 | 37 | def self.all(customer_uuid, options = {}) 38 | super(options.merge(customer_uuid: customer_uuid)) 39 | end 40 | 41 | def next(customer_uuid, options = {}) 42 | Subscriptions.all(customer_uuid, options.merge(cursor: cursor)) 43 | end 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/ltv.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class LTV < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :ltv 8 | readonly_attr :percentage_change 9 | end 10 | 11 | class LTVs < APIResource 12 | set_resource_name 'LTVs' 13 | set_resource_path '/v1/metrics/ltv' 14 | 15 | include Concerns::Entries 16 | include Concerns::Summary 17 | 18 | set_entry_class LTV 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/mrr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class MRR < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :mrr 8 | 9 | readonly_attr :mrr_new_business 10 | 11 | readonly_attr :mrr_expansion 12 | readonly_attr :mrr_contraction 13 | 14 | readonly_attr :mrr_churn 15 | readonly_attr :mrr_reactivation 16 | readonly_attr :percentage_change 17 | end 18 | 19 | class MRRs < APIResource 20 | set_resource_name 'MRRs' 21 | set_resource_path '/v1/metrics/mrr' 22 | 23 | include Concerns::Entries 24 | include Concerns::Summary 25 | 26 | set_entry_class MRR 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/chartmogul/metrics/mrr_churn_rate.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Metrics 5 | class MRRChurnRate < ChartMogul::Object 6 | readonly_attr :date, type: :date 7 | readonly_attr :mrr_churn_rate 8 | readonly_attr :percentage_change 9 | end 10 | 11 | class MRRChurnRates < APIResource 12 | set_resource_name 'MRR Churn Rates' 13 | set_resource_path '/v1/metrics/mrr-churn-rate' 14 | 15 | include Concerns::Entries 16 | include Concerns::Summary 17 | 18 | set_entry_class MRRChurnRate 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/chartmogul/note.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'forwardable' 4 | 5 | module ChartMogul 6 | class Note < APIResource 7 | set_resource_name 'CustomerNote' 8 | set_resource_path '/v1/customer_notes' 9 | 10 | readonly_attr :uuid 11 | 12 | writeable_attr :customer_uuid 13 | writeable_attr :type 14 | writeable_attr :text 15 | writeable_attr :author 16 | writeable_attr :text 17 | writeable_attr :call_duration 18 | writeable_attr :created_at 19 | writeable_attr :updated_at 20 | 21 | include API::Actions::Create 22 | include API::Actions::Destroy 23 | include API::Actions::Retrieve 24 | include API::Actions::Update 25 | 26 | def self.all(options = {}) 27 | Notes.all(options) 28 | end 29 | end 30 | 31 | class Notes < APIResource 32 | set_resource_name 'CustomerNotes' 33 | set_resource_path '/v1/customer_notes' 34 | 35 | include Concerns::Entries 36 | include Concerns::PageableWithCursor 37 | 38 | set_entry_class Note 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/chartmogul/opportunity.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'forwardable' 4 | 5 | module ChartMogul 6 | class Opportunity < APIResource 7 | set_resource_name 'Opportunity' 8 | set_resource_path '/v1/opportunities' 9 | set_immutable_keys([:custom]) 10 | 11 | readonly_attr :uuid 12 | readonly_attr :created_at 13 | readonly_attr :updated_at 14 | 15 | writeable_attr :customer_uuid 16 | writeable_attr :owner 17 | writeable_attr :pipeline 18 | writeable_attr :pipeline_stage 19 | writeable_attr :estimated_close_date 20 | writeable_attr :currency 21 | writeable_attr :amount_in_cents 22 | writeable_attr :type 23 | writeable_attr :forecast_category 24 | writeable_attr :win_likelihood 25 | writeable_attr :custom 26 | 27 | include API::Actions::Create 28 | include API::Actions::Destroy 29 | include API::Actions::Retrieve 30 | include API::Actions::Update 31 | 32 | def self.all(options = {}) 33 | Opportnities.all(options) 34 | end 35 | end 36 | 37 | class Opportnities < APIResource 38 | set_resource_name 'Opportunities' 39 | set_resource_path '/v1/opportunities' 40 | 41 | include Concerns::Entries 42 | include Concerns::PageableWithCursor 43 | 44 | set_entry_class Opportunity 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/chartmogul/ping.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class Ping < APIResource 5 | set_resource_name 'Ping' 6 | set_resource_path '/v1/ping' 7 | 8 | readonly_attr :data 9 | 10 | include API::Actions::Custom 11 | 12 | def self.ping 13 | custom!(:get, '/v1/ping') 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/chartmogul/plan.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class Plan < APIResource 5 | set_resource_name 'Plan' 6 | set_resource_path '/v1/plans' 7 | 8 | readonly_attr :uuid 9 | 10 | writeable_attr :name 11 | writeable_attr :interval_count 12 | writeable_attr :interval_unit 13 | writeable_attr :external_id 14 | 15 | writeable_attr :data_source_uuid 16 | 17 | include API::Actions::Create 18 | include API::Actions::Custom 19 | include API::Actions::Destroy 20 | include API::Actions::Retrieve 21 | include API::Actions::Update 22 | 23 | def self.all(options = {}) 24 | Plans.all(options) 25 | end 26 | end 27 | 28 | class Plans < APIResource 29 | set_resource_name 'Plans' 30 | set_resource_path '/v1/plans' 31 | 32 | set_resource_root_key :plans 33 | 34 | include Concerns::Entries 35 | include Concerns::Pageable2 36 | include Concerns::PageableWithCursor 37 | 38 | set_entry_class Plan 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/chartmogul/plan_group.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class PlanGroup < APIResource 5 | set_resource_name 'PlanGroup' 6 | set_resource_path '/v1/plan_groups' 7 | 8 | readonly_attr :uuid 9 | readonly_attr :plans_count 10 | 11 | writeable_attr :name 12 | writeable_attr :plans, default: [] 13 | 14 | include API::Actions::Create 15 | include API::Actions::Destroy 16 | include API::Actions::Retrieve 17 | include API::Actions::Update 18 | 19 | def self.all(options = {}) 20 | PlanGroups.all(options) 21 | end 22 | 23 | def serialize_plans 24 | plans.map(&:uuid) 25 | end 26 | 27 | class PlanGroups < APIResource 28 | set_resource_name 'PlanGroups' 29 | set_resource_path '/v1/plan_groups' 30 | 31 | set_resource_root_key :plan_groups 32 | 33 | include Concerns::Entries 34 | include Concerns::Pageable2 35 | include Concerns::PageableWithCursor 36 | 37 | set_entry_class PlanGroup 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/chartmogul/plan_groups/plans.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module PlanGroups 5 | class Plans < APIResource 6 | set_resource_name 'Plans' 7 | set_resource_path '/v1/plan_groups/:plan_group_uuid/plans' 8 | 9 | set_resource_root_key :plans 10 | 11 | include Concerns::Entries 12 | include Concerns::Pageable2 13 | include Concerns::PageableWithCursor 14 | include API::Actions::Custom 15 | 16 | set_entry_class Plan 17 | 18 | def self.all(plan_group_uuid, options = {}) 19 | super(options.merge(plan_group_uuid: plan_group_uuid)) 20 | end 21 | 22 | def next(plan_group_uuid, options = {}) 23 | path = ChartMogul::ResourcePath.new("/v1/plan_groups/#{plan_group_uuid}/plans") 24 | custom!(:get, path.apply_with_get_params(options.merge(cursor: cursor))) 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/chartmogul/resource_path.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'uri' 4 | 5 | module ChartMogul 6 | class ResourcePath 7 | attr_reader :path 8 | attr_reader :named_params 9 | 10 | class RequiredParameterMissing < StandardError; end 11 | 12 | DEPRECATED_PARAMETER = 'page' 13 | 14 | def initialize(path) 15 | @path = path 16 | @named_params = path.scan(/:\w+/).each_with_object({}) do |named_param, hash| 17 | hash[named_param] = named_param.delete(':').to_sym 18 | end 19 | end 20 | 21 | def apply(params = {}) 22 | apply_named_params(params) 23 | end 24 | 25 | # For path = '/hello/:hello_id/say' & params = { hello_id: 1, search: 'cat' } 26 | # it will return '/hello/1/say?search=cat' 27 | def apply_with_get_params(params = {}) 28 | base_path = apply_named_params(params) 29 | get_params = params.reject { |param_name| named_params.values.include?(param_name) } 30 | 31 | get_params.empty? ? base_path : "#{base_path}?#{URI.encode_www_form(get_params)}" 32 | end 33 | 34 | private 35 | 36 | def apply_named_params(params) 37 | if params.keys.map(&:to_s).include?(DEPRECATED_PARAMETER) 38 | raise(ChartMogul::DeprecatedParameterError, "#{DEPRECATED_PARAMETER} is deprecated.") 39 | end 40 | 41 | path.dup.tap do |path| 42 | named_params.each do |named_param, param_key| 43 | unless params.key?(param_key) 44 | raise(RequiredParameterMissing, "#{named_param} is required") 45 | end 46 | 47 | path.gsub!(named_param, params[param_key].to_s) 48 | end 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/chartmogul/summary.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class Summary < ChartMogul::Object 5 | readonly_attr :current 6 | readonly_attr :previous 7 | readonly_attr :percentage_change 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/chartmogul/summary_all.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | class SummaryAll < ChartMogul::Object 5 | readonly_attr :current_arpa 6 | readonly_attr :current_arr 7 | readonly_attr :current_asp 8 | readonly_attr :current_customer_churn_rate 9 | readonly_attr :current_customers 10 | readonly_attr :current_ltv 11 | readonly_attr :current_mrr 12 | readonly_attr :current_mrr_churn_rate 13 | readonly_attr :previous_arpa 14 | readonly_attr :previous_arr 15 | readonly_attr :previous_asp 16 | readonly_attr :previous_customer_churn_rate 17 | readonly_attr :previous_customers 18 | readonly_attr :previous_ltv 19 | readonly_attr :previous_mrr 20 | readonly_attr :previous_mrr_churn_rate 21 | readonly_attr :arpa_percentage_change 22 | readonly_attr :arr_percentage_change 23 | readonly_attr :asp_percentage_change 24 | readonly_attr :customer_churn_rate_percentage_change 25 | readonly_attr :customers_percentage_change 26 | readonly_attr :ltv_percentage_change 27 | readonly_attr :mrr_percentage_change 28 | readonly_attr :mrr_churn_rate_percentage_change 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/chartmogul/task.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'forwardable' 4 | 5 | module ChartMogul 6 | class Task < APIResource 7 | set_resource_name 'Task' 8 | set_resource_path '/v1/tasks' 9 | 10 | readonly_attr :customer_uuid 11 | readonly_attr :task_uuid 12 | readonly_attr :created_at 13 | readonly_attr :updated_at 14 | 15 | writeable_attr :task_details 16 | writeable_attr :assignee 17 | writeable_attr :due_date 18 | writeable_attr :completed_at 19 | 20 | include API::Actions::Create 21 | include API::Actions::Destroy 22 | include API::Actions::Retrieve 23 | include API::Actions::Update 24 | 25 | def self.all(options = {}) 26 | Tasks.all(options) 27 | end 28 | end 29 | 30 | class Tasks < APIResource 31 | set_resource_name 'Tasks' 32 | set_resource_path '/v1/tasks' 33 | 34 | include Concerns::Entries 35 | include Concerns::PageableWithCursor 36 | 37 | set_entry_class Task 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/chartmogul/transactions/payment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Transactions 5 | class Payment < APIResource 6 | set_resource_name 'Payment Transaction' 7 | set_resource_path '/v1/import/invoices/:invoice_uuid/transactions' 8 | 9 | readonly_attr :uuid 10 | 11 | writeable_attr :type, default: 'payment' 12 | writeable_attr :date, type: :time 13 | writeable_attr :result 14 | writeable_attr :external_id 15 | writeable_attr :amount_in_cents 16 | writeable_attr :transaction_fees_in_cents 17 | writeable_attr :invoice_uuid 18 | 19 | def initialize(attributes = {}) 20 | super(attributes) 21 | @type = 'payment' 22 | end 23 | 24 | include API::Actions::Create 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/chartmogul/transactions/refund.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Transactions 5 | class Refund < APIResource 6 | set_resource_name 'Refund Transaction' 7 | set_resource_path '/v1/import/invoices/:invoice_uuid/transactions' 8 | 9 | readonly_attr :uuid 10 | 11 | writeable_attr :type, default: 'refund' 12 | writeable_attr :date, type: :time 13 | writeable_attr :result 14 | writeable_attr :external_id 15 | writeable_attr :amount_in_cents 16 | writeable_attr :transaction_fees_in_cents 17 | writeable_attr :invoice_uuid 18 | 19 | def initialize(attributes = {}) 20 | super(attributes) 21 | @type = 'refund' 22 | end 23 | 24 | include API::Actions::Create 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/chartmogul/utils/hash_snake_caser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Utils 5 | class HashSnakeCaser 6 | # 7 | # Recursively converts CamelCase and camelBack JSON-style hash keys to 8 | # Rubyish snake_case, suitable for use during instantiation of Ruby 9 | # model attributes. 10 | # 11 | def initialize(hash, immutable_keys: []) 12 | @hash = hash 13 | @immutable_keys = immutable_keys 14 | end 15 | 16 | def to_snake_keys(value = @hash) 17 | case value 18 | when Array 19 | value.map { |v| to_snake_keys(v) } 20 | when Hash 21 | snake_hash(value) 22 | else 23 | value 24 | end 25 | end 26 | 27 | private 28 | 29 | def snake_hash(value) 30 | Hash[value.map { |k, v| [underscore_key(k), immutable_check(k, v)] }] 31 | end 32 | 33 | def immutable_check(k,v) 34 | return v if @immutable_keys.include?(k) 35 | 36 | to_snake_keys(v) 37 | end 38 | 39 | def underscore_key(k) 40 | if k.instance_of?(Symbol) 41 | underscore(k.to_s).to_sym 42 | elsif k.instance_of?(String) 43 | underscore(k) 44 | else 45 | k # Can't snakify anything except strings and symbols 46 | end 47 | end 48 | 49 | def underscore(string) 50 | string.gsub(/::/, '/') 51 | .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') 52 | .gsub(/([a-z\d])([A-Z])/, '\1_\2') 53 | .tr('-', '_') 54 | .downcase 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/chartmogul/utils/json_parser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | module Utils 5 | class JSONParser 6 | class << self 7 | def parse(json_string, immutable_keys: []) 8 | hash = JSON.parse(json_string, symbolize_names: true) 9 | HashSnakeCaser.new(hash, immutable_keys: immutable_keys).to_snake_keys 10 | end 11 | 12 | def typecast_custom_attributes(custom_attributes) 13 | return {} unless custom_attributes 14 | 15 | custom_attributes.each_with_object({}) do |(key, value), hash| 16 | hash[key] = opt_string_to_time(value) 17 | end 18 | end 19 | 20 | def opt_string_to_time(value) 21 | return value unless value.instance_of?(String) 22 | 23 | parse_timestamp(value) 24 | rescue ArgumentError 25 | value 26 | end 27 | 28 | def parse_timestamp(value) 29 | Time.iso8601(value) 30 | rescue ArgumentError 31 | Time.rfc2822(value) 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/chartmogul/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChartMogul 4 | VERSION = '4.7.0' 5 | end 6 | -------------------------------------------------------------------------------- /pre-commit.example: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # put in .git/hooks/ 3 | set -e 4 | 5 | bundle exec rspec 6 | -------------------------------------------------------------------------------- /spec/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmogul/chartmogul-ruby/3e62d8b07cb8e3f68822c4fc62f0df663ad0283e/spec/.DS_Store -------------------------------------------------------------------------------- /spec/chartmogul/account_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::Account, uses_api: true do 6 | describe 'API interactions' do 7 | around(:all) do |example| 8 | VCR.use_cassette('ChartMogul_Account/returns_details_of_current_account', &example) 9 | end 10 | 11 | let(:account) { ChartMogul::Account.retrieve } 12 | 13 | it 'returns the right account attributes' do 14 | expect(account).to have_attributes( 15 | name: 'Example Test Company', 16 | currency: 'EUR', 17 | time_zone: 'Europe/Berlin', 18 | week_start_on: 'sunday' 19 | ) 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/chartmogul/api_resource_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::APIResource do 6 | describe 'connection', vcr: true do 7 | it 'adds User-Agent header' do 8 | set_valid_credentials 9 | expect(ChartMogul::APIResource.connection.headers["User-Agent"]).to eq("chartmogul-ruby/#{ChartMogul::VERSION}") 10 | end 11 | 12 | it 'works when credentials are updated' do 13 | set_invalid_credentials 14 | expect { ChartMogul::Ping.ping }.to raise_error(ChartMogul::UnauthorizedError) 15 | 16 | set_valid_credentials 17 | expect { ChartMogul::Ping.ping }.not_to raise_error 18 | end 19 | 20 | it 'works in a threaded environment' do 21 | set_invalid_credentials 22 | expect { ChartMogul::Ping.ping }.to raise_error(ChartMogul::UnauthorizedError) 23 | 24 | Thread.new do 25 | set_valid_credentials 26 | expect { ChartMogul::Ping.ping }.not_to raise_error 27 | end.join 28 | 29 | expect { ChartMogul::Ping.ping }.to raise_error(ChartMogul::UnauthorizedError) 30 | end 31 | end 32 | 33 | def set_valid_credentials 34 | ChartMogul.api_key = 'dummy-token' 35 | end 36 | 37 | def set_invalid_credentials 38 | ChartMogul.api_key = 'invalid' 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/chartmogul/configuration_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'ChartMogul configuration' do 6 | describe 'api_key' do 7 | it 'sets the configuration' do 8 | ChartMogul.api_key = 'abcdef1234567890' 9 | expect(ChartMogul.api_key).to eq('abcdef1234567890') 10 | end 11 | 12 | it 'raises a ChartMogul::ConfigurationError when not set' do 13 | ChartMogul.api_key = nil 14 | expect { ChartMogul.api_key }.to raise_error(ChartMogul::ConfigurationError) 15 | end 16 | end 17 | 18 | describe 'api base' do 19 | it 'sets the api base' do 20 | dummy_base = 'https://dummy-api.chartmogul.com' 21 | 22 | ChartMogul.api_base = dummy_base 23 | expect(ChartMogul.api_base).to eq dummy_base 24 | end 25 | 26 | it 'uses default api base when not set' do 27 | ChartMogul.api_base = nil 28 | 29 | expect(ChartMogul.api_base).to eq ChartMogul::API_BASE 30 | end 31 | end 32 | 33 | describe 'global_api_key' do 34 | 35 | after { ChartMogul.global_api_key = nil } 36 | 37 | it 'sets the global configuration' do 38 | ChartMogul.global_api_key = 'abcdef1234567890' 39 | expect(ChartMogul.api_key).to eq('abcdef1234567890') 40 | expect(ChartMogul.global_api_key).to eq('abcdef1234567890') 41 | end 42 | 43 | it 'thread-safe overrides global configuration' do 44 | ChartMogul.global_api_key = 'abcdef1234567890' 45 | expect(ChartMogul.api_key).to eq('abcdef1234567890') 46 | ChartMogul.api_key = '00000000000' 47 | expect(ChartMogul.api_key).to eq('00000000000') 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /spec/chartmogul/connection_cache_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'Connection cache' do 6 | before do 7 | stub_request(:get, "https://api.chartmogul.com/v1/ping"). 8 | to_return(status: 200, body: '{"data":"pong!"}') 9 | 10 | stub_request(:get, "https://example.chartmogul.com/v1/ping"). 11 | to_return(status: 200, body: '{"data":"pong!"}') 12 | end 13 | 14 | it 'invalidates the connection and uses new one' do 15 | VCR.turned_off do 16 | ChartMogul.api_key = 'dummy-token' 17 | ChartMogul.max_retries = 0 18 | 19 | pong = ChartMogul::Ping.ping 20 | expect(WebMock).to have_requested(:get, "https://api.chartmogul.com/v1/ping") 21 | expect(pong.data).to eq('pong!') 22 | 23 | ChartMogul.api_base = 'https://example.chartmogul.com' 24 | pong = ChartMogul::Ping.ping 25 | expect(WebMock).to have_requested(:get, "https://example.chartmogul.com/v1/ping") 26 | expect(pong.data).to eq('pong!') 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/chartmogul/errors/chartmogul_error_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::ChartMogulError do 6 | let(:message) { 'This is a test error' } 7 | 8 | subject { ChartMogul::ChartMogulError.new(message, http_status: http_status) } 9 | 10 | context 'when a HTTP status is supplied' do 11 | let(:http_status) { 404 } 12 | 13 | it 'generates the correct error message' do 14 | expect(subject.to_s).to eq('This is a test error (HTTP Status: 404)') 15 | end 16 | end 17 | 18 | context 'when a HTTP status is not supplied' do 19 | let(:http_status) { nil } 20 | 21 | it 'generates the correct error message' do 22 | expect(subject.to_s).to eq('This is a test error') 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/chartmogul/line_items/one_time_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::LineItems::OneTime do 6 | ATTRS = { 7 | type: 'one_time', 8 | amount_in_cents: 1000, 9 | description: 'Dummy Description', 10 | quantity: 5, 11 | discount_amount_in_cents: 1200, 12 | discount_code: 'DISCCODE', 13 | tax_amount_in_cents: 200, 14 | external_id: 'one_time_ext_id', 15 | uuid: 'li_1234-5678-9012-34567', 16 | plan_uuid: 'pl_1234-5678-9012-34567', 17 | transaction_fees_currency: 'EUR', 18 | discount_description: '2 EUR', 19 | event_order: 5 20 | }.freeze 21 | 22 | describe '#initialize' do 23 | subject { described_class.new(ATTRS) } 24 | 25 | it 'doesnt set the uuid attribute' do 26 | expect(subject.uuid).to be_nil 27 | end 28 | 29 | ATTRS.each do |key, value| 30 | next if key == :uuid 31 | 32 | it "sets the #{key} attribute" do 33 | expect(subject.public_send(key)).to eq value 34 | end 35 | end 36 | end 37 | 38 | describe '.new_from_json' do 39 | subject { described_class.new_from_json(ATTRS) } 40 | 41 | ATTRS.each do |key, value| 42 | it "sets the #{key} attribute" do 43 | expect(subject.public_send(key)).to eq value 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/activities_export_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | RSpec.describe ChartMogul::Metrics::ActivitiesExport do 6 | describe 'API interactions', vcr: true, uses_api: true do 7 | describe '#create!' do 8 | it 'returns a pending activity export', vcr: { cassette_name: 'ChartMogul_Metrics_ActivitiesExport/post_activities_export', match_requests_on: [:method, :uri, :body] } do 9 | activities_export = ChartMogul::Metrics::ActivitiesExport.create!( 10 | start_date: '2020-01-01T00:00:00Z', 11 | end_date: '2020-12-31T00:00:00Z', 12 | type: 'new_biz' 13 | ) 14 | 15 | expect(activities_export.status).to eq('pending') 16 | expect(activities_export.file_url).to be_nil 17 | 18 | # the async export must be reloaded periodically until it is sucessful or fails permanently 19 | activities_export = ChartMogul::Metrics::ActivitiesExport.retrieve(activities_export.id) 20 | 21 | expect(activities_export.status).to eq('succeeded') 22 | expect(activities_export.file_url).not_to be_nil 23 | end 24 | end 25 | 26 | describe '#retrieve', vcr: 'ChartMogul_Metrics_ActivitiesExport/get_activities_export' do 27 | it 'returns the finished activity export' do 28 | activities_export = ChartMogul::Metrics::ActivitiesExport.retrieve('44037b8f-4a89-4fc6-8114-2288c71a9518') 29 | expect(activities_export.status).to eq('succeeded') 30 | expect(activities_export.file_url).not_to be_nil 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/activities_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require_relative 'shared/pageable_with_anchor' 5 | 6 | describe ChartMogul::Metrics::Activity, vcr: true, uses_api: true do 7 | let(:do_request) { ChartMogul::Metrics::Activity.all({ per_page: 2 }) } 8 | 9 | it_behaves_like 'PageableWithAnchor' 10 | 11 | it 'should have Activity entries' do 12 | response = do_request 13 | 14 | expect(response).to be_kind_of(ChartMogul::Metrics::Activities) 15 | expect(response.count).to be > 0 16 | expect(response.cursor).not_to be_nil 17 | 18 | activity = response[0] 19 | expect(activity).to be_kind_of(ChartMogul::Metrics::Activity) 20 | expect(activity.description).not_to be_nil 21 | expect(activity.type).not_to be_nil 22 | expect(activity.date).not_to be_nil 23 | expect(activity.activity_arr).not_to be_nil 24 | expect(activity.activity_mrr).not_to be_nil 25 | expect(activity.activity_mrr_movement).not_to be_nil 26 | expect(activity.currency).not_to be_nil 27 | expect(activity.subscription_external_id).not_to be_nil 28 | expect(activity.plan_external_id).not_to be_nil 29 | expect(activity.customer_name).not_to be_nil 30 | expect(activity.customer_uuid).not_to be_nil 31 | expect(activity.customer_external_id).not_to be_nil 32 | expect(activity.billing_connector_uuid).not_to be_nil 33 | expect(activity.uuid).not_to be_nil 34 | end 35 | 36 | it 'should paginate using cursor when called with #next' do 37 | activities = ChartMogul::Metrics::Activity.all(per_page: 1) 38 | expect(activities.size).to eq(1) 39 | expect(activities[0].uuid).to eq('561814e1-d7d3-42f3-8936-4689ec0fbb74') 40 | 41 | next_activities = activities.next(per_page: 1) 42 | expect(next_activities.size).to eq(1) 43 | expect(next_activities[0].uuid).to eq('d868a892-37c7-45e3-ae84-e693181d2344') 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/all_key_metrics_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::Metrics::AllKeyMetric, vcr: true, uses_api: true do 6 | let(:do_request) { ChartMogul::Metrics.all(start_date: '2015-01-01', end_date: '2015-02-01') } 7 | let(:metrics) { %w[arpa arr asp customer_churn_rate customers ltv mrr] } 8 | 9 | it 'should have summary' do 10 | response = do_request 11 | 12 | expect(response).to respond_to(:summary) 13 | summary = response.summary 14 | 15 | expect(summary).to be_kind_of(ChartMogul::SummaryAll) 16 | metrics.each do |metric| 17 | expect(summary.public_send("#{metric}_percentage_change")).not_to be_nil 18 | expect(summary.public_send("previous_#{metric}")).not_to be_nil 19 | expect(summary.public_send("current_#{metric}")).not_to be_nil 20 | end 21 | end 22 | 23 | it 'should have entries' do 24 | response = do_request 25 | expect(response.count).not_to be_nil 26 | 27 | entry = response[0] 28 | 29 | expect(entry).to be_kind_of(described_class) 30 | expect(entry.date).to be_kind_of(Date) 31 | metrics.each do |metric| 32 | expect(entry.public_send(metric)).not_to be_nil 33 | expect(entry.public_send("#{metric}_percentage_change")).not_to be_nil 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/customers/activities_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require_relative '../shared/pageable' 5 | 6 | describe ChartMogul::Metrics::Customers::Activity, vcr: true, uses_api: true do 7 | let(:do_request) { ChartMogul::Metrics::Customers::Activity.all('cus_23551596-2c7e-11ee-9ea1-2bfe193640c0') } 8 | 9 | it_behaves_like 'Pageable' 10 | 11 | it 'should have Activity entries' do 12 | response = do_request 13 | 14 | expect(response).to be_kind_of(ChartMogul::Metrics::Customers::Activities) 15 | expect(response.count).to be > 0 16 | expect(response.cursor).not_to be_nil 17 | 18 | activity = response[0] 19 | expect(activity).to be_kind_of(ChartMogul::Metrics::Customers::Activity) 20 | expect(activity.id).not_to be_nil 21 | expect(activity.description).not_to be_nil 22 | expect(activity.type).not_to be_nil 23 | expect(activity.date).not_to be_nil 24 | expect(activity.activity_arr).not_to be_nil 25 | expect(activity.activity_mrr).not_to be_nil 26 | expect(activity.activity_mrr_movement).not_to be_nil 27 | expect(activity.currency).not_to be_nil 28 | expect(activity.currency_sign).not_to be_nil 29 | expect(activity.subscription_external_id).not_to be_nil 30 | end 31 | 32 | it 'should paginate using cursor when called with #next' do 33 | customer_uuid = 'cus_23551596-2c7e-11ee-9ea1-2bfe193640c0' 34 | activities = ChartMogul::Metrics::Customers::Activity.all(customer_uuid, per_page: 1) 35 | expect(activities.size).to eq(1) 36 | expect(activities[0].id).to eq(2625867088) 37 | 38 | next_activities = activities.next(customer_uuid, per_page: 1) 39 | expect(next_activities.size).to eq(1) 40 | expect(next_activities[0].id).to eq(2625867087) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/customers/subscriptions_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require_relative '../shared/pageable' 5 | 6 | describe ChartMogul::Metrics::Customers::Subscription, vcr: true, uses_api: true do 7 | let(:do_request) { ChartMogul::Metrics::Customers::Subscription.all('cus_23551596-2c7e-11ee-9ea1-2bfe193640c0') } 8 | 9 | it_behaves_like 'Pageable' 10 | 11 | it 'should have Subscription entries' do 12 | response = do_request 13 | 14 | expect(response).to be_kind_of(ChartMogul::Metrics::Customers::Subscriptions) 15 | expect(response.count).to be > 0 16 | expect(response.cursor).not_to be_nil 17 | 18 | subscription = response[0] 19 | expect(subscription).to be_kind_of(ChartMogul::Metrics::Customers::Subscription) 20 | expect(subscription.id).not_to be_nil 21 | expect(subscription.uuid).not_to be_nil 22 | expect(subscription.plan).not_to be_nil 23 | expect(subscription.quantity).not_to be_nil 24 | expect(subscription.mrr).not_to be_nil 25 | expect(subscription.arr).not_to be_nil 26 | expect(subscription.status).not_to be_nil 27 | expect(subscription.billing_cycle).not_to be_nil 28 | expect(subscription.billing_cycle_count).not_to be_nil 29 | expect(subscription.start_date).to be_kind_of(Time) 30 | expect(subscription.end_date).to be_kind_of(Time) 31 | expect(subscription.currency).not_to be_nil 32 | expect(subscription.currency_sign).not_to be_nil 33 | end 34 | 35 | it 'should paginate using cursor when called with #next' do 36 | customer_uuid = 'cus_23551596-2c7e-11ee-9ea1-2bfe193640c0' 37 | subscriptions = ChartMogul::Metrics::Customers::Subscription.all(customer_uuid, per_page: 1) 38 | expect(subscriptions.size).to eq(1) 39 | expect(subscriptions[0].id).to eq(2293710870) 40 | 41 | next_subscriptions = subscriptions.next(customer_uuid, per_page: 1) 42 | expect(next_subscriptions.size).to eq(0) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/metrics_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require_relative 'shared/metrics_resource' 5 | 6 | METRICS = { 7 | arpa: ChartMogul::Metrics::ARPA, 8 | arr: ChartMogul::Metrics::ARR, 9 | asp: ChartMogul::Metrics::ASP, 10 | ltv: ChartMogul::Metrics::LTV, 11 | customer_churn_rate: ChartMogul::Metrics::CustomerChurnRate, 12 | customer_count: ChartMogul::Metrics::CustomerCount, 13 | mrr_churn_rate: ChartMogul::Metrics::MRRChurnRate 14 | }.freeze 15 | 16 | METRICS.each do |method_name, klass_name| 17 | describe klass_name, vcr: true, uses_api: true do 18 | let(:value_field) { method_name == :customer_count ? :customers : method_name } 19 | let(:do_request) { ChartMogul::Metrics.send(method_name, start_date: '2015-01-01', end_date: '2015-02-01') } 20 | 21 | it_behaves_like 'Metrics API resource' 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/mrr_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | require_relative 'shared/summary' 5 | 6 | describe ChartMogul::Metrics::MRR, vcr: true, uses_api: true do 7 | let(:do_request) { ChartMogul::Metrics.mrr(start_date: '2015-01-01', end_date: '2015-02-01') } 8 | 9 | it_behaves_like 'Summary' 10 | 11 | it 'should have entries' do 12 | response = do_request 13 | expect(response.count).not_to be_nil 14 | 15 | entry = response[0] 16 | 17 | expect(entry).to be_kind_of(described_class) 18 | 19 | expect(entry.date).to be_kind_of(Date) 20 | expect(entry.mrr).not_to be_nil 21 | 22 | expect(entry.mrr_new_business).not_to be_nil 23 | 24 | expect(entry.mrr_expansion).not_to be_nil 25 | expect(entry.mrr_contraction).not_to be_nil 26 | 27 | expect(entry.mrr_churn).not_to be_nil 28 | expect(entry.mrr_reactivation).not_to be_nil 29 | expect(entry.percentage_change).not_to be_nil 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/shared/metrics_resource.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'summary' 4 | 5 | shared_examples 'Metrics API resource' do 6 | it_behaves_like 'Summary' 7 | 8 | it 'should have entries' do 9 | response = do_request 10 | expect(response.count).not_to be_nil 11 | 12 | entry = response[0] 13 | 14 | expect(entry).to be_kind_of(described_class) 15 | expect(entry.date).to be_kind_of(Date) 16 | expect(entry.send(value_field)).not_to be_nil 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/shared/pageable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'Pageable' do 4 | it 'should be pageable' do 5 | response = do_request 6 | 7 | expect(response.page).not_to be_nil 8 | expect(response.has_more).not_to be_nil 9 | expect(response.per_page).not_to be_nil 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/shared/pageable_with_anchor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'PageableWithAnchor' do 4 | it 'should be pageable' do 5 | response = do_request 6 | 7 | expect(response.has_more).not_to be_nil 8 | expect(response.per_page).not_to be_nil 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/chartmogul/metrics/shared/summary.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'Summary' do 4 | it 'should have summary' do 5 | response = do_request 6 | 7 | expect(response).to respond_to(:summary) 8 | summary = response.summary 9 | 10 | expect(summary).to be_kind_of(ChartMogul::Summary) 11 | expect(summary.percentage_change).not_to be_nil 12 | expect(summary.previous).not_to be_nil 13 | expect(summary.current).not_to be_nil 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/chartmogul/ping_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::Ping do 6 | before do 7 | allow(ChartMogul).to receive(:max_retries).and_return(0) 8 | end 9 | describe 'pings', vcr: true do 10 | it 'when credentials correct', uses_api: true do 11 | pong = ChartMogul::Ping.ping 12 | 13 | expect(pong.data).to eq('pong!') 14 | end 15 | 16 | it 'and fails on incorrect credentials', uses_api: true do 17 | expect { ChartMogul::Ping.ping }.to raise_error(ChartMogul::UnauthorizedError) 18 | end 19 | 20 | it 'and fails with 500 internal server error', uses_api: true do 21 | expect { ChartMogul::Ping.ping }.to raise_error(ChartMogul::ServerError) 22 | end 23 | 24 | it 'and fails with 504 gateway timeout error', uses_api: true do 25 | expect { ChartMogul::Ping.ping }.to raise_error(ChartMogul::ServerError) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/chartmogul/plan_groups/plans_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::PlanGroups::Plans do 6 | describe 'API Actions', vcr: true, uses_api: true do 7 | let(:plan_group_uuid) { 'plg_5f1af63a-ec94-4688-9127-5eb816d05a8f' } 8 | 9 | context 'with old pagination' do 10 | let(:get_resources) do 11 | described_class.all(plan_group_uuid, per_page: 1, page: 1) 12 | end 13 | 14 | it_behaves_like 'raises deprecated param error' 15 | end 16 | 17 | context 'with pagination' do 18 | let(:first_cursor) do 19 | 'MjAyMy0xMC0yN1QxMDo0NTozNS4yMjM5MDUwMDBaJjEwOTk1ODQ=' 20 | end 21 | let(:next_cursor) do 22 | 'MjAyMy0xMC0yN1QwNzozMTo1NC40MzQzNDkwMDBaJjEwOTk1MzI=' 23 | end 24 | 25 | it 'paginates correctly' do 26 | plans = described_class.all(plan_group_uuid, per_page: 1) 27 | expect(plans).to have_attributes( 28 | cursor: first_cursor, 29 | has_more: true, 30 | size: 1 31 | ) 32 | expect(plans.plans.map(&:uuid)).to eq( 33 | ['pl_e205d990-56e3-013c-13ac-46813c1ddd3d'] 34 | ) 35 | 36 | next_plans = plans.next(plan_group_uuid, per_page: 1) 37 | expect(next_plans).to have_attributes( 38 | cursor: next_cursor, 39 | has_more: false, 40 | size: 1 41 | ) 42 | expect(next_plans.first).to have_attributes( 43 | uuid: 'pl_e6ffcc84-749a-11ee-be12-f32dce10118e' 44 | ) 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/chartmogul/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul do 6 | it 'has a version number' do 7 | expect(ChartMogul::VERSION).not_to be nil 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/chartmogul/transactions/refund_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::Transactions::Refund do 6 | let(:attrs) do 7 | { 8 | type: 'refund', 9 | date: '2016-01-01 12:00:00', 10 | result: 'successful', 11 | external_id: 'ref_ext_id', 12 | uuid: 'tr_1234-5678-9012-34567', 13 | amount_in_cents: 500 14 | } 15 | end 16 | 17 | describe '#initialize' do 18 | subject { described_class.new(attrs) } 19 | 20 | it 'doesnt set the uuid attribute' do 21 | expect(subject.uuid).to be_nil 22 | end 23 | 24 | it 'sets the type attribute' do 25 | expect(subject.type).to eq('refund') 26 | end 27 | 28 | it 'sets the date attribute' do 29 | expect(subject.date).to eq('2016-01-01 12:00:00') 30 | end 31 | 32 | it 'sets the result attribute' do 33 | expect(subject.result).to eq('successful') 34 | end 35 | 36 | it 'sets the external_id attribute' do 37 | expect(subject.external_id).to eq('ref_ext_id') 38 | end 39 | 40 | it 'sets the amount_in_cents attribute' do 41 | expect(subject.amount_in_cents).to eq(500) 42 | end 43 | end 44 | 45 | describe '.new_from_json' do 46 | subject { described_class.new_from_json(attrs) } 47 | it 'sets the uuid attribute' do 48 | expect(subject.uuid).to eq('tr_1234-5678-9012-34567') 49 | end 50 | 51 | it 'sets the type attribute' do 52 | expect(subject.type).to eq('refund') 53 | end 54 | 55 | it 'sets the date attribute' do 56 | expect(subject.date).to eq(Time.parse('2016-01-01 12:00:00')) 57 | end 58 | 59 | it 'sets the result attribute' do 60 | expect(subject.result).to eq('successful') 61 | end 62 | 63 | it 'sets the external_id attribute' do 64 | expect(subject.external_id).to eq('ref_ext_id') 65 | end 66 | 67 | it 'sets the amount_in_cents attribute' do 68 | expect(subject.amount_in_cents).to eq(500) 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /spec/chartmogul/utils/hash_snake_caser_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::Utils::HashSnakeCaser do 6 | let(:hash) do 7 | { 8 | 'key-key' => { 'withNestedHash' => true }, 9 | 'and-array' => [{}], 10 | :camelCasedKey => 'with string', 11 | :good_enough_key => 'here is nothing to do', 12 | :HUGE_SYMBOLS => 'wow' 13 | } 14 | end 15 | 16 | subject { described_class.new(hash, immutable_keys: []) } 17 | 18 | it 'returns snake_cased keys' do 19 | expect(subject.to_snake_keys).to eq( 20 | 'key_key' => { 'with_nested_hash' => true }, 21 | 'and_array' => [{}], 22 | :camel_cased_key => 'with string', 23 | :good_enough_key => 'here is nothing to do', 24 | :huge_symbols => 'wow' 25 | ) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/chartmogul/utils/json_parser_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe ChartMogul::Utils::JSONParser do 6 | describe '::typecast_custom_attributes' do 7 | it 'parses ISO 8601, returned by ChartMogul API' do 8 | result = described_class.typecast_custom_attributes(attr: '2016-02-01T00:00:00.000Z') 9 | expect(result[:attr]).to be_instance_of(Time) 10 | end 11 | 12 | it 'parses RFC 2822' do 13 | result = described_class.typecast_custom_attributes(attr: 'Fri, 30 Aug 2019 12:13:07 +0000') 14 | expect(result[:attr]).to be_instance_of(Time) 15 | end 16 | 17 | it 'doesn\'t parse string vaguely looking like a date' do 18 | result = described_class.typecast_custom_attributes(attr: 'May the force be with you.') 19 | expect(result[:attr]).to be_instance_of(String) 20 | end 21 | 22 | it 'return string if parse of timestamp failed' do 23 | result = described_class.typecast_custom_attributes(attr: '2016-02-01T0000:00.000Z') 24 | expect(result[:attr]).to be_instance_of(String) 25 | end 26 | 27 | it 'allows skipping camel case conversion' do 28 | json = {'custom': {'aKey': 'a_value', 'bKey': 'b_value'}}.to_json 29 | result = described_class.parse(json, immutable_keys: [:custom]) 30 | expect(result[:custom].keys).to contain_exactly(:aKey,:bKey) 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_APIResource/connection/works_when_credentials_are_updated.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/ping 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - Faraday v0.17.3 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 401 19 | message: Unauthorized 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | date: 24 | - Fri, 17 Jul 2020 08:25:25 GMT 25 | content-type: 26 | - application/json 27 | transfer-encoding: 28 | - chunked 29 | connection: 30 | - keep-alive 31 | status: 32 | - 401 Unauthorized 33 | body: 34 | encoding: UTF-8 35 | string: '{"code":401,"message":"No valid API key provided","param":null}' 36 | http_version: 37 | recorded_at: Fri, 17 Jul 2020 08:25:25 GMT 38 | - request: 39 | method: get 40 | uri: https://api.chartmogul.com/v1/ping 41 | body: 42 | encoding: UTF-8 43 | string: "{}" 44 | headers: 45 | User-Agent: 46 | - Faraday v0.17.3 47 | Content-Type: 48 | - application/json 49 | Authorization: 50 | - Basic hidden 51 | response: 52 | status: 53 | code: 200 54 | message: OK 55 | headers: 56 | server: 57 | - nginx/1.10.1 58 | date: 59 | - Fri, 17 Jul 2020 08:25:26 GMT 60 | content-type: 61 | - application/json 62 | transfer-encoding: 63 | - chunked 64 | connection: 65 | - keep-alive 66 | vary: 67 | - Accept-Encoding, Accept-Encoding 68 | status: 69 | - 200 OK 70 | access-control-allow-credentials: 71 | - 'true' 72 | body: 73 | encoding: ASCII-8BIT 74 | string: '{"data":"pong!"}' 75 | http_version: 76 | recorded_at: Fri, 17 Jul 2020 08:25:26 GMT 77 | recorded_with: VCR 5.1.0 78 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Account/returns_details_of_current_account.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/account 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - Faraday v1.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | date: 24 | - Wed, 03 Mar 2021 14:09:59 GMT 25 | content-type: 26 | - application/json; charset=utf-8 27 | transfer-encoding: 28 | - chunked 29 | connection: 30 | - keep-alive 31 | vary: 32 | - Accept-Encoding, Accept-Encoding 33 | status: 34 | - 200 OK 35 | x-frame-options: 36 | - SAMEORIGIN 37 | x-xss-protection: 38 | - 1; mode=block 39 | x-content-type-options: 40 | - nosniff 41 | x-download-options: 42 | - noopen 43 | x-permitted-cross-domain-policies: 44 | - none 45 | referrer-policy: 46 | - strict-origin-when-cross-origin 47 | etag: 48 | - W/"40c9400b568f357a5ea27c39820ee12c" 49 | cache-control: 50 | - max-age=0, private, must-revalidate 51 | x-request-id: 52 | - 40488095-438b-443f-bbce-a5f2c9dc3a07 53 | x-protected-by: 54 | - Sqreen 55 | x-runtime: 56 | - '0.047066' 57 | strict-transport-security: 58 | - max-age=15768000 59 | body: 60 | encoding: ASCII-8BIT 61 | string: '{"name":"Example Test Company","currency":"EUR","time_zone":"Europe/Berlin","week_start_on":"sunday"}' 62 | http_version: 63 | recorded_at: Wed, 03 Mar 2021 14:09:59 GMT 64 | recorded_with: VCR 5.1.0 65 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Contact/API_Actions/creates_the_contact_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/contacts 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_23e01538-2c7e-11ee-b2ce-fb986e96e21b","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","email":"contact@example.com"}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 201 19 | message: Created 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Sun, 29 Oct 2023 18:08:50 GMT 27 | content-length: 28 | - '365' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"con_36399f04-7686-11ee-86f6-8727560009c2","customer_uuid":"cus_23e01538-2c7e-11ee-b2ce-fb986e96e21b","customer_external_id":"cus_004","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","position":1,"first_name":null,"last_name":null,"title":null,"email":"contact@example.com","phone":null,"linked_in":null,"twitter":null,"notes":null,"custom":{}}' 34 | http_version: 35 | recorded_at: Sun, 29 Oct 2023 18:08:50 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Contact/API_Actions/destroys_the_contact_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/contacts/con_ab1e60d4-7690-11ee-84d7-f7e55168a5df 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 200 17 | message: OK 18 | headers: 19 | access-control-allow-credentials: 20 | - 'true' 21 | content-type: 22 | - application/json 23 | date: 24 | - Sun, 29 Oct 2023 19:25:28 GMT 25 | content-length: 26 | - '2' 27 | connection: 28 | - keep-alive 29 | body: 30 | encoding: UTF-8 31 | string: "{}" 32 | http_version: 33 | recorded_at: Sun, 29 Oct 2023 19:25:28 GMT 34 | recorded_with: VCR 5.1.0 35 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Contact/API_Actions/merges_contacts_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/contacts/con_36399f04-7686-11ee-86f6-8727560009c2/merge/con_6f0b7208-7690-11ee-8857-9f75f1321afd 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Sun, 29 Oct 2023 19:23:08 GMT 27 | content-length: 28 | - '446' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"con_36399f04-7686-11ee-86f6-8727560009c2","customer_uuid":null,"customer_external_id":"cus_004","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","position":9,"first_name":"Foo","last_name":"Bar","title":"CTO","email":"contact2@example.com","phone":"+9876543210","linked_in":"https://linkedin.com/about","twitter":"https://twitter.com/about","notes":"Heading\\nBody\\nFooter 34 | This contact was merged","custom":{"Toggle":false}}' 35 | http_version: 36 | recorded_at: Sun, 29 Oct 2023 19:23:08 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Contact/API_Actions/retrieves_the_contact_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/contacts/con_36399f04-7686-11ee-86f6-8727560009c2 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Sun, 29 Oct 2023 18:09:23 GMT 27 | content-length: 28 | - '365' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"con_36399f04-7686-11ee-86f6-8727560009c2","customer_uuid":"cus_23e01538-2c7e-11ee-b2ce-fb986e96e21b","customer_external_id":"cus_004","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","position":1,"first_name":null,"last_name":null,"title":null,"email":"contact@example.com","phone":null,"linked_in":null,"twitter":null,"notes":null,"custom":{}}' 34 | http_version: 35 | recorded_at: Sun, 29 Oct 2023 18:09:23 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Contact/API_Actions/updates_the_contact_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: patch 5 | uri: https://api.chartmogul.com/v1/contacts/con_36399f04-7686-11ee-86f6-8727560009c2 6 | body: 7 | encoding: UTF-8 8 | string: '{"position":9,"first_name":"Foo","last_name":"Bar","title":"CTO","email":"contact2@example.com","phone":"+9876543210","linked_in":"https://linkedin.com/about","twitter":"https://twitter.com/about","custom":[{"key":"Toggle","value":false}]}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Sun, 29 Oct 2023 19:09:59 GMT 27 | content-length: 28 | - '460' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"con_36399f04-7686-11ee-86f6-8727560009c2","customer_uuid":"cus_23e01538-2c7e-11ee-b2ce-fb986e96e21b","customer_external_id":"cus_004","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","position":9,"first_name":"Foo","last_name":"Bar","title":"CTO","email":"contact2@example.com","phone":"+9876543210","linked_in":"https://linkedin.com/about","twitter":"https://twitter.com/about","notes":"Heading\\nBody\\nFooter","custom":{"Toggle":false}}' 34 | http_version: 35 | recorded_at: Sun, 29 Oct 2023 19:09:59 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/Customer_Notes/creates_a_note_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customer_notes 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 9 | is a call","author_email":"soeun+staff@chartmogul.com"}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/4.0.1 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 201 20 | message: Created 21 | headers: 22 | access-control-allow-credentials: 23 | - 'true' 24 | content-type: 25 | - application/json 26 | date: 27 | - Fri, 15 Dec 2023 12:25:56 GMT 28 | content-length: 29 | - '312' 30 | connection: 31 | - keep-alive 32 | body: 33 | encoding: UTF-8 34 | string: '{"uuid":"note_18ffc3bc-9b45-11ee-8143-07ca86e5ee10","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 35 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:25:56.950Z","updated_at":"2023-12-15T12:25:56.950Z"}' 36 | recorded_at: Fri, 15 Dec 2023 12:25:56 GMT 37 | recorded_with: VCR 6.2.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/Customer_Notes/lists_the_notes_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customer_notes?customer_uuid=cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 15 Dec 2023 12:26:40 GMT 27 | content-length: 28 | - '451' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"entries":[{"uuid":"note_18ffc3bc-9b45-11ee-8143-07ca86e5ee10","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 34 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:25:56.950Z","updated_at":"2023-12-15T12:25:56.950Z"}],"cursor":"MjAyMy0xMi0xNVQxMjoyNTo1Ni45NTA4MTcwMDBaJm5vdGVfMThmZmMzYmMtOWI0NS0xMWVlLTgxNDMtMDdjYTg2ZTVlZTEw","has_more":false}' 35 | recorded_at: Fri, 15 Dec 2023 12:26:40 GMT 36 | recorded_with: VCR 6.2.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/adds_custom_attributes_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customers/cus_23740208-2c7e-11ee-9ea2-ffd2435982bb/attributes/custom 6 | body: 7 | encoding: UTF-8 8 | string: '{"custom":[{"type":"String","key":"StringKey","value":"String Value"},{"type":"Integer","key":"integer_key","value":1234},{"type":"Timestamp","key":"timestamp_key","value":"2016-01-31 9 | 00:00:00 UTC"},{"type":"Boolean","key":"boolean_key","value":true}]}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/3.3.1 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 200 20 | message: OK 21 | headers: 22 | access-control-allow-credentials: 23 | - 'true' 24 | content-type: 25 | - application/json 26 | date: 27 | - Mon, 30 Oct 2023 00:52:56 GMT 28 | content-length: 29 | - '120' 30 | connection: 31 | - keep-alive 32 | body: 33 | encoding: UTF-8 34 | string: '{"custom":{"StringKey":"String Value","integer_key":1234,"timestamp_key":"2016-01-31T00:00:00.000Z","boolean_key":true}}' 35 | http_version: 36 | recorded_at: Mon, 30 Oct 2023 00:52:56 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/adds_tags_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customers/cus_23740208-2c7e-11ee-9ea2-ffd2435982bb/attributes/tags 6 | body: 7 | encoding: UTF-8 8 | string: '{"tags":["test-tag"]}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Mon, 30 Oct 2023 00:32:14 GMT 27 | content-length: 28 | - '78' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"tags":["auto-churned-delinquent-subscription","merged-customer","test-tag"]}' 34 | http_version: 35 | recorded_at: Mon, 30 Oct 2023 00:32:14 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/creates_a_contact_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/contacts 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_23740208-2c7e-11ee-9ea2-ffd2435982bb","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","email":"new_contact@example.com"}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 201 19 | message: Created 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Mon, 30 Oct 2023 01:16:59 GMT 27 | content-length: 28 | - '369' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"con_066a8eb4-76c2-11ee-8f49-ffeda4a3d8f7","customer_uuid":"cus_23740208-2c7e-11ee-9ea2-ffd2435982bb","customer_external_id":"cus_002","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","position":2,"first_name":null,"last_name":null,"title":null,"email":"new_contact@example.com","phone":null,"linked_in":null,"twitter":null,"notes":null,"custom":{}}' 34 | http_version: 35 | recorded_at: Mon, 30 Oct 2023 01:16:59 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/creates_a_note_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customer_notes 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 9 | is a call"}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/4.0.1 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 201 20 | message: Created 21 | headers: 22 | access-control-allow-credentials: 23 | - 'true' 24 | content-type: 25 | - application/json 26 | date: 27 | - Fri, 15 Dec 2023 12:28:15 GMT 28 | content-length: 29 | - '312' 30 | connection: 31 | - keep-alive 32 | body: 33 | encoding: UTF-8 34 | string: '{"uuid":"note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 35 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:28:15.754Z","updated_at":"2023-12-15T12:28:15.754Z"}' 36 | recorded_at: Fri, 15 Dec 2023 12:28:15 GMT 37 | recorded_with: VCR 6.2.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/creates_a_opportunity_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/opportunities 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_4e49211a-df7b-11ee-8949-df3c4571686f","owner":"kamil+pavlicko@chartmogul.com","pipeline":"New 9 | Business","pipeline_stage":"Discovery","estimated_close_date":"2024-03-30","currency":"USD","amount_in_cents":200000,"type":"one-time","forecast_category":"best_case","win_likelihood":30,"custom":[{"key":"from_campaign","value":true}]}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/4.2.0 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 201 20 | message: Created 21 | headers: 22 | date: 23 | - Mon, 18 Mar 2024 17:12:39 GMT 24 | content-type: 25 | - application/json 26 | content-length: 27 | - '461' 28 | connection: 29 | - keep-alive 30 | access-control-allow-credentials: 31 | - 'true' 32 | body: 33 | encoding: UTF-8 34 | string: '{"uuid":"b94b55b2-e54a-11ee-97ac-7f3fb38fdeda","customer_uuid":"cus_4e49211a-df7b-11ee-8949-df3c4571686f","owner":"kamil+pavlicko@chartmogul.com","pipeline":"New 35 | Business","pipeline_stage":"Discovery","estimated_close_date":"2024-03-30","currency":"USD","amount_in_cents":200000,"type":"one-time","forecast_category":"best_case","win_likelihood":30,"custom":{"from_campaign":true},"created_at":"2024-03-18T17:12:39.411Z","updated_at":"2024-03-18T17:12:39.411Z"}' 36 | http_version: 37 | recorded_at: Mon, 18 Mar 2024 17:12:39 GMT 38 | recorded_with: VCR 5.1.0 39 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/creates_a_task_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/tasks 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64","task_details":"This 9 | is some task details text.","assignee":"keith+test1@chartmogul.com","due_date":"2025-04-30T00:00:00Z"}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/4.6.0 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 201 20 | message: Created 21 | headers: 22 | date: 23 | - Fri, 25 Apr 2025 02:03:03 GMT 24 | content-type: 25 | - application/json 26 | content-length: 27 | - '338' 28 | connection: 29 | - keep-alive 30 | access-control-allow-credentials: 31 | - 'true' 32 | body: 33 | encoding: UTF-8 34 | string: '{"task_uuid":"6bedc144-2179-11f0-9074-47237186e386","customer_uuid":"cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64","task_details":"This 35 | is some task details text.","assignee":"keith+test1@chartmogul.com","due_date":"2025-04-30T00:00:00.000Z","completed_at":null,"created_at":"2025-04-25T02:03:03.396Z","updated_at":"2025-04-25T02:03:03.396Z"}' 36 | recorded_at: Fri, 25 Apr 2025 02:03:03 GMT 37 | recorded_with: VCR 6.3.1 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/creates_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customers 6 | body: 7 | encoding: UTF-8 8 | string: '{"external_id":"cus_007","name":"New Customer","email":"new_customer@example.com","city":"Berlin","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","owner":"bruno+chartmogultest@chartmogul.com"}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 201 19 | message: Created 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Sun, 29 Oct 2023 21:46:40 GMT 27 | content-length: 28 | - '845' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: 34 | '{"id":133149145,"uuid":"cus_a4680a9c-76a4-11ee-83ab-d3b9aabc7f00","external_id":"cus_007","name":"New Customer","email":"new_customer@example.com","status":"New Lead","customer-since":null,"attributes":{"custom":{},"clearbit":{},"stripe":{},"tags":[]},"data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","data_source_uuids":["ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46"],"external_ids":["cus_007"],"company":"","country":null,"state":null,"city":"Berlin","zip":null,"lead_created_at":null,"free_trial_started_at":null,"address":{"country":null,"state":null,"city":"Berlin","address_zip":null},"mrr":0,"arr":0,"billing-system-url":null,"chartmogul-url":"https://app.chartmogul.com/#/customers/133149145-New_Customer","billing-system-type":"Google Sheets","currency":"EUR","currency-sign":"€","owner":"bruno+chartmogultest@chartmogul.com","website_url":"https://chartmogul.com"}' 35 | http_version: 36 | recorded_at: Sun, 29 Oct 2023 21:46:40 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/destroys_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/customers/cus_a4680a9c-76a4-11ee-83ab-d3b9aabc7f00 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 204 17 | message: No Content 18 | headers: 19 | access-control-allow-credentials: 20 | - 'true' 21 | date: 22 | - Sun, 29 Oct 2023 23:49:40 GMT 23 | connection: 24 | - keep-alive 25 | body: 26 | encoding: UTF-8 27 | string: '' 28 | http_version: 29 | recorded_at: Sun, 29 Oct 2023 23:49:40 GMT 30 | recorded_with: VCR 5.1.0 31 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/lists_the_contacts_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/contacts?customer_uuid=cus_23740208-2c7e-11ee-9ea2-ffd2435982bb 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Mon, 30 Oct 2023 01:16:10 GMT 27 | content-length: 28 | - '529' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"entries":[{"uuid":"con_a4fb9b64-76c1-11ee-9ff8-cb0ba2384523","customer_uuid":"cus_23740208-2c7e-11ee-9ea2-ffd2435982bb","customer_external_id":"cus_002","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","position":1,"first_name":"Test","last_name":"Contact","title":null,"email":"contact_123@example.com","phone":null,"linked_in":null,"twitter":null,"notes":null,"custom":{"Toggle":false}}],"cursor":"MjAyMy0xMC0zMFQwMToxNDoxNi4zNzIzODUwMDBaJmNvbl9hNGZiOWI2NC03NmMxLTExZWUtOWZmOC1jYjBiYTIzODQ1MjM=","has_more":false}' 34 | http_version: 35 | recorded_at: Mon, 30 Oct 2023 01:16:10 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/lists_the_notes_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customer_notes?customer_uuid=cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 15 Dec 2023 12:28:15 GMT 27 | content-length: 28 | - '451' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"entries":[{"uuid":"note_18ffc3bc-9b45-11ee-8143-07ca86e5ee10","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 34 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:25:56.950Z","updated_at":"2023-12-15T12:25:56.950Z"}],"cursor":"MjAyMy0xMi0xNVQxMjoyNTo1Ni45NTA4MTcwMDBaJm5vdGVfMThmZmMzYmMtOWI0NS0xMWVlLTgxNDMtMDdjYTg2ZTVlZTEw","has_more":false}' 35 | recorded_at: Fri, 15 Dec 2023 12:28:15 GMT 36 | recorded_with: VCR 6.2.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/lists_the_opportunities_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/opportunities?customer_uuid=cus_4e49211a-df7b-11ee-8949-df3c4571686f 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.2.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | date: 22 | - Mon, 18 Mar 2024 17:13:44 GMT 23 | content-type: 24 | - application/json 25 | content-length: 26 | - '597' 27 | connection: 28 | - keep-alive 29 | access-control-allow-credentials: 30 | - 'true' 31 | body: 32 | encoding: UTF-8 33 | string: '{"entries":[{"uuid":"5bee0a42-df7b-11ee-9506-cb238e9b1218","customer_uuid":"cus_4e49211a-df7b-11ee-8949-df3c4571686f","owner":"kamil+pavlicko@chartmogul.com","pipeline":"New 34 | Business","pipeline_stage":"Evaluation","estimated_close_date":"2024-03-28","currency":"USD","amount_in_cents":50000,"type":"recurring","forecast_category":"best_case","win_likelihood":80,"custom":{"from_campaign":true},"created_at":"2024-03-11T07:45:41.133Z","updated_at":"2024-03-11T07:45:41.133Z"}],"cursor":"MjAyNC0wMy0xMVQwNzo0NTo0MS4xMzM4NjEwMDBaJjViZWUwYTQyLWRmN2ItMTFlZS05NTA2LWNiMjM4ZTliMTIxOA==","has_more":false}' 35 | http_version: 36 | recorded_at: Mon, 18 Mar 2024 17:13:44 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/lists_the_subscriptions_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/import/customers/cus_23740208-2c7e-11ee-9ea2-ffd2435982bb/subscriptions 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | cache-control: 24 | - max-age=0, private, must-revalidate 25 | content-type: 26 | - application/json; charset=utf-8 27 | date: 28 | - Mon, 30 Oct 2023 01:20:07 GMT 29 | etag: 30 | - W/"4768a84541be8c93daad8004bb61b017" 31 | referrer-policy: 32 | - strict-origin-when-cross-origin 33 | x-content-type-options: 34 | - nosniff 35 | x-download-options: 36 | - noopen 37 | x-frame-options: 38 | - DENY 39 | x-permitted-cross-domain-policies: 40 | - none 41 | x-request-id: 42 | - f9d6070f5e6269168dc2c59c4bc8897a 43 | x-runtime: 44 | - '0.058804' 45 | x-xss-protection: 46 | - 1; mode=block 47 | content-length: 48 | - '692' 49 | connection: 50 | - keep-alive 51 | body: 52 | encoding: UTF-8 53 | string: '{"customer_uuid":"cus_23740208-2c7e-11ee-9ea2-ffd2435982bb","subscriptions":[{"external_id":"test_cus_sub_ext_id2","uuid":"sub_dd7ef9f2-1f60-4e36-bd8d-af8b20ad8f4f","cancellation_dates":[],"plan_uuid":"pl_ae02e740-34c6-013c-d52b-563f32a3b7a1","data_source_uuid":"ds_c0d412aa-5298-11ee-bb1f-332cea9687ed"},{"external_id":"test_cus_sub_ext_id1","uuid":"sub_6bb176ae-99a4-481d-8f48-1abe09a7fbfc","cancellation_dates":[],"plan_uuid":"pl_adcdb9f0-34c6-013c-82df-0230272d2d1f","data_source_uuid":"ds_c0d412aa-5298-11ee-bb1f-332cea9687ed"}],"current_page":1,"total_pages":1,"cursor":"MjAyMy0wOS0xNFQwMDo1MDo1My4zODY0OTgwMDBaJnN1Yl82YmIxNzZhZS05OWE0LTQ4MWQtOGY0OC0xYWJlMDlhN2ZiZmM=","has_more":false}' 54 | http_version: 55 | recorded_at: Mon, 30 Oct 2023 01:20:07 GMT 56 | recorded_with: VCR 5.1.0 57 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/lists_the_tasks_belonging_to_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/tasks?customer_uuid=cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.6.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | date: 22 | - Fri, 25 Apr 2025 02:03:02 GMT 23 | content-type: 24 | - application/json 25 | content-length: 26 | - '473' 27 | connection: 28 | - keep-alive 29 | access-control-allow-credentials: 30 | - 'true' 31 | body: 32 | encoding: UTF-8 33 | string: '{"entries":[{"task_uuid":"275bc0bc-2179-11f0-897b-f3e70d2aa58d","customer_uuid":"cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64","task_details":"This 34 | is some task details text.","assignee":"keith+test1@chartmogul.com","due_date":"2025-04-30T00:00:00.000Z","completed_at":null,"created_at":"2025-04-25T02:01:08.353Z","updated_at":"2025-04-25T02:01:08.353Z"}],"cursor":"MjAyNS0wNC0yNVQwMjowMTowOC4zNTM0NDEwMDBaJjI3NWJjMGJjLTIxNzktMTFmMC04OTdiLWYzZTcwZDJhYTU4ZA==","has_more":false}' 35 | recorded_at: Fri, 25 Apr 2025 02:03:02 GMT 36 | recorded_with: VCR 6.3.1 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/merges_customers_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customers/merges 6 | body: 7 | encoding: UTF-8 8 | string: '{"from":{"customer_uuid":"cus_c10aa086-5298-11ee-82da-ebac6f7a03c3"},"into":{"customer_uuid":"cus_23740208-2c7e-11ee-9ea2-ffd2435982bb"}}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 202 19 | message: Accepted 20 | headers: 21 | content-type: 22 | - application/json 23 | date: 24 | - Sun, 29 Oct 2023 23:57:02 GMT 25 | content-length: 26 | - '2' 27 | connection: 28 | - keep-alive 29 | body: 30 | encoding: UTF-8 31 | string: "{}" 32 | http_version: 33 | recorded_at: Sun, 29 Oct 2023 23:57:02 GMT 34 | recorded_with: VCR 5.1.0 35 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/raises_a_HTTP_404_if_searching_for_customers_does_not_find_any.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customers/search?email=no%40email.com 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 404 19 | message: Not Found 20 | headers: 21 | content-type: 22 | - application/json 23 | date: 24 | - Mon, 30 Oct 2023 00:28:18 GMT 25 | content-length: 26 | - '94' 27 | connection: 28 | - Close 29 | body: 30 | encoding: UTF-8 31 | string: '{"code":404,"message":"Can''t find any customers with email: \"no@email.com\"","param":"email"}' 32 | http_version: 33 | recorded_at: Mon, 30 Oct 2023 00:28:18 GMT 34 | recorded_with: VCR 5.1.0 35 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/removes_custom_attributes_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/customers/cus_23740208-2c7e-11ee-9ea2-ffd2435982bb/attributes/custom 6 | body: 7 | encoding: UTF-8 8 | string: '{"custom":["StringKey","integer_key","timestamp_key","boolean_key","Toggle"]}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 204 19 | message: No Content 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | date: 24 | - Mon, 30 Oct 2023 00:52:22 GMT 25 | connection: 26 | - keep-alive 27 | body: 28 | encoding: UTF-8 29 | string: '' 30 | http_version: 31 | recorded_at: Mon, 30 Oct 2023 00:52:23 GMT 32 | recorded_with: VCR 5.1.0 33 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/removes_tags_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/customers/cus_23740208-2c7e-11ee-9ea2-ffd2435982bb/attributes/tags 6 | body: 7 | encoding: UTF-8 8 | string: '{"tags":["test-tag"]}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Mon, 30 Oct 2023 00:36:11 GMT 27 | content-length: 28 | - '67' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"tags":["auto-churned-delinquent-subscription","merged-customer"]}' 34 | http_version: 35 | recorded_at: Mon, 30 Oct 2023 00:36:11 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/retrieves_the_customer_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customers/cus_23e01538-2c7e-11ee-b2ce-fb986e96e21b 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Sun, 29 Oct 2023 21:45:25 GMT 27 | content-length: 28 | - '913' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: 34 | '{"id":114167452,"uuid":"cus_23e01538-2c7e-11ee-b2ce-fb986e96e21b","external_id":"cus_004","name":"Richard Hendricks","email":"customer@example.com","status":"New Lead","customer-since":null,"attributes":{"custom":{},"clearbit":{},"stripe":{},"tags":["managed"]},"data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","data_source_uuids":["ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46"],"external_ids":["cus_004"],"company":"Pied Piper","country":"US","state":"CA","city":"San Francisco","zip":"12345","lead_created_at":"2015-11-01T00:00:00.000Z","free_trial_started_at":"2015-11-07T01:20:00.000Z","address":{"country":"United States","state":"California","city":"San Francisco","address_zip":"12345"},"mrr":0,"arr":0,"billing-system-url":null,"chartmogul-url":"https://app.chartmogul.com/#/customers/114167452-Pied_Piper","billing-system-type":"Google Sheets","currency":"EUR","currency-sign":"€","owner":null,"website_url":"https://chartmogul.com"}' 35 | http_version: 36 | recorded_at: Sun, 29 Oct 2023 21:45:25 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/unmerges_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customers/unmerges 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_cd9e5f29-6299-40e5-b343-0bd1ed228b4f","data_source_uuid":"ds_788ec6ae-dd51-11ee-bd46-a3ec952dc041","external_id":"cus_O075O8NH0LrtG8","move_to_new_customer":[]}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.3.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 202 19 | message: Accepted 20 | headers: 21 | date: 22 | - Wed, 16 Oct 2024 15:33:35 GMT 23 | content-type: 24 | - application/json 25 | content-length: 26 | - '2' 27 | connection: 28 | - keep-alive 29 | body: 30 | encoding: UTF-8 31 | string: "{}" 32 | http_version: 33 | recorded_at: Wed, 16 Oct 2024 15:33:35 GMT 34 | recorded_with: VCR 5.1.0 35 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/updates_custom_attributes_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://api.chartmogul.com/v1/customers/cus_23740208-2c7e-11ee-9ea2-ffd2435982bb/attributes/custom 6 | body: 7 | encoding: UTF-8 8 | string: '{"custom":{"StringKey":"Another String Value","integer_key":5678,"timestamp_key":"2016-02-01 9 | 00:00:00 UTC","boolean_key":false,"Toggle":false}}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/3.3.1 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 200 20 | message: OK 21 | headers: 22 | access-control-allow-credentials: 23 | - 'true' 24 | content-type: 25 | - application/json 26 | date: 27 | - Mon, 30 Oct 2023 00:47:16 GMT 28 | content-length: 29 | - '144' 30 | connection: 31 | - keep-alive 32 | body: 33 | encoding: UTF-8 34 | string: '{"custom":{"Toggle":false,"StringKey":"Another String Value","integer_key":5678,"timestamp_key":"2016-02-01T00:00:00.000Z","boolean_key":false}}' 35 | http_version: 36 | recorded_at: Mon, 30 Oct 2023 00:47:16 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/API_Actions/updates_customer_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: patch 5 | uri: https://api.chartmogul.com/v1/customers/cus_a4680a9c-76a4-11ee-83ab-d3b9aabc7f00 6 | body: 7 | encoding: UTF-8 8 | string: '{"attributes":{"custom":{"Toggle":false}},"name":"Test Customer","email":"customer_test@example.com","company":"Curry 9 | 42"}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/3.3.1 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 200 20 | message: OK 21 | headers: 22 | access-control-allow-credentials: 23 | - 'true' 24 | content-type: 25 | - application/json 26 | date: 27 | - Sun, 29 Oct 2023 23:40:02 GMT 28 | content-length: 29 | - '920' 30 | connection: 31 | - keep-alive 32 | body: 33 | encoding: UTF-8 34 | string: 35 | '{"id":133149145,"uuid":"cus_a4680a9c-76a4-11ee-83ab-d3b9aabc7f00","external_id":"cus_007","name":"Test Customer","email":"customer_test@example.com","status":"New Lead","customer-since":null,"attributes":{"custom":{"Toggle":true},"clearbit":{},"stripe":{},"tags":["wurst"]},"data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","data_source_uuids":["ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46"],"external_ids":["cus_007"],"company":"Curry 42","country":"DE","state":null,"city":"Berlin","zip":null,"lead_created_at":"2016-01-01T14:30:00.000Z","free_trial_started_at":"2016-02-02T22:40:00.000Z","address":{"country":"Germany","state":null,"city":"Berlin","address_zip":null},"mrr":0,"arr":0,"billing-system-url":null,"chartmogul-url":"https://app.chartmogul.com/#/customers/133149145-Curry_42","billing-system-type":"Google Sheets","currency":"EUR","currency-sign":"€","owner":"bruno+chartmogultest@chartmogul.com","website_url":"https://example.co"}' 36 | http_version: 37 | recorded_at: Sun, 29 Oct 2023 23:40:02 GMT 38 | recorded_with: VCR 5.1.0 39 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Customer/_find_by_external_id/returns_nil_if_customer_does_not_exist.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customers?external_id=unknown 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Sun, 29 Oct 2023 21:14:11 GMT 27 | content-length: 28 | - '102' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"entries":[],"current_page":1,"total_pages":1,"has_more":false,"per_page":200,"page":1,"cursor":null}' 34 | http_version: 35 | recorded_at: Sun, 29 Oct 2023 21:14:11 GMT 36 | recorded_with: VCR 5.1.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_CustomerInvoices/API_Actions/destroys_all_customer_invoices_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/data_sources/ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46/customers/cus_23551596-2c7e-11ee-9ea1-2bfe193640c0/invoices 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 204 17 | message: No Content 18 | headers: 19 | access-control-allow-credentials: 20 | - 'true' 21 | cache-control: 22 | - no-cache 23 | date: 24 | - Mon, 30 Oct 2023 02:54:04 GMT 25 | referrer-policy: 26 | - strict-origin-when-cross-origin 27 | x-content-type-options: 28 | - nosniff 29 | x-download-options: 30 | - noopen 31 | x-frame-options: 32 | - DENY 33 | x-permitted-cross-domain-policies: 34 | - none 35 | x-request-id: 36 | - f45f6d020724a1cd21cb11de8bdb4b01 37 | x-runtime: 38 | - '0.124159' 39 | x-xss-protection: 40 | - 1; mode=block 41 | connection: 42 | - keep-alive 43 | body: 44 | encoding: UTF-8 45 | string: '' 46 | http_version: 47 | recorded_at: Mon, 30 Oct 2023 02:54:04 GMT 48 | recorded_with: VCR 5.1.0 49 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_DataSource/API_Interactions/correctly_raises_errors_on_404.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/data_sources/1234-a-uuid-that-doesnt-exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.1 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 404 17 | message: 18 | headers: 19 | server: 20 | - nginx/1.9.10 21 | date: 22 | - Sun, 05 Jun 2016 17:05:01 GMT 23 | content-type: 24 | - application/json; charset=utf-8 25 | transfer-encoding: 26 | - chunked 27 | connection: 28 | - close 29 | x-frame-options: 30 | - SAMEORIGIN 31 | x-xss-protection: 32 | - 1; mode=block 33 | x-content-type-options: 34 | - nosniff 35 | cache-control: 36 | - no-cache 37 | x-request-id: 38 | - f12d6c48-58f5-4ccd-b398-ff4e7acb93bc 39 | x-runtime: 40 | - '0.010826' 41 | body: 42 | encoding: UTF-8 43 | string: '{"error":"Data source not found"}' 44 | http_version: 45 | recorded_at: Sun, 05 Jun 2016 17:05:01 GMT 46 | recorded_with: VCR 3.0.3 47 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_DataSource/API_Interactions/correctly_raises_errors_on_422.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/data_sources 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":null}' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 422 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Sun, 05 Jun 2016 17:04:50 GMT 25 | content-type: 26 | - application/json; charset=utf-8 27 | transfer-encoding: 28 | - chunked 29 | connection: 30 | - close 31 | x-frame-options: 32 | - SAMEORIGIN 33 | x-xss-protection: 34 | - 1; mode=block 35 | x-content-type-options: 36 | - nosniff 37 | cache-control: 38 | - no-cache 39 | x-request-id: 40 | - 76a25073-4c20-49fb-83b2-bbad2c361b0d 41 | x-runtime: 42 | - '0.009928' 43 | body: 44 | encoding: UTF-8 45 | string: '{"errors":{"name":"A name is required for each data source."}}' 46 | http_version: 47 | recorded_at: Sun, 05 Jun 2016 17:04:50 GMT 48 | recorded_with: VCR 3.0.3 49 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Invoice/API_Actions/destroys_the_invoice_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/invoices/inv_6fab6457-7b27-44c3-99ae-815923a22c7c 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 204 17 | message: No Content 18 | headers: 19 | access-control-allow-credentials: 20 | - 'true' 21 | cache-control: 22 | - no-cache 23 | date: 24 | - Mon, 30 Oct 2023 03:24:00 GMT 25 | referrer-policy: 26 | - strict-origin-when-cross-origin 27 | x-content-type-options: 28 | - nosniff 29 | x-download-options: 30 | - noopen 31 | x-frame-options: 32 | - DENY 33 | x-permitted-cross-domain-policies: 34 | - none 35 | x-request-id: 36 | - e48130466af0f2cda07821194a24d0ec 37 | x-runtime: 38 | - '0.092448' 39 | x-xss-protection: 40 | - 1; mode=block 41 | connection: 42 | - keep-alive 43 | body: 44 | encoding: UTF-8 45 | string: '' 46 | http_version: 47 | recorded_at: Mon, 30 Oct 2023 03:24:00 GMT 48 | recorded_with: VCR 5.1.0 49 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_ARPA/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/arpa?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:46 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '1165' 29 | connection: 30 | - close 31 | vary: 32 | - Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: UTF-8 39 | string: '{"entries":[{"date":"2015-01-01","arpa":0},{"date":"2015-01-02","arpa":0},{"date":"2015-01-03","arpa":0},{"date":"2015-01-04","arpa":0},{"date":"2015-01-05","arpa":0},{"date":"2015-01-06","arpa":0},{"date":"2015-01-07","arpa":0},{"date":"2015-01-08","arpa":0},{"date":"2015-01-09","arpa":11371},{"date":"2015-01-10","arpa":11371},{"date":"2015-01-11","arpa":11371},{"date":"2015-01-12","arpa":16092},{"date":"2015-01-13","arpa":16092},{"date":"2015-01-14","arpa":13963},{"date":"2015-01-15","arpa":13963},{"date":"2015-01-16","arpa":13963},{"date":"2015-01-17","arpa":13963},{"date":"2015-01-18","arpa":13171},{"date":"2015-01-19","arpa":13171},{"date":"2015-01-20","arpa":13171},{"date":"2015-01-21","arpa":13171},{"date":"2015-01-22","arpa":10996},{"date":"2015-01-23","arpa":13474},{"date":"2015-01-24","arpa":13474},{"date":"2015-01-25","arpa":13474},{"date":"2015-01-26","arpa":0},{"date":"2015-01-27","arpa":10000},{"date":"2015-01-28","arpa":10000},{"date":"2015-01-29","arpa":3436},{"date":"2015-01-30","arpa":15620},{"date":"2015-01-31","arpa":15620},{"date":"2015-02-01","arpa":15620}],"summary":{"current":10843,"previous":10843,"percentage-change":0.0}}' 40 | http_version: 41 | recorded_at: Fri, 01 Jul 2016 14:47:46 GMT 42 | recorded_with: VCR 3.0.3 43 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_ARPA/behaves_like_Metrics_API_resource/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/arpa?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:45 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '1165' 29 | connection: 30 | - close 31 | vary: 32 | - Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: UTF-8 39 | string: '{"entries":[{"date":"2022-04-30","arpa":656170,"percentage-change":0.0},{"date":"2022-05-31","arpa":1113423,"percentage-change":69.69}],"summary":{"current":1102906,"previous":1111529,"percentage-change":-0.78}}' 40 | http_version: 41 | recorded_at: Fri, 01 Jul 2016 14:47:45 GMT 42 | recorded_with: VCR 3.0.3 43 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_ARR/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/arr?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:45 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '1158' 29 | connection: 30 | - close 31 | vary: 32 | - Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: UTF-8 39 | string: '{"entries":[{"date":"2015-01-01","arr":0},{"date":"2015-01-02","arr":0},{"date":"2015-01-03","arr":0},{"date":"2015-01-04","arr":0},{"date":"2015-01-05","arr":0},{"date":"2015-01-06","arr":0},{"date":"2015-01-07","arr":0},{"date":"2015-01-08","arr":0},{"date":"2015-01-09","arr":409344},{"date":"2015-01-10","arr":409344},{"date":"2015-01-11","arr":409344},{"date":"2015-01-12","arr":772392},{"date":"2015-01-13","arr":772392},{"date":"2015-01-14","arr":670236},{"date":"2015-01-15","arr":670236},{"date":"2015-01-16","arr":670236},{"date":"2015-01-17","arr":670236},{"date":"2015-01-18","arr":790236},{"date":"2015-01-19","arr":790236},{"date":"2015-01-20","arr":790236},{"date":"2015-01-21","arr":790236},{"date":"2015-01-22","arr":659784},{"date":"2015-01-23","arr":646740},{"date":"2015-01-24","arr":646740},{"date":"2015-01-25","arr":646740},{"date":"2015-01-26","arr":0},{"date":"2015-01-27","arr":120000},{"date":"2015-01-28","arr":120000},{"date":"2015-01-29","arr":82452},{"date":"2015-01-30","arr":187440},{"date":"2015-01-31","arr":187440},{"date":"2015-02-01","arr":187440}],"summary":{"current":520452,"previous":520452,"percentage-change":0.0}}' 40 | http_version: 41 | recorded_at: Fri, 01 Jul 2016 14:47:45 GMT 42 | recorded_with: VCR 3.0.3 43 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_ARR/behaves_like_Metrics_API_resource/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/arr?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:45 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '1158' 29 | connection: 30 | - close 31 | vary: 32 | - Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: UTF-8 39 | string: '{"entries":[{"date":"2022-04-30","arr":4606319628,"percentage-change":0.0},{"date":"2022-05-31","arr":8043370848,"percentage-change":74.62}],"summary":{"current":8046802440,"previous":8043027072,"percentage-change":0.05}}' 40 | http_version: 41 | recorded_at: Fri, 01 Jul 2016 14:47:45 GMT 42 | recorded_with: VCR 3.0.3 43 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_ASP/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/asp?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:44 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '138' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2015-01-31","asp":12731},{"date":"2015-02-01","asp":0}],"summary":{"current":0,"previous":0,"percentage-change":0.0}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 14:47:44 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_ASP/behaves_like_Metrics_API_resource/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/asp?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:44 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '138' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2022-04-30","asp":46107,"percentage-change":0.0},{"date":"2022-05-31","asp":22035,"percentage-change":-52.21}],"summary":{"current":18160,"previous":23087,"percentage-change":-21.34}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 14:47:44 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_ActivitiesExport/get_activities_export.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/activities_export/44037b8f-4a89-4fc6-8114-2288c71a9518 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v1.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | date: 24 | - Fri, 09 Jul 2021 14:06:07 GMT 25 | content-type: 26 | - application/json 27 | transfer-encoding: 28 | - chunked 29 | connection: 30 | - keep-alive 31 | vary: 32 | - Accept-Encoding, Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: ASCII-8BIT 39 | string: '{"id":"44037b8f-4a89-4fc6-8114-2288c71a9518","status":"succeeded","file_url":"https://chartmogul-customer-export.s3.eu-west-1.amazonaws.com/activities-acme-corp-062ea48c-5d74-46dd-bd60-23206cdc241a.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=123%2Feu-west-1%2Fs3%2Faws4_request\u0026X-Amz-Date=20210709T135547Z\u0026X-Amz-Expires=604800\u0026X-Amz-SignedHeaders=host\u0026X-Amz-Signature=abc","params":{"kind":"activities","params":{"end_date":"2020-12-31 40 | 00:00:00 +0000","start_date":"2020-01-01 00:00:00 +0000","activity_type":"new_biz"}},"expires_at":"2021-07-16T13:55:47+00:00","created_at":"2021-07-09T13:55:44+00:00"}' 41 | http_version: 42 | recorded_at: Fri, 09 Jul 2021 14:06:07 GMT 43 | recorded_with: VCR 5.1.0 44 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/activities 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v1.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 401 19 | message: Unauthorized 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | date: 24 | - Fri, 18 Jun 2021 10:37:37 GMT 25 | content-type: 26 | - application/json 27 | transfer-encoding: 28 | - chunked 29 | connection: 30 | - keep-alive 31 | status: 32 | - 401 Unauthorized 33 | body: 34 | encoding: UTF-8 35 | string: '{"code":401,"message":"No valid API key provided","param":null}' 36 | recorded_at: Fri, 18 Jun 2021 10:37:37 GMT 37 | recorded_with: VCR 6.0.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity/behaves_like_PageableWithAnchor/should_be_pageable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/activities?per_page=2 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-encoding: 24 | - gzip 25 | content-type: 26 | - application/json 27 | date: 28 | - Fri, 27 Oct 2023 08:58:22 GMT 29 | vary: 30 | - Accept-Encoding 31 | content-length: 32 | - '478' 33 | connection: 34 | - keep-alive 35 | body: 36 | encoding: ASCII-8BIT 37 | string: '{"entries":[{"description":"purchased the Test Plan1 plan","activity-mrr-movement":4004,"activity-mrr":4004,"activity-arr":48048,"date":"2016-01-01T12:00:00+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"test_cus_sub_ext_id1","plan-external-id":"adcdb9f0-34c6-013c-82df-0230272d2d1f","customer-name":"Test 38 | Customer","customer-uuid":"cus_c10aa086-5298-11ee-82da-ebac6f7a03c3","customer-external-id":"test_cus_ext_id","billing-connector-uuid":"ds_c0d412aa-5298-11ee-bb1f-332cea9687ed","uuid":"561814e1-d7d3-42f3-8936-4689ec0fbb74"},{"description":"purchased 39 | the Test Plan2 plan","activity-mrr-movement":4004,"activity-mrr":8009,"activity-arr":96108,"date":"2016-01-01T12:00:00+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"test_cus_sub_ext_id2","plan-external-id":"ae02e740-34c6-013c-d52b-563f32a3b7a1","customer-name":"Test 40 | Customer","customer-uuid":"cus_c10aa086-5298-11ee-82da-ebac6f7a03c3","customer-external-id":"test_cus_ext_id","billing-connector-uuid":"ds_c0d412aa-5298-11ee-bb1f-332cea9687ed","uuid":"ff76d95f-0536-4b2e-85cf-cc49a42c8757"}],"has_more":true,"per_page":2,"cursor":"d868a892-37c7-45e3-ae84-e693181d2344"}' 41 | http_version: 42 | recorded_at: Fri, 27 Oct 2023 08:58:22 GMT 43 | recorded_with: VCR 5.1.0 44 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity/should_have_Activity_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/activities?per_page=2 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-encoding: 24 | - gzip 25 | content-type: 26 | - application/json 27 | date: 28 | - Fri, 27 Oct 2023 08:58:22 GMT 29 | vary: 30 | - Accept-Encoding 31 | content-length: 32 | - '478' 33 | connection: 34 | - keep-alive 35 | body: 36 | encoding: ASCII-8BIT 37 | string: '{"entries":[{"description":"purchased the Test Plan1 plan","activity-mrr-movement":4004,"activity-mrr":4004,"activity-arr":48048,"date":"2016-01-01T12:00:00+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"test_cus_sub_ext_id1","plan-external-id":"adcdb9f0-34c6-013c-82df-0230272d2d1f","customer-name":"Test 38 | Customer","customer-uuid":"cus_c10aa086-5298-11ee-82da-ebac6f7a03c3","customer-external-id":"test_cus_ext_id","billing-connector-uuid":"ds_c0d412aa-5298-11ee-bb1f-332cea9687ed","uuid":"561814e1-d7d3-42f3-8936-4689ec0fbb74"},{"description":"purchased 39 | the Test Plan2 plan","activity-mrr-movement":4004,"activity-mrr":8009,"activity-arr":96108,"date":"2016-01-01T12:00:00+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"test_cus_sub_ext_id2","plan-external-id":"ae02e740-34c6-013c-d52b-563f32a3b7a1","customer-name":"Test 40 | Customer","customer-uuid":"cus_c10aa086-5298-11ee-82da-ebac6f7a03c3","customer-external-id":"test_cus_ext_id","billing-connector-uuid":"ds_c0d412aa-5298-11ee-bb1f-332cea9687ed","uuid":"ff76d95f-0536-4b2e-85cf-cc49a42c8757"}],"has_more":true,"per_page":2,"cursor":"d868a892-37c7-45e3-ae84-e693181d2344"}' 41 | http_version: 42 | recorded_at: Fri, 27 Oct 2023 08:58:22 GMT 43 | recorded_with: VCR 5.1.0 44 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerChurnRate/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/customer-churn-rate?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:50 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '170' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2015-01-31","customer-churn-rate":0.0},{"date":"2015-02-01","customer-churn-rate":0.0}],"summary":{"current":0,"previous":0,"percentage-change":0.0}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 14:47:50 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerChurnRate/behaves_like_Metrics_API_resource/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/customer-churn-rate?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:49 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '170' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2022-04-30","customer-churn-rate":0.56,"percentage-change":0.0},{"date":"2022-05-31","customer-churn-rate":1.71,"percentage-change":205.36}],"summary":{"current":1.71,"previous":0.56,"percentage-change":205.36}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 14:47:49 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerCount/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/customer-count?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:51 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '1226' 29 | connection: 30 | - close 31 | vary: 32 | - Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: UTF-8 39 | string: '{"entries":[{"date":"2015-01-01","customers":0},{"date":"2015-01-02","customers":0},{"date":"2015-01-03","customers":0},{"date":"2015-01-04","customers":0},{"date":"2015-01-05","customers":0},{"date":"2015-01-06","customers":0},{"date":"2015-01-07","customers":0},{"date":"2015-01-08","customers":0},{"date":"2015-01-09","customers":3},{"date":"2015-01-10","customers":3},{"date":"2015-01-11","customers":3},{"date":"2015-01-12","customers":4},{"date":"2015-01-13","customers":4},{"date":"2015-01-14","customers":4},{"date":"2015-01-15","customers":4},{"date":"2015-01-16","customers":4},{"date":"2015-01-17","customers":4},{"date":"2015-01-18","customers":5},{"date":"2015-01-19","customers":5},{"date":"2015-01-20","customers":5},{"date":"2015-01-21","customers":5},{"date":"2015-01-22","customers":4},{"date":"2015-01-23","customers":4},{"date":"2015-01-24","customers":4},{"date":"2015-01-25","customers":4},{"date":"2015-01-26","customers":0},{"date":"2015-01-27","customers":1},{"date":"2015-01-28","customers":1},{"date":"2015-01-29","customers":1},{"date":"2015-01-30","customers":1},{"date":"2015-01-31","customers":1},{"date":"2015-02-01","customers":1}],"summary":{"current":4,"previous":4,"percentage-change":0.0}}' 40 | http_version: 41 | recorded_at: Fri, 01 Jul 2016 14:47:51 GMT 42 | recorded_with: VCR 3.0.3 43 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerCount/behaves_like_Metrics_API_resource/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/customer-count?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:50 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '1226' 29 | connection: 30 | - close 31 | vary: 32 | - Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: UTF-8 39 | string: '{"entries":[{"date":"2022-04-30","customers":585,"percentage-change":0.0},{"date":"2022-05-31","customers":602,"percentage-change":2.91}],"summary":{"current":608,"previous":603,"percentage-change":0.83}}' 40 | http_version: 41 | recorded_at: Fri, 01 Jul 2016 14:47:50 GMT 42 | recorded_with: VCR 3.0.3 43 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_Customers_Activity/behaves_like_Pageable/should_be_pageable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customers/cus_23551596-2c7e-11ee-9ea1-2bfe193640c0/activities 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 27 Oct 2023 08:32:48 GMT 27 | content-length: 28 | - '376' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: ASCII-8BIT 33 | string: !binary |- 34 | eyJlbnRyaWVzIjpbeyJpZCI6MjYyNTUyMzI3MSwiZGVzY3JpcHRpb24iOiJwdXJjaGFzZWQgdGhlIEdvbGQgYW5udWFsIHBsYW4iLCJhY3Rpdml0eS1tcnItbW92ZW1lbnQiOjc1NiwiYWN0aXZpdHktbXJyIjo3NTYsImFjdGl2aXR5LWFyciI6OTA3MiwiZGF0ZSI6IjIwMTYtMDItMjRUMDA6MDA6MDArMDA6MDAiLCJ0eXBlIjoibmV3X2JpeiIsImN1cnJlbmN5IjoiRVVSIiwiY3VycmVuY3ktc2lnbiI6IuKCrCIsInN1YnNjcmlwdGlvbi1leHRlcm5hbC1pZCI6IjEifV0sImhhc19tb3JlIjpmYWxzZSwicGVyX3BhZ2UiOjIwMCwicGFnZSI6MSwiY3Vyc29yIjoiTWpBeU15MHhNQzB5TjFRd056b3pPRG8wTkM0Mk1EUTJNVFV3TURCYUpqSTJNalUxTWpNeU56RT0ifQ== 35 | http_version: 36 | recorded_at: Fri, 27 Oct 2023 08:32:48 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_Customers_Activity/should_have_Activity_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customers/cus_23551596-2c7e-11ee-9ea1-2bfe193640c0/activities 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 27 Oct 2023 08:32:48 GMT 27 | content-length: 28 | - '376' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: ASCII-8BIT 33 | string: !binary |- 34 | eyJlbnRyaWVzIjpbeyJpZCI6MjYyNTUyMzI3MSwiZGVzY3JpcHRpb24iOiJwdXJjaGFzZWQgdGhlIEdvbGQgYW5udWFsIHBsYW4iLCJhY3Rpdml0eS1tcnItbW92ZW1lbnQiOjc1NiwiYWN0aXZpdHktbXJyIjo3NTYsImFjdGl2aXR5LWFyciI6OTA3MiwiZGF0ZSI6IjIwMTYtMDItMjRUMDA6MDA6MDArMDA6MDAiLCJ0eXBlIjoibmV3X2JpeiIsImN1cnJlbmN5IjoiRVVSIiwiY3VycmVuY3ktc2lnbiI6IuKCrCIsInN1YnNjcmlwdGlvbi1leHRlcm5hbC1pZCI6IjEifV0sImhhc19tb3JlIjpmYWxzZSwicGVyX3BhZ2UiOjIwMCwicGFnZSI6MSwiY3Vyc29yIjoiTWpBeU15MHhNQzB5TjFRd056b3pPRG8wTkM0Mk1EUTJNVFV3TURCYUpqSTJNalUxTWpNeU56RT0ifQ== 35 | http_version: 36 | recorded_at: Fri, 27 Oct 2023 08:32:48 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_Customers_Subscription/behaves_like_Pageable/should_be_pageable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customers/cus_23551596-2c7e-11ee-9ea1-2bfe193640c0/subscriptions 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 27 Oct 2023 08:31:18 GMT 27 | content-length: 28 | - '458' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: ASCII-8BIT 33 | string: !binary |- 34 | eyJlbnRyaWVzIjpbeyJpZCI6MjI5MzcxMDg3MCwiZXh0ZXJuYWxfaWQiOiIxIiwic3Vic2NyaXB0aW9uX3NldF9leHRlcm5hbF9pZCI6IjEiLCJxdWFudGl0eSI6MSwidXVpZCI6IjE0N2NiYTFhLTFmZDktNDExYi1iY2I3LTJlZDQ2N2NlYmUyNCIsIm1yciI6NzU2LCJhcnIiOjkwNzIsInN0YXR1cyI6ImFjdGl2ZSIsInBsYW4iOiJHb2xkIGFubnVhbCIsImJpbGxpbmctY3ljbGUiOiJ5ZWFyIiwiYmlsbGluZy1jeWNsZS1jb3VudCI6MSwic3RhcnQtZGF0ZSI6IjIwMTYtMDItMjRUMDA6MDA6MDArMDA6MDAiLCJlbmQtZGF0ZSI6IjIwMTctMDItMjRUMDA6MDA6MDArMDA6MDAiLCJjdXJyZW5jeSI6IkVVUiIsImN1cnJlbmN5LXNpZ24iOiLigqwifV0sImhhc19tb3JlIjpmYWxzZSwicGVyX3BhZ2UiOjIwMCwicGFnZSI6MSwiY3Vyc29yIjoiYzNWaWMyTnlhWEIwYVc5dWMxOXVaWGgwWDNCaFoyVTlNZz09In0= 35 | http_version: 36 | recorded_at: Fri, 27 Oct 2023 08:31:18 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_Customers_Subscription/should_have_Subscription_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customers/cus_23551596-2c7e-11ee-9ea1-2bfe193640c0/subscriptions 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 27 Oct 2023 08:31:09 GMT 27 | content-length: 28 | - '458' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: ASCII-8BIT 33 | string: !binary |- 34 | eyJlbnRyaWVzIjpbeyJpZCI6MjI5MzcxMDg3MCwiZXh0ZXJuYWxfaWQiOiIxIiwic3Vic2NyaXB0aW9uX3NldF9leHRlcm5hbF9pZCI6IjEiLCJxdWFudGl0eSI6MSwidXVpZCI6IjE0N2NiYTFhLTFmZDktNDExYi1iY2I3LTJlZDQ2N2NlYmUyNCIsIm1yciI6NzU2LCJhcnIiOjkwNzIsInN0YXR1cyI6ImFjdGl2ZSIsInBsYW4iOiJHb2xkIGFubnVhbCIsImJpbGxpbmctY3ljbGUiOiJ5ZWFyIiwiYmlsbGluZy1jeWNsZS1jb3VudCI6MSwic3RhcnQtZGF0ZSI6IjIwMTYtMDItMjRUMDA6MDA6MDArMDA6MDAiLCJlbmQtZGF0ZSI6IjIwMTctMDItMjRUMDA6MDA6MDArMDA6MDAiLCJjdXJyZW5jeSI6IkVVUiIsImN1cnJlbmN5LXNpZ24iOiLigqwifV0sImhhc19tb3JlIjpmYWxzZSwicGVyX3BhZ2UiOjIwMCwicGFnZSI6MSwiY3Vyc29yIjoiYzNWaWMyTnlhWEIwYVc5dWMxOXVaWGgwWDNCaFoyVTlNZz09In0= 35 | http_version: 36 | recorded_at: Fri, 27 Oct 2023 08:31:09 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_LTV/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/ltv?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:48 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '148' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2015-01-31","ltv":0},{"date":"2015-02-01","ltv":15620.0}],"summary":{"current":54213,"previous":54213,"percentage-change":0.0}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 14:47:48 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_LTV/behaves_like_Metrics_API_resource/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/ltv?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:48 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '148' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2022-04-30","ltv":117173214,"percentage-change":0.0},{"date":"2022-05-31","ltv":65112456,"percentage-change":-44.43}],"summary":{"current":65112456,"previous":117173214,"percentage-change":-44.43}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 14:47:48 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_MRR/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/mrr?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 14:47:47 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '4199' 29 | connection: 30 | - close 31 | vary: 32 | - Accept-Encoding 33 | status: 34 | - 200 OK 35 | access-control-allow-credentials: 36 | - 'true' 37 | body: 38 | encoding: UTF-8 39 | string: '{"entries":[{"date":"2022-04-30","mrr":383859969,"percentage-change":0.0,"mrr-new-business":2489791,"mrr-expansion":1502311,"mrr-contraction":-813307,"mrr-churn":-96723,"mrr-reactivation":54879},{"date":"2022-05-31","mrr":670280904,"percentage-change":74.62,"mrr-new-business":572899,"mrr-expansion":286342340,"mrr-contraction":-226820,"mrr-churn":-64750,"mrr-reactivation":5000}],"summary":{"current":670566870,"previous":670252256,"percentage-change":0.05}}' 40 | http_version: 41 | recorded_at: Fri, 01 Jul 2016 14:47:47 GMT 42 | recorded_with: VCR 3.0.3 43 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_MRRChurnRate/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/mrr-churn-rate?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 16:56:26 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '160' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2015-01-31","mrr-churn-rate":0.0},{"date":"2015-02-01","mrr-churn-rate":0.0}],"summary":{"current":0,"previous":0,"percentage-change":0.0}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 16:56:26 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Metrics_MRRChurnRate/behaves_like_Metrics_API_resource/should_have_entries.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/metrics/mrr-churn-rate?end-date=2015-02-01&start-date=2015-01-01 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - Faraday v0.9.2 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.9.10 23 | date: 24 | - Fri, 01 Jul 2016 16:56:25 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '160' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | access-control-allow-credentials: 34 | - 'true' 35 | body: 36 | encoding: UTF-8 37 | string: '{"entries":[{"date":"2022-04-30","mrr-churn-rate":-0.17,"percentage-change":0.0},{"date":"2022-05-31","mrr-churn-rate":-74.52,"percentage-change":-43735.29}],"summary":{"current":-74.52,"previous":-0.17,"percentage-change":-43735.29}}' 38 | http_version: 39 | recorded_at: Fri, 01 Jul 2016 16:56:25 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Note/API_Actions/creates_a_note_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/customer_notes 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"note","text":"This 9 | is a note"}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/4.0.1 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 201 20 | message: Created 21 | headers: 22 | access-control-allow-credentials: 23 | - 'true' 24 | content-type: 25 | - application/json 26 | date: 27 | - Fri, 15 Dec 2023 12:45:12 GMT 28 | content-length: 29 | - '311' 30 | connection: 31 | - keep-alive 32 | body: 33 | encoding: UTF-8 34 | string: '{"uuid":"note_c9c9e7b6-9b47-11ee-a3d8-0f695c53544c","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"note","text":"This 35 | is a note","call_duration":0,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:45:12.548Z","updated_at":"2023-12-15T12:45:12.548Z"}' 36 | recorded_at: Fri, 15 Dec 2023 12:45:12 GMT 37 | recorded_with: VCR 6.2.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Note/API_Actions/destroys_the_note_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/customer_notes/note_18ffc3bc-9b45-11ee-8143-07ca86e5ee10 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.0.1 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 200 17 | message: OK 18 | headers: 19 | access-control-allow-credentials: 20 | - 'true' 21 | content-type: 22 | - application/json 23 | date: 24 | - Fri, 15 Dec 2023 12:49:44 GMT 25 | content-length: 26 | - '2' 27 | connection: 28 | - keep-alive 29 | body: 30 | encoding: UTF-8 31 | string: "{}" 32 | recorded_at: Fri, 15 Dec 2023 12:49:44 GMT 33 | recorded_with: VCR 6.2.0 34 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Note/API_Actions/retrieves_a_note_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customer_notes/note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 15 Dec 2023 12:45:12 GMT 27 | content-length: 28 | - '312' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 34 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:28:15.754Z","updated_at":"2023-12-15T12:28:15.754Z"}' 35 | recorded_at: Fri, 15 Dec 2023 12:45:12 GMT 36 | recorded_with: VCR 6.2.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Note/API_Actions/retrieves_all_notes_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customer_notes?customer_uuid=cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 15 Dec 2023 12:41:20 GMT 27 | content-length: 28 | - '764' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"entries":[{"uuid":"note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 34 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:28:15.754Z","updated_at":"2023-12-15T12:28:15.754Z"},{"uuid":"note_18ffc3bc-9b45-11ee-8143-07ca86e5ee10","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 35 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:25:56.950Z","updated_at":"2023-12-15T12:25:56.950Z"}],"cursor":"MjAyMy0xMi0xNVQxMjoyNTo1Ni45NTA4MTcwMDBaJm5vdGVfMThmZmMzYmMtOWI0NS0xMWVlLTgxNDMtMDdjYTg2ZTVlZTEw","has_more":false}' 36 | recorded_at: Fri, 15 Dec 2023 12:41:20 GMT 37 | recorded_with: VCR 6.2.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Note/API_Actions/retrieves_the_note_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/customer_notes/note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 15 Dec 2023 12:44:47 GMT 27 | content-length: 28 | - '312' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 34 | is a call","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:28:15.754Z","updated_at":"2023-12-15T12:28:15.754Z"}' 35 | recorded_at: Fri, 15 Dec 2023 12:44:47 GMT 36 | recorded_with: VCR 6.2.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Note/API_Actions/updates_the_note_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: patch 5 | uri: https://api.chartmogul.com/v1/customer_notes/note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde 6 | body: 7 | encoding: UTF-8 8 | string: '{"text":"This is a updated note"}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.0.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | content-type: 24 | - application/json 25 | date: 26 | - Fri, 15 Dec 2023 12:45:33 GMT 27 | content-length: 28 | - '320' 29 | connection: 30 | - keep-alive 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"note_6bbb8a6e-9b45-11ee-8f1d-8f455cd2fcde","customer_uuid":"cus_58f81bdc-94e6-11ee-ba3e-63f79c1ac982","type":"call","text":"This 34 | is a updated note","call_duration":60,"author":"Soeun Lee[staff-user-2] (soeun+staff@chartmogul.com)","created_at":"2023-12-15T12:28:15.754Z","updated_at":"2023-12-15T12:45:33.363Z"}' 35 | recorded_at: Fri, 15 Dec 2023 12:45:33 GMT 36 | recorded_with: VCR 6.2.0 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Opportunity/API_Actions/creates_a_opportunity_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/opportunities 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_8bae29d0-df51-11ee-88c8-97dc7855258a","owner":"kamil+pavlicko@chartmogul.com","pipeline":"New 9 | Business","pipeline_stage":"Discovery","estimated_close_date":"2024-03-30","currency":"USD","amount_in_cents":100000,"type":"one-time","forecast_category":"best_case","win_likelihood":30,"custom":[{"key":"from_campaign","value":true}]}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/4.2.0 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 201 20 | message: Created 21 | headers: 22 | date: 23 | - Mon, 18 Mar 2024 17:15:57 GMT 24 | content-type: 25 | - application/json 26 | content-length: 27 | - '461' 28 | connection: 29 | - keep-alive 30 | access-control-allow-credentials: 31 | - 'true' 32 | body: 33 | encoding: UTF-8 34 | string: '{"uuid":"2f0b0748-e54b-11ee-81c1-5bf872d9787a","customer_uuid":"cus_8bae29d0-df51-11ee-88c8-97dc7855258a","owner":"kamil+pavlicko@chartmogul.com","pipeline":"New 35 | Business","pipeline_stage":"Discovery","estimated_close_date":"2024-03-30","currency":"USD","amount_in_cents":100000,"type":"one-time","forecast_category":"best_case","win_likelihood":30,"custom":{"from_campaign":true},"created_at":"2024-03-18T17:15:56.960Z","updated_at":"2024-03-18T17:15:56.960Z"}' 36 | http_version: 37 | recorded_at: Mon, 18 Mar 2024 17:15:57 GMT 38 | recorded_with: VCR 5.1.0 39 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Opportunity/API_Actions/destroys_the_opportunity_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/opportunities/52115b0c-e54b-11ee-b769-a7d79ddfc0fb 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.2.0 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 200 17 | message: OK 18 | headers: 19 | date: 20 | - Mon, 18 Mar 2024 17:17:36 GMT 21 | content-type: 22 | - application/json 23 | content-length: 24 | - '2' 25 | connection: 26 | - keep-alive 27 | access-control-allow-credentials: 28 | - 'true' 29 | body: 30 | encoding: UTF-8 31 | string: "{}" 32 | http_version: 33 | recorded_at: Mon, 18 Mar 2024 17:17:36 GMT 34 | recorded_with: VCR 5.1.0 35 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Opportunity/API_Actions/retrieves_a_opportunity_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/opportunities/3726cd86-e0f0-11ee-8d22-93b1d57bf35d 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.2.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | date: 22 | - Mon, 18 Mar 2024 17:15:35 GMT 23 | content-type: 24 | - application/json 25 | content-length: 26 | - '461' 27 | connection: 28 | - keep-alive 29 | access-control-allow-credentials: 30 | - 'true' 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"3726cd86-e0f0-11ee-8d22-93b1d57bf35d","customer_uuid":"cus_8bae29d0-df51-11ee-88c8-97dc7855258a","owner":"kamil+pavlicko@chartmogul.com","pipeline":"New 34 | Business","pipeline_stage":"Discovery","estimated_close_date":"2024-03-30","currency":"USD","amount_in_cents":100000,"type":"one-time","forecast_category":"best_case","win_likelihood":30,"custom":{"from_campaign":true},"created_at":"2024-03-13T04:14:41.711Z","updated_at":"2024-03-13T04:14:41.711Z"}' 35 | http_version: 36 | recorded_at: Mon, 18 Mar 2024 17:15:35 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Opportunity/API_Actions/updates_the_opportunity_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: patch 5 | uri: https://api.chartmogul.com/v1/opportunities/3726cd86-e0f0-11ee-8d22-93b1d57bf35d 6 | body: 7 | encoding: UTF-8 8 | string: '{"estimated_close_date":"2024-04-30"}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.2.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | date: 22 | - Mon, 18 Mar 2024 17:16:19 GMT 23 | content-type: 24 | - application/json 25 | content-length: 26 | - '461' 27 | connection: 28 | - keep-alive 29 | access-control-allow-credentials: 30 | - 'true' 31 | body: 32 | encoding: UTF-8 33 | string: '{"uuid":"3726cd86-e0f0-11ee-8d22-93b1d57bf35d","customer_uuid":"cus_8bae29d0-df51-11ee-88c8-97dc7855258a","owner":"kamil+pavlicko@chartmogul.com","pipeline":"New 34 | Business","pipeline_stage":"Discovery","estimated_close_date":"2024-04-30","currency":"USD","amount_in_cents":100000,"type":"one-time","forecast_category":"best_case","win_likelihood":30,"custom":{"from_campaign":true},"created_at":"2024-03-13T04:14:41.711Z","updated_at":"2024-03-18T17:16:19.297Z"}' 35 | http_version: 36 | recorded_at: Mon, 18 Mar 2024 17:16:19 GMT 37 | recorded_with: VCR 5.1.0 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Ping/pings/and_fails_on_incorrect_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/ping 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - Faraday v0.11.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 401 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | date: 24 | - Mon, 13 Feb 2017 15:09:26 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '63' 29 | connection: 30 | - close 31 | status: 32 | - 401 Unauthorized 33 | body: 34 | encoding: UTF-8 35 | string: '{"code":401,"message":"No valid API key provided","param":null}' 36 | http_version: 37 | recorded_at: Mon, 13 Feb 2017 15:09:28 GMT 38 | recorded_with: VCR 3.0.3 39 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Ping/pings/and_fails_with_500_internal_server_error.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/ping 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - Faraday v0.15.4 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 500 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | cache-control: 24 | - private 25 | content-length: 26 | - '25' 27 | content-type: 28 | - text/plain; charset=utf-8 29 | access-control-allow-origin: 30 | - "*" 31 | date: 32 | - Tue, 10 Dec 2019 07:43:50 GMT 33 | connection: 34 | - close 35 | body: 36 | encoding: UTF-8 37 | string: 500 Internal Server Error 38 | http_version: 39 | recorded_at: Tue, 10 Dec 2019 07:43:51 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Ping/pings/and_fails_with_504_gateway_timeout_error.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/ping 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - Faraday v0.15.4 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 504 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | cache-control: 24 | - private 25 | content-length: 26 | - '25' 27 | content-type: 28 | - text/plain; charset=utf-8 29 | access-control-allow-origin: 30 | - "*" 31 | date: 32 | - Tue, 10 Dec 2019 07:43:50 GMT 33 | connection: 34 | - close 35 | body: 36 | encoding: UTF-8 37 | string: 504 Gateway Timeout Error 38 | http_version: 39 | recorded_at: Tue, 10 Dec 2019 07:43:51 GMT 40 | recorded_with: VCR 3.0.3 41 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Ping/pings/when_credentials_correct.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/ping 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - Faraday v0.11.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: 20 | headers: 21 | server: 22 | - nginx/1.10.1 23 | date: 24 | - Mon, 13 Feb 2017 15:04:03 GMT 25 | content-type: 26 | - application/json 27 | content-length: 28 | - '16' 29 | connection: 30 | - close 31 | status: 32 | - 200 OK 33 | body: 34 | encoding: UTF-8 35 | string: '{"data":"pong!"}' 36 | http_version: 37 | recorded_at: Mon, 13 Feb 2017 15:04:05 GMT 38 | recorded_with: VCR 3.0.3 39 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Plan/API_Actions/creates_the_plan_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/plans 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"Another Test Plan","interval_count":1,"interval_unit":"month","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46"}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 201 19 | message: Created 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | cache-control: 24 | - max-age=0, private, must-revalidate 25 | content-type: 26 | - application/json; charset=utf-8 27 | date: 28 | - Mon, 30 Oct 2023 03:48:10 GMT 29 | etag: 30 | - W/"f3aaf84b099a0421ba8b59887443272c" 31 | referrer-policy: 32 | - strict-origin-when-cross-origin 33 | x-content-type-options: 34 | - nosniff 35 | x-download-options: 36 | - noopen 37 | x-frame-options: 38 | - DENY 39 | x-permitted-cross-domain-policies: 40 | - none 41 | x-request-id: 42 | - b94db83baa7dc1b3096910dbba06f0dd 43 | x-runtime: 44 | - '0.054636' 45 | x-xss-protection: 46 | - 1; mode=block 47 | content-length: 48 | - '234' 49 | connection: 50 | - keep-alive 51 | body: 52 | encoding: UTF-8 53 | string: '{"external_id":"1184b750-5905-013c-13b1-46813c1ddd3d","name":"Another 54 | Test Plan","interval_count":1,"interval_unit":"month","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","uuid":"pl_1184b750-5905-013c-13b1-46813c1ddd3d"}' 55 | http_version: 56 | recorded_at: Mon, 30 Oct 2023 03:48:10 GMT 57 | recorded_with: VCR 5.1.0 58 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Plan/API_Actions/destroys_the_plan_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/plans/pl_1184b750-5905-013c-13b1-46813c1ddd3d 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 204 17 | message: No Content 18 | headers: 19 | access-control-allow-credentials: 20 | - 'true' 21 | cache-control: 22 | - no-cache 23 | date: 24 | - Mon, 30 Oct 2023 03:50:50 GMT 25 | referrer-policy: 26 | - strict-origin-when-cross-origin 27 | x-content-type-options: 28 | - nosniff 29 | x-download-options: 30 | - noopen 31 | x-frame-options: 32 | - DENY 33 | x-permitted-cross-domain-policies: 34 | - none 35 | x-request-id: 36 | - 5d23c509efbe57c9b2230d246b7643cd 37 | x-runtime: 38 | - '0.057753' 39 | x-xss-protection: 40 | - 1; mode=block 41 | connection: 42 | - keep-alive 43 | body: 44 | encoding: UTF-8 45 | string: '' 46 | http_version: 47 | recorded_at: Mon, 30 Oct 2023 03:50:50 GMT 48 | recorded_with: VCR 5.1.0 49 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Plan/API_Actions/retrieves_the_plan_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/plans/pl_de9e281e-76cb-11ee-b63f-b727630ce4d4 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | cache-control: 24 | - max-age=0, private, must-revalidate 25 | content-type: 26 | - application/json; charset=utf-8 27 | date: 28 | - Mon, 30 Oct 2023 03:47:36 GMT 29 | etag: 30 | - W/"fe6ec38e44f2cb5de77ecfc2db2ddd07" 31 | referrer-policy: 32 | - strict-origin-when-cross-origin 33 | x-content-type-options: 34 | - nosniff 35 | x-download-options: 36 | - noopen 37 | x-frame-options: 38 | - DENY 39 | x-permitted-cross-domain-policies: 40 | - none 41 | x-request-id: 42 | - 1ce480559b4090227e54fcca33aaa2b5 43 | x-runtime: 44 | - '0.025952' 45 | x-xss-protection: 46 | - 1; mode=block 47 | content-length: 48 | - '206' 49 | connection: 50 | - keep-alive 51 | body: 52 | encoding: UTF-8 53 | string: '{"external_id":"test_cus_pl_ext_id","name":"Test Plan","interval_count":7,"interval_unit":"day","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","uuid":"pl_de9e281e-76cb-11ee-b63f-b727630ce4d4"}' 54 | http_version: 55 | recorded_at: Mon, 30 Oct 2023 03:47:36 GMT 56 | recorded_with: VCR 5.1.0 57 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Plan/API_Actions/updates_the_plan_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: patch 5 | uri: https://api.chartmogul.com/v1/plans/pl_1184b750-5905-013c-13b1-46813c1ddd3d 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"Another Test Plan","interval_count":1}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 202 19 | message: Accepted 20 | headers: 21 | cache-control: 22 | - no-cache 23 | content-type: 24 | - application/json; charset=utf-8 25 | date: 26 | - Mon, 30 Oct 2023 03:50:22 GMT 27 | referrer-policy: 28 | - strict-origin-when-cross-origin 29 | x-content-type-options: 30 | - nosniff 31 | x-download-options: 32 | - noopen 33 | x-frame-options: 34 | - DENY 35 | x-permitted-cross-domain-policies: 36 | - none 37 | x-request-id: 38 | - 9f11c63f8c1c542ec7b49db2ad0f21d6 39 | x-runtime: 40 | - '0.059153' 41 | x-xss-protection: 42 | - 1; mode=block 43 | content-length: 44 | - '234' 45 | connection: 46 | - keep-alive 47 | body: 48 | encoding: UTF-8 49 | string: '{"external_id":"1184b750-5905-013c-13b1-46813c1ddd3d","name":"Another 50 | Test Plan","interval_count":1,"interval_unit":"month","data_source_uuid":"ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46","uuid":"pl_1184b750-5905-013c-13b1-46813c1ddd3d"}' 51 | http_version: 52 | recorded_at: Mon, 30 Oct 2023 03:50:22 GMT 53 | recorded_with: VCR 5.1.0 54 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_Actions/correctly_handles_a_422_error.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/plan_groups 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 422 19 | message: Unprocessable Content 20 | headers: 21 | cache-control: 22 | - no-cache 23 | content-type: 24 | - application/json; charset=utf-8 25 | date: 26 | - Mon, 30 Oct 2023 04:00:23 GMT 27 | referrer-policy: 28 | - strict-origin-when-cross-origin 29 | x-content-type-options: 30 | - nosniff 31 | x-download-options: 32 | - noopen 33 | x-frame-options: 34 | - DENY 35 | x-permitted-cross-domain-policies: 36 | - none 37 | x-request-id: 38 | - df66edf9df80e8a0d7683af697ccf160 39 | x-runtime: 40 | - '0.024525' 41 | x-xss-protection: 42 | - 1; mode=block 43 | transfer-encoding: 44 | - chunked 45 | connection: 46 | - keep-alive 47 | body: 48 | encoding: UTF-8 49 | string: '{"name":["Name can''t be blank"],"plan_ids":["Plan ids can''t be blank"],"error_details":[{"param":"name","code":"blank","message":"Name 50 | can''t be blank"},{"param":"plan_ids","code":"blank","message":"Plan ids can''t 51 | be blank"}]}' 52 | http_version: 53 | recorded_at: Mon, 30 Oct 2023 04:00:23 GMT 54 | recorded_with: VCR 5.1.0 55 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_Actions/retrieves_the_plan_group_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/plan_groups/plg_e6ae207a-ff32-4431-ae46-34f20b61e17a 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | cache-control: 24 | - max-age=0, private, must-revalidate 25 | content-type: 26 | - application/json; charset=utf-8 27 | date: 28 | - Mon, 30 Oct 2023 03:55:33 GMT 29 | etag: 30 | - W/"cc31e79d8c8c118a0847d629bf702d1d" 31 | referrer-policy: 32 | - strict-origin-when-cross-origin 33 | x-content-type-options: 34 | - nosniff 35 | x-download-options: 36 | - noopen 37 | x-frame-options: 38 | - DENY 39 | x-permitted-cross-domain-policies: 40 | - none 41 | x-request-id: 42 | - 3687e3e4eff5144677e95142b0abc9a7 43 | x-runtime: 44 | - '0.025782' 45 | x-xss-protection: 46 | - 1; mode=block 47 | content-length: 48 | - '90' 49 | connection: 50 | - keep-alive 51 | body: 52 | encoding: UTF-8 53 | string: '{"name":"My plan group","uuid":"plg_e6ae207a-ff32-4431-ae46-34f20b61e17a","plans_count":2}' 54 | http_version: 55 | recorded_at: Mon, 30 Oct 2023 03:55:33 GMT 56 | recorded_with: VCR 5.1.0 57 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_Actions/updates_the_plan_group_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: patch 5 | uri: https://api.chartmogul.com/v1/plan_groups/plg_e6ae207a-ff32-4431-ae46-34f20b61e17a 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"Another name"}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/3.3.1 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | access-control-allow-credentials: 22 | - 'true' 23 | cache-control: 24 | - max-age=0, private, must-revalidate 25 | content-type: 26 | - application/json; charset=utf-8 27 | date: 28 | - Mon, 30 Oct 2023 04:04:51 GMT 29 | etag: 30 | - W/"f79332b69b7a92568a243cbe551b82ee" 31 | referrer-policy: 32 | - strict-origin-when-cross-origin 33 | x-content-type-options: 34 | - nosniff 35 | x-download-options: 36 | - noopen 37 | x-frame-options: 38 | - DENY 39 | x-permitted-cross-domain-policies: 40 | - none 41 | x-request-id: 42 | - 7c6eb94bc13195ee0c7d478aa05a8b03 43 | x-runtime: 44 | - '0.036283' 45 | x-xss-protection: 46 | - 1; mode=block 47 | content-length: 48 | - '89' 49 | connection: 50 | - keep-alive 51 | body: 52 | encoding: UTF-8 53 | string: '{"name":"Another name","uuid":"plg_e6ae207a-ff32-4431-ae46-34f20b61e17a","plans_count":2}' 54 | http_version: 55 | recorded_at: Mon, 30 Oct 2023 04:04:51 GMT 56 | recorded_with: VCR 5.1.0 57 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Task/API_Actions/creates_a_task_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.chartmogul.com/v1/tasks 6 | body: 7 | encoding: UTF-8 8 | string: '{"customer_uuid":"cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64","task_details":"This 9 | is some task details text.","assignee":"keith+test1@chartmogul.com","due_date":"2025-04-30T00:00:00.000Z"}' 10 | headers: 11 | User-Agent: 12 | - chartmogul-ruby/4.6.0 13 | Content-Type: 14 | - application/json 15 | Authorization: 16 | - Basic hidden 17 | response: 18 | status: 19 | code: 201 20 | message: Created 21 | headers: 22 | date: 23 | - Fri, 25 Apr 2025 02:15:06 GMT 24 | content-type: 25 | - application/json 26 | content-length: 27 | - '338' 28 | connection: 29 | - keep-alive 30 | access-control-allow-credentials: 31 | - 'true' 32 | body: 33 | encoding: UTF-8 34 | string: '{"task_uuid":"1aeae108-217b-11f0-b2b4-5b42f025062c","customer_uuid":"cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64","task_details":"This 35 | is some task details text.","assignee":"keith+test1@chartmogul.com","due_date":"2025-04-30T00:00:00.000Z","completed_at":null,"created_at":"2025-04-25T02:15:06.474Z","updated_at":"2025-04-25T02:15:06.474Z"}' 36 | recorded_at: Fri, 25 Apr 2025 02:15:06 GMT 37 | recorded_with: VCR 6.3.1 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Task/API_Actions/destroys_the_task_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://api.chartmogul.com/v1/tasks/d8c374e0-b9ef-47cf-a5a5-4c71fe0a1466 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.6.0 12 | Authorization: 13 | - Basic hidden 14 | response: 15 | status: 16 | code: 200 17 | message: OK 18 | headers: 19 | date: 20 | - Fri, 25 Apr 2025 02:41:12 GMT 21 | content-type: 22 | - application/json 23 | content-length: 24 | - '2' 25 | connection: 26 | - keep-alive 27 | body: 28 | encoding: UTF-8 29 | string: '{}' 30 | recorded_at: Fri, 25 Apr 2025 02:41:11 GMT 31 | recorded_with: VCR 6.3.1 32 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Task/API_Actions/retrieves_a_task_correctly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.chartmogul.com/v1/tasks/6c969fee-2179-11f0-8d8c-ef2a5afba642 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.6.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | date: 22 | - Fri, 25 Apr 2025 02:15:04 GMT 23 | content-type: 24 | - application/json 25 | content-length: 26 | - '338' 27 | connection: 28 | - keep-alive 29 | access-control-allow-credentials: 30 | - 'true' 31 | body: 32 | encoding: UTF-8 33 | string: '{"task_uuid":"6c969fee-2179-11f0-8d8c-ef2a5afba642","customer_uuid":"cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64","task_details":"This 34 | is some task details text.","assignee":"keith+test1@chartmogul.com","due_date":"2025-04-30T00:00:00.000Z","completed_at":null,"created_at":"2025-04-25T02:03:04.503Z","updated_at":"2025-04-25T02:03:04.503Z"}' 35 | recorded_at: Fri, 25 Apr 2025 02:15:04 GMT 36 | recorded_with: VCR 6.3.1 37 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/ChartMogul_Task/API_Actions/updates_the_task_correctly_with_the_class_method.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: patch 5 | uri: https://api.chartmogul.com/v1/tasks/6c969fee-2179-11f0-8d8c-ef2a5afba642 6 | body: 7 | encoding: UTF-8 8 | string: '{"task_details":"This is updated task details text."}' 9 | headers: 10 | User-Agent: 11 | - chartmogul-ruby/4.6.0 12 | Content-Type: 13 | - application/json 14 | Authorization: 15 | - Basic hidden 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | date: 22 | - Fri, 25 Apr 2025 02:47:57 GMT 23 | content-type: 24 | - application/json 25 | content-length: 26 | - '341' 27 | connection: 28 | - keep-alive 29 | access-control-allow-credentials: 30 | - 'true' 31 | body: 32 | encoding: UTF-8 33 | string: '{"task_uuid":"6c969fee-2179-11f0-8d8c-ef2a5afba642","customer_uuid":"cus_9c8cc2bd-762e-4d93-ae34-1cfb53a53f64","task_details":"This 34 | is updated task details text.","assignee":"keith+test1@chartmogul.com","due_date":"2025-04-30T00:00:00.000Z","completed_at":null,"created_at":"2025-04-25T02:03:04.503Z","updated_at":"2025-04-25T02:47:57.793Z"}' 35 | recorded_at: Fri, 25 Apr 2025 02:47:57 GMT 36 | recorded_with: VCR 6.3.1 37 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path('../lib', __dir__) 4 | 5 | require 'simplecov' 6 | SimpleCov.start do 7 | add_filter 'vendor/ruby' 8 | end 9 | 10 | require 'chartmogul' 11 | require 'vcr' 12 | require 'webmock/rspec' 13 | require_relative 'support/shared_example_raises_deprecated_param_error' 14 | 15 | VCR.configure do |config| 16 | config.cassette_library_dir = 'spec/fixtures/vcr_cassettes' 17 | config.hook_into :faraday 18 | config.configure_rspec_metadata! 19 | config.filter_sensitive_data('Basic hidden') do |interaction| 20 | interaction.request.headers['Authorization'].first # returns an array 21 | end 22 | end 23 | 24 | RSpec.configure do |config| 25 | config.order = 'random' 26 | 27 | config.before(:each) do |example| 28 | Thread.current[ChartMogul::CONFIG_THREAD_KEY] = nil 29 | 30 | if example.metadata[:uses_api] 31 | ChartMogul.api_key = ENV['TEST_API_KEY'] || 'dummy-token' 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/support/shared_example_raises_deprecated_param_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'raises deprecated param error' do 4 | it 'raises a DeprecatedParameter error' do 5 | expect { get_resources }.to raise_error(ChartMogul::ChartMogulError, 'page is deprecated.') 6 | end 7 | end 8 | --------------------------------------------------------------------------------