From 7dd7fb13f6b7b01da8a47fc97e3e5ad1c9013dee Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Mon, 4 Apr 2016 17:41:32 +0200 Subject: [PATCH 01/64] removing spec folder --- spec/factories/abuses.rb | 10 --- spec/factories/auth_providers.rb | 8 -- spec/factories/availabilities.rb | 6 -- spec/factories/availability_tags.rb | 7 -- spec/factories/avoirs.rb | 6 -- spec/factories/credits.rb | 6 -- spec/factories/custom_assets.rb | 6 -- spec/factories/database_providers.rb | 6 -- spec/factories/invoices.rb | 6 -- spec/factories/machines.rb | 6 -- spec/factories/o_auth2_mappings.rb | 10 --- spec/factories/o_auth2_providers.rb | 11 --- spec/factories/plans.rb | 6 -- spec/factories/prices.rb | 9 -- spec/factories/profile.rb | 11 --- spec/factories/projects.rb | 8 -- spec/factories/reservations.rb | 6 -- spec/factories/stylesheets.rb | 6 -- spec/factories/subscriptions.rb | 6 -- spec/factories/tags.rb | 6 -- spec/factories/trainings.rb | 6 -- spec/factories/user_tags.rb | 7 -- spec/factories/users.rb | 14 --- spec/mailers/.keep | 0 .../mailers/previews/devise_mailer_preview.rb | 9 -- .../previews/notifications_mailer_preview.rb | 7 -- spec/mailers/previews/users_mailer_preview.rb | 5 -- spec/models/abuse_spec.rb | 5 -- spec/models/auth_provider_spec.rb | 5 -- spec/models/availability_spec.rb | 24 ----- spec/models/availability_tag_spec.rb | 5 -- spec/models/avoir_spec.rb | 9 -- spec/models/credit_spec.rb | 11 --- spec/models/custom_asset_spec.rb | 5 -- spec/models/database_provider_spec.rb | 5 -- spec/models/invoice_spec.rb | 9 -- spec/models/machine_spec.rb | 21 ----- spec/models/o_auth2_mapping_spec.rb | 5 -- spec/models/o_auth2_provider_spec.rb | 5 -- spec/models/plan_spec.rb | 60 ------------- spec/models/price_spec.rb | 5 -- spec/models/project_spec.rb | 30 ------- spec/models/reservation_spec.rb | 28 ------ spec/models/stylesheet_spec.rb | 5 -- spec/models/subscription_spec.rb | 26 ------ spec/models/tag_spec.rb | 5 -- spec/models/training_spec.rb | 18 ---- spec/models/user_spec.rb | 74 ---------------- spec/models/user_tag_spec.rb | 5 -- spec/rails_helper.rb | 50 ----------- spec/services/notification_center_spec.rb | 31 ------- spec/spec_helper.rb | 87 ------------------- spec/support/database_cleaner.rb | 17 ---- spec/support/factory_girl.rb | 12 --- 54 files changed, 756 deletions(-) delete mode 100644 spec/factories/abuses.rb delete mode 100644 spec/factories/auth_providers.rb delete mode 100644 spec/factories/availabilities.rb delete mode 100644 spec/factories/availability_tags.rb delete mode 100644 spec/factories/avoirs.rb delete mode 100644 spec/factories/credits.rb delete mode 100644 spec/factories/custom_assets.rb delete mode 100644 spec/factories/database_providers.rb delete mode 100644 spec/factories/invoices.rb delete mode 100644 spec/factories/machines.rb delete mode 100644 spec/factories/o_auth2_mappings.rb delete mode 100644 spec/factories/o_auth2_providers.rb delete mode 100644 spec/factories/plans.rb delete mode 100644 spec/factories/prices.rb delete mode 100644 spec/factories/profile.rb delete mode 100644 spec/factories/projects.rb delete mode 100644 spec/factories/reservations.rb delete mode 100644 spec/factories/stylesheets.rb delete mode 100644 spec/factories/subscriptions.rb delete mode 100644 spec/factories/tags.rb delete mode 100644 spec/factories/trainings.rb delete mode 100644 spec/factories/user_tags.rb delete mode 100644 spec/factories/users.rb delete mode 100644 spec/mailers/.keep delete mode 100644 spec/mailers/previews/devise_mailer_preview.rb delete mode 100644 spec/mailers/previews/notifications_mailer_preview.rb delete mode 100644 spec/mailers/previews/users_mailer_preview.rb delete mode 100644 spec/models/abuse_spec.rb delete mode 100644 spec/models/auth_provider_spec.rb delete mode 100644 spec/models/availability_spec.rb delete mode 100644 spec/models/availability_tag_spec.rb delete mode 100644 spec/models/avoir_spec.rb delete mode 100644 spec/models/credit_spec.rb delete mode 100644 spec/models/custom_asset_spec.rb delete mode 100644 spec/models/database_provider_spec.rb delete mode 100644 spec/models/invoice_spec.rb delete mode 100644 spec/models/machine_spec.rb delete mode 100644 spec/models/o_auth2_mapping_spec.rb delete mode 100644 spec/models/o_auth2_provider_spec.rb delete mode 100644 spec/models/plan_spec.rb delete mode 100644 spec/models/price_spec.rb delete mode 100644 spec/models/project_spec.rb delete mode 100644 spec/models/reservation_spec.rb delete mode 100644 spec/models/stylesheet_spec.rb delete mode 100644 spec/models/subscription_spec.rb delete mode 100644 spec/models/tag_spec.rb delete mode 100644 spec/models/training_spec.rb delete mode 100644 spec/models/user_spec.rb delete mode 100644 spec/models/user_tag_spec.rb delete mode 100644 spec/rails_helper.rb delete mode 100644 spec/services/notification_center_spec.rb delete mode 100644 spec/spec_helper.rb delete mode 100644 spec/support/database_cleaner.rb delete mode 100644 spec/support/factory_girl.rb diff --git a/spec/factories/abuses.rb b/spec/factories/abuses.rb deleted file mode 100644 index 053c56201..000000000 --- a/spec/factories/abuses.rb +++ /dev/null @@ -1,10 +0,0 @@ -FactoryGirl.define do - factory :abus, :class => 'Abuse' do - signaled nil -first_name "MyString" -last_name "MyString" -email "" -message "MyText" - end - -end diff --git a/spec/factories/auth_providers.rb b/spec/factories/auth_providers.rb deleted file mode 100644 index 5825df85a..000000000 --- a/spec/factories/auth_providers.rb +++ /dev/null @@ -1,8 +0,0 @@ -FactoryGirl.define do - factory :auth_provider do - name "MyString" -type "" -status "MyString" - end - -end diff --git a/spec/factories/availabilities.rb b/spec/factories/availabilities.rb deleted file mode 100644 index 566352913..000000000 --- a/spec/factories/availabilities.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :availability do - - #end - -#end diff --git a/spec/factories/availability_tags.rb b/spec/factories/availability_tags.rb deleted file mode 100644 index db9c2dafe..000000000 --- a/spec/factories/availability_tags.rb +++ /dev/null @@ -1,7 +0,0 @@ -FactoryGirl.define do - factory :availability_tag do - availability nil -tag nil - end - -end diff --git a/spec/factories/avoirs.rb b/spec/factories/avoirs.rb deleted file mode 100644 index fee25ded1..000000000 --- a/spec/factories/avoirs.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :avoir do - - #end - -#end diff --git a/spec/factories/credits.rb b/spec/factories/credits.rb deleted file mode 100644 index 3072f8855..000000000 --- a/spec/factories/credits.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :credit do - - #end - -#end diff --git a/spec/factories/custom_assets.rb b/spec/factories/custom_assets.rb deleted file mode 100644 index 288d4dab1..000000000 --- a/spec/factories/custom_assets.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - factory :custom_asset do - - end - -end diff --git a/spec/factories/database_providers.rb b/spec/factories/database_providers.rb deleted file mode 100644 index 2c42ffeaf..000000000 --- a/spec/factories/database_providers.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - factory :database_provider do - - end - -end diff --git a/spec/factories/invoices.rb b/spec/factories/invoices.rb deleted file mode 100644 index c7b688824..000000000 --- a/spec/factories/invoices.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :invoice do - - #end - -#end diff --git a/spec/factories/machines.rb b/spec/factories/machines.rb deleted file mode 100644 index 22dc14da5..000000000 --- a/spec/factories/machines.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :machine do - - #end - -#end diff --git a/spec/factories/o_auth2_mappings.rb b/spec/factories/o_auth2_mappings.rb deleted file mode 100644 index 8945ae6d3..000000000 --- a/spec/factories/o_auth2_mappings.rb +++ /dev/null @@ -1,10 +0,0 @@ -FactoryGirl.define do - factory :o_auth2_mapping do - o_auth2_provider nil -resource_url "MyString" -local_field "MyString" -api_field "MyString" -data_type "MyString" - end - -end diff --git a/spec/factories/o_auth2_providers.rb b/spec/factories/o_auth2_providers.rb deleted file mode 100644 index a6c72e70b..000000000 --- a/spec/factories/o_auth2_providers.rb +++ /dev/null @@ -1,11 +0,0 @@ -FactoryGirl.define do - factory :o_auth2_provider do - base_url "MyString" -token_endpoint "MyString" -authorization_endpoint "MyString" -client_id "MyString" -client_secret "MyString" -auth_provider nil - end - -end diff --git a/spec/factories/plans.rb b/spec/factories/plans.rb deleted file mode 100644 index f1a7428aa..000000000 --- a/spec/factories/plans.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :plan do - - #end - -#end diff --git a/spec/factories/prices.rb b/spec/factories/prices.rb deleted file mode 100644 index 1c349b91b..000000000 --- a/spec/factories/prices.rb +++ /dev/null @@ -1,9 +0,0 @@ -FactoryGirl.define do - factory :price do - group nil -plan nil -priceable nil -amount 1 - end - -end diff --git a/spec/factories/profile.rb b/spec/factories/profile.rb deleted file mode 100644 index 3483e0c31..000000000 --- a/spec/factories/profile.rb +++ /dev/null @@ -1,11 +0,0 @@ -FactoryGirl.define do - sequence(:last_name) { |n| n } - - factory :profile do - first_name 'member' - last_name { FactoryGirl.generate :last_name } - gender true - birthday { 30.years.ago } - phone '0606060606' - end -end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb deleted file mode 100644 index ef4d79834..000000000 --- a/spec/factories/projects.rb +++ /dev/null @@ -1,8 +0,0 @@ -FactoryGirl.define do - sequence(:name) { |n| "project#{n}" } - - factory :project do - name { FactoryGirl.generate :name } - description { Faker::Lorem.paragraph } - end -end diff --git a/spec/factories/reservations.rb b/spec/factories/reservations.rb deleted file mode 100644 index 4cafa3f7e..000000000 --- a/spec/factories/reservations.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :reservation do - - #end - -#end diff --git a/spec/factories/stylesheets.rb b/spec/factories/stylesheets.rb deleted file mode 100644 index a581bf44c..000000000 --- a/spec/factories/stylesheets.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - factory :stylesheet do - contents "MyString" - end - -end diff --git a/spec/factories/subscriptions.rb b/spec/factories/subscriptions.rb deleted file mode 100644 index 5d145f9c5..000000000 --- a/spec/factories/subscriptions.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :subscription do - - #end - -#end diff --git a/spec/factories/tags.rb b/spec/factories/tags.rb deleted file mode 100644 index 1cda84a6d..000000000 --- a/spec/factories/tags.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - factory :tag do - name "MyString" - end - -end diff --git a/spec/factories/trainings.rb b/spec/factories/trainings.rb deleted file mode 100644 index 47e11f9c0..000000000 --- a/spec/factories/trainings.rb +++ /dev/null @@ -1,6 +0,0 @@ -#FactoryGirl.define do - #factory :training do - - #end - -#end diff --git a/spec/factories/user_tags.rb b/spec/factories/user_tags.rb deleted file mode 100644 index 8f8e796da..000000000 --- a/spec/factories/user_tags.rb +++ /dev/null @@ -1,7 +0,0 @@ -FactoryGirl.define do - factory :user_tag do - user nil -tag nil - end - -end diff --git a/spec/factories/users.rb b/spec/factories/users.rb deleted file mode 100644 index 2a8d75c67..000000000 --- a/spec/factories/users.rb +++ /dev/null @@ -1,14 +0,0 @@ -FactoryGirl.define do - sequence(:email) { |n| "member#{n}@sleede.com" } - sequence(:username) { |n| "member#{n}" } - - factory :user do - email { FactoryGirl.generate :email } - username { FactoryGirl.generate :username } - password 'sleede22' - password_confirmation 'sleede22' - association :profile, strategy: :build - group { Group.first } - end - -end diff --git a/spec/mailers/.keep b/spec/mailers/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/mailers/previews/devise_mailer_preview.rb b/spec/mailers/previews/devise_mailer_preview.rb deleted file mode 100644 index d00d4411c..000000000 --- a/spec/mailers/previews/devise_mailer_preview.rb +++ /dev/null @@ -1,9 +0,0 @@ -class DeviseMailerPreview < ActionMailer::Preview - def confirmation_instructions - Devise::Mailer.confirmation_instructions(User.last, SecureRandom.hex) - end - - def reset_password_instructions - Devise::Mailer.reset_password_instructions(User.last, SecureRandom.hex) - end -end diff --git a/spec/mailers/previews/notifications_mailer_preview.rb b/spec/mailers/previews/notifications_mailer_preview.rb deleted file mode 100644 index c25687360..000000000 --- a/spec/mailers/previews/notifications_mailer_preview.rb +++ /dev/null @@ -1,7 +0,0 @@ -class NotificationsMailerPreview < ActionMailer::Preview - NotificationType::NAMES.each do |name| - define_method name do - NotificationsMailer.send_mail_by(Notification.where(notification_type_id: NotificationType.find_by_name(name)).last) - end - end -end diff --git a/spec/mailers/previews/users_mailer_preview.rb b/spec/mailers/previews/users_mailer_preview.rb deleted file mode 100644 index 9a61b3ad9..000000000 --- a/spec/mailers/previews/users_mailer_preview.rb +++ /dev/null @@ -1,5 +0,0 @@ -class UsersMailerPreview < ActionMailer::Preview - def notify_user_account_created - UsersMailer.notify_user_account_created(User.first, 'wfwwefwefsdfsdf') - end -end diff --git a/spec/models/abuse_spec.rb b/spec/models/abuse_spec.rb deleted file mode 100644 index 63525cbfc..000000000 --- a/spec/models/abuse_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Abuse, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/auth_provider_spec.rb b/spec/models/auth_provider_spec.rb deleted file mode 100644 index 176f501d9..000000000 --- a/spec/models/auth_provider_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe AuthProvider, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/availability_spec.rb b/spec/models/availability_spec.rb deleted file mode 100644 index 412931f92..000000000 --- a/spec/models/availability_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'rails_helper' - -RSpec.describe Availability, type: :model do - - describe 'create' do - it 'is success with start at, end at and type' - it 'is invalid without start at' - it 'is invalid without end at' - it 'is invalid without type' - it 'is invalid type isnt in [training, machines, event]' - it 'is invalid without training_ids when type training' - it 'is invalid without machine_ids when type machines' - end - - it 'should can associate one or many reservations' - - it 'should can destroy if dont any reservations' - - it 'should get a title' - - it 'should set a number of places' - - it 'should be completed when number of reservations equal number of places' -end diff --git a/spec/models/availability_tag_spec.rb b/spec/models/availability_tag_spec.rb deleted file mode 100644 index 3107b4b33..000000000 --- a/spec/models/availability_tag_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe AvailabilityTag, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/avoir_spec.rb b/spec/models/avoir_spec.rb deleted file mode 100644 index 85d095e97..000000000 --- a/spec/models/avoir_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rails_helper' - -RSpec.describe Avoir, type: :model do - it 'should generate a reference after create' - - it 'is invoiced if avoir mode isnt in [stripe, cheque, transfer, none, cash]' - - it 'should can expire user subscription if avoir indicate subscription to expire' -end diff --git a/spec/models/credit_spec.rb b/spec/models/credit_spec.rb deleted file mode 100644 index 358bc728f..000000000 --- a/spec/models/credit_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'rails_helper' - -RSpec.describe Credit, type: :model do - context 'training' do - it 'should is saved with plan' - end - - context 'machine' do - it 'should is saved with plan and hours' - end -end diff --git a/spec/models/custom_asset_spec.rb b/spec/models/custom_asset_spec.rb deleted file mode 100644 index 0ff1263fd..000000000 --- a/spec/models/custom_asset_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe CustomAsset, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/database_provider_spec.rb b/spec/models/database_provider_spec.rb deleted file mode 100644 index 4b43e2344..000000000 --- a/spec/models/database_provider_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe DatabaseProvider, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/invoice_spec.rb b/spec/models/invoice_spec.rb deleted file mode 100644 index 7d1a78204..000000000 --- a/spec/models/invoice_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rails_helper' - -RSpec.describe Invoice, type: :model do - it 'should generate a reference after create' - - it 'should generate a invoice pdf' - - it 'should can build a avoir' -end diff --git a/spec/models/machine_spec.rb b/spec/models/machine_spec.rb deleted file mode 100644 index a00e0843e..000000000 --- a/spec/models/machine_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'rails_helper' - -RSpec.describe Machine, type: :model do - - describe 'create' do - it 'is success with name, image, description and spec' - it 'is invalid without name' - it 'is invalid without image' - it 'is invalid without description' - it 'is invalid without spec' - it 'should auto generate slug by name' - end - - it 'can have many machine files' - - it 'can have many projects' - - it 'can have many trainings' - - it 'should return an amount by user group' -end diff --git a/spec/models/o_auth2_mapping_spec.rb b/spec/models/o_auth2_mapping_spec.rb deleted file mode 100644 index 9022984ed..000000000 --- a/spec/models/o_auth2_mapping_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe OAuth2Mapping, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/o_auth2_provider_spec.rb b/spec/models/o_auth2_provider_spec.rb deleted file mode 100644 index 67f2cd8cd..000000000 --- a/spec/models/o_auth2_provider_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe OAuth2Provider, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/plan_spec.rb b/spec/models/plan_spec.rb deleted file mode 100644 index 9133ce664..000000000 --- a/spec/models/plan_spec.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'rails_helper' - -RSpec.describe Plan, type: :model do - let(:group){ Group.new(name: 'groupe test', slug: SecureRandom.hex) } - - describe 'validations' do - it 'is success with amount and group' do - plan = Plan.new(amount: 500, group: group) - expect(plan).to be_valid - end - - it 'is invalid without amount' do - plan = Plan.new(group: group) - expect(plan).to be_invalid - end - - it 'is invalid without group' do - plan = Plan.new(amount: 500) - expect(plan).to be_invalid - end - end - - context "on creation" do - before :each do - @plan_id = SecureRandom.hex - @plan_name = SecureRandom.hex - allow(Stripe::Plan).to receive(:create).and_return(double(id: @plan_id, name: @plan_name)) - end - - it 'calls Stripe::Plan create method' do - plan = Plan.create(amount: 500, interval: 'month', group: group) - expect(Stripe::Plan).to have_received :create - end - - it 'saves stripe_plan.id' do - plan = Plan.create(amount: 500, interval: 'month', group: group) - expect(plan.stp_plan_id).to eq(@plan_id) - end - - it 'saves stripe_plan.name' do - plan = Plan.create(amount: 500, interval: 'month', group: group) - expect(plan.name).to eq(@plan_name) - end - end - - context "on update" do - before :each do - allow(Stripe::Plan).to receive(:create).and_return(double(id: SecureRandom.hex, name: SecureRandom.hex)) - end - - let(:plan){ Plan.create(amount: 500, interval: 'month', group: group) } - - describe "update_stripe_plan" do - it "should return false if plan already has subscriptions" do - allow(plan).to receive(:subscriptions).and_return([1,2]) - expect(plan.send(:update_stripe_plan)).to eq(false) - end - end - end -end diff --git a/spec/models/price_spec.rb b/spec/models/price_spec.rb deleted file mode 100644 index 5ce528be5..000000000 --- a/spec/models/price_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Price, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb deleted file mode 100644 index 7ba6c2523..000000000 --- a/spec/models/project_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'rails_helper' - -RSpec.describe Project, type: :model do - - describe 'create' do - it 'is success with author, name and description' - it 'is invalid without author' - it 'is invalid without name' - it 'is invalid without description' - it 'should auto generate slug by name' - end - - it 'save as draft by default' - - it 'should can published' - - it 'should have a published time after published' - - it 'can only add one project main image' - - it 'can have many project caos' - - it 'can have many machines' - - it 'can have many components' - - it 'can have many project steps' - - it 'can add a licence' -end diff --git a/spec/models/reservation_spec.rb b/spec/models/reservation_spec.rb deleted file mode 100644 index 51cbeebd6..000000000 --- a/spec/models/reservation_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'rails_helper' - -RSpec.describe Reservation, type: :model do - describe 'create' do - it 'is success with user, slots and reservable' - it 'is invalid if reservable isnt in [Training, Machine, Event]' - - it 'is success with a subscription' - - context 'stripe' do - it 'should payment success' - it 'is invalid if payment info invalid' - end - - context 'satori' do - it 'should success' - it 'is invalid if payment info invalid' - end - end - - it 'should update user credit after creation' - - it 'should create a invoice' - - it 'should can set a nb reserve places' - - it 'should can set a nb reserve reduced places' -end diff --git a/spec/models/stylesheet_spec.rb b/spec/models/stylesheet_spec.rb deleted file mode 100644 index 68291eb3b..000000000 --- a/spec/models/stylesheet_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Stylesheet, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb deleted file mode 100644 index ffa54d5bd..000000000 --- a/spec/models/subscription_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'rails_helper' - -RSpec.describe Subscription, type: :model do - describe 'create' do - it 'is success with user, plan' - - it 'is success with a subscription' - - context 'stripe' do - it 'should payment success' - it 'is invalid if payment info invalid' - end - - context 'satori' do - it 'should success' - it 'is invalid if payment info invalid' - end - end - - it 'should reset user credit after creation' - - it 'should set a expired at after creation' - - it 'should create a invoice' - -end diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb deleted file mode 100644 index 0d0fcb057..000000000 --- a/spec/models/tag_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Tag, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/training_spec.rb b/spec/models/training_spec.rb deleted file mode 100644 index b3fae28ba..000000000 --- a/spec/models/training_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'rails_helper' - -RSpec.describe Training, type: :model do - - describe 'create' do - it 'is success with name' - it 'is invalid without name' - it 'should auto generate slug by name' - end - - it 'can associate many machines' - - it 'can return a user list that valided by traning' - - it 'should return an amount by user group' - - it 'should can add a number place' -end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb deleted file mode 100644 index e6fef8ef6..000000000 --- a/spec/models/user_spec.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'rails_helper' - -RSpec.describe User, type: :model do - let!(:user) { build :user } - - describe 'create' do - it 'is success if user email, gender, first name, last name, group, birthday and phone are presents' do - expect(user.save).to be true - end - - it 'is invalid when email is empty' do - user.email = nil - expect(user).to be_invalid - end - - it 'is invalid when email format invalid' do - user.email = 'this a invalid email' - expect(user).to be_invalid - end - - it 'is invalid when first name is empty' do - user.profile.first_name = nil - expect(user).to be_invalid - end - - it 'is invalid when last name is empty' do - user.profile.last_name = nil - expect(user).to be_invalid - end - - it 'is invalid when birthday is empty' do - user.profile.birthday = nil - expect(user).to be_invalid - end - - it 'is invalid when phone is empty or not numerical' do - user.profile.phone = nil - expect(user).to be_invalid - user.profile.phone = "phone" - expect(user).to be_invalid - end - - it 'is invalid when group is empty' do - user.group = nil - expect(user).to be_invalid - end - - it 'is invalid when group is empty' do - user.group = nil - expect(user).to be_invalid - end - - it 'is invalid when dont accept cgu' do - user.cgu = '0' - expect(user).to be_invalid - expect(user.errors[:cgu]).to include(I18n.t('activerecord.errors.messages.empty')) - end - end - - context 'after creation' do - it 'has a member role' do - member = create(:user) - expect(member.is_member?).to be true - end - - it 'create a stripe customer' do - member = create(:user) - allow(member).to receive(:create_stripe_customer) { |u| member.stp_customer_id = 'stripe customer id' } - member.run_callbacks(:commit) - expect(member.stp_customer_id).to eq 'stripe customer id' - end - end -end - diff --git a/spec/models/user_tag_spec.rb b/spec/models/user_tag_spec.rb deleted file mode 100644 index 11a927391..000000000 --- a/spec/models/user_tag_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe UserTag, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb deleted file mode 100644 index b4d9ec782..000000000 --- a/spec/rails_helper.rb +++ /dev/null @@ -1,50 +0,0 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV['RAILS_ENV'] ||= 'test' -require 'spec_helper' -require File.expand_path('../../config/environment', __FILE__) -require 'rspec/rails' -# Add additional requires below this line. Rails is not loaded until this point! - -# Requires supporting ruby files with custom matchers and macros, etc, in -# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are -# run as spec files by default. This means that files in spec/support that end -# in _spec.rb will both be required and run as specs, causing the specs to be -# run twice. It is recommended that you do not name files matching this glob to -# end with _spec.rb. You can configure this pattern with the --pattern -# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. -# -# The following line is provided for convenience purposes. It has the downside -# of increasing the boot-up time by auto-requiring all files in the support -# directory. Alternatively, in the individual `*_spec.rb` files, manually -# require only the support files necessary. -# -Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } - -# Checks for pending migrations before tests are run. -# If you are not using ActiveRecord, you can remove this line. -ActiveRecord::Migration.maintain_test_schema! - -RSpec.configure do |config| - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = true - - # RSpec Rails can automatically mix in different behaviours to your tests - # based on their file location, for example enabling you to call `get` and - # `post` in specs under `spec/controllers`. - # - # You can disable this behaviour by removing the line below, and instead - # explicitly tag your specs with their type, e.g.: - # - # RSpec.describe UsersController, :type => :controller do - # # ... - # end - # - # The different available types are documented in the features, such as in - # https://relishapp.com/rspec/rspec-rails/docs - config.infer_spec_type_from_file_location! -end diff --git a/spec/services/notification_center_spec.rb b/spec/services/notification_center_spec.rb deleted file mode 100644 index 424b8ca47..000000000 --- a/spec/services/notification_center_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'rails_helper' - -RSpec.describe NotificationCenter do - let(:receiver1) { create :user } - let(:receiver2) { create :user } - let(:project) { create :project } - - it 'should respond to method .call' do - expect(NotificationCenter).to respond_to(:call) - end - - it 'should create a notification' do - options = { - type: 'notify_admin_when_project_published', - receiver: receiver1, - attached_object: project - } - NotificationCenter.call(options) - expect(Notification.count).to eq 1 - end - - it 'should create same number of notifications with number of receiver' do - options = { - type: 'notify_admin_when_project_published', - receiver: [receiver1, receiver2], - attached_object: project - } - NotificationCenter.call(options) - expect(Notification.count).to eq 2 - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index 38a4f9a16..000000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,87 +0,0 @@ -# This file was generated by the `rails generate rspec:install` command. Conventionally, all -# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. -# The generated `.rspec` file contains `--require spec_helper` which will cause -# this file to always be loaded, without a need to explicitly require it in any -# files. -# -# Given that it is always loaded, you are encouraged to keep this file as -# light-weight as possible. Requiring heavyweight dependencies from this file -# will add to the boot time of your test suite on EVERY test run, even for an -# individual file that may not need all of that loaded. Instead, consider making -# a separate helper file that requires the additional dependencies and performs -# the additional setup, and require it from the spec files that actually need -# it. -# -# The `.rspec` file also contains a few flags that are not defaults but that -# users commonly want. -# -# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration -RSpec.configure do |config| - # rspec-expectations config goes here. You can use an alternate - # assertion/expectation library such as wrong or the stdlib/minitest - # assertions if you prefer. - config.expect_with :rspec do |expectations| - # This option will default to `true` in RSpec 4. It makes the `description` - # and `failure_message` of custom matchers include text for helper methods - # defined using `chain`, e.g.: - # be_bigger_than(2).and_smaller_than(4).description - # # => "be bigger than 2 and smaller than 4" - # ...rather than: - # # => "be bigger than 2" - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - # rspec-mocks config goes here. You can use an alternate test double - # library (such as bogus or mocha) by changing the `mock_with` option here. - config.mock_with :rspec do |mocks| - # Prevents you from mocking or stubbing a method that does not exist on - # a real object. This is generally recommended, and will default to - # `true` in RSpec 4. - mocks.verify_partial_doubles = true - end - -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # These two settings work together to allow you to limit a spec run - # to individual examples or groups you care about by tagging them with - # `:focus` metadata. When nothing is tagged with `:focus`, all examples - # get run. - config.filter_run :focus - config.run_all_when_everything_filtered = true - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax - # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end -end diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb deleted file mode 100644 index 4a54cd361..000000000 --- a/spec/support/database_cleaner.rb +++ /dev/null @@ -1,17 +0,0 @@ -RSpec.configure do |config| - - config.before(:suite) do - # The :transaction strategy prevents :after_commit hooks from running - DatabaseCleaner.strategy = :transaction - DatabaseCleaner.clean_with(:truncation) - # load seeds only for test - load "#{Rails.root}/db/test_seeds.rb" - end - - config.around(:each) do |example| - DatabaseCleaner.cleaning do - example.run - end - end - -end diff --git a/spec/support/factory_girl.rb b/spec/support/factory_girl.rb deleted file mode 100644 index 43662908a..000000000 --- a/spec/support/factory_girl.rb +++ /dev/null @@ -1,12 +0,0 @@ -RSpec.configure do |config| - config.include FactoryGirl::Syntax::Methods - - config.before(:suite) do - begin - DatabaseCleaner.start - FactoryGirl.lint - ensure - DatabaseCleaner.clean - end - end -end From fafec2153c2dc8d45bdf5f54c610013abcbe3df7 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Mon, 4 Apr 2016 17:42:45 +0200 Subject: [PATCH 02/64] setup test environment and add the first test --- Gemfile | 10 ++-- Gemfile.lock | 78 +++++--------------------------- app/models/availability.rb | 4 +- config/environments/test.rb | 2 +- test/fixtures/availabilities.yml | 11 +++++ test/models/availability_test.rb | 9 ++++ test/test_helper.rb | 13 ++++++ 7 files changed, 51 insertions(+), 76 deletions(-) create mode 100644 test/fixtures/availabilities.yml create mode 100644 test/models/availability_test.rb diff --git a/Gemfile b/Gemfile index 0a4c19a8d..a007840fa 100644 --- a/Gemfile +++ b/Gemfile @@ -34,12 +34,6 @@ group :development, :test do # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' - gem 'factory_girl_rails' - gem 'rspec-rails' - gem 'spring-commands-rspec' - - gem 'guard-rspec', require: false - gem 'railroady' end @@ -62,6 +56,8 @@ end group :test do gem 'database_cleaner' gem 'faker' + gem 'test_after_commit' + gem 'minitest-reporters' end group :production do @@ -137,4 +133,4 @@ gem 'chroma' gem 'protected_attributes' -gem 'message_format' \ No newline at end of file +gem 'message_format' diff --git a/Gemfile.lock b/Gemfile.lock index 2d6b1b45e..4d973af84 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -41,6 +41,7 @@ GEM thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) addressable (2.3.8) + ansi (1.5.0) arel (6.0.3) autoprefixer-rails (5.1.8) execjs @@ -80,7 +81,6 @@ GEM chroma (0.0.1) chunky_png (1.3.4) cldr-plurals-runtime-rb (1.0.1) - coderay (1.1.0) coercible (1.0.0) descendants_tracker (~> 0.0.1) coffee-rails (4.1.0) @@ -120,7 +120,6 @@ GEM warden (~> 1.2.3) devise-async (0.9.0) devise (~> 3.2) - diff-lcs (1.2.5) domain_name (0.5.25) unf (>= 0.0.5, < 1.0.0) elasticsearch (1.0.12) @@ -146,11 +145,6 @@ GEM equalizer (0.0.11) erubis (2.7.0) execjs (2.4.0) - factory_girl (4.5.0) - activesupport (>= 3.0.0) - factory_girl_rails (4.5.0) - factory_girl (~> 4.5.0) - railties (>= 3.0.0) faker (1.4.3) i18n (~> 0.5) faraday (0.9.1) @@ -163,25 +157,10 @@ GEM foreman (0.78.0) thor (~> 0.19.1) forgery (0.6.0) - formatador (0.2.5) friendly_id (5.1.0) activerecord (>= 4.0.0) globalid (0.3.6) activesupport (>= 4.1.0) - guard (2.12.5) - formatador (>= 0.2.4) - listen (~> 2.7) - lumberjack (~> 1.0) - nenv (~> 0.1) - notiffany (~> 0.0) - pry (>= 0.9.12) - shellany (~> 0.0) - thor (>= 0.18.1) - guard-compat (1.2.1) - guard-rspec (4.5.0) - guard (~> 2.1) - guard-compat (~> 1.1) - rspec (>= 2.99.0, < 4.0) hashie (3.4.2) highline (1.7.1) hike (1.2.3) @@ -211,29 +190,27 @@ GEM letter_opener (1.3.0) launchy (~> 2.2) libv8 (3.16.14.11) - listen (2.10.0) - celluloid (~> 0.16.0) - rb-fsevent (>= 0.9.3) - rb-inotify (>= 0.9) loofah (2.0.3) nokogiri (>= 1.5.9) - lumberjack (1.0.9) mail (2.6.3) mime-types (>= 1.16, < 3) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) message_format (0.0.3) twitter_cldr (~> 3.1) - method_source (0.8.2) mime-types (2.99) mini_magick (4.2.0) mini_portile (0.6.2) minitest (5.8.3) + minitest-reporters (1.1.8) + ansi + builder + minitest (>= 5.0) + ruby-progressbar multi_json (1.11.2) multi_xml (0.5.5) multipart-post (2.0.0) naught (1.0.0) - nenv (0.2.0) net-scp (1.2.1) net-ssh (>= 2.6.5) net-sftp (2.1.2) @@ -244,9 +221,6 @@ GEM netrc (0.10.3) nokogiri (1.6.6.4) mini_portile (~> 0.6.0) - notiffany (0.0.6) - nenv (~> 0.1) - shellany (~> 0.0) notify_with (0.0.2) jbuilder (~> 2.0) rails (>= 4.2.0) @@ -273,10 +247,6 @@ GEM prawn-table (0.2.1) protected_attributes (1.1.3) activemodel (>= 4.0.1, < 5.0) - pry (0.10.1) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) puma (2.11.1) rack (>= 1.1, < 2.0) pundit (1.0.0) @@ -338,27 +308,7 @@ GEM mime-types (>= 1.16, < 3.0) netrc (~> 0.7) rolify (4.0.0) - rspec (3.2.0) - rspec-core (~> 3.2.0) - rspec-expectations (~> 3.2.0) - rspec-mocks (~> 3.2.0) - rspec-core (3.2.2) - rspec-support (~> 3.2.0) - rspec-expectations (3.2.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) - rspec-mocks (3.2.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) - rspec-rails (3.2.1) - actionpack (>= 3.0, < 4.3) - activesupport (>= 3.0, < 4.3) - railties (>= 3.0, < 4.3) - rspec-core (~> 3.2.0) - rspec-expectations (~> 3.2.0) - rspec-mocks (~> 3.2.0) - rspec-support (~> 3.2.0) - rspec-support (3.2.2) + ruby-progressbar (1.7.5) rufus-scheduler (3.0.9) tzinfo rvm-capistrano (1.5.6) @@ -376,7 +326,6 @@ GEM seed_dump (3.2.2) activerecord (~> 4) activesupport (~> 4) - shellany (0.0.1) sidekiq (3.3.4) celluloid (>= 0.16.0) connection_pool (>= 2.1.1) @@ -392,10 +341,7 @@ GEM rack (~> 1.4) rack-protection (~> 1.4) tilt (>= 1.3, < 3) - slop (3.6.0) spring (1.3.5) - spring-commands-rspec (1.0.4) - spring (>= 0.9.1) sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) @@ -408,6 +354,8 @@ GEM stripe (1.30.2) json (~> 1.8.1) rest-client (~> 1.4) + test_after_commit (1.0.0) + activerecord (>= 3.2) therubyracer (0.12.0) libv8 (~> 3.16.14.0) ref @@ -482,20 +430,19 @@ DEPENDENCIES elasticsearch-model elasticsearch-persistence elasticsearch-rails - factory_girl_rails faker figaro font-awesome-rails foreman forgery friendly_id (~> 5.1.0) - guard-rspec jbuilder (~> 2.0) jquery-rails kaminari letter_opener message_format mini_magick + minitest-reporters notify_with oj omniauth @@ -513,7 +460,6 @@ DEPENDENCIES recurrence responders (~> 2.0) rolify - rspec-rails rvm-capistrano sass-rails (= 5.0.1) sdoc (~> 0.4.0) @@ -522,8 +468,8 @@ DEPENDENCIES sidekiq-cron sinatra spring - spring-commands-rspec stripe (= 1.30.2) + test_after_commit therubyracer (= 0.12.0) twitter twitter-text @@ -532,4 +478,4 @@ DEPENDENCIES web-console (~> 2.0) BUNDLED WITH - 1.10.6 + 1.11.2 diff --git a/app/models/availability.rb b/app/models/availability.rb index 11135cd85..d360b3861 100644 --- a/app/models/availability.rb +++ b/app/models/availability.rb @@ -64,13 +64,13 @@ class Availability < ActiveRecord::Base private def length_must_be_1h_minimum if end_at < (start_at + 1.hour) - errors.add(:end_at, t('availabilities.must_be_at_least_1_hour_after_the_start_date')) + errors.add(:end_at, I18n.t('availabilities.must_be_at_least_1_hour_after_the_start_date')) end end def should_be_associated if available_type == 'machines' and machine_ids.count == 0 - errors.add(:machine_ids, t('availabilities.must_be_associated_with_at_least_1_machine')) + errors.add(:machine_ids, I18n.t('availabilities.must_be_associated_with_at_least_1_machine')) end end diff --git a/config/environments/test.rb b/config/environments/test.rb index d9cabe25b..224c4f69f 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -39,6 +39,6 @@ Rails.application.configure do # Raises error for missing translations # config.action_view.raise_on_missing_translations = true - + config.active_support.test_order = :random end diff --git a/test/fixtures/availabilities.yml b/test/fixtures/availabilities.yml new file mode 100644 index 000000000..937a0c002 --- /dev/null +++ b/test/fixtures/availabilities.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/models/availability_test.rb b/test/models/availability_test.rb new file mode 100644 index 000000000..53d48faf7 --- /dev/null +++ b/test/models/availability_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class AvailabilityTest < ActiveSupport::TestCase + test "length must be at least 1h" do + a = Availability.new(start_at: Time.now, end_at: 15.minutes.from_now) + assert a.invalid? + assert a.errors.key?(:end_at) + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 3acf9ae30..d4ed115ca 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,7 +1,20 @@ ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' +require 'sidekiq/testing' +Sidekiq::Testing.fake! + +require 'minitest/reporters' +Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new({ color: true })] + class ActiveSupport::TestCase # Add more helper methods to be used by all tests here... + + fixtures :all +end + +class ActionDispatch::IntegrationTest + include Warden::Test::Helpers + Warden.test_mode! end From 4a1c67c8d55ca015d19af8af51fe86663c0a78c4 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 09:51:12 +0200 Subject: [PATCH 03/64] adds method to parse json reponse --- test/test_helper.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_helper.rb b/test/test_helper.rb index d4ed115ca..4e951ee6f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -12,6 +12,10 @@ class ActiveSupport::TestCase # Add more helper methods to be used by all tests here... fixtures :all + + def json_response(body) + JSON.parse(body, symbolize_names: true) + end end class ActionDispatch::IntegrationTest From 5d38f1e3a56a45b402e996502cdb10c84364e77c Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 09:57:09 +0200 Subject: [PATCH 04/64] does not validate length of availability if start_at or end_at are blank and already missing --- app/models/availability.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/availability.rb b/app/models/availability.rb index d360b3861..0790fdc8f 100644 --- a/app/models/availability.rb +++ b/app/models/availability.rb @@ -20,7 +20,8 @@ class Availability < ActiveRecord::Base attr_accessor :is_reserved, :slot_id, :can_modify - validate :length_must_be_1h_minimum + validates :start_at, :end_at, presence: true + validate :length_must_be_1h_minimum, unless: proc { end_at.blank? or start_at.blank? } validate :should_be_associated def safe_destroy From 26e3f5bf8c0223127a119d24aa6970017b863375 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 10:03:58 +0200 Subject: [PATCH 05/64] adds a test to availability model test --- test/models/availability_test.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/models/availability_test.rb b/test/models/availability_test.rb index 53d48faf7..e7b35b388 100644 --- a/test/models/availability_test.rb +++ b/test/models/availability_test.rb @@ -6,4 +6,10 @@ class AvailabilityTest < ActiveSupport::TestCase assert a.invalid? assert a.errors.key?(:end_at) end + + test "if type available_type is 'machines' check that there is minimum 1 association" do + a = Availability.new(start_at: Time.now, end_at: 2.hours.from_now, available_type: 'machines') + assert a.invalid? + assert a.errors.key?(:machine_ids) + end end From 272400a889fa564b867095b20224dda699ab60b1 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 10:04:15 +0200 Subject: [PATCH 06/64] adds a dummy integration test --- test/integration/availabilities_test.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/integration/availabilities_test.rb diff --git a/test/integration/availabilities_test.rb b/test/integration/availabilities_test.rb new file mode 100644 index 000000000..aa9213667 --- /dev/null +++ b/test/integration/availabilities_test.rb @@ -0,0 +1,16 @@ +class AvailabilitiesTest < ActionDispatch::IntegrationTest + setup do + @profile = Profile.create!(gender: true, birthday: 20.years.ago, first_name: "Admin", last_name: "Sleede", phone: "06542868451") + @admin = User.create!(cgu: true, username: 'blabla', email: 'abc@sleede.com', password: 'kikoulol', password_confirmation: 'kikoulol', profile: @profile) + @admin.add_role(:admin) + login_as(@admin, scope: :user) + end + + test "return availability by id" do + a = Availability.create!(start_at: Time.now, end_at: 2.hours.from_now, available_type: 'trainings') + + + get "/api/availabilities/#{a.id}" + assert_equal 200, response.status + end +end From 6bcc03834a58f869e986d5ae2c13a698654f57a4 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 10:08:29 +0200 Subject: [PATCH 07/64] adds a method to ActiveRecord::Base to dump a model to fixture --- config/initializers/active_record_base.rb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 config/initializers/active_record_base.rb diff --git a/config/initializers/active_record_base.rb b/config/initializers/active_record_base.rb new file mode 100644 index 000000000..f54d93090 --- /dev/null +++ b/config/initializers/active_record_base.rb @@ -0,0 +1,9 @@ +ActiveRecord::Base.class_eval do + def dump_fixture + fixture_file = "#{Rails.root}/test/fixtures/#{self.class.table_name}.yml" + File.open(fixture_file, "a") do |f| + f.puts({ "#{self.class.table_name.singularize}_#{id}" => attributes }. + to_yaml.sub!(/---\s?/, "\n")) + end + end +end From 3e112c13ebcec291545be6185d16a3924b169785 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 10:52:29 +0200 Subject: [PATCH 08/64] removes model and migrations relative to old model machines_pricings --- app/models/machines_pricing.rb | 9 - ...20140606133116_create_machines_pricings.rb | 13 -- ...e_data_from_machines_pricings_to_prices.rb | 35 ---- .../20150603133050_drop_machines_pricings.rb | 5 - db/schema.rb | 178 +++++++++--------- 5 files changed, 89 insertions(+), 151 deletions(-) delete mode 100644 app/models/machines_pricing.rb delete mode 100644 db/migrate/20140606133116_create_machines_pricings.rb delete mode 100644 db/migrate/20150520133409_migrate_data_from_machines_pricings_to_prices.rb delete mode 100644 db/migrate/20150603133050_drop_machines_pricings.rb diff --git a/app/models/machines_pricing.rb b/app/models/machines_pricing.rb deleted file mode 100644 index f52d5d245..000000000 --- a/app/models/machines_pricing.rb +++ /dev/null @@ -1,9 +0,0 @@ -##DEPRECATED, this class is not used anymore from the migration to the Pricing model -##TODO remove in future update, in conjunction with the following migrations: -# - 20140606133116_create_machines_pricings.rb -# - 20150520133409_migrate_data_from_machines_pricings_to_prices.rb -# - 20150603133050_drop_machines_pricings.rb -class MachinesPricing < ActiveRecord::Base - belongs_to :machine - belongs_to :group -end diff --git a/db/migrate/20140606133116_create_machines_pricings.rb b/db/migrate/20140606133116_create_machines_pricings.rb deleted file mode 100644 index 148705e10..000000000 --- a/db/migrate/20140606133116_create_machines_pricings.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateMachinesPricings < ActiveRecord::Migration - def change - create_table :machines_pricings do |t| - t.belongs_to :machine, index: true - t.belongs_to :group, index: true - t.integer :not_subscribe_amount - t.integer :month_amount - t.integer :year_amount - - t.timestamps - end - end -end diff --git a/db/migrate/20150520133409_migrate_data_from_machines_pricings_to_prices.rb b/db/migrate/20150520133409_migrate_data_from_machines_pricings_to_prices.rb deleted file mode 100644 index d9c71c79c..000000000 --- a/db/migrate/20150520133409_migrate_data_from_machines_pricings_to_prices.rb +++ /dev/null @@ -1,35 +0,0 @@ -class MigrateDataFromMachinesPricingsToPrices < ActiveRecord::Migration - def up - insert <<-SQL - DELETE FROM machines_pricings WHERE machine_id NOT IN ( select distinct machines.id from machines ) - SQL - - machines_pricings = select_all("SELECT * FROM machines_pricings") - machines_pricings.each do |m_pricing| - time = "'#{Time.now.to_s(:db)}'" - - plan_year = select_one("SELECT id FROM plans where plans.group_id = #{m_pricing['group_id']} and plans.interval = 'year'") - insert <<-SQL - INSERT INTO prices (group_id, plan_id, priceable_id, priceable_type, amount, created_at, updated_at) - VALUES (#{m_pricing['group_id']}, #{plan_year['id']}, #{m_pricing['machine_id']}, 'Machine', #{m_pricing['year_amount']}, #{time}, #{time}) - SQL - - plan_month = select_one("SELECT id FROM plans where plans.group_id = #{m_pricing['group_id']} and plans.interval = 'month'") - insert <<-SQL - INSERT INTO prices (group_id, plan_id, priceable_id, priceable_type, amount, created_at, updated_at) - VALUES (#{m_pricing['group_id']}, #{plan_month['id']}, #{m_pricing['machine_id']}, 'Machine', #{m_pricing['month_amount']}, #{time}, #{time}) - SQL - - insert <<-SQL - INSERT INTO prices (group_id, plan_id, priceable_id, priceable_type, amount, created_at, updated_at) - VALUES (#{m_pricing['group_id']}, NULL, #{m_pricing['machine_id']}, 'Machine', #{m_pricing['not_subscribe_amount']}, #{time}, #{time}) - SQL - end - end - - def down - insert <<-SQL - DELETE FROM prices - SQL - end -end diff --git a/db/migrate/20150603133050_drop_machines_pricings.rb b/db/migrate/20150603133050_drop_machines_pricings.rb deleted file mode 100644 index f1502b997..000000000 --- a/db/migrate/20150603133050_drop_machines_pricings.rb +++ /dev/null @@ -1,5 +0,0 @@ -class DropMachinesPricings < ActiveRecord::Migration - def up - drop_table :machines_pricings - end -end diff --git a/db/schema.rb b/db/schema.rb index 162b94922..f346c4f84 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -30,23 +30,23 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "abuses", ["signaled_type", "signaled_id"], name: "index_abuses_on_signaled_type_and_signaled_id", using: :btree create_table "addresses", force: :cascade do |t| - t.string "address", limit: 255 - t.string "street_number", limit: 255 - t.string "route", limit: 255 - t.string "locality", limit: 255 - t.string "country", limit: 255 - t.string "postal_code", limit: 255 + t.string "address" + t.string "street_number" + t.string "route" + t.string "locality" + t.string "country" + t.string "postal_code" t.integer "placeable_id" - t.string "placeable_type", limit: 255 + t.string "placeable_type" t.datetime "created_at" t.datetime "updated_at" end create_table "assets", force: :cascade do |t| t.integer "viewable_id" - t.string "viewable_type", limit: 255 - t.string "attachment", limit: 255 - t.string "type", limit: 255 + t.string "viewable_type" + t.string "attachment" + t.string "type" t.datetime "created_at" t.datetime "updated_at" end @@ -63,11 +63,11 @@ ActiveRecord::Schema.define(version: 20160119131623) do create_table "availabilities", force: :cascade do |t| t.datetime "start_at" t.datetime "end_at" - t.string "available_type", limit: 255 + t.string "available_type" t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.boolean "destroying", default: false + t.boolean "destroying", default: false end create_table "availability_tags", force: :cascade do |t| @@ -81,18 +81,18 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree create_table "categories", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.datetime "created_at" t.datetime "updated_at" end create_table "components", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false end create_table "credits", force: :cascade do |t| t.integer "creditable_id" - t.string "creditable_type", limit: 255 + t.string "creditable_type" t.integer "plan_id" t.integer "hours" t.datetime "created_at" @@ -113,7 +113,7 @@ ActiveRecord::Schema.define(version: 20160119131623) do end create_table "events", force: :cascade do |t| - t.string "title", limit: 255 + t.string "title" t.text "description" t.datetime "created_at" t.datetime "updated_at" @@ -139,10 +139,10 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "events_categories", ["event_id"], name: "index_events_categories_on_event_id", using: :btree create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", limit: 255, null: false - t.integer "sluggable_id", null: false + t.string "slug", null: false + t.integer "sluggable_id", null: false t.string "sluggable_type", limit: 50 - t.string "scope", limit: 255 + t.string "scope" t.datetime "created_at" end @@ -152,17 +152,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "groups", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.datetime "created_at" t.datetime "updated_at" - t.string "slug", limit: 255 + t.string "slug" end add_index "groups", ["slug"], name: "index_groups_on_slug", unique: true, using: :btree create_table "invoice_items", force: :cascade do |t| t.integer "invoice_id" - t.string "stp_invoice_item_id", limit: 255 + t.string "stp_invoice_item_id" t.integer "amount" t.datetime "created_at" t.datetime "updated_at" @@ -175,17 +175,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do create_table "invoices", force: :cascade do |t| t.integer "invoiced_id" - t.string "invoiced_type", limit: 255 - t.string "stp_invoice_id", limit: 255 + t.string "invoiced_type" + t.string "stp_invoice_id" t.integer "total" t.datetime "created_at" t.datetime "updated_at" t.integer "user_id" - t.string "reference", limit: 255 - t.string "avoir_mode", limit: 255 + t.string "reference" + t.string "avoir_mode" t.datetime "avoir_date" t.integer "invoice_id" - t.string "type", limit: 255 + t.string "type" t.boolean "subscription_to_expire" t.text "description" end @@ -194,17 +194,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "invoices", ["user_id"], name: "index_invoices_on_user_id", using: :btree create_table "licences", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false t.text "description" end create_table "machines", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false t.text "description" t.text "spec" t.datetime "created_at" t.datetime "updated_at" - t.string "slug", limit: 255 + t.string "slug" end add_index "machines", ["slug"], name: "index_machines_on_slug", unique: true, using: :btree @@ -220,14 +220,14 @@ ActiveRecord::Schema.define(version: 20160119131623) do create_table "notifications", force: :cascade do |t| t.integer "receiver_id" t.integer "attached_object_id" - t.string "attached_object_type", limit: 255 + t.string "attached_object_type" t.integer "notification_type_id" - t.boolean "is_read", default: false + t.boolean "is_read", default: false t.datetime "created_at" t.datetime "updated_at" - t.string "receiver_type", limit: 255 - t.boolean "is_send", default: false - t.jsonb "meta_data", default: {} + t.string "receiver_type" + t.boolean "is_send", default: false + t.jsonb "meta_data", default: {} end add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree @@ -268,20 +268,20 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "offer_days", ["subscription_id"], name: "index_offer_days_on_subscription_id", using: :btree create_table "plans", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.integer "amount" - t.string "interval", limit: 255 + t.string "interval" t.integer "group_id" - t.string "stp_plan_id", limit: 255 + t.string "stp_plan_id" t.datetime "created_at" t.datetime "updated_at" - t.integer "training_credit_nb", default: 0 - t.boolean "is_rolling", default: true + t.integer "training_credit_nb", default: 0 + t.boolean "is_rolling", default: true t.text "description" t.string "type" t.string "base_name" - t.integer "ui_weight", default: 0 - t.integer "interval_count", default: 1 + t.integer "ui_weight", default: 0 + t.integer "interval_count", default: 1 end add_index "plans", ["group_id"], name: "index_plans_on_group_id", using: :btree @@ -302,11 +302,11 @@ ActiveRecord::Schema.define(version: 20160119131623) do create_table "profiles", force: :cascade do |t| t.integer "user_id" - t.string "first_name", limit: 255 - t.string "last_name", limit: 255 + t.string "first_name" + t.string "last_name" t.boolean "gender" t.date "birthday" - t.string "phone", limit: 255 + t.string "phone" t.text "interest" t.text "software_mastered" t.datetime "created_at" @@ -320,7 +320,7 @@ ActiveRecord::Schema.define(version: 20160119131623) do t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" - t.string "title", limit: 255 + t.string "title" end add_index "project_steps", ["project_id"], name: "index_project_steps_on_project_id", using: :btree @@ -330,23 +330,23 @@ ActiveRecord::Schema.define(version: 20160119131623) do t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_valid", default: false - t.string "valid_token", limit: 255 + t.boolean "is_valid", default: false + t.string "valid_token" end add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree create_table "projects", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.text "description" t.datetime "created_at" t.datetime "updated_at" t.integer "author_id" t.text "tags" t.integer "licence_id" - t.string "state", limit: 255 - t.string "slug", limit: 255 + t.string "state" + t.string "slug" t.datetime "published_at" end @@ -382,20 +382,20 @@ ActiveRecord::Schema.define(version: 20160119131623) do t.datetime "created_at" t.datetime "updated_at" t.integer "reservable_id" - t.string "reservable_type", limit: 255 - t.string "stp_invoice_id", limit: 255 + t.string "reservable_type" + t.string "stp_invoice_id" t.integer "nb_reserve_places" t.integer "nb_reserve_reduced_places" end - add_index "reservations", ["reservable_id", "reservable_type"], name: "index_reservations_on_reservable_id_and_reservable_type", using: :btree + add_index "reservations", ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id", using: :btree add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree add_index "reservations", ["user_id"], name: "index_reservations_on_user_id", using: :btree create_table "roles", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.integer "resource_id" - t.string "resource_type", limit: 255 + t.string "resource_type" t.datetime "created_at" t.datetime "updated_at" end @@ -420,8 +420,8 @@ ActiveRecord::Schema.define(version: 20160119131623) do t.datetime "updated_at" t.integer "availability_id" t.datetime "ex_start_at" - t.datetime "canceled_at" t.datetime "ex_end_at" + t.datetime "canceled_at" t.boolean "offered", default: false end @@ -430,18 +430,18 @@ ActiveRecord::Schema.define(version: 20160119131623) do create_table "statistic_fields", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key", limit: 255 - t.string "label", limit: 255 + t.string "key" + t.string "label" t.datetime "created_at" t.datetime "updated_at" - t.string "data_type", limit: 255 + t.string "data_type" end add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree create_table "statistic_graphs", force: :cascade do |t| t.integer "statistic_index_id" - t.string "chart_type", limit: 255 + t.string "chart_type" t.integer "limit" t.datetime "created_at" t.datetime "updated_at" @@ -450,17 +450,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree create_table "statistic_indices", force: :cascade do |t| - t.string "es_type_key", limit: 255 - t.string "label", limit: 255 + t.string "es_type_key" + t.string "label" t.datetime "created_at" t.datetime "updated_at" - t.boolean "table", default: true - t.boolean "ca", default: true + t.boolean "table", default: true + t.boolean "ca", default: true end create_table "statistic_sub_types", force: :cascade do |t| - t.string "key", limit: 255 - t.string "label", limit: 255 + t.string "key" + t.string "label" t.datetime "created_at" t.datetime "updated_at" end @@ -477,8 +477,8 @@ ActiveRecord::Schema.define(version: 20160119131623) do create_table "statistic_types", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key", limit: 255 - t.string "label", limit: 255 + t.string "key" + t.string "label" t.boolean "graph" t.datetime "created_at" t.datetime "updated_at" @@ -496,7 +496,7 @@ ActiveRecord::Schema.define(version: 20160119131623) do create_table "subscriptions", force: :cascade do |t| t.integer "plan_id" t.integer "user_id" - t.string "stp_subscription_id", limit: 255 + t.string "stp_subscription_id" t.datetime "created_at" t.datetime "updated_at" t.datetime "expired_at" @@ -515,15 +515,15 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree create_table "themes", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false end create_table "trainings", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.string "slug", limit: 255 + t.string "slug" t.text "description" end @@ -579,32 +579,32 @@ ActiveRecord::Schema.define(version: 20160119131623) do add_index "user_trainings", ["user_id"], name: "index_user_trainings_on_user_id", using: :btree create_table "users", force: :cascade do |t| - t.string "username", limit: 255 - t.string "email", limit: 255, default: "", null: false - t.string "encrypted_password", limit: 255, default: "", null: false - t.string "reset_password_token", limit: 255 + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip", limit: 255 - t.string "last_sign_in_ip", limit: 255 - t.string "confirmation_token", limit: 255 + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email", limit: 255 - t.integer "failed_attempts", default: 0, null: false - t.string "unlock_token", limit: 255 + t.string "unconfirmed_email" + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" t.datetime "locked_at" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_allow_contact", default: true + t.boolean "is_allow_contact", default: true t.integer "group_id" - t.string "stp_customer_id", limit: 255 - t.string "slug", limit: 255 - t.boolean "is_active", default: true - t.boolean "invoicing_disabled", default: false + t.string "stp_customer_id" + t.string "username" + t.string "slug" + t.boolean "is_active", default: true + t.boolean "invoicing_disabled", default: false t.string "provider" t.string "uid" t.string "auth_token" From a2c09a3ff22391a97932f5506d456314288aad7e Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 11:02:49 +0200 Subject: [PATCH 09/64] adds rake task to generate fixtures from db, adds a class method to ActiveRecord::Base to generate fixtures --- config/initializers/active_record_base.rb | 9 +++++++++ lib/tasks/fablab.rake | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/config/initializers/active_record_base.rb b/config/initializers/active_record_base.rb index f54d93090..fc57f008d 100644 --- a/config/initializers/active_record_base.rb +++ b/config/initializers/active_record_base.rb @@ -6,4 +6,13 @@ ActiveRecord::Base.class_eval do to_yaml.sub!(/---\s?/, "\n")) end end + + def self.dump_fixtures + fixture_file = "#{Rails.root}/test/fixtures/#{self.table_name}.yml" + File.open(fixture_file, "w") do |f| + self.all.each do |instance| + f.puts({ "#{self.table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) + end + end + end end diff --git a/lib/tasks/fablab.rake b/lib/tasks/fablab.rake index 7aa432945..28dbc701a 100644 --- a/lib/tasks/fablab.rake +++ b/lib/tasks/fablab.rake @@ -177,4 +177,13 @@ namespace :fablab do puts "\nUsers successfully notified\n\n" end + + desc "generate fixtures from db" + task generate_fixtures: :environment do + Rails.application.eager_load! + ActiveRecord::Base.descendants.reject { |c| c == ActiveRecord::SchemaMigration }.each do |ar_base| + p "========== #{ar_base} ==============" + ar_base.dump_fixtures + end + end end From dd6ecaa1cdb30573ded99841bb7d97e51eb38ef9 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 12:05:40 +0200 Subject: [PATCH 10/64] finally succeed to generate fixtures from db --- config/initializers/active_record_base.rb | 3 +- lib/tasks/fablab.rake | 2 +- test/fixtures/abuses.yml | 0 test/fixtures/addresses.yml | 52 ++++ test/fixtures/assets.yml | 126 +++++++++ test/fixtures/auth_providers.yml | 9 + test/fixtures/availabilities.yml | 119 +++++++- test/fixtures/availability_tags.yml | 21 ++ test/fixtures/categories.yml | 12 + test/fixtures/components.yml | 40 +++ test/fixtures/credits.yml | 99 +++++++ test/fixtures/custom_assets.yml | 0 test/fixtures/database_providers.yml | 5 + test/fixtures/events.yml | 42 +++ test/fixtures/events_categories.yml | 84 ++++++ test/fixtures/groups.yml | 14 + test/fixtures/invoice_items.yml | 23 ++ test/fixtures/invoices.yml | 34 +++ test/fixtures/licences.yml | 47 ++++ test/fixtures/machines.yml | 125 +++++++++ test/fixtures/machines_availabilities.yml | 85 ++++++ test/fixtures/notifications.yml | 182 +++++++++++++ test/fixtures/o_auth2_mappings.yml | 0 test/fixtures/o_auth2_providers.yml | 0 test/fixtures/offer_days.yml | 0 test/fixtures/plans.yml | 52 ++++ test/fixtures/prices.yml | 300 +++++++++++++++++++++ test/fixtures/profiles.yml | 78 ++++++ test/fixtures/project_steps.yml | 18 ++ test/fixtures/project_users.yml | 0 test/fixtures/projects.yml | 14 + test/fixtures/projects_components.yml | 20 ++ test/fixtures/projects_machines.yml | 20 ++ test/fixtures/projects_themes.yml | 10 + test/fixtures/reservations.yml | 0 test/fixtures/roles.yml | 32 +++ test/fixtures/settings.yml | 235 ++++++++++++++++ test/fixtures/slots.yml | 0 test/fixtures/statistic_fields.yml | 90 +++++++ test/fixtures/statistic_graphs.yml | 48 ++++ test/fixtures/statistic_indices.yml | 63 +++++ test/fixtures/statistic_sub_types.yml | 155 +++++++++++ test/fixtures/statistic_type_sub_types.yml | 245 +++++++++++++++++ test/fixtures/statistic_types.yml | 110 ++++++++ test/fixtures/stylesheets.yml | 39 +++ test/fixtures/subscriptions.yml | 20 ++ test/fixtures/tags.yml | 12 + test/fixtures/themes.yml | 28 ++ test/fixtures/trainings.yml | 45 ++++ test/fixtures/trainings_availabilities.yml | 21 ++ test/fixtures/trainings_machines.yml | 50 ++++ test/fixtures/trainings_pricings.yml | 80 ++++++ test/fixtures/user_tags.yml | 0 test/fixtures/user_trainings.yml | 0 test/fixtures/users.yml | 198 ++++++++++++++ test/fixtures/users_credits.yml | 0 test/fixtures/users_roles.yml | 56 ++++ 57 files changed, 3151 insertions(+), 12 deletions(-) create mode 100644 test/fixtures/abuses.yml create mode 100644 test/fixtures/addresses.yml create mode 100644 test/fixtures/assets.yml create mode 100644 test/fixtures/auth_providers.yml create mode 100644 test/fixtures/availability_tags.yml create mode 100644 test/fixtures/categories.yml create mode 100644 test/fixtures/components.yml create mode 100644 test/fixtures/credits.yml create mode 100644 test/fixtures/custom_assets.yml create mode 100644 test/fixtures/database_providers.yml create mode 100644 test/fixtures/events.yml create mode 100644 test/fixtures/events_categories.yml create mode 100644 test/fixtures/groups.yml create mode 100644 test/fixtures/invoice_items.yml create mode 100644 test/fixtures/invoices.yml create mode 100644 test/fixtures/licences.yml create mode 100644 test/fixtures/machines.yml create mode 100644 test/fixtures/machines_availabilities.yml create mode 100644 test/fixtures/notifications.yml create mode 100644 test/fixtures/o_auth2_mappings.yml create mode 100644 test/fixtures/o_auth2_providers.yml create mode 100644 test/fixtures/offer_days.yml create mode 100644 test/fixtures/plans.yml create mode 100644 test/fixtures/prices.yml create mode 100644 test/fixtures/profiles.yml create mode 100644 test/fixtures/project_steps.yml create mode 100644 test/fixtures/project_users.yml create mode 100644 test/fixtures/projects.yml create mode 100644 test/fixtures/projects_components.yml create mode 100644 test/fixtures/projects_machines.yml create mode 100644 test/fixtures/projects_themes.yml create mode 100644 test/fixtures/reservations.yml create mode 100644 test/fixtures/roles.yml create mode 100644 test/fixtures/settings.yml create mode 100644 test/fixtures/slots.yml create mode 100644 test/fixtures/statistic_fields.yml create mode 100644 test/fixtures/statistic_graphs.yml create mode 100644 test/fixtures/statistic_indices.yml create mode 100644 test/fixtures/statistic_sub_types.yml create mode 100644 test/fixtures/statistic_type_sub_types.yml create mode 100644 test/fixtures/statistic_types.yml create mode 100644 test/fixtures/stylesheets.yml create mode 100644 test/fixtures/subscriptions.yml create mode 100644 test/fixtures/tags.yml create mode 100644 test/fixtures/themes.yml create mode 100644 test/fixtures/trainings.yml create mode 100644 test/fixtures/trainings_availabilities.yml create mode 100644 test/fixtures/trainings_machines.yml create mode 100644 test/fixtures/trainings_pricings.yml create mode 100644 test/fixtures/user_tags.yml create mode 100644 test/fixtures/user_trainings.yml create mode 100644 test/fixtures/users.yml create mode 100644 test/fixtures/users_credits.yml create mode 100644 test/fixtures/users_roles.yml diff --git a/config/initializers/active_record_base.rb b/config/initializers/active_record_base.rb index fc57f008d..6c20d1d81 100644 --- a/config/initializers/active_record_base.rb +++ b/config/initializers/active_record_base.rb @@ -9,7 +9,8 @@ ActiveRecord::Base.class_eval do def self.dump_fixtures fixture_file = "#{Rails.root}/test/fixtures/#{self.table_name}.yml" - File.open(fixture_file, "w") do |f| + mode = (File.exists?(fixture_file) ? 'a' : 'w') + File.open(fixture_file, mode) do |f| self.all.each do |instance| f.puts({ "#{self.table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) end diff --git a/lib/tasks/fablab.rake b/lib/tasks/fablab.rake index 28dbc701a..5ca3a43fa 100644 --- a/lib/tasks/fablab.rake +++ b/lib/tasks/fablab.rake @@ -181,7 +181,7 @@ namespace :fablab do desc "generate fixtures from db" task generate_fixtures: :environment do Rails.application.eager_load! - ActiveRecord::Base.descendants.reject { |c| c == ActiveRecord::SchemaMigration }.each do |ar_base| + ActiveRecord::Base.descendants.reject { |c| c == ActiveRecord::SchemaMigration or c == PartnerPlan }.each do |ar_base| p "========== #{ar_base} ==============" ar_base.dump_fixtures end diff --git a/test/fixtures/abuses.yml b/test/fixtures/abuses.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/addresses.yml b/test/fixtures/addresses.yml new file mode 100644 index 000000000..f1a7d1d92 --- /dev/null +++ b/test/fixtures/addresses.yml @@ -0,0 +1,52 @@ + +address_1: + id: 1 + address: 14 rue Brecourt, Annecy + street_number: + route: + locality: + country: + postal_code: + placeable_id: 2 + placeable_type: Profile + created_at: 2016-04-04 15:06:22.166469000 Z + updated_at: 2016-04-04 15:06:22.166469000 Z + +address_2: + id: 2 + address: 23 cours Berriat, Grenoble + street_number: + route: + locality: + country: + postal_code: + placeable_id: 4 + placeable_type: Profile + created_at: 2016-04-04 15:10:42.353039000 Z + updated_at: 2016-04-04 15:10:42.353039000 Z + +address_3: + id: 3 + address: 36 chemin des puits, Mousson-sur-Luire + street_number: + route: + locality: + country: + postal_code: + placeable_id: 5 + placeable_type: Profile + created_at: 2016-04-04 15:14:08.579603000 Z + updated_at: 2016-04-04 15:14:08.579603000 Z + +address_4: + id: 4 + address: '' + street_number: + route: + locality: + country: + postal_code: + placeable_id: 3 + placeable_type: Profile + created_at: 2016-04-05 08:35:18.597812000 Z + updated_at: 2016-04-05 08:35:18.597812000 Z diff --git a/test/fixtures/assets.yml b/test/fixtures/assets.yml new file mode 100644 index 000000000..fd85c1e8a --- /dev/null +++ b/test/fixtures/assets.yml @@ -0,0 +1,126 @@ + +asset_1: + id: 1 + viewable_id: 2 + viewable_type: Profile + attachment: user_avatar.jpg + type: UserAvatar + created_at: 2016-04-04 15:06:22.151882000 Z + updated_at: 2016-04-04 15:06:22.151882000 Z + +asset_2: + id: 2 + viewable_id: 5 + viewable_type: Profile + attachment: user_avatar.jpg + type: UserAvatar + created_at: 2016-04-04 15:31:14.607327000 Z + updated_at: 2016-04-04 15:31:14.607327000 Z + +asset_3: + id: 3 + viewable_id: 1 + viewable_type: Project + attachment: project_image.jpg + type: ProjectImage + created_at: 2016-04-04 15:39:08.230159000 Z + updated_at: 2016-04-04 15:39:08.230159000 Z + +asset_4: + id: 4 + viewable_id: 1 + viewable_type: Event + attachment: event_image.jpg + type: EventImage + created_at: 2016-04-04 15:44:02.242194000 Z + updated_at: 2016-04-04 15:44:02.242194000 Z + +asset_5: + id: 5 + viewable_id: 2 + viewable_type: Event + attachment: event_image.jpg + type: EventImage + created_at: 2016-04-04 15:44:03.164384000 Z + updated_at: 2016-04-04 15:44:03.164384000 Z + +asset_6: + id: 6 + viewable_id: 3 + viewable_type: Event + attachment: event_image.jpg + type: EventImage + created_at: 2016-04-04 15:44:04.031482000 Z + updated_at: 2016-04-04 15:44:04.031482000 Z + +asset_7: + id: 7 + viewable_id: 3 + viewable_type: Profile + attachment: user_avatar.jpg + type: UserAvatar + created_at: 2016-04-05 08:35:18.585573000 Z + updated_at: 2016-04-05 08:35:18.585573000 Z + +asset_4: + id: 4 + viewable_id: 1 + viewable_type: Event + attachment: event_image.jpg + type: EventImage + created_at: 2016-04-04 15:44:02.242194000 Z + updated_at: 2016-04-04 15:44:02.242194000 Z + +asset_5: + id: 5 + viewable_id: 2 + viewable_type: Event + attachment: event_image.jpg + type: EventImage + created_at: 2016-04-04 15:44:03.164384000 Z + updated_at: 2016-04-04 15:44:03.164384000 Z + +asset_6: + id: 6 + viewable_id: 3 + viewable_type: Event + attachment: event_image.jpg + type: EventImage + created_at: 2016-04-04 15:44:04.031482000 Z + updated_at: 2016-04-04 15:44:04.031482000 Z + +asset_3: + id: 3 + viewable_id: 1 + viewable_type: Project + attachment: project_image.jpg + type: ProjectImage + created_at: 2016-04-04 15:39:08.230159000 Z + updated_at: 2016-04-04 15:39:08.230159000 Z + +asset_1: + id: 1 + viewable_id: 2 + viewable_type: Profile + attachment: user_avatar.jpg + type: UserAvatar + created_at: 2016-04-04 15:06:22.151882000 Z + updated_at: 2016-04-04 15:06:22.151882000 Z + +asset_2: + id: 2 + viewable_id: 5 + viewable_type: Profile + attachment: user_avatar.jpg + type: UserAvatar + created_at: 2016-04-04 15:31:14.607327000 Z + updated_at: 2016-04-04 15:31:14.607327000 Z + +asset_7: + id: 7 + viewable_id: 3 + viewable_type: Profile + attachment: user_avatar.jpg + type: UserAvatar + created_at: 2016-04-05 08:35:18.585573000 Z + updated_at: 2016-04-05 08:35:18.585573000 Z diff --git a/test/fixtures/auth_providers.yml b/test/fixtures/auth_providers.yml new file mode 100644 index 000000000..42c404a86 --- /dev/null +++ b/test/fixtures/auth_providers.yml @@ -0,0 +1,9 @@ + +auth_provider_1: + id: 1 + name: Fablab + status: active + created_at: 2016-04-04 14:11:34.743728000 Z + updated_at: 2016-04-04 14:11:34.743728000 Z + providable_type: DatabaseProvider + providable_id: 1 diff --git a/test/fixtures/availabilities.yml b/test/fixtures/availabilities.yml index 937a0c002..e1ba699de 100644 --- a/test/fixtures/availabilities.yml +++ b/test/fixtures/availabilities.yml @@ -1,11 +1,110 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -# This model initially had no columns defined. If you add columns to the -# model remove the '{}' from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value +availability_1: + id: 1 + start_at: 2016-04-11 06:00:00.000000000 Z + end_at: 2016-04-11 10:00:00.000000000 Z + available_type: training + created_at: 2016-04-04 15:24:01.517486000 Z + updated_at: 2016-04-04 15:24:01.517486000 Z + nb_total_places: + destroying: false + +availability_2: + id: 2 + start_at: 2016-04-12 06:00:00.000000000 Z + end_at: 2016-04-12 10:00:00.000000000 Z + available_type: training + created_at: 2016-04-04 15:24:09.169364000 Z + updated_at: 2016-04-04 15:24:09.169364000 Z + nb_total_places: + destroying: false + +availability_3: + id: 3 + start_at: 2016-04-11 12:00:00.000000000 Z + end_at: 2016-04-11 18:00:00.000000000 Z + available_type: machines + created_at: 2016-04-04 15:24:27.587583000 Z + updated_at: 2016-04-04 15:24:27.587583000 Z + nb_total_places: + destroying: false + +availability_4: + id: 4 + start_at: 2016-04-12 12:00:00.000000000 Z + end_at: 2016-04-12 18:00:00.000000000 Z + available_type: machines + created_at: 2016-04-04 15:24:44.044908000 Z + updated_at: 2016-04-04 15:24:44.044908000 Z + nb_total_places: + destroying: false + +availability_5: + id: 5 + start_at: 2016-04-13 12:00:00.000000000 Z + end_at: 2016-04-13 18:00:00.000000000 Z + available_type: machines + created_at: 2016-04-04 15:25:48.584444000 Z + updated_at: 2016-04-04 15:25:48.584444000 Z + nb_total_places: + destroying: false + +availability_6: + id: 6 + start_at: 2016-04-14 12:00:00.000000000 Z + end_at: 2016-04-14 18:00:00.000000000 Z + available_type: machines + created_at: 2016-04-04 15:26:17.953216000 Z + updated_at: 2016-04-04 15:26:17.953216000 Z + nb_total_places: + destroying: false + +availability_7: + id: 7 + start_at: 2016-04-14 12:00:00.000000000 Z + end_at: 2016-04-14 18:00:00.000000000 Z + available_type: machines + created_at: 2016-04-04 15:26:39.278627000 Z + updated_at: 2016-04-04 15:26:39.278627000 Z + nb_total_places: + destroying: false + +availability_8: + id: 8 + start_at: 2016-04-13 06:00:00.000000000 Z + end_at: 2016-04-13 10:00:00.000000000 Z + available_type: training + created_at: 2016-04-04 15:26:49.572724000 Z + updated_at: 2016-04-04 15:26:49.572724000 Z + nb_total_places: + destroying: false + +availability_9: + id: 9 + start_at: 2016-04-18 16:00:28.000000000 Z + end_at: 2016-04-18 20:00:28.000000000 Z + available_type: event + created_at: 2016-04-04 15:44:02.228661000 Z + updated_at: 2016-04-04 15:44:02.228661000 Z + nb_total_places: + destroying: false + +availability_10: + id: 10 + start_at: 2016-05-18 16:00:28.000000000 Z + end_at: 2016-05-18 20:00:28.000000000 Z + available_type: event + created_at: 2016-04-04 15:44:03.156629000 Z + updated_at: 2016-04-04 15:44:03.156629000 Z + nb_total_places: + destroying: false + +availability_11: + id: 11 + start_at: 2016-06-18 16:00:28.000000000 Z + end_at: 2016-06-18 20:00:28.000000000 Z + available_type: event + created_at: 2016-04-04 15:44:04.023557000 Z + updated_at: 2016-04-04 15:44:04.023557000 Z + nb_total_places: + destroying: false diff --git a/test/fixtures/availability_tags.yml b/test/fixtures/availability_tags.yml new file mode 100644 index 000000000..d02a75a49 --- /dev/null +++ b/test/fixtures/availability_tags.yml @@ -0,0 +1,21 @@ + +availability_tag_1: + id: 1 + availability_id: 5 + tag_id: 2 + created_at: 2016-04-04 15:25:48.587799000 Z + updated_at: 2016-04-04 15:25:48.587799000 Z + +availability_tag_2: + id: 2 + availability_id: 6 + tag_id: 1 + created_at: 2016-04-04 15:26:17.957014000 Z + updated_at: 2016-04-04 15:26:17.957014000 Z + +availability_tag_3: + id: 3 + availability_id: 8 + tag_id: 2 + created_at: 2016-04-04 15:26:49.576178000 Z + updated_at: 2016-04-04 15:26:49.576178000 Z diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml new file mode 100644 index 000000000..69b183ad8 --- /dev/null +++ b/test/fixtures/categories.yml @@ -0,0 +1,12 @@ + +category_1: + id: 1 + name: Stage + created_at: 2016-04-04 14:11:34.544995000 Z + updated_at: 2016-04-04 14:11:34.544995000 Z + +category_2: + id: 2 + name: Atelier + created_at: 2016-04-04 14:11:34.547621000 Z + updated_at: 2016-04-04 14:11:34.547621000 Z diff --git a/test/fixtures/components.yml b/test/fixtures/components.yml new file mode 100644 index 000000000..54d51048a --- /dev/null +++ b/test/fixtures/components.yml @@ -0,0 +1,40 @@ + +component_1: + id: 1 + name: Silicone + +component_2: + id: 2 + name: Vinyle + +component_3: + id: 3 + name: Bois Contre plaqué + +component_4: + id: 4 + name: Bois Medium + +component_5: + id: 5 + name: Plexi / PMMA + +component_6: + id: 6 + name: Flex + +component_7: + id: 7 + name: Vinyle + +component_8: + id: 8 + name: Parafine + +component_9: + id: 9 + name: Fibre de verre + +component_10: + id: 10 + name: Résine diff --git a/test/fixtures/credits.yml b/test/fixtures/credits.yml new file mode 100644 index 000000000..6f80545a8 --- /dev/null +++ b/test/fixtures/credits.yml @@ -0,0 +1,99 @@ + +credit_1: + id: 1 + creditable_id: 2 + creditable_type: Training + plan_id: 1 + hours: + created_at: 2016-04-04 15:19:28.414019000 Z + updated_at: 2016-04-04 15:19:28.414019000 Z + +credit_2: + id: 2 + creditable_id: 3 + creditable_type: Training + plan_id: 1 + hours: + created_at: 2016-04-04 15:19:28.449511000 Z + updated_at: 2016-04-04 15:19:28.449511000 Z + +credit_3: + id: 3 + creditable_id: 1 + creditable_type: Training + plan_id: 1 + hours: + created_at: 2016-04-04 15:19:28.495141000 Z + updated_at: 2016-04-04 15:19:28.495141000 Z + +credit_5: + id: 5 + creditable_id: 2 + creditable_type: Training + plan_id: 2 + hours: + created_at: 2016-04-04 15:19:39.416054000 Z + updated_at: 2016-04-04 15:19:39.416054000 Z + +credit_7: + id: 7 + creditable_id: 4 + creditable_type: Training + plan_id: 2 + hours: + created_at: 2016-04-04 15:19:39.486949000 Z + updated_at: 2016-04-04 15:19:39.486949000 Z + +credit_8: + id: 8 + creditable_id: 1 + creditable_type: Training + plan_id: 2 + hours: + created_at: 2016-04-04 15:19:39.521993000 Z + updated_at: 2016-04-04 15:19:39.521993000 Z + +credit_9: + id: 9 + creditable_id: 3 + creditable_type: Training + plan_id: 2 + hours: + created_at: 2016-04-04 15:19:39.553519000 Z + updated_at: 2016-04-04 15:19:39.553519000 Z + +credit_10: + id: 10 + creditable_id: 2 + creditable_type: Training + plan_id: 3 + hours: + created_at: 2016-04-04 15:21:35.437032000 Z + updated_at: 2016-04-04 15:21:35.437032000 Z + +credit_11: + id: 11 + creditable_id: 1 + creditable_type: Training + plan_id: 3 + hours: + created_at: 2016-04-04 15:21:35.470423000 Z + updated_at: 2016-04-04 15:21:35.470423000 Z + +credit_12: + id: 12 + creditable_id: 3 + creditable_type: Training + plan_id: 3 + hours: + created_at: 2016-04-04 15:21:35.547043000 Z + updated_at: 2016-04-04 15:21:35.547043000 Z + +credit_13: + id: 13 + creditable_id: 4 + creditable_type: Machine + plan_id: 2 + hours: 1 + created_at: 2016-04-04 15:21:57.547939000 Z + updated_at: 2016-04-04 15:21:57.547939000 Z diff --git a/test/fixtures/custom_assets.yml b/test/fixtures/custom_assets.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/database_providers.yml b/test/fixtures/database_providers.yml new file mode 100644 index 000000000..42c6cc13c --- /dev/null +++ b/test/fixtures/database_providers.yml @@ -0,0 +1,5 @@ + +database_provider_1: + id: 1 + created_at: 2016-04-04 14:11:34.737301000 Z + updated_at: 2016-04-04 14:11:34.737301000 Z diff --git a/test/fixtures/events.yml b/test/fixtures/events.yml new file mode 100644 index 000000000..624603910 --- /dev/null +++ b/test/fixtures/events.yml @@ -0,0 +1,42 @@ + +event_2: + id: 2 + title: Skateboard DIY + description: "Apprenez à fabriquer vous-même votre skateboard :\r\n- impression + 3D des roulettes\r\n- découpe moulage et décoration de la planche\r\n- assemblage" + created_at: 2016-04-04 15:44:03.161942000 Z + updated_at: 2016-04-04 15:44:03.161942000 Z + availability_id: 10 + amount: 2000 + reduced_amount: 1500 + nb_total_places: 10 + nb_free_places: 10 + recurrence_id: 1 + +event_3: + id: 3 + title: Skateboard DIY + description: "Apprenez à fabriquer vous-même votre skateboard :\r\n- impression + 3D des roulettes\r\n- découpe moulage et décoration de la planche\r\n- assemblage" + created_at: 2016-04-04 15:44:04.028290000 Z + updated_at: 2016-04-04 15:44:04.028290000 Z + availability_id: 11 + amount: 2000 + reduced_amount: 1500 + nb_total_places: 10 + nb_free_places: 10 + recurrence_id: 1 + +event_1: + id: 1 + title: Skateboard DIY + description: "Apprenez à fabriquer vous-même votre skateboard :\r\n- impression + 3D des roulettes\r\n- découpe moulage et décoration de la planche\r\n- assemblage" + created_at: 2016-04-04 15:44:02.236165000 Z + updated_at: 2016-04-04 15:44:02.236165000 Z + availability_id: 9 + amount: 2000 + reduced_amount: 1500 + nb_total_places: 10 + nb_free_places: 10 + recurrence_id: 1 diff --git a/test/fixtures/events_categories.yml b/test/fixtures/events_categories.yml new file mode 100644 index 000000000..3d0913d07 --- /dev/null +++ b/test/fixtures/events_categories.yml @@ -0,0 +1,84 @@ + +events_category_1: + id: 1 + event_id: 1 + category_id: 2 + created_at: 2016-04-04 15:44:02.258622000 Z + updated_at: 2016-04-04 15:44:02.258622000 Z + +events_category_2: + id: 2 + event_id: 2 + category_id: 2 + created_at: 2016-04-04 15:44:03.173253000 Z + updated_at: 2016-04-04 15:44:03.173253000 Z + +events_category_3: + id: 3 + event_id: 2 + category_id: 2 + created_at: 2016-04-04 15:44:03.177952000 Z + updated_at: 2016-04-04 15:44:03.177952000 Z + +events_category_4: + id: 4 + event_id: 3 + category_id: 2 + created_at: 2016-04-04 15:44:04.041364000 Z + updated_at: 2016-04-04 15:44:04.041364000 Z + +events_category_5: + id: 5 + event_id: 3 + category_id: 2 + created_at: 2016-04-04 15:44:04.044667000 Z + updated_at: 2016-04-04 15:44:04.044667000 Z + +events_category_6: + id: 6 + event_id: 1 + category_id: 2 + created_at: 2016-04-04 15:44:04.049543000 Z + updated_at: 2016-04-04 15:44:04.049543000 Z + +events_category_1: + id: 1 + event_id: 1 + category_id: 2 + created_at: 2016-04-04 15:44:02.258622000 Z + updated_at: 2016-04-04 15:44:02.258622000 Z + +events_category_2: + id: 2 + event_id: 2 + category_id: 2 + created_at: 2016-04-04 15:44:03.173253000 Z + updated_at: 2016-04-04 15:44:03.173253000 Z + +events_category_3: + id: 3 + event_id: 2 + category_id: 2 + created_at: 2016-04-04 15:44:03.177952000 Z + updated_at: 2016-04-04 15:44:03.177952000 Z + +events_category_4: + id: 4 + event_id: 3 + category_id: 2 + created_at: 2016-04-04 15:44:04.041364000 Z + updated_at: 2016-04-04 15:44:04.041364000 Z + +events_category_5: + id: 5 + event_id: 3 + category_id: 2 + created_at: 2016-04-04 15:44:04.044667000 Z + updated_at: 2016-04-04 15:44:04.044667000 Z + +events_category_6: + id: 6 + event_id: 1 + category_id: 2 + created_at: 2016-04-04 15:44:04.049543000 Z + updated_at: 2016-04-04 15:44:04.049543000 Z diff --git a/test/fixtures/groups.yml b/test/fixtures/groups.yml new file mode 100644 index 000000000..3d5a01f8e --- /dev/null +++ b/test/fixtures/groups.yml @@ -0,0 +1,14 @@ + +group_1: + id: 1 + name: standard, association + created_at: 2016-04-04 14:11:33.612700000 Z + updated_at: 2016-04-04 14:11:33.612700000 Z + slug: standard + +group_2: + id: 2 + name: étudiant, - de 25 ans, enseignant, demandeur d'emploi + created_at: 2016-04-04 14:11:33.656537000 Z + updated_at: 2016-04-04 14:11:33.656537000 Z + slug: student diff --git a/test/fixtures/invoice_items.yml b/test/fixtures/invoice_items.yml new file mode 100644 index 000000000..babd3946f --- /dev/null +++ b/test/fixtures/invoice_items.yml @@ -0,0 +1,23 @@ + +invoice_item_1: + id: 1 + invoice_id: 1 + stp_invoice_item_id: sub_8DGB4ErIc2asOv + amount: 10000 + created_at: 2016-04-05 08:35:52.934725000 Z + updated_at: 2016-04-05 08:35:52.934725000 Z + description: Sleede - standard, association - month + subscription_id: 1 + invoice_item_id: + +invoice_item_2: + id: 2 + invoice_id: 2 + stp_invoice_item_id: + amount: 2000 + created_at: 2016-04-05 08:36:46.856021000 Z + updated_at: 2016-04-05 08:36:46.856021000 Z + description: Mensuel tarif réduit - étudiant, - de 25 ans, enseignant, demandeur + d'emploi - month + subscription_id: 2 + invoice_item_id: diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml new file mode 100644 index 000000000..da9488003 --- /dev/null +++ b/test/fixtures/invoices.yml @@ -0,0 +1,34 @@ + +invoice_1: + id: 1 + invoiced_id: 1 + invoiced_type: Subscription + stp_invoice_id: in_17wpf92sOmf47Nz9itj6vmJw + total: 10000 + created_at: 2016-04-05 08:35:52.931187000 Z + updated_at: 2016-04-05 08:35:52.931187000 Z + user_id: 3 + reference: 1604001/VL + avoir_mode: + avoir_date: + invoice_id: + type: + subscription_to_expire: + description: + +invoice_2: + id: 2 + invoiced_id: 2 + invoiced_type: Subscription + stp_invoice_id: + total: 2000 + created_at: 2016-04-05 08:36:46.853368000 Z + updated_at: 2016-04-05 08:36:46.853368000 Z + user_id: 4 + reference: '1604002' + avoir_mode: + avoir_date: + invoice_id: + type: + subscription_to_expire: + description: diff --git a/test/fixtures/licences.yml b/test/fixtures/licences.yml new file mode 100644 index 000000000..7920920ba --- /dev/null +++ b/test/fixtures/licences.yml @@ -0,0 +1,47 @@ + +licence_1: + id: 1 + name: Attribution (BY) + description: Le titulaire des droits autorise toute exploitation de l’œuvre, y compris + à des fins commerciales, ainsi que la création d’œuvres dérivées, dont la distribution + est également autorisé sans restriction, à condition de l’attribuer à son l’auteur + en citant son nom. Cette licence est recommandée pour la diffusion et l’utilisation + maximale des œuvres. + +licence_2: + id: 2 + name: Attribution + Pas de modification (BY ND) + description: Le titulaire des droits autorise toute utilisation de l’œuvre originale + (y compris à des fins commerciales), mais n’autorise pas la création d’œuvres + dérivées. + +licence_3: + id: 3 + name: Attribution + Pas d'Utilisation Commerciale + Pas de Modification (BY NC ND) + description: Le titulaire des droits autorise l’utilisation de l’œuvre originale + à des fins non commerciales, mais n’autorise pas la création d’œuvres dérivés. + +licence_4: + id: 4 + name: Attribution + Pas d'Utilisation Commerciale (BY NC) + description: Le titulaire des droits autorise l’exploitation de l’œuvre, ainsi que + la création d’œuvres dérivées, à condition qu’il ne s’agisse pas d’une utilisation + commerciale (les utilisations commerciales restant soumises à son autorisation). + +licence_5: + id: 5 + name: Attribution + Pas d'Utilisation Commerciale + Partage dans les mêmes conditions + (BY NC SA) + description: Le titulaire des droits autorise l’exploitation de l’œuvre originale + à des fins non commerciales, ainsi que la création d’œuvres dérivées, à condition + qu’elles soient distribuées sous une licence identique à celle qui régit l’œuvre + originale. + +licence_6: + id: 6 + name: Attribution + Partage dans les mêmes conditions (BY SA) + description: Le titulaire des droits autorise toute utilisation de l’œuvre originale + (y compris à des fins commerciales) ainsi que la création d’œuvres dérivées, à + condition qu’elles soient distribuées sous une licence identique à celle qui régit + l’œuvre originale. Cette licence est souvent comparée aux licences « copyleft + » des logiciels libres. C’est la licence utilisée par Wikipedia. diff --git a/test/fixtures/machines.yml b/test/fixtures/machines.yml new file mode 100644 index 000000000..8f5876290 --- /dev/null +++ b/test/fixtures/machines.yml @@ -0,0 +1,125 @@ + +machine_1: + id: 1 + name: Découpeuse laser + description: "Préparation à l'utilisation de l'EPILOG Legend 36EXT\r\nInformations + générales \r\n Pour la découpe, il suffit d'apporter votre fichier vectorisé + type illustrator, svg ou dxf avec des \"lignes de coupe\" d'une épaisseur inférieur + à 0,01 mm et la machine s'occupera du reste!\r\n La gravure est basée sur + le spectre noir et blanc. Les nuances sont obtenues par différentes profondeurs + de gravure correspondant aux niveaux de gris de votre image. Il suffit pour cela + d'apporter une image scannée ou un fichier photo en noir et blanc pour pouvoir + reproduire celle-ci sur votre support! \r\nQuels types de matériaux pouvons nous + graver/découper?\r\n Du bois au tissu, du plexiglass au cuir, cette machine + permet de découper et graver la plupart des matériaux sauf les métaux. La gravure + est néanmoins possible sur les métaux recouverts d'une couche de peinture ou les + aluminiums anodisés. \r\n Concernant l'épaisseur des matériaux découpés, + il est préférable de ne pas dépasser 5 mm pour le bois et 6 mm pour le plexiglass.\r\n" + spec: "Puissance: 40W\r\nSurface de travail: 914x609 mm \r\nEpaisseur maximale de + la matière: 305mm\r\nSource laser: tube laser type CO2\r\nContrôles de vitesse + et de puissance: ces deux paramètres sont ajustables en fonction du matériau (de + 1% à 100%) .\r\n" + created_at: 2016-04-04 14:11:34.210242000 Z + updated_at: 2016-04-04 14:11:34.210242000 Z + slug: decoupeuse-laser + +machine_2: + id: 2 + name: Découpeuse vinyle + description: "Préparation à l'utilisation de la Roland CAMM-1 GX24\r\nInformations + générales \r\n Envie de réaliser un tee shirt personnalisé ? Un sticker + à l'effigie votre groupe préféré? Un masque pour la réalisation d'un circuit imprimé? + Pour cela, il suffit simplement de venir avec votre fichier vectorisé (ne pas + oublier de vectoriser les textes) type illustrator svg ou dxf.\r\n \r\nMatériaux + utilisés:\r\n Cette machine permet de découper principalement du vinyle,vinyle + réfléchissant, flex.\r\n" + spec: "Largeurs de support acceptées: de 50 mm à 700 mm\r\nVitesse de découpe: 50 + cm/sec\r\nRésolution mécanique: 0,0125 mm/pas\r\n" + created_at: 2016-04-04 14:11:34.274025000 Z + updated_at: 2016-04-04 14:11:34.274025000 Z + slug: decoupeuse-vinyle + +machine_3: + id: 3 + name: Shopbot / Grande fraiseuse + description: "La fraiseuse numérique ShopBot PRS standard\r\nInformations générales\r\nCette + machine est un fraiseuse 3 axes idéale pour l'usinage de pièces de grandes dimensions. + De la réalisation d'une chaise ou d'un meuble jusqu'à la construction d'une maison + ou d'un assemblage immense, le ShopBot ouvre de nombreuses portes à votre imagination! + \r\nMatériaux usinables\r\nLes principaux matériaux usinables sont le bois, le + plastique, le laiton et bien d'autres.\r\nCette machine n'usine pas les métaux.\r\n" + spec: "Surface maximale de travail: 2440x1220x150 (Z) mm\r\nLogiciel utilisé: Partworks + 2D & 3D\r\nRésolution mécanique: 0,015 mm\r\nPrécision de la position: +/- 0,127mm\r\nFormats + acceptés: DXF, STL \r\n" + created_at: 2016-04-04 14:11:34.304247000 Z + updated_at: 2016-04-04 14:11:34.304247000 Z + slug: shopbot-grande-fraiseuse + +machine_4: + id: 4 + name: Imprimante 3D + description: "L'utimaker est une imprimante 3D low cost utilisant une technologie + FFF (Fused Filament Fabrication) avec extrusion thermoplastique.\r\nC'est une + machine idéale pour réaliser rapidement des prototypes 3D dans des couleurs différentes.\r\n" + spec: "Surface maximale de travail: 210x210x220mm \r\nRésolution méchanique: 0,02 + mm \r\nPrécision de position: +/- 0,05 \r\nLogiciel utilisé: Cura\r\nFormats de + fichier acceptés: STL \r\nMatériaux utilisés: PLA (en stock)." + created_at: 2016-04-04 14:11:34.341810000 Z + updated_at: 2016-04-04 14:11:34.341810000 Z + slug: imprimante-3d + +machine_5: + id: 5 + name: Petite Fraiseuse + description: "La fraiseuse numérique Roland Modela MDX-20\r\nInformations générales\r\nCette + machine est utilisée pour l'usinage et le scannage 3D de précision. Elle permet + principalement d'usiner des circuits imprimés et des moules de petite taille. + Le faible diamètre des fraises utilisées (Ø 0,3 mm à Ø 6mm) induit que certains + temps d'usinages peuvent êtres long (> 12h), c'est pourquoi cette fraiseuse peut + être laissée en autonomie toute une nuit afin d'obtenir le plus précis des usinages + au FabLab.\r\nMatériaux usinables:\r\nLes principaux matériaux usinables sont + le bois, plâtre, résine, cire usinable, cuivre.\r\n" + spec: "Taille du plateau X/Y : 220 mm x 160 mm\r\nVolume maximal de travail: 203,2 + mm (X), 152,4 mm (Y), 60,5 mm (Z)\r\nPrécision usinage: 0,00625 mm\r\nPrécision + scannage: réglable de 0,05 à 5 mm (axes X,Y) et 0,025 mm (axe Z)\r\nVitesse d'analyse + (scannage): 4-15 mm/sec\r\n \r\n \r\nLogiciel utilisé pour le fraisage: Roland + Modela player 4 \r\nLogiciel utilisé pour l'usinage de circuits imprimés: Cad.py + (linux)\r\nFormats acceptés: STL,PNG 3D\r\nFormat d'exportation des données scannées: + DXF, VRML, STL, 3DMF, IGES, Grayscale, Point Group et BMP\r\n" + created_at: 2016-04-04 14:11:34.379481000 Z + updated_at: 2016-04-04 14:11:34.379481000 Z + slug: petite-fraiseuse + +machine_6: + id: 6 + name: FORM1+ imprimante 3D + description: |- + Form 1+, imprimante 3D stéréolithographie. + + La photopolymérisation est le premier procédé de prototypage rapide à avoir été développé dans les années 1980. Le nom de SLA (pour StereoLithography Apparatus) lui a été donné. Il repose sur les propriétés qu'ont certaines résines à se polymériser sous l'effet de la lumière et de la chaleur. (Source : wikipédia) + + Possibilité d'utiliser 3 résines de couleurs différentes au Lab : noir, blanc et translucide. + + Plus d'infos sur le site web de Formlab + spec: |- + Imprimante : + - Dimensions : 30 × 28 × 45 cm + - Poids : 8 kg + - Température d'utilisation : 18–28° C + - Alimentation : 100–240 V ; 1.5 A 50/60 Hz ; 60 W. + + Caractéristiques du laser : + - EN 60825-1:2007 certifié + - Class 1 Laser Product + - 405nm violet laser + + Propriétés d'impression : + - Technologie stéréolithographie (SLA) + - Volume d'impression : 125 × 125 × 165 mm + - Dimension minimale : 300 microns + - Épaisseur des couches (Résolution verticale) : 25, 50, 100 microns + - Ressources Générées automatiquement + - Facilement amovible + created_at: 2016-04-04 14:11:34.424740000 Z + updated_at: 2016-04-04 14:11:34.424740000 Z + slug: form1-imprimante-3d diff --git a/test/fixtures/machines_availabilities.yml b/test/fixtures/machines_availabilities.yml new file mode 100644 index 000000000..c045b25ac --- /dev/null +++ b/test/fixtures/machines_availabilities.yml @@ -0,0 +1,85 @@ + +machines_availability_1: + id: 1 + machine_id: 1 + availability_id: 3 + +machines_availability_2: + id: 2 + machine_id: 2 + availability_id: 3 + +machines_availability_3: + id: 3 + machine_id: 4 + availability_id: 3 + +machines_availability_4: + id: 4 + machine_id: 6 + availability_id: 3 + +machines_availability_5: + id: 5 + machine_id: 5 + availability_id: 3 + +machines_availability_6: + id: 6 + machine_id: 1 + availability_id: 4 + +machines_availability_7: + id: 7 + machine_id: 2 + availability_id: 4 + +machines_availability_8: + id: 8 + machine_id: 4 + availability_id: 4 + +machines_availability_9: + id: 9 + machine_id: 5 + availability_id: 4 + +machines_availability_10: + id: 10 + machine_id: 6 + availability_id: 4 + +machines_availability_11: + id: 11 + machine_id: 3 + availability_id: 5 + +machines_availability_12: + id: 12 + machine_id: 3 + availability_id: 6 + +machines_availability_13: + id: 13 + machine_id: 1 + availability_id: 7 + +machines_availability_14: + id: 14 + machine_id: 2 + availability_id: 7 + +machines_availability_15: + id: 15 + machine_id: 4 + availability_id: 7 + +machines_availability_16: + id: 16 + machine_id: 5 + availability_id: 7 + +machines_availability_17: + id: 17 + machine_id: 6 + availability_id: 7 diff --git a/test/fixtures/notifications.yml b/test/fixtures/notifications.yml new file mode 100644 index 000000000..7428a79ac --- /dev/null +++ b/test/fixtures/notifications.yml @@ -0,0 +1,182 @@ + +notification_7: + id: 7 + receiver_id: 1 + attached_object_id: 1 + attached_object_type: Project + notification_type_id: 1 + is_read: false + created_at: 2016-04-04 15:39:08.273215000 Z + updated_at: 2016-04-04 15:39:08.273215000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_1: + id: 1 + receiver_id: 1 + attached_object_id: 1 + attached_object_type: User + notification_type_id: 11 + is_read: true + created_at: 2016-04-04 14:11:33.885243000 Z + updated_at: 2016-04-04 14:11:33.885243000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_2: + id: 2 + receiver_id: 1 + attached_object_id: 2 + attached_object_type: User + notification_type_id: 11 + is_read: true + created_at: 2016-04-04 15:00:29.145046000 Z + updated_at: 2016-04-04 15:00:29.145046000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_3: + id: 3 + receiver_id: 1 + attached_object_id: 3 + attached_object_type: User + notification_type_id: 11 + is_read: true + created_at: 2016-04-04 15:07:46.698906000 Z + updated_at: 2016-04-04 15:07:46.698906000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_4: + id: 4 + receiver_id: 1 + attached_object_id: 4 + attached_object_type: User + notification_type_id: 11 + is_read: true + created_at: 2016-04-04 15:10:42.365920000 Z + updated_at: 2016-04-04 15:10:42.365920000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_5: + id: 5 + receiver_id: 1 + attached_object_id: 5 + attached_object_type: User + notification_type_id: 11 + is_read: true + created_at: 2016-04-04 15:14:08.589419000 Z + updated_at: 2016-04-04 15:14:08.589419000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_6: + id: 6 + receiver_id: 1 + attached_object_id: 6 + attached_object_type: User + notification_type_id: 11 + is_read: true + created_at: 2016-04-04 15:17:12.548875000 Z + updated_at: 2016-04-04 15:17:12.548875000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_10: + id: 10 + receiver_id: 6 + attached_object_id: 1 + attached_object_type: Subscription + notification_type_id: 23 + is_read: false + created_at: 2016-04-05 08:35:51.844242000 Z + updated_at: 2016-04-05 08:35:51.844242000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_11: + id: 11 + receiver_id: 3 + attached_object_id: 1 + attached_object_type: Invoice + notification_type_id: 13 + is_read: false + created_at: 2016-04-05 08:35:53.327086000 Z + updated_at: 2016-04-05 08:35:53.327086000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_9: + id: 9 + receiver_id: 1 + attached_object_id: 1 + attached_object_type: Subscription + notification_type_id: 12 + is_read: false + created_at: 2016-04-05 08:35:51.837022000 Z + updated_at: 2016-04-05 08:35:51.837022000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_13: + id: 13 + receiver_id: 1 + attached_object_id: 2 + attached_object_type: Subscription + notification_type_id: 12 + is_read: false + created_at: 2016-04-05 08:36:46.841579000 Z + updated_at: 2016-04-05 08:36:46.841579000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_14: + id: 14 + receiver_id: 4 + attached_object_id: 2 + attached_object_type: Invoice + notification_type_id: 13 + is_read: false + created_at: 2016-04-05 08:36:47.235854000 Z + updated_at: 2016-04-05 08:36:47.235854000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_8: + id: 8 + receiver_id: 3 + attached_object_id: 1 + attached_object_type: Subscription + notification_type_id: 5 + is_read: false + created_at: 2016-04-05 08:35:51.792984000 Z + updated_at: 2016-04-05 08:35:51.792984000 Z + receiver_type: User + is_send: true + meta_data: {} + +notification_12: + id: 12 + receiver_id: 4 + attached_object_id: 2 + attached_object_type: Subscription + notification_type_id: 5 + is_read: false + created_at: 2016-04-05 08:36:46.833829000 Z + updated_at: 2016-04-05 08:36:46.833829000 Z + receiver_type: User + is_send: true + meta_data: {} diff --git a/test/fixtures/o_auth2_mappings.yml b/test/fixtures/o_auth2_mappings.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/o_auth2_providers.yml b/test/fixtures/o_auth2_providers.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/offer_days.yml b/test/fixtures/offer_days.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/plans.yml b/test/fixtures/plans.yml new file mode 100644 index 000000000..18a9e1379 --- /dev/null +++ b/test/fixtures/plans.yml @@ -0,0 +1,52 @@ + +plan_1: + id: 1 + name: Mensuel - standard, association - month + amount: 3000 + interval: month + group_id: 1 + stp_plan_id: mensuel-standard-month-20160404171519 + created_at: 2016-04-04 15:15:19.860064000 Z + updated_at: 2016-04-04 15:19:28.367161000 Z + training_credit_nb: 1 + is_rolling: + description: + type: Plan + base_name: Mensuel + ui_weight: 1 + interval_count: 1 + +plan_2: + id: 2 + name: Sleede - standard, association - month + amount: 10000 + interval: month + group_id: 1 + stp_plan_id: nicolas-standard-month-20160404171724 + created_at: 2016-04-04 15:17:24.026385000 Z + updated_at: 2016-04-04 15:19:39.357636000 Z + training_credit_nb: 2 + is_rolling: + description: + type: PartnerPlan + base_name: Sleede + ui_weight: 5 + interval_count: 2 + +plan_3: + id: 3 + name: Mensuel tarif réduit - étudiant, - de 25 ans, enseignant, demandeur d'emploi + - month + amount: 2000 + interval: month + group_id: 2 + stp_plan_id: mensuel-tarif-reduit-student-month-20160404171827 + created_at: 2016-04-04 15:18:27.734657000 Z + updated_at: 2016-04-04 15:21:35.501739000 Z + training_credit_nb: 1 + is_rolling: + description: + type: Plan + base_name: Mensuel tarif réduit + ui_weight: 0 + interval_count: 1 diff --git a/test/fixtures/prices.yml b/test/fixtures/prices.yml new file mode 100644 index 000000000..e8f08d9ff --- /dev/null +++ b/test/fixtures/prices.yml @@ -0,0 +1,300 @@ + +price_1: + id: 1 + group_id: 1 + plan_id: + priceable_id: 1 + priceable_type: Machine + amount: 2400 + created_at: 2016-04-04 14:11:34.242608000 Z + updated_at: 2016-04-04 14:11:34.242608000 Z + +price_2: + id: 2 + group_id: 2 + plan_id: + priceable_id: 1 + priceable_type: Machine + amount: 5300 + created_at: 2016-04-04 14:11:34.247363000 Z + updated_at: 2016-04-04 14:11:34.247363000 Z + +price_5: + id: 5 + group_id: 1 + plan_id: + priceable_id: 2 + priceable_type: Machine + amount: 4200 + created_at: 2016-04-04 14:11:34.290427000 Z + updated_at: 2016-04-04 14:11:34.290427000 Z + +price_6: + id: 6 + group_id: 2 + plan_id: + priceable_id: 2 + priceable_type: Machine + amount: 1100 + created_at: 2016-04-04 14:11:34.293603000 Z + updated_at: 2016-04-04 14:11:34.293603000 Z + +price_9: + id: 9 + group_id: 1 + plan_id: + priceable_id: 3 + priceable_type: Machine + amount: 4100 + created_at: 2016-04-04 14:11:34.320809000 Z + updated_at: 2016-04-04 14:11:34.320809000 Z + +price_10: + id: 10 + group_id: 2 + plan_id: + priceable_id: 3 + priceable_type: Machine + amount: 5300 + created_at: 2016-04-04 14:11:34.325274000 Z + updated_at: 2016-04-04 14:11:34.325274000 Z + +price_13: + id: 13 + group_id: 1 + plan_id: + priceable_id: 4 + priceable_type: Machine + amount: 900 + created_at: 2016-04-04 14:11:34.362313000 Z + updated_at: 2016-04-04 14:11:34.362313000 Z + +price_14: + id: 14 + group_id: 2 + plan_id: + priceable_id: 4 + priceable_type: Machine + amount: 5100 + created_at: 2016-04-04 14:11:34.366049000 Z + updated_at: 2016-04-04 14:11:34.366049000 Z + +price_17: + id: 17 + group_id: 1 + plan_id: + priceable_id: 5 + priceable_type: Machine + amount: 1600 + created_at: 2016-04-04 14:11:34.398206000 Z + updated_at: 2016-04-04 14:11:34.398206000 Z + +price_18: + id: 18 + group_id: 2 + plan_id: + priceable_id: 5 + priceable_type: Machine + amount: 2000 + created_at: 2016-04-04 14:11:34.407216000 Z + updated_at: 2016-04-04 14:11:34.407216000 Z + +price_21: + id: 21 + group_id: 1 + plan_id: + priceable_id: 6 + priceable_type: Machine + amount: 3200 + created_at: 2016-04-04 14:11:34.442054000 Z + updated_at: 2016-04-04 14:11:34.442054000 Z + +price_22: + id: 22 + group_id: 2 + plan_id: + priceable_id: 6 + priceable_type: Machine + amount: 3400 + created_at: 2016-04-04 14:11:34.445147000 Z + updated_at: 2016-04-04 14:11:34.445147000 Z + +price_25: + id: 25 + group_id: 1 + plan_id: 1 + priceable_id: 1 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:15:21.038387000 Z + updated_at: 2016-04-04 15:15:45.691674000 Z + +price_26: + id: 26 + group_id: 1 + plan_id: 1 + priceable_id: 2 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:15:21.048838000 Z + updated_at: 2016-04-04 15:15:45.693896000 Z + +price_27: + id: 27 + group_id: 1 + plan_id: 1 + priceable_id: 3 + priceable_type: Machine + amount: 2500 + created_at: 2016-04-04 15:15:21.053412000 Z + updated_at: 2016-04-04 15:15:45.697794000 Z + +price_28: + id: 28 + group_id: 1 + plan_id: 1 + priceable_id: 4 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:15:21.057117000 Z + updated_at: 2016-04-04 15:15:45.700657000 Z + +price_29: + id: 29 + group_id: 1 + plan_id: 1 + priceable_id: 5 + priceable_type: Machine + amount: 1300 + created_at: 2016-04-04 15:15:21.061171000 Z + updated_at: 2016-04-04 15:15:45.707564000 Z + +price_30: + id: 30 + group_id: 1 + plan_id: 1 + priceable_id: 6 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:15:21.065166000 Z + updated_at: 2016-04-04 15:15:45.710945000 Z + +price_31: + id: 31 + group_id: 1 + plan_id: 2 + priceable_id: 1 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:17:24.920457000 Z + updated_at: 2016-04-04 15:17:34.255229000 Z + +price_32: + id: 32 + group_id: 1 + plan_id: 2 + priceable_id: 2 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:17:24.926967000 Z + updated_at: 2016-04-04 15:17:34.257285000 Z + +price_33: + id: 33 + group_id: 1 + plan_id: 2 + priceable_id: 3 + priceable_type: Machine + amount: 2500 + created_at: 2016-04-04 15:17:24.932723000 Z + updated_at: 2016-04-04 15:17:34.258741000 Z + +price_34: + id: 34 + group_id: 1 + plan_id: 2 + priceable_id: 4 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:17:24.937168000 Z + updated_at: 2016-04-04 15:17:34.260503000 Z + +price_35: + id: 35 + group_id: 1 + plan_id: 2 + priceable_id: 5 + priceable_type: Machine + amount: 1300 + created_at: 2016-04-04 15:17:24.940520000 Z + updated_at: 2016-04-04 15:17:34.263627000 Z + +price_36: + id: 36 + group_id: 1 + plan_id: 2 + priceable_id: 6 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:17:24.944460000 Z + updated_at: 2016-04-04 15:17:34.267328000 Z + +price_37: + id: 37 + group_id: 2 + plan_id: 3 + priceable_id: 1 + priceable_type: Machine + amount: 1000 + created_at: 2016-04-04 15:18:28.836899000 Z + updated_at: 2016-04-04 15:18:50.507019000 Z + +price_38: + id: 38 + group_id: 2 + plan_id: 3 + priceable_id: 2 + priceable_type: Machine + amount: 1000 + created_at: 2016-04-04 15:18:28.842674000 Z + updated_at: 2016-04-04 15:18:50.508799000 Z + +price_39: + id: 39 + group_id: 2 + plan_id: 3 + priceable_id: 3 + priceable_type: Machine + amount: 1500 + created_at: 2016-04-04 15:18:28.847736000 Z + updated_at: 2016-04-04 15:18:50.510437000 Z + +price_40: + id: 40 + group_id: 2 + plan_id: 3 + priceable_id: 4 + priceable_type: Machine + amount: 1000 + created_at: 2016-04-04 15:18:28.852783000 Z + updated_at: 2016-04-04 15:18:50.512239000 Z + +price_41: + id: 41 + group_id: 2 + plan_id: 3 + priceable_id: 5 + priceable_type: Machine + amount: 800 + created_at: 2016-04-04 15:18:28.856602000 Z + updated_at: 2016-04-04 15:18:50.514062000 Z + +price_42: + id: 42 + group_id: 2 + plan_id: 3 + priceable_id: 6 + priceable_type: Machine + amount: 1000 + created_at: 2016-04-04 15:18:28.860220000 Z + updated_at: 2016-04-04 15:18:50.517702000 Z diff --git a/test/fixtures/profiles.yml b/test/fixtures/profiles.yml new file mode 100644 index 000000000..96ccdb0e6 --- /dev/null +++ b/test/fixtures/profiles.yml @@ -0,0 +1,78 @@ + +profile_1: + id: 1 + user_id: 1 + first_name: admin + last_name: admin + gender: true + birthday: 2016-04-04 + phone: 0123456789 + interest: + software_mastered: + created_at: 2016-04-04 14:11:33.858015000 Z + updated_at: 2016-04-04 14:11:33.858015000 Z + +profile_2: + id: 2 + user_id: 2 + first_name: Jean + last_name: Dupont + gender: true + birthday: 1975-06-07 + phone: '0214321420' + interest: 3D printers + software_mastered: autocad + created_at: 2016-04-04 15:00:29.131180000 Z + updated_at: 2016-04-04 15:06:22.148303000 Z + +profile_4: + id: 4 + user_id: 4 + first_name: Kevin + last_name: Dumas + gender: true + birthday: 1998-06-05 + phone: 0446124793 + interest: '' + software_mastered: solidworks + created_at: 2016-04-04 15:10:42.350790000 Z + updated_at: 2016-04-04 15:10:42.350790000 Z + +profile_5: + id: 5 + user_id: 5 + first_name: Vanessa + last_name: Lonchamp + gender: false + birthday: 1994-05-03 + phone: 0233412482 + interest: vélo, natation + software_mastered: '' + created_at: 2016-04-04 15:14:08.577633000 Z + updated_at: 2016-04-04 15:14:08.577633000 Z + +profile_6: + id: 6 + user_id: 6 + first_name: Gilbert + last_name: Partenaire + gender: true + birthday: 2016-04-04 + phone: '0000000000' + interest: + software_mastered: + created_at: 2016-04-04 15:17:12.535971000 Z + updated_at: 2016-04-04 15:17:12.535971000 Z + +profile_3: + id: 3 + user_id: 3 + first_name: Paulette + last_name: Durand + gender: false + birthday: 1949-06-18 + phone: '0474264261' + interest: '' + software_mastered: '' + created_at: 2016-04-04 15:07:46.687390000 Z + updated_at: 2016-04-05 08:35:18.580745000 Z diff --git a/test/fixtures/project_steps.yml b/test/fixtures/project_steps.yml new file mode 100644 index 000000000..cc2516cba --- /dev/null +++ b/test/fixtures/project_steps.yml @@ -0,0 +1,18 @@ + +project_step_1: + id: 1 + description: "

Impression du manche à l'imprimante 3D puis découpe d'un vinyle + de protection à coller tout autour du manche.

" + project_id: 1 + created_at: 2016-04-04 15:39:08.259759000 Z + updated_at: 2016-04-04 15:39:08.259759000 Z + title: Le manche + +project_step_2: + id: 2 + description: "

Impression de la presse à l'imprimante 3D puis assemblage avec + le manche et vissage de l'ensemble.

" + project_id: 1 + created_at: 2016-04-04 15:39:08.265840000 Z + updated_at: 2016-04-04 15:39:08.265840000 Z + title: La presse diff --git a/test/fixtures/project_users.yml b/test/fixtures/project_users.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/projects.yml b/test/fixtures/projects.yml new file mode 100644 index 000000000..d371acfd9 --- /dev/null +++ b/test/fixtures/projects.yml @@ -0,0 +1,14 @@ + +project_1: + id: 1 + name: Presse-purée + description: "

Réalisation d'un ustensile de cuisine permettant d'écraser des + pommes de terre ou d'outres légumes afin de confectionner de la purée.

" + created_at: 2016-04-04 15:39:08.224918000 Z + updated_at: 2016-04-04 15:39:08.224918000 Z + author_id: 5 + tags: cuisine + licence_id: 1 + state: published + slug: presse-puree + published_at: 2016-04-04 15:39:08.267614000 Z diff --git a/test/fixtures/projects_components.yml b/test/fixtures/projects_components.yml new file mode 100644 index 000000000..8daaaa399 --- /dev/null +++ b/test/fixtures/projects_components.yml @@ -0,0 +1,20 @@ + +projects_component_1: + id: 1 + project_id: 1 + component_id: 10 + +projects_component_2: + id: 2 + project_id: 1 + component_id: 7 + +projects_component_1: + id: 1 + project_id: 1 + component_id: 10 + +projects_component_2: + id: 2 + project_id: 1 + component_id: 7 diff --git a/test/fixtures/projects_machines.yml b/test/fixtures/projects_machines.yml new file mode 100644 index 000000000..76772f78f --- /dev/null +++ b/test/fixtures/projects_machines.yml @@ -0,0 +1,20 @@ + +projects_machine_1: + id: 1 + project_id: 1 + machine_id: 6 + +projects_machine_2: + id: 2 + project_id: 1 + machine_id: 2 + +projects_machine_1: + id: 1 + project_id: 1 + machine_id: 6 + +projects_machine_2: + id: 2 + project_id: 1 + machine_id: 2 diff --git a/test/fixtures/projects_themes.yml b/test/fixtures/projects_themes.yml new file mode 100644 index 000000000..7adc67cc8 --- /dev/null +++ b/test/fixtures/projects_themes.yml @@ -0,0 +1,10 @@ + +projects_theme_1: + id: 1 + project_id: 1 + theme_id: 1 + +projects_theme_1: + id: 1 + project_id: 1 + theme_id: 1 diff --git a/test/fixtures/reservations.yml b/test/fixtures/reservations.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml new file mode 100644 index 000000000..8a6e880ce --- /dev/null +++ b/test/fixtures/roles.yml @@ -0,0 +1,32 @@ + +role_1: + id: 1 + name: admin + resource_id: + resource_type: + created_at: 2016-04-04 14:11:33.826505000 Z + updated_at: 2016-04-04 14:11:33.826505000 Z + +role_2: + id: 2 + name: member + resource_id: + resource_type: + created_at: 2016-04-04 15:00:29.112744000 Z + updated_at: 2016-04-04 15:00:29.112744000 Z + +role_3: + id: 3 + name: partner + resource_id: + resource_type: + created_at: 2016-04-04 15:17:12.586692000 Z + updated_at: 2016-04-04 15:17:12.586692000 Z + +role_4: + id: 4 + name: partner + resource_id: 2 + resource_type: PartnerPlan + created_at: 2016-04-04 15:17:24.964272000 Z + updated_at: 2016-04-04 15:17:24.964272000 Z diff --git a/test/fixtures/settings.yml b/test/fixtures/settings.yml new file mode 100644 index 000000000..856dc615f --- /dev/null +++ b/test/fixtures/settings.yml @@ -0,0 +1,235 @@ + +setting_1: + id: 1 + name: about_body + value: '

Le Fab Lab de La Casemate + est un atelier de fabrication numérique où l’on peut utiliser des machines de + découpe, des imprimantes 3D,… permettant de travailler sur des matériaux variés + : plastique, bois, carton, vinyle, … afin de créer toute sorte d’objet grâce à + la conception assistée par ordinateur ou à l’électronique. Mais le Fab Lab est + aussi un lieu d’échange de compétences technique.

Le Fab Lab de La Casemate est un espace permanent : ouvert à tous, il offre + la possibilité de réaliser des objets soi-même, de partager ses compétences et + d’apprendre au contact des médiateurs du Fab Lab et des autres usagers.

La + formation au Fab Lab s’appuie sur des projets et le partage de connaissances : + vous devez prendre part à la capitalisation des connaissances et à l’instruction + des autres utilisateurs.

' + created_at: 2016-04-04 14:11:34.559256000 Z + updated_at: 2016-04-04 14:11:34.559256000 Z + +setting_2: + id: 2 + name: about_title + value: Imaginer, Fabriquer,
Partager au Fab Lab
de La Casemate + created_at: 2016-04-04 14:11:34.565164000 Z + updated_at: 2016-04-04 14:11:34.565164000 Z + +setting_3: + id: 3 + name: about_contacts + value: "
Manager Fab Lab :
jean-michel.molenaar@lacasemate.fr
+ \
Responsable médiation :
catherine.demarcq@lacasemate.fr
Animateur + scientifique :
diego.scharager@lacasemate.fr


Visitez le site de La Casemate

" + created_at: 2016-04-04 14:11:34.569316000 Z + updated_at: 2016-04-04 14:11:34.569316000 Z + +setting_4: + id: 4 + name: twitter_name + value: fablabgrenoble + created_at: 2016-04-04 14:11:34.572468000 Z + updated_at: 2016-04-04 14:11:34.572468000 Z + +setting_5: + id: 5 + name: machine_explications_alert + value: Tout achat d'heure machine est définitif. Aucune annulation ne pourra être + effectuée, néanmoins au plus tard 24h avant le créneau fixé, vous pouvez en modifier + la date et l'horaire à votre convenance et en fonction du calendrier proposé. + Passé ce délais, aucun changement ne pourra être effectué. + created_at: 2016-04-04 14:11:34.578108000 Z + updated_at: 2016-04-04 14:11:34.578108000 Z + +setting_6: + id: 6 + name: training_explications_alert + value: Toute réservation de formation est définitive. Aucune annulation ne pourra + être effectuée, néanmoins au plus tard 24h avant le créneau fixé, vous pouvez + en modifier la date et l'horaire à votre convenance et en fonction du calendrier + proposé. Passé ce délais, aucun changement ne pourra être effectué. + created_at: 2016-04-04 14:11:34.584331000 Z + updated_at: 2016-04-04 14:11:34.584331000 Z + +setting_7: + id: 7 + name: subscription_explications_alert + value: '

Règle sur la date de début des abonnements

  • Si vous êtes un nouvel utilisateur + - i.e aucune formation d''enregistrée sur le site - votre abonnement débutera + à la date de réservation de votre première formation.
  • Si vous avez déjà une formation + ou plus de validée, votre abonnement débutera à la date de votre achat d''abonnement.
  • +

Merci de bien prendre ses informations en compte, et merci de votre compréhension. + L''équipe du Fab Lab.

' + created_at: 2016-04-04 14:11:34.588478000 Z + updated_at: 2016-04-04 14:11:34.588478000 Z + +setting_8: + id: 8 + name: event_reduced_amount_alert + value: "* Tarif réduit si vous avez moins de 25 ans, que vous êtes étudiant ou demandeur + d'emploi." + created_at: 2016-04-04 14:11:34.592250000 Z + updated_at: 2016-04-04 14:11:34.592250000 Z + +setting_9: + id: 9 + name: invoice_logo + value: iVBORw0KGgoAAAANSUhEUgAAAyAAAABNCAYAAABe8gBxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjVEMjA4OTI0OTNCRkRCMTE5MTRBODU5MEQzMTUwOEM4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjAzODFDRjYwMEE1RTExRTQ5NzJDRkFDOTI4MTJEOEM1IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjAzODFDRjVGMEE1RTExRTQ5NzJDRkFDOTI4MTJEOEM1IiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIElsbHVzdHJhdG9yIENTNCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ1dWlkOjI2NzQ5N2UwLTgyODEtNDg4Ny1iOGZlLTExMzA0ODhhZjRhOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3RDc4OUVFODZFRjBFMzExQjU4NTg3NzUwQzc4MzhDMCIvPiA8ZGM6dGl0bGU+IDxyZGY6QWx0PiA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPkxBQ0FTRU1BVEUtTE9HTy1WRUNUT1JJU0U8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pri35wEAAEzrSURBVHja7F0HeFRF17676b33RnqvJCEEklACBAg1CSSCiihgRxQQBUERBEQpioiiIApIU0TTezZ103vvvfdkN9lk88+Jyffz8dGzd0syL899ErJ3751y5sx5z5w5QxkbGyMwMGY6GAwG0dDYqFhSXGza0dFhkZuXZ8FgMgzz8/O10cfK6JJHlyS6RCa+MoKuQXR1s9nsNlMT03o5ObkSQ0PDfGsrq1wjY+NSNVVVBpVKxY07A9HX30+pq6tTrygvN21qajIrLikxRnKim5uXqz4yMiJLoVCkJmSJgi4WuoZGR0f7NDQ0ug30DZrQPfX2dnZV0tLSFYZGRlVqamqNqioqLNyy/Al2X5/QSGub0mh7h8JQTp48ISQE/Ss83rejo0NCqiq94jZW3Wi27RDR1WFQhIX5sA79xEhzs9zYyKgSMzVdfozFkiUoFFH00SgxNjZEERXtF3ee3U0REuoQ1lDvo0pL818d+lEdmpqlxkahDhkKY8PDUAfxiY+HiVF2v5i9dbeQomIXVUa6S1hVFRtAGBg8AuX1N964zOmHDg8PixkZGWV8tG/f19O58S5cuPAyPS1tubiYGIPsdyGiCJYsc9++fQdm6em1YdGd4kTFZhNVVVVKBQUFTjm5ufNKSkrmtLa1mgwODqqhthYHYo6MREL4KQ0FZDyOPxMgIiIygAzHGm0t7czZDg5R8+fPjzY2Nq5Ffxe4djp+4sT7ZWVlTqKiokwu9ImwhIRE68FPPjmgqKjIEKR2AnlBhEOJTqe7IpKxoLS0zKmjs8MIEVsgryKTjp4nyQDIEMjSuHJG8oe+x5KUlOyWkpJq0NTQRATXINPI0CjdysoqR1tbu0NcXJzUetXV16seQUBlEUMXe7rpASaTKeE6d+7Nbdu23Z3Kc3rv3F3b9Po7P1PExITYvX2iqPOEJsjlGOpENjLeR5DB209QqV2iOtr1wlpaxeJWFulijg6pErPty4SUFEe5Kq8sFsGqrZdjpmdYI8LkOFRQaMtqbjFGxrs6KrvCaHePOCq38EQdxkUT/X1ESF6Ogf7eJayp0SSiplYqZmmeLe7kSJeY55IvrKLMRPdwc9ARIy2t4szcfHNmCt2RkZ5lN9LaajbS2KSJyqGI6iA1UQfqf+owNjZKlZVhIgLYIyQn14qIVIWYuVmOhKtLqvhs+ywRXe0eigDq6ftx48YNr9CwsC1Il3JDh1LQGKKi8XMUjaOSZ/1yS2urwmeffXYU6T1ppF9GiRmCoaEhSQd7++tvv/32vUfd89358yvTMzJeQvbl4HRtB+Gs7KwtJCh1YpQ9qoJ+nbYEpLGxUeLGrZsfDQwMmAoJCXHlnehdxF/3/kp9792dP2MK8XworyhXotHilyckJvggw9odEQ5FMPSQgU1APz5vX97/XWQ0SvX29lrkdORYpGekb/7l1ysMfX392CWeS64s8fQM0tLS6heEtsrLz9P68+6f+1H7jLcRt2TcxcUl1H/jxghBaKPOri7R0NDQxbR42kvFxcVL+vr6lGDVa1KehJ/R0w3ffWDVTGR4eFgF6VSVlpYWu7T0tI1AZhAp6VRXV89wmeMS6uHhHmZpaVUkIS7OcYLAGByUQ3PESxMEZNrpA5A3DQ31MvTrlAjI2PCwPLuzW5EqJ0cgsvFQY5nd3QtLBuqMljZzIiVtSe+tP0BxjIhoaxVIus/7S3ajz3XpJZ6lhBB5q6bM7FzVvsBgr4GQiLXDJWWuoz09alA2MLopoL8m5PURKzRi7J4+WNlRHuosMh7KyXfvCwqFOhCIfFSK29uGyL286ar0ksV0qpwsaSsLrJpaqf7wyIX9fwevY2blLBxp75hFjIxQxokDKgvl8XUgxgaZkmgMKbK7evSHyyvnDETHvUB89wMBhETU2DBG1t/3msz6NREiOtpMQZPnkZER4u69vz5Ac5un6MPkkASgOZTQCNKoRwTk42c2xJlMqeyc7M2o3DIzKVoA2kxWTrYQ/fpIAlJRWWGdkZG+Aen6adsOwmJiYqQ8GAk/ezoLUFJysgcyNkylubgMDQZASkqK/9CO138mq9+mI/r7+4kUeopTYFDQa5mZmevR/5VBOcNFRv9BP8EFfQQXmuwkKisrl3977tvlV369Urts2bKLARv9f9TT02vl53aj0WgrR0dHFbkp42Bcx8fT/PmdgFRVVcncunP7pYSEhLcaGhrMYWWDTHmaJLiT4x4MKPTeJdd/v77k1u1bX+rq6mY4OzvfWLZk6W0rK6t6Tk3mFCqVjd45NinT0w2w2iQsIjLGgU4aN34JKuUxn//7GUUI+lBscmlBeLS93bbn6g3b3t9vfSThPu+e0q53j0kv88wiONSHo13dxEBoxNzuq7/vYCQmr2b3DyhQxETHiRJVVuYZPS3UiTr8a9xSCInxn+z+foP+iOi3+kPD3xQ1M0lQfGPHMbkX/UOoMjKc0QssFjEQFmnSc+3GawPRsf6jHV06QJao4mIEVeoZDbTxPqKM14UiIkxQJP5dRRwbHVFl5uZtZKRlbOw48XWJ7Av+pxV3vnlFkIgIsg8sqqur3UAPcWu8gpMF5tWmpqbDGhoazGfUbaBf2KDbZhIBgZVukSfoHRFhkf/YENMVOED9ORESEuzP7ZAaeF9NTY0b7E/APfBkgHfz5q2bni9veTl830cfpSQlJW1Hf1aWQZMiDGpuKejJFRaYFEZGRnTv3Lnz+eaXXiw89Omhg3V1dXL82nZRUVH+3FZ+0E6FRUUrkIGvwo/t0tPTI/zV11+99vIrW3Jv3bp1rrOz0xzkCUKhuDmBgkyBPgCZQu8WQmTE+caNG6def/ONwm07tv0aGRnpBN5QDAEAGNKICFCkpEQH45P86lb7pdb7vPAtq7JqSrqB3dtLdJ761rPaZUFUw0uvJg1ExbyMhFSBKidLUCB0j5PyCgYkIgJUWVkKq7rWrfmdXcHV85f8MxAZbTil5yIZ7vvrH6taT++rdev9c3r/vLdnbJilA3UYJx6cjD5A7QHtAs8eHWSYdpw6e6HGfWlq14WfFhJswfCnRsfG+CBSzdXVSiAPra2tprR42gI8mDEwASEZRcXFqiWlpSu4tcR5v9HBYrHEAgMDfXAvPB5BQUHOm198MfzEyZMRTc3NS6SkpKgSEhI89+KCkYrKAr8qBQUHf4aISM7Fixf9Ub/yVftlZmZa1zc0uHGbZEP79Pb2qoeEhi7nN5kKDQ112PTiZtrvN25cHBsbmwXGvzCfbCaeJCOoPDL5+QUv7vv4o5TXtm0LRETEZXJPCYYATMiSyIiXkRbuCwp5u2reYnrvzT8cn+c5ff8EW1cvWh7U/MG+CFZj4yJEDJDBLkVwY4/G+MqKvDwxXFbmXeftk972yeENz/McRnqmeq33+u/r/TZlMFLTNlFlZMTHN75zgehDOJqQoiIx0t5u3fzWe1ENm7YeHu3s5OslwJaWFuHk5GRfsveFPUr/xMTGBuARjIEJCMlISEhYyWAwVHhhzIJHOjMr06e7u1sY98T/oqKyUunNt976/tDhT5OaW5qXyKAJix83f08SEWQc6n3/w4Xft+3Y/kdBYaE6v5QvjhbnA5vCefFuIPbJKckb+cWDPzw8TBz69NNd+w8eSOrs7JwLhj6/hguATgIDBAh3UUnRSkREkl55desNOp1uiLWDgAD1IYQusQcGTBs2vRKNDHjvp/3qSEOjeMPGFw83+G1KGy4sXiGkpPjwPSncqAY4fCQk5NuPfnmzdd8ne5/2e6jeRNv+Qy/XLPDKGYiNfx2RJ1EKL+LgYW/Mv2SK0nPj1if1fpuvsbu7RflVbFJSUua3trbacGtP6oN2SW5e7vL8ggJVPIAxMAEhCQwmgwgPD/PnVVweeFwbGxtto2Oi5+Pe+H+Al/fqtaver772alZaetrrUpJSQqKionxfbpgsIISnsLBw/ZtvvZl25487i3hdppaWFlFafDxPPGmTBKSkpGRhCp1uyuu2qK+vF9++Y/uvQcFBp5BMiQlSJjNxsXEiQkFtuXHnrveyPzn4yYdtbW0iWFsICA9BskaVkZZpO3LidsfJM15Pur/vz3uW1QuWxff+ce8TZLCLAQEgeJ1mH5IqyMsRHSdPn2j98MDuJ90+lF+oVLt09a32Y1//QhERVqX+u1rMez2NiNxgXEJA3foXfh3t6uLLlZC4eJo/L8jHpONjiDmkkpiYuBKPXAxMQEhCTk6OeV19vQcvDRFQMjQabSPujX/R1t4uvO+jfV99ferUPyMjIzqCmDUCwsNQ2bWPnzgRevKrk29AJjlegZ5Kd+vs7LTk1WQGYLPZEnG0uHU8JR8N9TK73t91Ly8//0VYrRLUTdhAJBGpkw4OCTn+8itbaIhcWmGtISgzNJUQkpMVbz964re+v4MsH3Vbx1dn/Oo3vpg00tTsCAY/wU+yCis6cnJE+5enT7YfOfHI8OGe3353qPFcmczMyPSjKshzJdTqqYF4HLTrQGzcxqYd7xznNzGpqKhQyMzMXMnLDcvgOIqNiw3g5dyFgQnItEZgYND4Ji9eGxQZmZneJaWlijO9P/Lz81XfefedkKjo6A9kZWUJXhrNUwWsbiHyJHL12rXzBw5+8unQ0BBPyhEUHOzP63aEiTQtLc23t7eXJzqqvr5e8r1du/6orqlZKsOhTD68tQEp4yttXV1dLnv27kk+//35rRBahiEAQGNxjMVSbnl/3wVEMP7L8zU2NEw0vPTa7taPDt6iSkvLUsAA5cfDhSGTm5wsEKXvGEn0WQ9+3Hn2/IrGV3ZEjw0OGlP48IDDfxt7jBBSUICVpr0dJ8+s4qei0RLivXr7+rR5GRoKBAQRIffMrExzPGgxMAHhMDo6OoTQ4PLldVo0MCYGBwe14+Pjl87k/khPTzd6Z+e7MZVVlZ5APqYDoG/l5eWJ6OjoQ/sP7D/CbRJSXl6uVFxc7M3r8DUgY3V1dbPjaLS53H73IINB7Pto34/V1dWQvIAYG5sehyVDPaBfkf6SPn/h+58/P3pkL4EhGHpBQoJgVVfPbz3w2dv/6U9EIBtf2X6w5+rvJ8fT3fJ7GlNEpNhMplrLxweP3J9VqvPsd+tb9nz0J1VaSo6AyAI+H28UpBPavzx1fLiklC88E+BIiIyM9Bfjg5BjpGPEIiIjcZIcDExAOI3UtLT5bW1ttvzgZYcQsMSkRH82mz0j+yItPd1yz4d7I5lMpoWEuMS0MRInAd7q6JiY/Qc/PcRVIzEhMXF5f3+/Oj9ssqbyKNTw1KlTHxYVF2+aTuTjQSIiLSXd7T7fLQprdYHptPGN6b137n7AzMweT1Hd+PL23T037nwGXnlCQMIDYU8HI4m+qe+vf9wmyMeylj0fX6NKSooRArJ6DQccsru6LDrPXdjOD+XJy88zrKioWMQPex7BOZuUlOSL7CQhPGgxMAHhIAKDAv0pVP5Q9DDQCwsLPZEhbjADyYfx3g/3BiLyoScIG82nQkKioqJOXPzppw3ceB940kLDQgP4pU3FkYynpqWuqays5NpZKX/du+f8172/PpXik82vZADOeHlx8+a3lyxZkoG1uiDN1lRibJCh1X3pil/nmXNePTdvnxSCvRKCBkQ0ui5efq3vn2CD1n0HryLyIU4IWOgspAPuvfnHjuGSUp5vOIyj0dawWCxp/uhaIYgUsc3IyMBJcjAwAeEUampqFJDB7y0myj+nUo6MjkjRaLS1M6kfcnJy1Pbs3XMXkY9Z05l8TAI2p//080/fx8bFkX74ZH5+vjGS8wX8kukJVmH6+/t1ExMTPbnxPjRxUn755ZcvUf3Fp+Op34DBwUFi7ty5Z994/Y1rWKsL4IQtgwzf23f3tn169GcheXnBrIOkBMFITfdu2rojhCImqkwI4r49VObRjk7j/iDenlfU09NDxMbGbuBVxsJH6e3QsFB/PFoxMAHhEEJCQ5b19vZq81P+f0izGRsXu6Gzq3NG9EFra6vIF8ePXRlkDFrOBPIxqczRpfjlVyfPw0FTZL7r78B/1rFYLEl+Mr6BDMXF0wK4EQp19do1/5raGg+xaSpbcNilqopqwv6P9++jUrHqF0igsTk2PKyHlIImIcgkeWxMcWxk1IQQ4KQhcEZIX3AYT/c7pGekz2lsapzDLweiAiA6Iys727u6uloBD1gMTECmCDhjIjEpKYDfjF5QOsgon5OWlj5nuvcB7HU5duL4F2VlZcskJSRnlPyBQm9pbvb45ty3u8l6R3dPDyUzI3MDrxMsPAgYcwUFBUuzs7N1yXwPIvHUsLCwnZDCeWwayhAQODSG2j788MPXNDU0cJ5MwfZKEISgr9BB+QWcBFPExYihvIL5rKpqnm1GDwoO9qNSqHwmnlQI89SOjI5aigcrBiYgU0R+QYFBZWXlIn49hCwuLnbDdO+DX678sjo2NnY37IuYjhuDn2Q8wp6EqKiojxMSE0gJxUpPT3dtbmmezU+etH/tFArsTZGBOGcy3xMTHbO4ta11Dr/Vn1Po7+8nXn7ppbfc3dxKsEbHwOAMERzt6tZh5uTxJO1sQ0ODdE5Ozjp+cxoBwFaKjo72HxkZwXKCgQnIlLwMQYFrmEND0vwYFw6xn8kpKWtra2un7a7ZouJilSu//np6Om8MfhpDHBERmQs//HCUjPMbAgMD+ZbEgoxHx0T79/b2kkdA4mIDpmNYEsgNkA/Xua5f7di+4zbW5hgYHMQYm0AEhCcHeyYnJy/q7u424Ee9BQSkpqbGs6ioyAALCQYmIM8JmLzT0tM38GtcOCgfZJgZJCUnL56uffDjjz8cHBgYMOB1+mNYibj/4oUhXlhYuPb69escPQSroaFBNr8gfzU/etIAsCrR3NzskpmZOZuM5yPyLovadQlZ9YfwQQaDMZ596lEXbA4HYgnhnpwEnEqsP0s/5tNDh/bjfR8YGJzHaGubGS/eGxIaEsCvURng+BgaGpJGZVyDJQTjkXM7boLHI44W51xbV+cizcfed1BCwSHBARv8/P6ebkZGWHiYMy0+/nVpLp+OCwQDlo9h4y4Yhcg4HRMVFR1Afx+a+FwKGY7i0N6wT4FboTtAQv64++fHa9asCVZQUOCItRoaFubZ2dU1S4ZfTyD+t72pUdHRfgsWLOB46tjc3Fy7np4ebU7L2ET4GMhOs5Oj4217e/s0NTW1FiRPsAeDij6XQJO0fHFxsXp3T49BdXW1cWdnpymUBcmdMIxrkKvnJd4gtyLCws379n24TVlZeZhP+5Wn72fD+8fGpmfKMwzyDW0RUWKosEib2+8tKirSKikt9eLnZCzg0ElMStrQP9B/WlrqkbqVgnQAhZNOPTIjVThVxgm9M2P1LiYgT01AaH5UPt/wB0qooqJiWWFRoZaVpVXDdGl7IAC/37ixHxliwtwcmAwmk6BSKcN6unppNtY2MaamJhk62jqV6urq3WA8IgVHQYajVFl5mW5+foELPZXu3dTU5IL+LER2OkQwShsaGlz+vHvX79WtW29wor6JSYkBonzqSbufeCWnJK9rbGr8TFNDk8HJZxcUFTqRMWmB/MrKymZ9efzEChsbm+ZH3bdm9Zr/TAhtbW3idXV1hjm5uc4pKSmLqqqrFiBSog1ERExMFE2uT+9ggBPdd+3c+brjbMcKfuxTNpvNQNcA2Ay8KsPoyIgsKsMgnukwntPaJdiDg8rjJ7tz0fkXHBKyCs1T8vzsGAWdBfNiQkKCk9cyr7RH+0lGO9CFVOAYJzaMUNF75cnQKah8TFTOfk48G+kdOdB/PNS93RPtzVPjFhOQxwANHr7d5PUg42cymQpxcXGrEAG5MF3aPyoqagGEBklJckfJQhiMsIhw6wIPj583+G24Ym1tXSL+mL43NzevXL1qdezAwMDxjMxMhxs3buxKS0/zR4RQmKwVEfBqwwWHYr704os3proEX1hYqFtWVraE39Maw0pTd3e3SVJS0kJfH99gTj67orzcmoz+QiSVePutt/c9jnzcP4YBqqqqTHQVzJ49u+CVLVsuI0IiSU9NdQ0JDdmYm5u7lsHoV4azYR63KgLP6uvrI5YtWXp086bN9/ixP2Gs+fj4XPDf6L8P/S7Hq3KgiZgiLy8/gGc7jOefgKlS3MxKBuGcySnJ/oKQLhwcKxGRkRseRUDU1NRaf7jwgzMnDGGkw1mdnZ2aBw8dTEZtJMvJaBBocw93j+tvvvnmW+j3KWc9A70jKyvbz4s+YbFYox9++OFqZCtmozmKpwfIYALyGERGRS1EBoAhZF7idwBJQuX13/LylgvTYbM2GNm/37yxkxv7PuBdaCCy3N3cz7380kvHkMHY9izfh/Z2d3PLRNeLf//zz7ffnf/uXEdHhxMn+wHKCEpQQV6h0me9z3feK1de5UT8b3BoyGowAKX5OPzqvgmGCAkJ9eckAYH9GYhA6nJ6BQQmXnFxcYa1tVXhVBwLiIwMrvL2jkT9HVlSWvphSEiIf3hE+NstLS3mkDL4YeMD5MRA3yDsg/ffP8SvBypCu6soKw/M0tOD0LA2AgNDcMFVJpCYmGhTW1s7DxwRgmCX5OXlrWtpbflUTVXtf4i+qKgo28LcvJ1T70MERAwRjzFOhxiBvpKTk2Xoz5oF4bMCm8Z8ItRtbJberC5DA4M+9Kc+XpYH70p8DBIS4v3J2OQ1MjLSgWSAozHZUM7GxkbXrKwsm+nQ9lHR0Tb5+fkr4bBFsjCxUQ7arvzgJwcXfv3VV+8/K/l4EKtXrUr95dLl+R7uHt9BAgMOeCvGNykjMpOz6YVNr/x25VfrXe+9d8rY2Lh1qs8GL3RqaiopZ3+gcrchGWdzdJYXFSXKysu8ikuK1TkpAxQqVZkk2ZJA7evBqeeZmZp2or4/j2TAfttr215GpLEMZOz+yRaIKmqnug8//HCHsrLyKIExswGyAeFB91+CmMacv+vAVZYfHRvjh8Y8R53HoF+QXQIhxhwNCwIHCSIFhpGRUYvwYJyZ8ooJyHMgOydbMzcvbzmnjTPYlOrq6npaQV6hBFg1h1m6yD+BgX7Tof1jYmM2I6VI2sYEULhggGtqaNIu/nhx3ipv70ROPVtDQ2P45Jdfvu3t7X3weUkIECMIo1FXV6ft2b1n7c3fbzi+v2vXLxqaGhyLV09ITLSvqqqax2mSDXsfFixY8IW4uHgrJz1R0GeIjKkEBQev5NQzW1tbhdrb28XJWGmDfSs/X7r0/YkvT+yqqKyUY3OoLRCxGHrj9dd/vXL5F7tV3qsOILLXD/ICYDAY7B3bt7/uOHt2DdbiMxRoXhlDuo3d00uMDQ2xKGJiLRRR0YrxS0yseWyYxZr4jK+J0xiDMV4Hdn8/myIi0o7KX4muclSHevQ5Y7wOqJ7EDDoXqr2jQzQ7K9uH03YJ6A9zc/MrmpqaNE6f3QG6NS4uNgAPTIwHgUOwHoH4+PhViCwocDo2HlY+vFd6X/mD+YdOS2uLNScVCTwrJzdnfVtb2+cqKirDgtr2dXV1Eunp6aTuvYH0pNra2rFnTp1eraury/FlSIg//fTgoc/Re+QjIiLel5WVfarME1AuRCRHbG1sg5ctW/r1iuUraGSF1NFocX4UCmeP0YU6CgsLN69fu+5SdXX1cnSpc5LggEyk0un+zKGhn8U5IB9ojFPAKUBGqBI8E8mBzO07d04FBgXtMzUxjbOxsYm0tbVNNjMzK1NTVZ3SUr6amtrgp4cOHfXyWnbn61Onvs/Pz1+4bu3azzZv2hxMYMxI4oGMdYIqLdMkucD9b+kVy8LFLM3zxYwM28YmPNsUISHx4Zpa1cGEJMe+P//exMzO9aJKSVIJHqc4/69qoDpQhIX7JFzmhEotcg8Ss7HOFLcwa0KKZQApGDaqg+hoV5fSYEqaVX9giM9AdCw43aQoEJI0zclITHS0B7IbzDkdMstCpMPPx/dWQWHhnOu/X1/GyT1xoLMLi4q8cnNzNZH+a8QDFQMTkMcAYqgTk5I2cpp8gGdBXV09x23+/Pra2troxKTEHZw0ssHT0N7RYZGUlOSxZs2aCEFtf0Si5nZ2dhqRtS9hIkyl5LNDnwaQQT7uN0B3f7B7b0VFhW19ff3iR/U1rIQB8QDRs7ezv7V58+bT8+fNyyEzpXJra6tEZmbmejJW+MzNzJIdHR177e3to0pLS5dykoDAxFhTW+uelZlpOXfu3IKpPk9LS2tUU1NzGPURQcZGfJABIJCImKnmF+T7ZWVn+aFxypaXl6/R1NDMNTDQTzcxMck2MjIq1tPVq1NSUhp61n53meNS8sOFH1ZeunxpzeYXNgVhDT4DucfgIEERFW1UeOv14wrbXrmCiMejTu1kCuvqdEu6zStV3v3e9c5zP3i2HTn289jwsC5FFHQBjwx4OGh1aIhA5RiQ9Vv/ndLOt74Vd7CrfwQxGkJ16BOztalW2PFq4EBY5PHmXXt/Gq6qnk8FZ800JiGxcXH+nE6YAfOPlKRko4ODQwaFSh3kfNeORxsoxMTGrEIE5Ac8WjEwAXkM6Kl0a2SQuMEmT04CljmdnJzCwMBwnTs34aeff+pCg1+Bk4amEHpWcGiIvyATkMTEJC8yjW/YcP7poUPbra2tm8mui4qy8uh7O3fu3LN3Lx3ODrnf0w6rBRAGJi4u3rls6bJfVqxY8d0cZ+dKbmy8R5OBR3NLiymnEyzAnpX58+ePG8FOjo4RN2/dOk5wMOZ0IlZZNCgk2IcTBAQ9D6yVHvLtK8q4J3CC8FFRv+sXlxTrI1KyBuQAkZ9hWVnZOg0NjRIDff1sY2OTdGNj43z9WbOqFRUVWU9aoVFUUGDsfv+DGwTGzAKSHXZvL4EIxTW1UyfeE7e3ffoNvSIihOKutyNFzU09G198NXqMxdLmyUoIpLJFdRDR0kxS/fLoNkRAnilxg9QyzxLd8H+8ar3WBLKqqhdQxMWnZVcXFhaq5OblruC00wh0tqWlZZyKisqQg719gbKyclF/f785J+chCEelxcf7b9269QcZaRk8bnmsNXjnacAE5Mlehtg4X7Laxt7OLgR+6unpNWppaiVVVVet5KTnFZ5VUlKyory8XMXIyEjgssuAQV5aWuJB1gmvsLrlOtf125UrVtK4Vaf58+YXIGP5fHx8/B7whsNKGJRDQlKyfrnX8gubN236ydTUtIWb7UyjxZNyii565oCtrV00/G5tZZ2LCFhuX1+fLScnM5iAs7KyfDo6Oo4pKSmxpma/QVYQdgu35RzaA677jAlRJPuGaOwaFhQUrACvpLCw8DCqX5Wujk6WkZFhkp2dQ4qFuXmRmppavxAfhcw8DyCDT2hY2Jq8vDzN0dFRnuQTReNQHBG+1AP7D5wUyANcYa8HgzEmv+Wl3WrfnDxFfU6HmbTXkjLFd998r+2zo3eoctzPiMzu6SGkFi/8Wf38mbdEDfSfa2OKiLbWgNqXR1+v3/hiGhrQMgRl+p0tGUejLUc6Qp3j4VeIgMxzdQ2E3xH5YNnZ2UVGRUWZc9IBC3NNTU3NvLS0dOtFCxfmYSuTNwBHFuoLobNnzxyXkZHpQPMMTyYSSP+7Y/uOU5iAPICmpibRxKREX057GSDsR0lJsXi2w+zxk5xhGdXZ2SmopLSEowQEJlJk8KmHhIZ6vfP2278JWvtXVlbqNLe0mJNxLsOEp7ll22uvfc3tem1+YdOFxMTE13t6emTUVNWKXwgI+BaRj6v6+vq93C4LMnBVs3Oyl5PhSdPR0aFbWlhUwf+R8TyKCHdYRGSkLScnM5CN5uZmm+iY6Hl+vn6xUx0verp61aWlZQSvz0KBskAZ7iuHaG9vr2l2To5pekaG/81bt8fQpNGop6ubbmVpFenu4R5hZWVVIiEuIWjDfLwPGxsbrWtra615VQYIFzQ0MJRBeuGkwDUgEGdUfpVP97+mtG/3pak+Tn7blj+6f72WMtLS6kLh4qGk7EEGIbN65Rmt3y7tokhOTY6lVywrQUTman9oxBtUKUliOmFkdIRISk7yJ2FPKjgDuue6zI2b/Ju9rV1wRETEOyRUQyQ+nuaHCQjPSQilqLjYm9NJkJ4F4ID19fH9ExOQB0BPTXXv6uqy4PTGX5js5s6dG6mmpvYfD4+bm3vkrdu3mUgJiHNyEywoqRR6iv/rO3b8JsLnJ1w/iKrqanPm0JAMGSe8gtAvXbr0V2S0cX0jnL29feXixYvPqigr12zetPk3WO7mVRvTEuJXMplMFU570kDGnZ2dg+/PT+/qOi84PCJiL6frACsA8fEJ/lMlIABDQ6OcsPBwvhwPD6yUUBDJ00KTh1Zefv6aW3dusxDhS5vj7HzLc7HnbSRjArPBcyJZAUHWgZ1PS/jExEQFcsMAe2CAkHvxhS84QT7GCaG6OiG1ZHFg90+XuUZAgECJmRiFal66MGXyMQmZlV5/9QeFvDHd7JLU1DTT0tLSBeIcDi+D1Xhtbe0UfX39hsm/Oc9xTpaRkakbHR3V4eTKIJQ9OSVlfXNz8xF1dfVhAoNn4LWzDfQ/Fc1rOA3vA4iOjvanCnG+WWAFxGWOy39lp7G0sCjT0NDI4HTaOyAdVVVVC7Ozs00Frf2RkrUiaxMhInkjXsu8rvHI60B8ceToJ7ve2/UTL8kHhLhFREQEkJFhDE1W7LkuLv+198jKyjINTWaVnPa2QPnzC/K9KysrFadOQAyzoOyCMD7+NZrFxje2o58icPbPjZs3z7z59lvFb73z9uWg4GAHWInCmOYYZRPCKirlnHykpKtLFndZFJugyshUczLsS8LFqYgqJztAsNnTqrtjY2PWIRuC40udsC8V2SUh9xMb/Vn6Pebm5rHgUOK0M6W1rc0SkRB3PIAxxucz3AT3Gb9lpUpZ2VkcP/wOjC9paelmO1vblAc9AtZW1uGcHuhg7KJnSoSEhq4TtD6ob6g3JyO+HUielpZWGuqDnJks49k52eYNDQ3unF4ZA4KNiFWuhblF/v1/n6U3axD9LY7TMg6GeHd3t1ZEVOTSqT7L1tamUFVVNR/qIEiYiOcF3QI/ZdLS0rYcPHQwbcvWV/4MCQ2xxxp92oOjipIiLtYq6HUQUlDopYiKdU+nTFjt7e3UhIQEX06vfkwmv1jg4RH54GfOTs5BZDgyRISFibDwMH88dDEwAXkAcXG0FbDJi9NnAoynJjU3jzM0NOx68LOFCxaEkrEBEryk6Rnpfl1dXQK1WxUpW10yCAj0ga2NTQynsz4JGqJjYnyQoc3x5Q/wpDnY24crKir+j+vRw909cIQE4x5kPDEhMWCqE6WCvMKIra3tvYlUyAIJ0FkQ+obICLWiomLdJwcPpr6z893zJaWlygQGxtNhZBrUYXTimjag0+muLW2tszk9L4LDRVlZOdPIyOh/so7NdnBIQISnZ4zDRG585To/f0VJaQnWSxiYgNxvQEVERgSQERsH3ndrK6vAh31mZmaWJS8nV8Bp7yvEVjc0NDjE0WgugtIHTNQHiCiok3EoHHuMTSAjM3Umy3hbW5tQfHy8nzhJaSrnz5//0APwrK2tEyTExds4PZnBWC0uLV6cnpFhMNVneS1bdg1N8IPToZ8nQrSEU1JS3ti+Y3vGr7/+umxsBp0WjTGjMe3SX8XR4jZQKZw31cApZ29nFwqH5D4IS0vLBgMDgyROr4LA3M5gMDQSExOXY1HFwARkAnn5+Sa1dXUcT/8KEz8yCHrmuc6LfdjnampqLEsrK46HYQHGN+omxG8UlD6Aw/FaWlpkyFgBEREWYaO2Lp/JMk6n0+d3dHTYcLp9IcRQRkam3MLcIu1hn5uYmLQa6BvEk7Gkzx5lS8XH06Ycauju5l6CJuNfIVHBdAFkHhsdHdU9883ZkMOfH97b29tLYGBgCA6qqqrkUtPS1pDhNAIy4OHhEfoo28FljksQGXYJOI4iIiP9wemLgQkIBkJkZOS6ERZLktPedzC69PX1ky0tLesfY/wEk5ESDTyhOTk5a2pqa2QFQhgpFAnU/hzPnzh+0quUVI/+LP32mSzjQcFB/mSQO5hILC0sonV0dAYfNZm5urqSElMMMp6ckrKhp2fqZwlu377jKJocG9nTaAMrtD0ih5S7f/11YvfePacxCcHAEBwkJCZ69vX16XI6TBsiLhQUFIptbW0fmXgAfRaJ9AfHWQIQkMrKyoW5ebkmuIcxAZnx6O7upsQnxPuRkRno32VO+9DHraw4zp6dCmnvOG34gNLq7OzUjY6JWSIgXSEycZGBPnQNzlQZr6quUigqKfEmI8QQ5NbD3SPkcfe4zJkTi8bAIKdDgSDUsLa21jkpOWnOVJ/lYG9fH+Af8H5/f/+06385OTkiPSPjvb37PjxFhlcTAwODs4DQ7bDwMFLCwsf3pZqZRykrKT9SGdjZ2ZVoampyPEvnOAFisyWCQ0LW4V7GBGTGIzkl2bW1tXU2GTnphYSERpycnCIfd4+Ojk6voYFhHBkeYlBeNBrtBQHJ8CNEcDgryn2Axh2ZqTIeF0db1tfXp81pT9rEQVZt9vb2iY+7z9jEpFJDQzOdjMkMvPyIZHMk1PCNN9646enp+WVvXy9BmWanKctISxOpaWm7zn7zzftY62Ng8Dfy8/P1Kiorl5Bxltcoe5Rwd3cPepK+cHZ2DiMjVEoM2SV0Ot2vq7sb26CYgMxshISEbiDD2ABjS1NTM3O2g0PBk+6dP39+EFkEpKioaEl2drauAHQFe+Iii9zMSHkHOQyPCPcXJWEiA0+akaFRvIGBQdvj7pOSlCTmODsHk+F9h5XLtLS0tdU1NVM+vZKK9MCe3Xv2mZuZ/w4rIdONhEhLSxHXrl87cf36dU+s+TEw+Be0+PjVw0NDspzWQbBiLS8nX+/s5JT8pHvRPWFk1A2cvW1tbbPT09JccE9jAjJj0dDQIFdQWLCGjPCrf1OTOoQ+zYnTrnPnxklJSXVyOkQFlBciNjLxCQlrBMFWJv5dqSADYJxKzEQZz83NNaiurl5MhicNSLOLi0vg00yS8+fPCxMSEuI4wYRVnb6+Pv2U5GSOGNWqKipjZ06d3mJqYnJ7uu2ZoKB/SB8J/3Tp53Nl5eXyeArEwOA/IH1GREVHbSRj8znobD1dvTgtLa3uJ91ra2ObpaysXERGBAXMGUHBwRtxb2MCMmMRExOzuKenR4+MszjGB7CtbcjT3Kenp9ekoaGRREaICpCrhIT4jf39fXzdF2w2mwkXpz0+8DxEBuVaW1vlZqKMIyW/Znh4WJoMb76wsHC/ra1NzNPca2pimqugoJhDxmQG5ApN2AGc2kelqqo6fOrrUwFz5sw5Bysh0ymNLYSs9fT2mP7008VdeArEwOA/ZGRmODQ1NbmSERYOBGTePNegp5kPVFRUhm1sbCLIWrnOzctdU19fL4t7HBOQGQcwKiKjIgPIGORgZCkqKpbMcXbOfNrB6DJnThAZ8ZZgnFXX1Mylp6bO5uf+kJOTG1SQV+jntIE6kXtctLGp0WCmyXgfIp1oMttAxgofTGQ6OjppNtY21U9zv7KyMtvOzjacDBmHUMOCwsKlBQUF2px6ppqa2ui3Z795Z4Pfhq1MJrNXkA8qfBBSklKQYWdHTm6OGp4GMTD4C4GBgRsIEs40AZtHSkqq122+W/zTfmeeq2sQGU4jcPr29PbohYWH43BQTEBmHnJyc3XLKyqWkJVlws7WNlpdXf2pXQce7h4xyFAcJsPbioxwalRUtB+fExC2nJxsGxlpUIGEFBUVOcw0Gaen0J0bGxtdyCDZIOOINIfCeRNPiwUeHqTEFEP/ovIoREVHr+Lkc6HdPty79/LZM2dnm5qa/g0hWdMhixS0FyJUauHh4evxNIiBwT9oamoSR7bJejLsEnAaaWlpJRsYGNQ/7XesraxTyMjSCRARFoEkOQH4oFRMQGYcwsLCVjMYDDmyNqA7OMwOepbvmJqZlqiqqmaQ4W2AWFI6nb6uoaGBr/dBiEtI1JGhjGAVKCs7ewEZIW78jJDQ0A2kKXcKhe042zH8Wb5iY2OTJisrW0XGZAYTdmxs7EYy0ujOdXEp/+H7C2sO7N/vpa2tnQwx2oJORMY376enr8UHgmFg8A9S6PRFXV1dxmSc2QQ6y8nRMehZHFKIrPSamZrFk3UoYUVlxdLCokId3POYgMwYgAFBT6VvJCM0BYwrZGQ1Ojs7JT3L9yAswt7ePpgMgwCWO7t7uk3oqakL+blfDA0My8jIBgYEpKKiYm5BQcGMUXT19fXSuXm5a8mQcSDJaqqqOba2trnP8j1NDc1+czOzaDImM+jjxubGeTm5ObZktKeEhAThs94n7Lcrv87f/9HHy3W0dUIHBwdZ6CIEJM31fwGMkKamJsfqmmochoWBwScICgokJSwcHFFIRw7Nnzc/4lm/6+HuHkSG8248PJrJlA0OCVmDex4TkBmDxKREh9ra2nkiJKUmNTc3DzfQN+h69oHu8beQkBAp1gwotfCI8AB+7hddXZ18Mp47uRE9JjaWZ4cfXb12dU1sXKwVt5abI6OjFnZ0dBiSdfr5bAeHewoKCs+8lOHm5v4HWQb7GHtMODQ0zJfMdhUXF2f7+PiE/nL58vKzZ87arVix4igiJ0UDAwNj6Bof/4JwmvpEGJZiTU2NGZ4KMTB4j9LSUvXSsjIvMsKvQOeqqqrSTUxMip/1u3AquqSkZBsZcxecCZKcnOIPjhyMmQXhmVrx+Ph4PwpJSf7HPbGNjXrv7tx5DA36p3Y/U6lUNoPBEENgoP9Kc3ygi4nB4UZexSXFGmamZk382C8GBgaFqP1gCYTjzBA82CGhIds3bthwUUNDg8HNeiEjT+b7Cxe+QYa7lsucOVf9fP3OOjk5ZT3L/olnRVJiUgAZBHtSlgqLiuyRjB9HMi76DDI+2tvbK4/6AhiIEBnloqfS17e2th5Bky2psUXQd65z5xai60BbR9tnGWkZdtk52UsKCgsX1tXX2/b39alMeB3HyT+sQvLbuSJAlCorK03Rr3HcfjeSG+bIyAhYHTxpFEQUpdA1/Y69xxBYBAUHew8MDCg/Ter+ZwXoHzT/yB745JNjSC89tV0COguN1VERUZHRERbnV0FAP9bV185NSEhwWLp0aSaWAvLBYrF6ke7n2bI9kkMp9PrhGUlAEDmQSM/IWE9GaAoAPM6dnZ0Lm5ubFz6PkiDD+zGpSJhMpnJUVNQKREB+5se+MTY2rlRSUqro6ekx47TnHp7X3tFhefXa1Vf27N5znpv1unHzpi9qe12YWNLS019OpqdsNjQwDA3w9z/ttcwrBhnkHHWZFxQUaBYVF3mRJeNgUCP5XlNXV7fmefqBLGI0MfYsaDSau6+vbwQnntnf3y8SR4uzWeK5JAuNzYf2k4qSCsvLyysNLqTcv2hqblYoKMi3KC8vn4P6wrm2rs62u7tbHxm8YpPtB2WFi5ekBPRNW1u7Hrffy2AwiNWrVp9fv379PtiHx4u6IyOMIi4uPkRWCnYMjGc0yogUeoo/WTob5ByNNbu09DS757EdoFyk6aoxghodG+OHCQj5GBkZGd313i5vMzOzLDQfifOiDIj8UAwNDXtnJAGJo9EWtLW1mcjIyJA6sZNxiNBUAeQmOibWf+vWV3+W4MPyKcgrDBsYGCTT6XQzWLHgNOBE7rv37h1ctmxZkI21TQ036lRZVSUbFh62d3K1Y0IuhJDxvvLI0aMrr/9+I2XxwoWn1/usv6eqwhmvfXhkxKqBwQEFGWlyZBw8+5MGNL8ByhQWEeHPKQJy+84d7xNfnvhzy5Yt+9/bufMLcbHHjxsgV7o6Ol3oSkT/TYRVBkSoRVB/a5dXlJuXlpbaVVVXWyMdZNbe3q43MDCgAO0JOgOIyeRqCbcISH1DvSK3+wjCQTQ01ActzM1htbMdmwUYMx05ubmWNbW1bqIkOWcmiQQ/2iVAbnJycta3tbd9pqKswsTSQJrTBYz/MRMTky5rKytY/eXpCvCMJCCxcbGkhabwO6DeDQ317unpaZZu890K+LGMrnNdQ5OSkl4hSwGzR0fVjh0/fu7HCz+sQSSUTfaAP/vN2U/6+vrMHgy3AjIIF+oPlx9/unjz7r2/ilevWn1u9erVV3W0tXue952wDyE5Kdn/SYbydAW0aVlZ6cqqqioVfX39tqk8q6CwUOOXK1dOKysrE7du3TpaUVFh/Pnhz99WV1MbeBYjX0FBgYWuKhsbmyr0p2D4e39/P7WxsVGpobFBHz3Xoqys3KGmpsa+qbnJAvWh4uTETMaG1AcImxSemjEweIt/Av/xGWGxRMVIioDgZ4DTqLW11SQqKnqh/8aNIVgaSAXfxAHPuLXnvPw8tby8vOVkLXMKAkZGRkRDQkL5Nv8/MtJiJSQkWsnarA19X15e7v3Z4c9OkZ2C9MeLF/3j4+N3P26vB5BCWI1DRqfZpcuXzm3avKlw/4EDnxaXFGs+zzvpdLp1ZVXl/JlKssHgR8a9Wlh4+PKpPAfS+X5+5PMzTCZDDyZI6KOcnJwtL295OTEkNGTKh3pKS0uzTUxM2hYuWJj62quv/XLi+PF3r1696nb50mWTQwcPLVq7Zu2nSkpKGRCuRHLiAgqBgYHBM3R1dQlnZWX5zGS7BBwtcXFx/lgaZtBcPdMqnJiYuBIZncr8thmUm4Al2JzcHF+k9PjSQrW0sGhFJCSMTHIAhCA6Jmbnx/v3f0XWe27eurX08i+Xf37aDYVg5E7cqxkWHnZo2/bthW+9/fZ3sXFx5s+SVSk+IR4OnJyxCSYmSV0cLc6fNYXUkT9c/HF7aWnphvtDFiAssK+vz/azw4cT9n9y4CDsJ+PoJIxkwEBfv2OVt3fMgf37P7t+7brjq1tf9UUy2k1WWyFywyIwMDB4hqjoaLempiYbslc7+RlAvvLy85bnF+TjtOCYgEw/gCcRGXMBojNwifNBQ7e1tdUmjkabx69ldHdz/5WM80DuB3i0afG0D7bt2H6roqJCgVPPhfj2K1euBJw6feoumlAkn5Xswv1SUlLwUy4tPe3NPXv3ZO144/Wb4RERc+H8msehpbVFhJ6a6sOPcb7cJiDV1dUL09JSTZ7n+zExMeZ37tw5Dv3wsGcjHSIeGhr62UtbXk779bffVjGZ5IQtS6P379i+/Y8Af//DZKWpRPXpITAwMHgGNA9t5Mf9dNzE+JkgDIZKXBxtJZYITECmijF+q2xmZqYFMjTdZjoBmRzsERERfLvc6bVsWZSOjk4K2SQEVkKKi4v9tr++I/3q1aurp3qKNpIvmbffeefsN+e+vS4mJiY5lUkF+gg87qiMYnl5eRs++vijxJe3bIm6cePGSlTOh7rKEhMSPZpbWizwZEaBVIPiSMafOdSwrb1d+NTp09+hXxUetRkcng+rVYh4WH7z7Td/b37pxag7d/5YQBZJ0NOb1UDG2SJwuJi5mRneBI6BwSPU1NYoFhQUeM/k8KtJgG2WlJzkT8ahhxj8B9LW+8bYbAoIEZo0qZDukBuVERERGX1c9piIyEgf9AOPcuLf5c6CwoJVZWVlHxsbG3fyW/nk5eXH1q1dd/6bc9+4kL2XAYz8oaEhg9Nnz9z7488/I319fb+EEBhZWdmn1oLt7e0Sd/780//WrZsH+vr6DDidxx36C12U5pbmRV+cOL4oKib69x8vXHiBQvlveUd/9xcRFsYCPtFmmVlZG1B/nJSRkXnqnOffnvv2o8amxoVP04dA9GCVpKGhYdGxE8cW3bpzK3blipXfLFmyJFSTg2fNxMRELyUrPAONrype9M/IyOi48KKxx1O2DOcvoTYYwyMGgxcICwtf2tXdpUVWxkJBIyDl5eXudDrdYt68eYVYOsgBa3iYL3SvMFlCVFlV5er/QkAuwZ0NjsLDw8Ndx744ttrSwuKh3rzW1lZhxKx9sJfhP5Mu0dvbqxkZFbUUEZAb/FjGdWvX3rr7191dbW1t9mSTkMn9Fy2tLZ6nzpz2/P3G7wWOsx3vOTs7RRsZGhUrKyu3QiYj8EJPeNeJpqYm+aLiIovY2LiV2TnZAYiE6EtIjq9YkEmyx/cJODk6xT9IPopLSpRzcnJWYhmfUArIYG9sbLSPo8XN9V7pnfA037l9545bcHDwgYeFXj1J58FVV1+/4Ow3Zxf8dvW3Slsb27seHh7/2NvZZWhqavY/z6pUZ2en0Lnvvns/LT39VTLC6qBMZqZm5dzuG2jfv+79tS0yKnLl2NgYzyZBBoMhs3Dhwq92v//BOTxiMLgNmE+QXRIgKoKjMiYBhzfHxMauxwSE8wDbBdkQQp8fPfIHmq8Y3Foc4CoBmTDQpNHkb82NSkCGGPS+7uGhoUfWJz0jYz6azG2f1bCY7t6GFHrKC6/v2HGDHzfly8nJDa1ft/7YmbNnbnEroxO8B66uri7LoOAgy8CgwI+R4dcnLy/fgsrTjiaMftRWsLqn0NLSoj04OKgK3wOjn4zTax8ErCpqaWnl+vn6Xn7ws+TkpOXIoFLnRjkECdHRMRufhoDAeS0//PjDd6gvRZ93PEAOf7iYTKZBfEL8B4j8fCAjI9Ogra2daWxklGFubp6PZKnK0MCwFY2/fiRPg4iwshDBHUNEmwonxHZ3dytVVFaYpKWleSC9ta6jo8OcjDNxQG+iuraoqKhwnYBA+/b396v09PSo8FI2IGV1V2cX3vSKwROkpqUaFhUVLZ7pe/buB7RFQmKCL9KHx5FuwrFYJOje9vZ2I5IzK/KOgNzHtLhSicmGpFAfbTSEhoVupArhE28fJCBlZWWL09LTDZydnCr5sYy+Pj63Ud+FVFVVcTV18uSBcBPyJYMIiQwyBI3ul2/4nMzVjocB9hi8unXrFwoKCv+163loeJiIjIoKwPub/ncyy87JXlNZWbnfwMCg91H3wYrWqdOnjiGD2JoTfQorC5OkAZFGrfLyci1kaKz6+59/xv+GSOIAkqFeJFsDQEDU1dXZzc3NQqh/pdH9yohIisMqJcg8WTIGZFZbSyt71qxZPAnBhPrx+hRyGC9CwkI4/AqDJ6DRaGtHR0exV/QB3dnW3mabkpIyf9WqVbG4Rcixb/gBM8IiR8arYk5OjreYKA5NeZAkDg0NSUZFRa3j1zLCitVrW1/9CCnpAV4x9kmyMRlmAxeQa26vGkG6YGNj41BfX7+bD36Wm5NjgozcBZiA/K+R293drRNHi1v6uPt+vnRpfWJi4ptkGPtQBugXkOXJC4wORAA00E+j3t5e88KiIkv00wz9XxvdLw6rWFAWMpMJAGl1cnIOwyF7GBjcR19fHyWFTt+AdfbDdKYQEUejbcAtMc37eSZUEvY5DAwMaPPa28aPAA9xckryhq6uLr4t4+LFi3NWrFhxGDJUzdTzW4B8IeOU8erWrR/LyvzvZsWwiPB16HMJLNH/C5jgE5OSAh71eV5enta169fOcDN0bdL7DxeQDDj9GH7C/7kl48JCQkx3N7dALCEYGNxHQmKic21trfNMPTD2sXaJmBiRlp62uqKyQhG3BiYgAgsIrYiGzEB4kD/cCBEWhgw+zknJyXP4uZzvvv3OSUNDw2A4y2WmAQxSiFVfunTp8WVLl2U9+HlnVyc1KSnJD3uyH01AioqKPLOysvQe/Ky3t5c4dvz4WaQndGaSgwJW00xNTUMdHR3LsIRgYHAfcbS4jTP5QOTHGqZIF/f392slJCQuwa2BCYjAorCoyLCmpmYxJiCPH+zxCfEb+bmMSkpKYx/t27dDUkqqcqblCAdjUU1dPQmRsBMP+zwzI3NuW1vbbGGcfveRBI7JZMrGxsWuefCz7y9ceKOouGjGZccDmfJc7Hlupp8Xg4HBCyCbRJpOp6/Fm88fDXAchYWHBZB9FhgGJiCkISQkZM3w8LA09jQ8GqAE09PT19bW1vJ1+iQHe4f6Xe/u3MxgMPvIOJSNHwGhV+jq2bt795tqampDD7snODQEe9KeQsZpNNrGnp7/P/SbFh9vdfevu8dkZGZW/n04td3CwiLQ18cnCksGBgb3kZSctLi3t1cfh4U/GuA0rqqq8szLz9PHrYEJiMChr78fBvoGHJryBCFASrCzs1M/PiFhMb+XdfXq1cm73nsPkRAGayaQEAgReunFl95Z4LEg52Gf19fXy2ZlZa3GMv54wOpQXX29S3pGuiP8v6amRvLoF0cvItmXm0nkbYLQMl979bVD3M7ghoGBMX7OBREcEhIgIoqjMh4H0MvDw8NSNFr8WtwamIAIHBLi452bm5vn4NCUJwOWO6OiogJAOfI7Xty8+e+d7+58CZGQkelMQvr6+mAD/mevvfrqb4+6JzIqyhPdp4c9aU9FtKmhYWG+8HtrW5smIneGYJDPJAICe4lWeXsfW7hgQSaWCAwM7qOwsFCrsrJyGT588MmAleuo6Kj/WrnGmD6Y1pZ5RGTEBrJTtyKGPoLewRWrXVhEWFSIKkSKtTS+Ube4aGl+Qb62rY1tvQCQkBuQRfj02TNXxcXEJacbyQTysWjhwm+PHjn66aPSNAL5io6JDiC77kPDQyxijOAG06OIiIiIkkWmYJUoIyNjXX1Dw2EnR8fyr09+Ne+L48duNLc0O0hJTu9U/BT0j8FkENra2mFvvvHmUTz1YWDwBrFxcauZTKY8mVn3kF0yiuwSrmyWFBISEhERFqGOEZy3tWBua2lpmZORmeG8aOGiVCw9mIAIBJBRIZ1fULCOzNAUBpNJvPrKKxvd3d3TkEIhbTcZMsjGWCMjQ8ePHbvU2NzsKUKCwTmx3KmQkJCwChGQ7wWhjzdv2nwXGefLz50/f2NoaEgDvCX8cLonR8jHokXfHP38yM7HyW9WdpZuRUXFUjLzyLNYrP5d7+1aaW1lVYPamLQXoUmM3dPTQz36xRd/9vf3W5GxORqIDXqHSUpKykJfH58gV1fXsgvnv3c/9Nmn32RnZ2+F8zmm62oIIpGEjIxM4aeHDm1RUlIaJTAwMLgOSCUfFR3lT6pdwmAQvr6+769eteoO+p1Uzwqae/rPf//9kfT09K1kbqgPDAzciAkIJiACg8jIqEWdnZ0GYFSQAQhVkpOVLVmzek2Qurr6EDfqhAymu9euX/cUIclzAkoxOiZm48svvfw9N89EmAo2+G2gGRoazjt8+PDV+oYGV0Ep98MA5An2fCzx9Dx05PMjh580SYWHR4AnTZasOkP2EQ0NjbRVK71p3NovYGtrGxIdHW1F1vtgY2NYWJi/z/r1QUA2tLW1By58//2rl3/5JfrSpUtn2Gy28uQJ5tMBExnA4OT1ypNfnlxrb2fXjKc9DAzeIDMry7apqcmVLGMd5hCk47pXLl/xh5mpWSM36uS1bNltOp2+laznwzyYm5e3trGx8aCmpuYAlqLpg2kbOB4bFxtAZorJ4eFhwsbGJpJb5APg5uYeKSoqyiTLyw/GWW1t7bys7CxbQerr2Q6zq366+NOihQsXnuwfGGALYppeMPaHhob6t2/b9uLRI0efSD7Ay5WekU6qJw1k3NnJOZibm5U93NyDyHz+RKihV0lJicZ/5F5YhNj+2rZr354962BhYXEbVqBGRgU/1TOQj8HBQUJaSir3qy9PLkXkA5/5gYHBQwQG/uPLZrNJc/zC3KepoUk3MDBo4FadLC0sk6WkpOrI2o8JK9ddXV0G4RHhi7EEYQLC98jJydEsLi72ItM4gxUQlzkuwdysl5WlZamGhkYmyQa2cEhIiK+g9bmKisoQMrL2Hvrk4EJpaek8WOoWhHAsKCOUVU5OLhOVf96bb7x59WlCqhISEx3q6upcyTzfBhmw7LlzXSK42R4ODg5pqC2qyJrMJlYElEPDQlc++JmTk3PdxR9+3LBn956V0lLSeb19vYQgJGV4lFz19PYQ+vr6f505fWaBnZ1dBZ7uMDB4h9bWVrGc3FxSzxyCUEvnOc4h3FzFRWSnx9TUNA4cVmQB5jlafHwAliJMQPge0THRqwcZg/JkxXOzx9gEYvxNdra2ydysFygVK0ursGEWeQMdlGNaevr6ltYWgczrunrVKtqvv1xxXr9u3e7hYVYbeID5lYjAYXBM5hDDa5nXYVTmeW5ubrlP+92oqCg/VC/SNiyA4a2srJxnYW6Rx802UVdXHzQ2Mo4lczIDghefkLAR9nA9bKIL8PcPvvzzJcfNL2zejsZDBRBEQVpVg5Ar1H7969es2/nD9xfWW1lZdeGpDgODt0hMSvLo6OgwJysyYzz8SliEtcBjQQS36+Y+3y2ITGcN6OyysrKlxSXFWliSMAHhSwhRhcYtTTqd7i8mSmJoytAwgRg/zdjYmOsT+4IFHqGQ0Ya0NkTKsaury4JOT3UXVDlQU1Nj7v94/9c/XbxotWjRoqPIeGwHI5JfvNlAPFB5xgwNDP48e/r07KNHjhxSUVFhPu336+rrxTMyM9aT6klDZbS3tw9FJITreY7d3d2CyDT4gWTU19d75OTkWD7qHk1NzeEP3n//4m9XfrV5ISBgm5ysbD6ksIV24VdA2VAZx8zNzW+fP/ed/SeffPKNvLy84GdlwMCYBggJCfEnMyx8wmmUYWxsVMjtujk6Osaj+aiHLGffRDipYlBQ8CosSZiA8CXQAGAi8mFWVV09j8zMQGAczXN1DeRFHZFRmIUM7HwyDTRQkqAsBV0erCwtW08cO37gxws/WGzcsGG3nJxcIRiRsH+C2+eHwPtgNQa9n2VkZPTX54cPz7t86bLP3Llzi571WTQabWFHR4cJmZMZTCNu892CedFvLnNc4mVkZNrI7CP0bJHg4CCfJ92HiMjgB+9/8NON3284oJ8rTE1N/2IymQwgtLBvh9cAowPkCl3DiHjcPX7s2Lyffry4wcHBoRxPbxgY/IHSsjLVktKSFWTaJbBqbGdrGyovJ8/1+qE5rWGWnl4SmToRHG70VPpGJpOJBWqaQJifPXpPbSwh1g2CjyZjVmh42AtoMhYmK/xq4uCyHhsb21he1FVBXoGlr68fUVdXZ0VWnCfk887MzFxTUlp6wNTEpEngiYiVVRu6vt6+fcc3MTHR7jExsZsKCguWdXd3a8IGN/CIQ75xTssMGIcgl3ApKCjUz3Odd3vVKu+fZ8+eXSAu9vxZUKKjo18C45yssQvPlhAXL7e0sEjjRX/p6uq2amhoxBeXFK8ncyUzITHRv62t7QTsH3rSvbKysqwAf/8QX1+fkJycHP24uLi1KXT6WjQOHVH/SgIZBDmCn2Sm8gX9A86HyRA1VPaSBR4L7qxateqqvZ1dMacNnDE2m4rkjAJ1mo4pisGYGWGxpl6xkVFibIRBjDG4c7r12Ch6F6eNvdFRyhiLyb06MNC7kGxxdnygi8mkwLMJEh00/3kfc7wOT3Tk/v3332vaO9rVZKRlSCsLzDPu7h4hPDEk0fw5Z45LUE5u7nIyM1EWFRe7x8bGOnh5eWU+Qj9SkG4EnUVw0kEHz2OxRrjqsGeNjCemIYS4IMc8IyDW1tZJ06EeyNjrZI2MSAwPDWk5OjpmoAFBinWGJn8JNTW1JGSc8eywvlXe3ne6urrcEQEZJgiClDVPROIk62przacDAZmEvJwca93adVFwNTY1yaSkpLhkZ2d7lpSWzGtqarJEdR53HYGhNUlInvaQPyAbYLiDcQg/kTE6oqioWInIYrzLHJd7Hh4esTra2n1TrQMyeGWoQlQZJONpqHykuJuQApcyNTX9AxEBBi/6CRTu6lWrr6GfhkjGyUq7SEHGp1B9fb0RMuILnvZLkDHLcbZjFbpOMxiM0yUlJTq5eXmuubm57mXlZY5oXBpBqMD9dQGSC9ezTCSTRGNC50w6PghJSck2bW3tPHt7+zgHe4dwZyenTERuSdswg9p/EM0RyejdEuiadueHIBmQ1tXVq52yzKoqt0o4u+RSpaT6uVFudv+ApMgs3RaOjjtlpX5UhySqlCQYWqQvEY8NDUuLmplwdKWOIiY6KuHsmI6IQTMadKQvUY4ND4uLGhnmPMmh09vXa+Tk6JSD5gVS9Bl6h6i4uHi14+zZubwaS56enqFZ2VkJSM+BA5gU+UE6V6ahsdEK/Zr5CCI0bGFhkYLuk0U6d5SD75XS0dHh6qryLL1Z9ba2tnmoX/uIaQrKdDi47f76TFxsAoMToM6EtgQvQ1VVlVpFZYU5Miitenp6zCurqgxYLJYGIiZK6BY4TAaWm8A1OGlFQruA4cdAY6hfVVW1Q0pKqhYRjlINdfVcOzu7LBNjkzJkHHKUCKOJZtIbjWP7+Uxf9PX1URoaGlTqG+oNy8rKjNH/TWrr6vRgpQ1NYKqtra0wKUJOY1j+Ep2Qp0kPMPQnMI4hJE8MNJEOaGpqtqP/Q2hDpYaGRhEihQUGBgYl6mrqHdxMjYyBgTEFkoJsLHShoU/Fdgm2SzDuw/8JMADl5cyT9j6pfQAAAABJRU5ErkJggg== + created_at: 2016-04-04 14:11:34.596760000 Z + updated_at: 2016-04-04 14:11:34.596760000 Z + +setting_10: + id: 10 + name: invoice_reference + value: YYMMmmmX[/VL]R[/A] + created_at: 2016-04-04 14:11:34.603733000 Z + updated_at: 2016-04-04 14:11:34.603733000 Z + +setting_11: + id: 11 + name: invoice_code-active + value: 'true' + created_at: 2016-04-04 14:11:34.607174000 Z + updated_at: 2016-04-04 14:11:34.607174000 Z + +setting_12: + id: 12 + name: invoice_code-value + value: INMEDFABLAB + created_at: 2016-04-04 14:11:34.610103000 Z + updated_at: 2016-04-04 14:11:34.610103000 Z + +setting_13: + id: 13 + name: invoice_order-nb + value: nnnnnn-MM-YY + created_at: 2016-04-04 14:11:34.615671000 Z + updated_at: 2016-04-04 14:11:34.615671000 Z + +setting_14: + id: 14 + name: invoice_VAT-active + value: 'false' + created_at: 2016-04-04 14:11:34.618886000 Z + updated_at: 2016-04-04 14:11:34.618886000 Z + +setting_15: + id: 15 + name: invoice_VAT-rate + value: '20.0' + created_at: 2016-04-04 14:11:34.625154000 Z + updated_at: 2016-04-04 14:11:34.625154000 Z + +setting_16: + id: 16 + name: invoice_text + value: Notre association n'est pas assujettie à la TVA + created_at: 2016-04-04 14:11:34.632653000 Z + updated_at: 2016-04-04 14:11:34.632653000 Z + +setting_17: + id: 17 + name: invoice_legals + value: 'La Casemate
2 Place St Laurent 38000 GRENOBLE France
Tél. Administration + : +33 4 76 44 88 80
Fax. : +33 4 76 42 76 66
SIRET : 317 270 593 00013 + - APE 913 E' + created_at: 2016-04-04 14:11:34.636940000 Z + updated_at: 2016-04-04 14:11:34.636940000 Z + +setting_18: + id: 18 + name: booking_window_start + value: '1970-01-01 08:00:00' + created_at: 2016-04-04 14:11:34.639995000 Z + updated_at: 2016-04-04 14:11:34.639995000 Z + +setting_19: + id: 19 + name: booking_window_end + value: '1970-01-01 23:59:59' + created_at: 2016-04-04 14:11:34.643667000 Z + updated_at: 2016-04-04 14:11:34.643667000 Z + +setting_20: + id: 20 + name: booking_move_enable + value: 'true' + created_at: 2016-04-04 14:11:34.647950000 Z + updated_at: 2016-04-04 14:11:34.647950000 Z + +setting_21: + id: 21 + name: booking_move_delay + value: '24' + created_at: 2016-04-04 14:11:34.650611000 Z + updated_at: 2016-04-04 14:11:34.650611000 Z + +setting_22: + id: 22 + name: booking_cancel_enable + value: 'false' + created_at: 2016-04-04 14:11:34.653441000 Z + updated_at: 2016-04-04 14:11:34.653441000 Z + +setting_23: + id: 23 + name: booking_cancel_delay + value: '24' + created_at: 2016-04-04 14:11:34.655971000 Z + updated_at: 2016-04-04 14:11:34.655971000 Z + +setting_24: + id: 24 + name: main_color + value: "#cb1117" + created_at: 2016-04-04 14:11:34.658780000 Z + updated_at: 2016-04-04 14:11:34.658780000 Z + +setting_25: + id: 25 + name: secondary_color + value: "#ffdd00" + created_at: 2016-04-04 14:11:34.666698000 Z + updated_at: 2016-04-04 14:11:34.666698000 Z + +setting_26: + id: 26 + name: training_information_message + value: Avant de réserver une formation, nous vous conseillons de consulter nos offres + d'abonnement qui proposent des conditions avantageuses sur le prix des formations + et les heures machines. + created_at: 2016-04-04 14:11:34.717053000 Z + updated_at: 2016-04-04 14:11:34.717053000 Z + +setting_27: + id: 27 + name: fablab_name + value: Fab Lab de La Casemate + created_at: 2016-04-04 14:11:34.724770000 Z + updated_at: 2016-04-04 14:11:34.724770000 Z + +setting_28: + id: 28 + name: name_genre + value: male + created_at: 2016-04-04 14:11:34.728465000 Z + updated_at: 2016-04-04 14:11:34.728465000 Z + +setting_29: + id: 29 + name: home_blogpost + value: + created_at: 2016-04-04 14:12:01.271670000 Z + updated_at: 2016-04-04 14:12:01.271670000 Z diff --git a/test/fixtures/slots.yml b/test/fixtures/slots.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/statistic_fields.yml b/test/fixtures/statistic_fields.yml new file mode 100644 index 000000000..644d66006 --- /dev/null +++ b/test/fixtures/statistic_fields.yml @@ -0,0 +1,90 @@ + +statistic_field_1: + id: 1 + statistic_index_id: 3 + key: trainingId + label: ID Formation + created_at: 2016-04-04 14:11:33.394574000 Z + updated_at: 2016-04-04 14:11:33.394574000 Z + data_type: index + +statistic_field_2: + id: 2 + statistic_index_id: 3 + key: trainingDate + label: Date Formation + created_at: 2016-04-04 14:11:33.397731000 Z + updated_at: 2016-04-04 14:11:33.397731000 Z + data_type: date + +statistic_field_3: + id: 3 + statistic_index_id: 4 + key: eventId + label: ID Évènement + created_at: 2016-04-04 14:11:33.400109000 Z + updated_at: 2016-04-04 14:11:33.400109000 Z + data_type: index + +statistic_field_4: + id: 4 + statistic_index_id: 4 + key: eventDate + label: Date Évènement + created_at: 2016-04-04 14:11:33.402256000 Z + updated_at: 2016-04-04 14:11:33.402256000 Z + data_type: date + +statistic_field_5: + id: 5 + statistic_index_id: 6 + key: themes + label: Thèmes + created_at: 2016-04-04 14:11:33.404480000 Z + updated_at: 2016-04-04 14:11:33.404480000 Z + data_type: list + +statistic_field_6: + id: 6 + statistic_index_id: 6 + key: components + label: Composants + created_at: 2016-04-04 14:11:33.406774000 Z + updated_at: 2016-04-04 14:11:33.406774000 Z + data_type: list + +statistic_field_7: + id: 7 + statistic_index_id: 6 + key: machines + label: Machines + created_at: 2016-04-04 14:11:33.410472000 Z + updated_at: 2016-04-04 14:11:33.410472000 Z + data_type: list + +statistic_field_8: + id: 8 + statistic_index_id: 4 + key: name + label: Nom Évènement + created_at: 2016-04-04 14:11:33.413525000 Z + updated_at: 2016-04-04 14:11:33.413525000 Z + data_type: text + +statistic_field_9: + id: 9 + statistic_index_id: 7 + key: userId + label: ID Utilisateur + created_at: 2016-04-04 14:11:33.416626000 Z + updated_at: 2016-04-04 14:11:33.416626000 Z + data_type: index + +statistic_field_10: + id: 10 + statistic_index_id: 1 + key: groupName + label: Groupe + created_at: 2016-04-04 14:11:33.423307000 Z + updated_at: 2016-04-04 14:11:33.423307000 Z + data_type: text diff --git a/test/fixtures/statistic_graphs.yml b/test/fixtures/statistic_graphs.yml new file mode 100644 index 000000000..fe94a87b6 --- /dev/null +++ b/test/fixtures/statistic_graphs.yml @@ -0,0 +1,48 @@ + +statistic_graph_1: + id: 1 + statistic_index_id: 1 + chart_type: stackedAreaChart + limit: 0 + created_at: 2016-04-04 14:11:33.585281000 Z + updated_at: 2016-04-04 14:11:33.585281000 Z + +statistic_graph_2: + id: 2 + statistic_index_id: 2 + chart_type: stackedAreaChart + limit: 0 + created_at: 2016-04-04 14:11:33.588092000 Z + updated_at: 2016-04-04 14:11:33.588092000 Z + +statistic_graph_3: + id: 3 + statistic_index_id: 3 + chart_type: discreteBarChart + limit: 10 + created_at: 2016-04-04 14:11:33.590494000 Z + updated_at: 2016-04-04 14:11:33.590494000 Z + +statistic_graph_4: + id: 4 + statistic_index_id: 4 + chart_type: discreteBarChart + limit: 10 + created_at: 2016-04-04 14:11:33.592600000 Z + updated_at: 2016-04-04 14:11:33.592600000 Z + +statistic_graph_5: + id: 5 + statistic_index_id: 5 + chart_type: lineChart + limit: 0 + created_at: 2016-04-04 14:11:33.594459000 Z + updated_at: 2016-04-04 14:11:33.594459000 Z + +statistic_graph_6: + id: 6 + statistic_index_id: 7 + chart_type: discreteBarChart + limit: 10 + created_at: 2016-04-04 14:11:33.596654000 Z + updated_at: 2016-04-04 14:11:33.596654000 Z diff --git a/test/fixtures/statistic_indices.yml b/test/fixtures/statistic_indices.yml new file mode 100644 index 000000000..2de3f9b3d --- /dev/null +++ b/test/fixtures/statistic_indices.yml @@ -0,0 +1,63 @@ + +statistic_index_1: + id: 1 + es_type_key: subscription + label: Abonnements + created_at: 2016-04-04 14:11:33.355566000 Z + updated_at: 2016-04-04 14:11:33.355566000 Z + table: true + ca: true + +statistic_index_2: + id: 2 + es_type_key: machine + label: Heures machines + created_at: 2016-04-04 14:11:33.359367000 Z + updated_at: 2016-04-04 14:11:33.359367000 Z + table: true + ca: true + +statistic_index_3: + id: 3 + es_type_key: training + label: Formations + created_at: 2016-04-04 14:11:33.362171000 Z + updated_at: 2016-04-04 14:11:33.362171000 Z + table: true + ca: true + +statistic_index_4: + id: 4 + es_type_key: event + label: Ateliers/Stages + created_at: 2016-04-04 14:11:33.366381000 Z + updated_at: 2016-04-04 14:11:33.366381000 Z + table: true + ca: true + +statistic_index_5: + id: 5 + es_type_key: account + label: Inscriptions + created_at: 2016-04-04 14:11:33.369042000 Z + updated_at: 2016-04-04 14:11:33.369042000 Z + table: true + ca: false + +statistic_index_6: + id: 6 + es_type_key: project + label: Projets + created_at: 2016-04-04 14:11:33.373066000 Z + updated_at: 2016-04-04 14:11:33.373066000 Z + table: true + ca: false + +statistic_index_7: + id: 7 + es_type_key: user + label: Utilisateurs + created_at: 2016-04-04 14:11:33.376810000 Z + updated_at: 2016-04-04 14:11:33.376810000 Z + table: false + ca: false diff --git a/test/fixtures/statistic_sub_types.yml b/test/fixtures/statistic_sub_types.yml new file mode 100644 index 000000000..38f6dc2ab --- /dev/null +++ b/test/fixtures/statistic_sub_types.yml @@ -0,0 +1,155 @@ + +statistic_sub_type_1: + id: 1 + key: Stage + label: Stage + created_at: 2016-04-04 14:11:33.510241000 Z + updated_at: 2016-04-04 14:11:33.510241000 Z + +statistic_sub_type_2: + id: 2 + key: Atelier + label: Atelier + created_at: 2016-04-04 14:11:33.535339000 Z + updated_at: 2016-04-04 14:11:33.535339000 Z + +statistic_sub_type_3: + id: 3 + key: created + label: Création de compte + created_at: 2016-04-04 14:11:33.553667000 Z + updated_at: 2016-04-04 14:11:33.553667000 Z + +statistic_sub_type_4: + id: 4 + key: published + label: Publication de projet + created_at: 2016-04-04 14:11:33.564828000 Z + updated_at: 2016-04-04 14:11:33.564828000 Z + +statistic_sub_type_5: + id: 5 + key: standard + label: standard, association + created_at: 2016-04-04 14:11:33.652127000 Z + updated_at: 2016-04-04 14:11:33.652127000 Z + +statistic_sub_type_6: + id: 6 + key: student + label: étudiant, - de 25 ans, enseignant, demandeur d'emploi + created_at: 2016-04-04 14:11:33.662695000 Z + updated_at: 2016-04-04 14:11:33.662695000 Z + +statistic_sub_type_7: + id: 7 + key: merchant + label: artisan, commerçant, chercheur, auto-entrepreneur + created_at: 2016-04-04 14:11:33.674691000 Z + updated_at: 2016-04-04 14:11:33.674691000 Z + +statistic_sub_type_8: + id: 8 + key: business + label: PME, PMI, SARL, SA + created_at: 2016-04-04 14:11:33.688291000 Z + updated_at: 2016-04-04 14:11:33.688291000 Z + +statistic_sub_type_9: + id: 9 + key: formation-imprimante-3d + label: Formation Imprimante 3D + created_at: 2016-04-04 14:11:34.042407000 Z + updated_at: 2016-04-04 14:11:34.042407000 Z + +statistic_sub_type_10: + id: 10 + key: formation-laser-vinyle + label: Formation Laser / Vinyle + created_at: 2016-04-04 14:11:34.082412000 Z + updated_at: 2016-04-04 14:11:34.082412000 Z + +statistic_sub_type_11: + id: 11 + key: formation-petite-fraiseuse-numerique + label: Formation Petite fraiseuse numerique + created_at: 2016-04-04 14:11:34.109571000 Z + updated_at: 2016-04-04 14:11:34.109571000 Z + +statistic_sub_type_12: + id: 12 + key: formation-shopbot-grande-fraiseuse + label: Formation Shopbot Grande Fraiseuse + created_at: 2016-04-04 14:11:34.138418000 Z + updated_at: 2016-04-04 14:11:34.138418000 Z + +statistic_sub_type_13: + id: 13 + key: formation-logiciel-2d + label: Formation logiciel 2D + created_at: 2016-04-04 14:11:34.158874000 Z + updated_at: 2016-04-04 14:11:34.158874000 Z + +statistic_sub_type_14: + id: 14 + key: decoupeuse-laser + label: Découpeuse laser + created_at: 2016-04-04 14:11:34.216583000 Z + updated_at: 2016-04-04 14:11:34.216583000 Z + +statistic_sub_type_15: + id: 15 + key: decoupeuse-vinyle + label: Découpeuse vinyle + created_at: 2016-04-04 14:11:34.280012000 Z + updated_at: 2016-04-04 14:11:34.280012000 Z + +statistic_sub_type_16: + id: 16 + key: shopbot-grande-fraiseuse + label: Shopbot / Grande fraiseuse + created_at: 2016-04-04 14:11:34.311844000 Z + updated_at: 2016-04-04 14:11:34.311844000 Z + +statistic_sub_type_17: + id: 17 + key: imprimante-3d + label: Imprimante 3D + created_at: 2016-04-04 14:11:34.351362000 Z + updated_at: 2016-04-04 14:11:34.351362000 Z + +statistic_sub_type_18: + id: 18 + key: petite-fraiseuse + label: Petite Fraiseuse + created_at: 2016-04-04 14:11:34.387590000 Z + updated_at: 2016-04-04 14:11:34.387590000 Z + +statistic_sub_type_19: + id: 19 + key: form1-imprimante-3d + label: FORM1+ imprimante 3D + created_at: 2016-04-04 14:11:34.432323000 Z + updated_at: 2016-04-04 14:11:34.432323000 Z + +statistic_sub_type_20: + id: 20 + key: mensuel-standard-month-20160404171519 + label: Mensuel - standard, association - month + created_at: 2016-04-04 15:15:21.125089000 Z + updated_at: 2016-04-04 15:15:21.125089000 Z + +statistic_sub_type_21: + id: 21 + key: nicolas-standard-month-20160404171724 + label: Sleede - standard, association - month + created_at: 2016-04-04 15:17:24.952312000 Z + updated_at: 2016-04-04 15:17:24.952312000 Z + +statistic_sub_type_22: + id: 22 + key: mensuel-tarif-reduit-student-month-20160404171827 + label: Mensuel tarif réduit - étudiant, - de 25 ans, enseignant, demandeur d'emploi + - month + created_at: 2016-04-04 15:18:28.864495000 Z + updated_at: 2016-04-04 15:18:28.864495000 Z diff --git a/test/fixtures/statistic_type_sub_types.yml b/test/fixtures/statistic_type_sub_types.yml new file mode 100644 index 000000000..751a34706 --- /dev/null +++ b/test/fixtures/statistic_type_sub_types.yml @@ -0,0 +1,245 @@ + +statistic_type_sub_type_1: + id: 1 + statistic_type_id: 6 + statistic_sub_type_id: 1 + created_at: 2016-04-04 14:11:33.513238000 Z + updated_at: 2016-04-04 14:11:33.513238000 Z + +statistic_type_sub_type_2: + id: 2 + statistic_type_id: 5 + statistic_sub_type_id: 1 + created_at: 2016-04-04 14:11:33.516138000 Z + updated_at: 2016-04-04 14:11:33.516138000 Z + +statistic_type_sub_type_3: + id: 3 + statistic_type_id: 6 + statistic_sub_type_id: 2 + created_at: 2016-04-04 14:11:33.538652000 Z + updated_at: 2016-04-04 14:11:33.538652000 Z + +statistic_type_sub_type_4: + id: 4 + statistic_type_id: 5 + statistic_sub_type_id: 2 + created_at: 2016-04-04 14:11:33.542486000 Z + updated_at: 2016-04-04 14:11:33.542486000 Z + +statistic_type_sub_type_5: + id: 5 + statistic_type_id: 7 + statistic_sub_type_id: 3 + created_at: 2016-04-04 14:11:33.555871000 Z + updated_at: 2016-04-04 14:11:33.555871000 Z + +statistic_type_sub_type_6: + id: 6 + statistic_type_id: 8 + statistic_sub_type_id: 4 + created_at: 2016-04-04 14:11:33.567632000 Z + updated_at: 2016-04-04 14:11:33.567632000 Z + +statistic_type_sub_type_7: + id: 7 + statistic_type_id: 9 + statistic_sub_type_id: 5 + created_at: 2016-04-04 14:11:33.653644000 Z + updated_at: 2016-04-04 14:11:33.653644000 Z + +statistic_type_sub_type_8: + id: 8 + statistic_type_id: 9 + statistic_sub_type_id: 6 + created_at: 2016-04-04 14:11:33.664529000 Z + updated_at: 2016-04-04 14:11:33.664529000 Z + +statistic_type_sub_type_9: + id: 9 + statistic_type_id: 9 + statistic_sub_type_id: 7 + created_at: 2016-04-04 14:11:33.676852000 Z + updated_at: 2016-04-04 14:11:33.676852000 Z + +statistic_type_sub_type_10: + id: 10 + statistic_type_id: 9 + statistic_sub_type_id: 8 + created_at: 2016-04-04 14:11:33.690793000 Z + updated_at: 2016-04-04 14:11:33.690793000 Z + +statistic_type_sub_type_11: + id: 11 + statistic_type_id: 4 + statistic_sub_type_id: 9 + created_at: 2016-04-04 14:11:34.044221000 Z + updated_at: 2016-04-04 14:11:34.044221000 Z + +statistic_type_sub_type_12: + id: 12 + statistic_type_id: 3 + statistic_sub_type_id: 9 + created_at: 2016-04-04 14:11:34.045765000 Z + updated_at: 2016-04-04 14:11:34.045765000 Z + +statistic_type_sub_type_13: + id: 13 + statistic_type_id: 4 + statistic_sub_type_id: 10 + created_at: 2016-04-04 14:11:34.084202000 Z + updated_at: 2016-04-04 14:11:34.084202000 Z + +statistic_type_sub_type_14: + id: 14 + statistic_type_id: 3 + statistic_sub_type_id: 10 + created_at: 2016-04-04 14:11:34.085725000 Z + updated_at: 2016-04-04 14:11:34.085725000 Z + +statistic_type_sub_type_15: + id: 15 + statistic_type_id: 4 + statistic_sub_type_id: 11 + created_at: 2016-04-04 14:11:34.113011000 Z + updated_at: 2016-04-04 14:11:34.113011000 Z + +statistic_type_sub_type_16: + id: 16 + statistic_type_id: 3 + statistic_sub_type_id: 11 + created_at: 2016-04-04 14:11:34.115670000 Z + updated_at: 2016-04-04 14:11:34.115670000 Z + +statistic_type_sub_type_17: + id: 17 + statistic_type_id: 4 + statistic_sub_type_id: 12 + created_at: 2016-04-04 14:11:34.139750000 Z + updated_at: 2016-04-04 14:11:34.139750000 Z + +statistic_type_sub_type_18: + id: 18 + statistic_type_id: 3 + statistic_sub_type_id: 12 + created_at: 2016-04-04 14:11:34.141062000 Z + updated_at: 2016-04-04 14:11:34.141062000 Z + +statistic_type_sub_type_19: + id: 19 + statistic_type_id: 4 + statistic_sub_type_id: 13 + created_at: 2016-04-04 14:11:34.160439000 Z + updated_at: 2016-04-04 14:11:34.160439000 Z + +statistic_type_sub_type_20: + id: 20 + statistic_type_id: 3 + statistic_sub_type_id: 13 + created_at: 2016-04-04 14:11:34.161861000 Z + updated_at: 2016-04-04 14:11:34.161861000 Z + +statistic_type_sub_type_21: + id: 21 + statistic_type_id: 2 + statistic_sub_type_id: 14 + created_at: 2016-04-04 14:11:34.218360000 Z + updated_at: 2016-04-04 14:11:34.218360000 Z + +statistic_type_sub_type_22: + id: 22 + statistic_type_id: 1 + statistic_sub_type_id: 14 + created_at: 2016-04-04 14:11:34.220463000 Z + updated_at: 2016-04-04 14:11:34.220463000 Z + +statistic_type_sub_type_23: + id: 23 + statistic_type_id: 2 + statistic_sub_type_id: 15 + created_at: 2016-04-04 14:11:34.281962000 Z + updated_at: 2016-04-04 14:11:34.281962000 Z + +statistic_type_sub_type_24: + id: 24 + statistic_type_id: 1 + statistic_sub_type_id: 15 + created_at: 2016-04-04 14:11:34.284179000 Z + updated_at: 2016-04-04 14:11:34.284179000 Z + +statistic_type_sub_type_25: + id: 25 + statistic_type_id: 2 + statistic_sub_type_id: 16 + created_at: 2016-04-04 14:11:34.313711000 Z + updated_at: 2016-04-04 14:11:34.313711000 Z + +statistic_type_sub_type_26: + id: 26 + statistic_type_id: 1 + statistic_sub_type_id: 16 + created_at: 2016-04-04 14:11:34.315260000 Z + updated_at: 2016-04-04 14:11:34.315260000 Z + +statistic_type_sub_type_27: + id: 27 + statistic_type_id: 2 + statistic_sub_type_id: 17 + created_at: 2016-04-04 14:11:34.353541000 Z + updated_at: 2016-04-04 14:11:34.353541000 Z + +statistic_type_sub_type_28: + id: 28 + statistic_type_id: 1 + statistic_sub_type_id: 17 + created_at: 2016-04-04 14:11:34.357176000 Z + updated_at: 2016-04-04 14:11:34.357176000 Z + +statistic_type_sub_type_29: + id: 29 + statistic_type_id: 2 + statistic_sub_type_id: 18 + created_at: 2016-04-04 14:11:34.389833000 Z + updated_at: 2016-04-04 14:11:34.389833000 Z + +statistic_type_sub_type_30: + id: 30 + statistic_type_id: 1 + statistic_sub_type_id: 18 + created_at: 2016-04-04 14:11:34.392790000 Z + updated_at: 2016-04-04 14:11:34.392790000 Z + +statistic_type_sub_type_31: + id: 31 + statistic_type_id: 2 + statistic_sub_type_id: 19 + created_at: 2016-04-04 14:11:34.434454000 Z + updated_at: 2016-04-04 14:11:34.434454000 Z + +statistic_type_sub_type_32: + id: 32 + statistic_type_id: 1 + statistic_sub_type_id: 19 + created_at: 2016-04-04 14:11:34.436807000 Z + updated_at: 2016-04-04 14:11:34.436807000 Z + +statistic_type_sub_type_33: + id: 33 + statistic_type_id: 10 + statistic_sub_type_id: 20 + created_at: 2016-04-04 15:15:21.138545000 Z + updated_at: 2016-04-04 15:15:21.138545000 Z + +statistic_type_sub_type_34: + id: 34 + statistic_type_id: 11 + statistic_sub_type_id: 21 + created_at: 2016-04-04 15:17:24.955599000 Z + updated_at: 2016-04-04 15:17:24.955599000 Z + +statistic_type_sub_type_35: + id: 35 + statistic_type_id: 10 + statistic_sub_type_id: 22 + created_at: 2016-04-04 15:18:28.867317000 Z + updated_at: 2016-04-04 15:18:28.867317000 Z diff --git a/test/fixtures/statistic_types.yml b/test/fixtures/statistic_types.yml new file mode 100644 index 000000000..a309c1e7d --- /dev/null +++ b/test/fixtures/statistic_types.yml @@ -0,0 +1,110 @@ + +statistic_type_1: + id: 1 + statistic_index_id: 2 + key: booking + label: Réservations + graph: true + created_at: 2016-04-04 14:11:33.441638000 Z + updated_at: 2016-04-04 14:11:33.441638000 Z + simple: true + +statistic_type_2: + id: 2 + statistic_index_id: 2 + key: hour + label: Nombre d'heures + graph: true + created_at: 2016-04-04 14:11:33.445526000 Z + updated_at: 2016-04-04 14:11:33.445526000 Z + simple: false + +statistic_type_3: + id: 3 + statistic_index_id: 3 + key: booking + label: Réservations + graph: false + created_at: 2016-04-04 14:11:33.448982000 Z + updated_at: 2016-04-04 14:11:33.448982000 Z + simple: true + +statistic_type_4: + id: 4 + statistic_index_id: 3 + key: hour + label: Nombre d'heures + graph: false + created_at: 2016-04-04 14:11:33.452261000 Z + updated_at: 2016-04-04 14:11:33.452261000 Z + simple: false + +statistic_type_5: + id: 5 + statistic_index_id: 4 + key: booking + label: Nombre de places + graph: false + created_at: 2016-04-04 14:11:33.455220000 Z + updated_at: 2016-04-04 14:11:33.455220000 Z + simple: false + +statistic_type_6: + id: 6 + statistic_index_id: 4 + key: hour + label: Nombre d'heures + graph: false + created_at: 2016-04-04 14:11:33.457727000 Z + updated_at: 2016-04-04 14:11:33.457727000 Z + simple: false + +statistic_type_7: + id: 7 + statistic_index_id: 5 + key: member + label: Utilisateurs + graph: true + created_at: 2016-04-04 14:11:33.460565000 Z + updated_at: 2016-04-04 14:11:33.460565000 Z + simple: true + +statistic_type_8: + id: 8 + statistic_index_id: 6 + key: project + label: Projets + graph: false + created_at: 2016-04-04 14:11:33.463420000 Z + updated_at: 2016-04-04 14:11:33.463420000 Z + simple: true + +statistic_type_9: + id: 9 + statistic_index_id: 7 + key: revenue + label: Chiffre d'affaires + graph: false + created_at: 2016-04-04 14:11:33.466257000 Z + updated_at: 2016-04-04 14:11:33.466257000 Z + simple: false + +statistic_type_10: + id: 10 + statistic_index_id: 1 + key: '2592000' + label: 'Durée : one month' + graph: true + created_at: 2016-04-04 15:15:21.110438000 Z + updated_at: 2016-04-04 15:15:21.110438000 Z + simple: true + +statistic_type_11: + id: 11 + statistic_index_id: 1 + key: '5184000' + label: 'Durée : 2 months' + graph: true + created_at: 2016-04-04 15:17:24.950033000 Z + updated_at: 2016-04-04 15:17:24.950033000 Z + simple: true diff --git a/test/fixtures/stylesheets.yml b/test/fixtures/stylesheets.yml new file mode 100644 index 000000000..9dac239f7 --- /dev/null +++ b/test/fixtures/stylesheets.yml @@ -0,0 +1,39 @@ + +stylesheet_1: + id: 1 + contents: |- + .bg-red { background-color: #cb1117; } + .bg-red-dark { background-color: #cb1117; } + #nav .nav { background-color: #cb1117; } + #nav .nav > li > a { color: white; } + #nav .nav > li > a:hover, #nav .nav > li > a:focus { background-color: #ed2229; } + #nav .nav > li > a.active { border-left: 3px solid #6d090c; background-color: #ed2229; } + #nav .nav > li > a.active { border-left: 3px solid #6d090c; background-color: #ed2229; } + .btn-theme { background-color: #cb1117; color: white; } + .btn-theme:active, .btn-theme:hover { background-color: #6d090c; } + .label-theme { background-color: #cb1117 } + .btn-link { color: #cb1117 !important; } + .btn-link:hover { color: #6d090c !important; } + a { color: #cb1117; } + a:hover, a:focus { color: #6d090c; } + h2, h3, h5 { color: #cb1117; } + h5:after { background-color: #cb1117; } + .bg-yellow { background-color: #ffdd00 !important; } + .event:hover { background-color: #cb1117; } + .widget h3 { color: #cb1117; } + .modal-header h1, .custom-invoice .modal-header h1 { color: #cb1117; } + .block-link:hover, .fc-toolbar .fc-button:hover, .fc-toolbar .fc-button:active, .fc-toolbar .fc-button.fc-state-active { background-color: #ffdd00; } + .carousel-control:hover, .carousel-control:focus, .carousel-caption .title a:hover { color: #ffdd00; } + .well.well-warning { border-color: #ffdd00; background-color: #ffdd00; } + .text-yellow { color: #ffdd00 !important; } + .red { color: #cb1117 !important; } + .btn-warning, .editable-buttons button[type=submit].btn-primary { background-color: #ffdd00 !important; border-color: #ffdd00 !important; } + .btn-warning:hover, .editable-buttons button[type=submit].btn-primary:hover, .btn-warning:focus, .editable-buttons button[type=submit].btn-primary:focus, .btn-warning.focus, .editable-buttons button.focus[type=submit].btn-primary, .btn-warning:active, .editable-buttons button[type=submit].btn-primary:active, .btn-warning.active, .editable-buttons button.active[type=submit].btn-primary, .open > .btn-warning.dropdown-toggle, .editable-buttons .open > button.dropdown-toggle[type=submit].btn-primary { background-color: #998500 !important; border-color: #998500 !important; } + .btn-warning-full { border-color: #ffdd00; background-color: #ffdd00; } + .heading .heading-btn a:hover { background-color: #ffdd00; } + .pricing-panel .content .wrap { border-color: #ffdd00; } + .pricing-panel .cta-button .btn:hover, .pricing-panel .cta-button .custom-invoice .modal-body .elements li:hover, .custom-invoice .modal-body .elements .pricing-panel .cta-button li:hover { background-color: #ffdd00 !important; } + a.label:hover, .form-control.form-control-ui-select .select2-choices a.select2-search-choice:hover, a.label:focus, .form-control.form-control-ui-select .select2-choices a.select2-search-choice:focus { color: #cb1117; } + .about-picture { background: linear-gradient( rgba(255,255,255,0.12), rgba(255,255,255,0.13) ), linear-gradient( rgba(203, 17, 23, 0.78), rgba(203, 17, 23, 0.82) ), url('/about-fablab.jpg') no-repeat; } + created_at: 2016-04-04 14:11:34.712927000 Z + updated_at: 2016-04-04 14:11:34.712927000 Z diff --git a/test/fixtures/subscriptions.yml b/test/fixtures/subscriptions.yml new file mode 100644 index 000000000..ed5e346aa --- /dev/null +++ b/test/fixtures/subscriptions.yml @@ -0,0 +1,20 @@ + +subscription_1: + id: 1 + plan_id: 2 + user_id: 3 + stp_subscription_id: sub_8DGB4ErIc2asOv + created_at: 2016-04-05 08:35:51.784514000 Z + updated_at: 2016-04-05 08:35:51.784514000 Z + expired_at: 2016-06-05 08:35:51.000000000 Z + canceled_at: 2016-04-05 08:35:55.615387000 Z + +subscription_2: + id: 2 + plan_id: 3 + user_id: 4 + stp_subscription_id: + created_at: 2016-04-05 08:36:46.829879000 Z + updated_at: 2016-04-05 08:36:46.829879000 Z + expired_at: 2016-05-05 08:36:46.828332000 Z + canceled_at: diff --git a/test/fixtures/tags.yml b/test/fixtures/tags.yml new file mode 100644 index 000000000..2aa8cb7dd --- /dev/null +++ b/test/fixtures/tags.yml @@ -0,0 +1,12 @@ + +tag_1: + id: 1 + name: experts + created_at: 2016-04-04 15:25:13.744539000 Z + updated_at: 2016-04-04 15:25:13.744539000 Z + +tag_2: + id: 2 + name: débutants + created_at: 2016-04-04 15:25:30.321953000 Z + updated_at: 2016-04-04 15:25:30.321953000 Z diff --git a/test/fixtures/themes.yml b/test/fixtures/themes.yml new file mode 100644 index 000000000..95e0416ca --- /dev/null +++ b/test/fixtures/themes.yml @@ -0,0 +1,28 @@ + +theme_1: + id: 1 + name: Vie quotidienne + +theme_2: + id: 2 + name: Robotique + +theme_3: + id: 3 + name: Arduine + +theme_4: + id: 4 + name: Capteurs + +theme_5: + id: 5 + name: Musique + +theme_6: + id: 6 + name: Sport + +theme_7: + id: 7 + name: Autre diff --git a/test/fixtures/trainings.yml b/test/fixtures/trainings.yml new file mode 100644 index 000000000..150996ec7 --- /dev/null +++ b/test/fixtures/trainings.yml @@ -0,0 +1,45 @@ + +training_1: + id: 1 + name: Formation Imprimante 3D + created_at: 2016-04-04 14:11:34.033464000 Z + updated_at: 2016-04-04 14:11:34.033464000 Z + nb_total_places: + slug: formation-imprimante-3d + description: + +training_2: + id: 2 + name: Formation Laser / Vinyle + created_at: 2016-04-04 14:11:34.075249000 Z + updated_at: 2016-04-04 14:11:34.075249000 Z + nb_total_places: + slug: formation-laser-vinyle + description: + +training_3: + id: 3 + name: Formation Petite fraiseuse numerique + created_at: 2016-04-04 14:11:34.103077000 Z + updated_at: 2016-04-04 14:11:34.103077000 Z + nb_total_places: + slug: formation-petite-fraiseuse-numerique + description: + +training_4: + id: 4 + name: Formation Shopbot Grande Fraiseuse + created_at: 2016-04-04 14:11:34.132899000 Z + updated_at: 2016-04-04 14:11:34.132899000 Z + nb_total_places: + slug: formation-shopbot-grande-fraiseuse + description: + +training_5: + id: 5 + name: Formation logiciel 2D + created_at: 2016-04-04 14:11:34.152000000 Z + updated_at: 2016-04-04 14:11:34.152000000 Z + nb_total_places: + slug: formation-logiciel-2d + description: diff --git a/test/fixtures/trainings_availabilities.yml b/test/fixtures/trainings_availabilities.yml new file mode 100644 index 000000000..0f2b65ec7 --- /dev/null +++ b/test/fixtures/trainings_availabilities.yml @@ -0,0 +1,21 @@ + +trainings_availability_1: + id: 1 + training_id: 2 + availability_id: 1 + created_at: 2016-04-04 15:24:01.522700000 Z + updated_at: 2016-04-04 15:24:01.522700000 Z + +trainings_availability_2: + id: 2 + training_id: 1 + availability_id: 2 + created_at: 2016-04-04 15:24:09.172367000 Z + updated_at: 2016-04-04 15:24:09.172367000 Z + +trainings_availability_3: + id: 3 + training_id: 4 + availability_id: 8 + created_at: 2016-04-04 15:26:49.574308000 Z + updated_at: 2016-04-04 15:26:49.574308000 Z diff --git a/test/fixtures/trainings_machines.yml b/test/fixtures/trainings_machines.yml new file mode 100644 index 000000000..797e6cbcb --- /dev/null +++ b/test/fixtures/trainings_machines.yml @@ -0,0 +1,50 @@ + +trainings_machine_1: + id: 1 + training_id: 2 + machine_id: 1 + +trainings_machine_2: + id: 2 + training_id: 2 + machine_id: 2 + +trainings_machine_3: + id: 3 + training_id: 4 + machine_id: 3 + +trainings_machine_4: + id: 4 + training_id: 1 + machine_id: 4 + +trainings_machine_5: + id: 5 + training_id: 3 + machine_id: 5 + +trainings_machine_1: + id: 1 + training_id: 2 + machine_id: 1 + +trainings_machine_2: + id: 2 + training_id: 2 + machine_id: 2 + +trainings_machine_3: + id: 3 + training_id: 4 + machine_id: 3 + +trainings_machine_4: + id: 4 + training_id: 1 + machine_id: 4 + +trainings_machine_5: + id: 5 + training_id: 3 + machine_id: 5 diff --git a/test/fixtures/trainings_pricings.yml b/test/fixtures/trainings_pricings.yml new file mode 100644 index 000000000..54a494111 --- /dev/null +++ b/test/fixtures/trainings_pricings.yml @@ -0,0 +1,80 @@ + +trainings_pricing_1: + id: 1 + group_id: 1 + amount: 5100 + created_at: 2016-04-04 14:11:34.062630000 Z + updated_at: 2016-04-04 14:11:34.062630000 Z + training_id: 1 + +trainings_pricing_2: + id: 2 + group_id: 2 + amount: 4500 + created_at: 2016-04-04 14:11:34.065365000 Z + updated_at: 2016-04-04 14:11:34.065365000 Z + training_id: 1 + +trainings_pricing_5: + id: 5 + group_id: 1 + amount: 2900 + created_at: 2016-04-04 14:11:34.091905000 Z + updated_at: 2016-04-04 14:11:34.091905000 Z + training_id: 2 + +trainings_pricing_6: + id: 6 + group_id: 2 + amount: 1700 + created_at: 2016-04-04 14:11:34.093952000 Z + updated_at: 2016-04-04 14:11:34.093952000 Z + training_id: 2 + +trainings_pricing_9: + id: 9 + group_id: 1 + amount: 3000 + created_at: 2016-04-04 14:11:34.122221000 Z + updated_at: 2016-04-04 14:11:34.122221000 Z + training_id: 3 + +trainings_pricing_10: + id: 10 + group_id: 2 + amount: 2600 + created_at: 2016-04-04 14:11:34.124626000 Z + updated_at: 2016-04-04 14:11:34.124626000 Z + training_id: 3 + +trainings_pricing_13: + id: 13 + group_id: 1 + amount: 5200 + created_at: 2016-04-04 14:11:34.143982000 Z + updated_at: 2016-04-04 14:11:34.143982000 Z + training_id: 4 + +trainings_pricing_14: + id: 14 + group_id: 2 + amount: 4400 + created_at: 2016-04-04 14:11:34.145380000 Z + updated_at: 2016-04-04 14:11:34.145380000 Z + training_id: 4 + +trainings_pricing_17: + id: 17 + group_id: 1 + amount: 1800 + created_at: 2016-04-04 14:11:34.165146000 Z + updated_at: 2016-04-04 14:11:34.165146000 Z + training_id: 5 + +trainings_pricing_18: + id: 18 + group_id: 2 + amount: 1900 + created_at: 2016-04-04 14:11:34.166759000 Z + updated_at: 2016-04-04 14:11:34.166759000 Z + training_id: 5 diff --git a/test/fixtures/user_tags.yml b/test/fixtures/user_tags.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/user_trainings.yml b/test/fixtures/user_trainings.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 000000000..e84e28270 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,198 @@ + +user_2: + id: 2 + username: jdupont + email: jean.dupont@gmail.com + encrypted_password: "$2a$10$M41moTmI.I4xNVeOPzS1JeplUM0B5b0KfQqBZ./fgHZVn7BcIAY.m" + reset_password_token: + reset_password_sent_at: + remember_created_at: + sign_in_count: 1 + current_sign_in_at: 2016-04-04 15:00:29.439018000 Z + last_sign_in_at: 2016-04-04 15:00:29.439018000 Z + current_sign_in_ip: 127.0.0.1 + last_sign_in_ip: 127.0.0.1 + confirmation_token: + confirmed_at: 2016-04-04 15:00:43.555678000 Z + confirmation_sent_at: 2016-04-04 15:00:29.424011000 Z + unconfirmed_email: + failed_attempts: 0 + unlock_token: + locked_at: + created_at: 2016-04-04 15:00:29.107434000 Z + updated_at: 2016-04-04 15:00:43.556308000 Z + is_allow_contact: true + group_id: 1 + stp_customer_id: cus_8CzAgnSeFbDuG2 + slug: jdupont + is_active: true + invoicing_disabled: false + provider: + uid: + auth_token: + merged_at: + +user_4: + id: 4 + username: kdumas + email: kevin.dumas@orange.fr + encrypted_password: "$2a$10$N6Q4SHkkUtwlnMNFvN6nF.rkmLFTIPsARk7xEuR1Dws7Dy2sSrSOW" + reset_password_token: + reset_password_sent_at: + remember_created_at: + sign_in_count: 0 + current_sign_in_at: + last_sign_in_at: + current_sign_in_ip: + last_sign_in_ip: + confirmation_token: + confirmed_at: 2016-04-04 15:11:02.968494000 Z + confirmation_sent_at: 2016-04-04 15:10:42.376191000 Z + unconfirmed_email: + failed_attempts: 0 + unlock_token: + locked_at: + created_at: 2016-04-04 15:10:42.340868000 Z + updated_at: 2016-04-04 15:11:02.969182000 Z + is_allow_contact: true + group_id: 2 + stp_customer_id: cus_8CzKe50I0J1gaI + slug: kdumas + is_active: true + invoicing_disabled: + provider: + uid: + auth_token: + merged_at: + +user_6: + id: 6 + username: GilbertPartenaire + email: gilbert.partenaire@nicolas.com + encrypted_password: "$2a$10$UtWcIYMd2aOtQjw6OFL4cuMV1MB20Bfs/opzJDqWXqu8woUo.2cLu" + reset_password_token: + reset_password_sent_at: + remember_created_at: + sign_in_count: 0 + current_sign_in_at: + last_sign_in_at: + current_sign_in_ip: + last_sign_in_ip: + confirmation_token: + confirmed_at: + confirmation_sent_at: + unconfirmed_email: + failed_attempts: 0 + unlock_token: + locked_at: + created_at: 2016-04-04 15:17:12.522028000 Z + updated_at: 2016-04-04 15:17:12.522028000 Z + is_allow_contact: true + group_id: 1 + stp_customer_id: cus_8CzQK5uXPeyh4K + slug: gilbertpartenaire + is_active: true + invoicing_disabled: false + provider: + uid: + auth_token: + merged_at: + +user_5: + id: 5 + username: vlonchamp + email: vanessa.lonchamp@sfr.fr + encrypted_password: "$2a$10$HOEk.QyGwpd9nsk2gVXGSuAxig9jMrNFHVqYMW1.Sp41EtN7rdBbG" + reset_password_token: + reset_password_sent_at: + remember_created_at: + sign_in_count: 1 + current_sign_in_at: 2016-04-04 15:34:23.343596000 Z + last_sign_in_at: 2016-04-04 15:34:23.343596000 Z + current_sign_in_ip: 127.0.0.1 + last_sign_in_ip: 127.0.0.1 + confirmation_token: 59cfd407491c4e1d95a9f91f81e710a62a83a6fd7171ad22823b4c4395312c4d + confirmed_at: + confirmation_sent_at: 2016-04-04 15:14:08.599603000 Z + unconfirmed_email: + failed_attempts: 0 + unlock_token: + locked_at: + created_at: 2016-04-04 15:14:08.563152000 Z + updated_at: 2016-04-04 15:34:23.344613000 Z + is_allow_contact: true + group_id: 2 + stp_customer_id: cus_8CzNtM08NVlSGN + slug: vlonchamp + is_active: true + invoicing_disabled: + provider: + uid: + auth_token: + merged_at: + +user_3: + id: 3 + username: pdurand + email: paulette.durand@hotmail.fr + encrypted_password: "$2a$10$Ri5kcxmonFsZDDWLxjVUy.KoM2coBmB.W6ED11KDDaAuaBV8dVsim" + reset_password_token: + reset_password_sent_at: + remember_created_at: + sign_in_count: 2 + current_sign_in_at: 2016-04-05 08:35:05.676918000 Z + last_sign_in_at: 2016-04-04 15:07:46.733781000 Z + current_sign_in_ip: 127.0.0.1 + last_sign_in_ip: 127.0.0.1 + confirmation_token: + confirmed_at: 2016-04-04 15:08:00.893381000 Z + confirmation_sent_at: 2016-04-04 15:07:46.726886000 Z + unconfirmed_email: + failed_attempts: 0 + unlock_token: + locked_at: + created_at: 2016-04-04 15:07:46.675613000 Z + updated_at: 2016-04-05 08:35:05.678582000 Z + is_allow_contact: false + group_id: 1 + stp_customer_id: cus_8CzHcwBJtlA3IL + slug: pdurand + is_active: true + invoicing_disabled: false + provider: + uid: + auth_token: + merged_at: + +user_1: + id: 1 + username: admin + email: admin@fab-manager.com + encrypted_password: "$2a$10$LtQ2OggropcXpmcsPTEPruuGZrwuFYGOo8qjh.po91YDna/K4/Bbe" + reset_password_token: + reset_password_sent_at: + remember_created_at: + sign_in_count: 8 + current_sign_in_at: 2016-04-05 08:36:08.361260000 Z + last_sign_in_at: 2016-04-05 08:34:28.227054000 Z + current_sign_in_ip: 127.0.0.1 + last_sign_in_ip: 127.0.0.1 + confirmation_token: + confirmed_at: + confirmation_sent_at: + unconfirmed_email: + failed_attempts: 0 + unlock_token: + locked_at: + created_at: 2016-04-04 14:11:33.852719000 Z + updated_at: 2016-04-05 08:36:08.362215000 Z + is_allow_contact: true + group_id: 1 + stp_customer_id: cus_8CyNk3UTi8lvCc + slug: admin + is_active: true + invoicing_disabled: false + provider: + uid: + auth_token: + merged_at: diff --git a/test/fixtures/users_credits.yml b/test/fixtures/users_credits.yml new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/users_roles.yml b/test/fixtures/users_roles.yml new file mode 100644 index 000000000..bb571d62b --- /dev/null +++ b/test/fixtures/users_roles.yml @@ -0,0 +1,56 @@ + +users_role_: + user_id: 1 + role_id: 1 + +users_role_: + user_id: 2 + role_id: 2 + +users_role_: + user_id: 3 + role_id: 2 + +users_role_: + user_id: 4 + role_id: 2 + +users_role_: + user_id: 5 + role_id: 2 + +users_role_: + user_id: 6 + role_id: 3 + +users_role_: + user_id: 6 + role_id: 4 + +users_role_: + user_id: 1 + role_id: 1 + +users_role_: + user_id: 2 + role_id: 2 + +users_role_: + user_id: 3 + role_id: 2 + +users_role_: + user_id: 4 + role_id: 2 + +users_role_: + user_id: 5 + role_id: 2 + +users_role_: + user_id: 6 + role_id: 3 + +users_role_: + user_id: 6 + role_id: 4 From a5f6839e39f28f5bba9cd66ceaa20b05faad5136 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 12:27:48 +0200 Subject: [PATCH 11/64] fix users_roles.yml fixture file --- test/fixtures/users_roles.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/fixtures/users_roles.yml b/test/fixtures/users_roles.yml index bb571d62b..740006e62 100644 --- a/test/fixtures/users_roles.yml +++ b/test/fixtures/users_roles.yml @@ -1,56 +1,56 @@ -users_role_: +users_role_0: user_id: 1 role_id: 1 -users_role_: +users_role_1: user_id: 2 role_id: 2 -users_role_: +users_role_2: user_id: 3 role_id: 2 -users_role_: +users_role_3: user_id: 4 role_id: 2 -users_role_: +users_role_4: user_id: 5 role_id: 2 -users_role_: +users_role_5: user_id: 6 role_id: 3 -users_role_: +users_role_6: user_id: 6 role_id: 4 -users_role_: +users_role_0: user_id: 1 role_id: 1 -users_role_: +users_role_1: user_id: 2 role_id: 2 -users_role_: +users_role_2: user_id: 3 role_id: 2 -users_role_: +users_role_3: user_id: 4 role_id: 2 -users_role_: +users_role_4: user_id: 5 role_id: 2 -users_role_: +users_role_5: user_id: 6 role_id: 3 -users_role_: +users_role_6: user_id: 6 role_id: 4 From 2c2e4dfb51c62998621cc7be2ab33b58bdb52c65 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 12:28:22 +0200 Subject: [PATCH 12/64] active_record_base dump_fixtures method handle model without id column --- config/initializers/active_record_base.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/config/initializers/active_record_base.rb b/config/initializers/active_record_base.rb index 6c20d1d81..07b68d779 100644 --- a/config/initializers/active_record_base.rb +++ b/config/initializers/active_record_base.rb @@ -11,8 +11,15 @@ ActiveRecord::Base.class_eval do fixture_file = "#{Rails.root}/test/fixtures/#{self.table_name}.yml" mode = (File.exists?(fixture_file) ? 'a' : 'w') File.open(fixture_file, mode) do |f| - self.all.each do |instance| - f.puts({ "#{self.table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) + + if self.attribute_names.include?("id") + self.all.each do |instance| + f.puts({ "#{self.table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) + end + else + self.all.each_with_index do |instance, i| + f.puts({ "#{self.table_name.singularize}_#{i}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) + end end end end From b6dcacaa8a2ad28a0d8a416d864790e170613420 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Apr 2016 12:28:42 +0200 Subject: [PATCH 13/64] updates tests to use fixtures --- test/integration/availabilities_test.rb | 9 +++------ test/models/availability_test.rb | 6 ++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/test/integration/availabilities_test.rb b/test/integration/availabilities_test.rb index aa9213667..94db8f5da 100644 --- a/test/integration/availabilities_test.rb +++ b/test/integration/availabilities_test.rb @@ -1,14 +1,11 @@ class AvailabilitiesTest < ActionDispatch::IntegrationTest setup do - @profile = Profile.create!(gender: true, birthday: 20.years.ago, first_name: "Admin", last_name: "Sleede", phone: "06542868451") - @admin = User.create!(cgu: true, username: 'blabla', email: 'abc@sleede.com', password: 'kikoulol', password_confirmation: 'kikoulol', profile: @profile) - @admin.add_role(:admin) - login_as(@admin, scope: :user) + admin = User.with_role(:admin).first + login_as(admin, scope: :user) end test "return availability by id" do - a = Availability.create!(start_at: Time.now, end_at: 2.hours.from_now, available_type: 'trainings') - + a = Availability.take get "/api/availabilities/#{a.id}" assert_equal 200, response.status diff --git a/test/models/availability_test.rb b/test/models/availability_test.rb index e7b35b388..b14e1c70b 100644 --- a/test/models/availability_test.rb +++ b/test/models/availability_test.rb @@ -2,13 +2,15 @@ require 'test_helper' class AvailabilityTest < ActiveSupport::TestCase test "length must be at least 1h" do - a = Availability.new(start_at: Time.now, end_at: 15.minutes.from_now) + a = Availability.first + a.end_at = a.start_at + 15.minutes assert a.invalid? assert a.errors.key?(:end_at) end test "if type available_type is 'machines' check that there is minimum 1 association" do - a = Availability.new(start_at: Time.now, end_at: 2.hours.from_now, available_type: 'machines') + a = Availability.where(available_type: 'machines').first + a.machines_availabilities.destroy_all assert a.invalid? assert a.errors.key?(:machine_ids) end From 76c70b0ed4088f4c0830eff4d6b1b6785408a3e4 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 11:27:56 +0200 Subject: [PATCH 14/64] basic subscription test --- test/integration/subscriptions_test.rb | 33 ++++++++++++++++++++++++++ test/test_helper.rb | 13 ++++++++++ 2 files changed, 46 insertions(+) create mode 100644 test/integration/subscriptions_test.rb diff --git a/test/integration/subscriptions_test.rb b/test/integration/subscriptions_test.rb new file mode 100644 index 000000000..b58ab10eb --- /dev/null +++ b/test/integration/subscriptions_test.rb @@ -0,0 +1,33 @@ +class SubscriptionsTest < ActionDispatch::IntegrationTest + + + setup do + @user = User.find_by_username('jdupont') + login_as(@user, scope: :user) + end + + test "user take a subscription" do + plan = Plan.where(group_id: @user.group.id, type: 'Plan').first + + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: @user.id, + card_token: stripe_card_token + } + }.to_json, + { + 'Accept' => Mime::JSON, + 'Content-Type' => Mime::JSON.to_s + } + + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + subscription = json_response(response.body) + assert_equal plan.id, subscription[:plan_id] + + end + +end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 4e951ee6f..e13e11357 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -7,6 +7,8 @@ Sidekiq::Testing.fake! require 'minitest/reporters' Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new({ color: true })] +require "stripe" + class ActiveSupport::TestCase # Add more helper methods to be used by all tests here... @@ -16,6 +18,17 @@ class ActiveSupport::TestCase def json_response(body) JSON.parse(body, symbolize_names: true) end + + def stripe_card_token + Stripe::Token.create( + :card => { + :number => "4242424242424242", + :exp_month => 4, + :exp_year => DateTime.now.next_year.year, + :cvc => "314" + }, + ).id + end end class ActionDispatch::IntegrationTest From 773e87ecd45ae1e158dec0c0189d651eeec3d137 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 14:45:39 +0200 Subject: [PATCH 15/64] abuses test --- app/views/api/abuses/create.json.jbuilder | 2 +- test/integration/abuses_test.rb | 53 +++++++++++++++++++++++ test/integration/subscriptions_test.rb | 1 + 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 test/integration/abuses_test.rb diff --git a/app/views/api/abuses/create.json.jbuilder b/app/views/api/abuses/create.json.jbuilder index c45f25a2a..2caa02c0e 100644 --- a/app/views/api/abuses/create.json.jbuilder +++ b/app/views/api/abuses/create.json.jbuilder @@ -1,3 +1,3 @@ -json.admin do +json.reporting do json.extract! @abuse, :id, :signaled_id, :signaled_type end diff --git a/test/integration/abuses_test.rb b/test/integration/abuses_test.rb new file mode 100644 index 000000000..f8a5742ee --- /dev/null +++ b/test/integration/abuses_test.rb @@ -0,0 +1,53 @@ +class AbusesTest < ActionDispatch::IntegrationTest + + # Called before every test method runs. Can be used + # to set up fixture information. + def setup + # Do nothing + end + + # Called after every test method runs. Can be used to tear + # down fixture information. + + def teardown + # Do nothing + end + + # Abuse report + test 'visitor report an abuse' do + project = Project.first + + post '/api/abuses', + { + abuse: { + signaled_type: 'Project', + signaled_id: project.id, + first_name: 'William', + last_name: 'Prindle', + email: 'wprindle@iastate.edu', + message: 'This project is in infringement with the patent US5014921 A.' + } + }.to_json, + { + 'Accept' => Mime::JSON, + 'Content-Type' => Mime::JSON.to_s + } + + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the correct object was signaled + abuse = json_response(response.body) + assert_equal project.id, abuse[:reporting][:signaled_id], 'project ID mismatch' + assert_equal 'Project', abuse[:reporting][:signaled_type], 'signaled object type mismatch' + + # Check notifications were sent for every admins + notifications = Notification.where(notification_type_id: NotificationType.find_by_name('notify_admin_abuse_reported'), attached_object_type: 'Abuse', attached_object_id: abuse[:reporting][:id]) + assert_not_empty notifications, 'no notifications were created' + notified_users_ids = notifications.map {|n| n.receiver_id } + User.admins.each do |adm| + assert_includes notified_users_ids, adm.id, "Admin #{adm.id} was not notified" + end + end +end \ No newline at end of file diff --git a/test/integration/subscriptions_test.rb b/test/integration/subscriptions_test.rb index b58ab10eb..249b3c63b 100644 --- a/test/integration/subscriptions_test.rb +++ b/test/integration/subscriptions_test.rb @@ -7,6 +7,7 @@ class SubscriptionsTest < ActionDispatch::IntegrationTest end test "user take a subscription" do + skip plan = Plan.where(group_id: @user.group.id, type: 'Plan').first post '/api/subscriptions', From 150e58d47f2340bea6fbcb3ad1572f181bc47983 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 14:58:53 +0200 Subject: [PATCH 16/64] test invalid abuse --- app/models/abuse.rb | 2 ++ test/integration/abuses_test.rb | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/app/models/abuse.rb b/app/models/abuse.rb index b0752611f..56c80fe73 100644 --- a/app/models/abuse.rb +++ b/app/models/abuse.rb @@ -5,6 +5,8 @@ class Abuse < ActiveRecord::Base after_create :notify_admins_abuse_reported + validates :first_name, :last_name, :email, :message, :presence => true + private def notify_admins_abuse_reported diff --git a/test/integration/abuses_test.rb b/test/integration/abuses_test.rb index f8a5742ee..1d9820a22 100644 --- a/test/integration/abuses_test.rb +++ b/test/integration/abuses_test.rb @@ -50,4 +50,29 @@ class AbusesTest < ActionDispatch::IntegrationTest assert_includes notified_users_ids, adm.id, "Admin #{adm.id} was not notified" end end + + # Incomplete abuse report + test 'visitor send an invalid report' do + project = Project.first + + post '/api/abuses', + { + abuse: { + signaled_type: 'Project', + signaled_id: project.id, + first_name: 'John', + last_name: 'Wrong', + email: '', + message: '' + } + }.to_json, + { + 'Accept' => Mime::JSON, + 'Content-Type' => Mime::JSON.to_s + } + + assert_equal 422, response.status, response.body + assert_match /can't be blank/, response.body + end + end \ No newline at end of file From 83d8bdf9b0181925951030d68370b7005ff2ba8b Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Wed, 6 Apr 2016 15:15:09 +0200 Subject: [PATCH 17/64] installs vcr and adds an integration test for reservation --- Gemfile | 2 + Gemfile.lock | 11 + .../reservations/create_as_admin_test.rb | 11 + test/integration/reservations/create_test.rb | 60 ++ test/test_helper.rb | 11 +- ...servations_create_without_plan_success.yml | 642 ++++++++++++++++++ 6 files changed, 735 insertions(+), 2 deletions(-) create mode 100644 test/integration/reservations/create_as_admin_test.rb create mode 100644 test/integration/reservations/create_test.rb create mode 100644 test/vcr_cassettes/reservations_create_without_plan_success.yml diff --git a/Gemfile b/Gemfile index a007840fa..50b95f0e7 100644 --- a/Gemfile +++ b/Gemfile @@ -58,6 +58,8 @@ group :test do gem 'faker' gem 'test_after_commit' gem 'minitest-reporters' + gem 'webmock' + gem 'vcr' end group :production do diff --git a/Gemfile.lock b/Gemfile.lock index 4d973af84..7c1b4b090 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -107,6 +107,8 @@ GEM sass-rails (<= 5.0.1) sprockets (< 2.13) connection_pool (2.2.0) + crack (0.4.3) + safe_yaml (~> 1.0.0) database_cleaner (1.4.1) debug_inspector (0.0.2) descendants_tracker (0.0.4) @@ -161,6 +163,7 @@ GEM activerecord (>= 4.0.0) globalid (0.3.6) activesupport (>= 4.1.0) + hashdiff (0.3.0) hashie (3.4.2) highline (1.7.1) hike (1.2.3) @@ -313,6 +316,7 @@ GEM tzinfo rvm-capistrano (1.5.6) capistrano (~> 2.15.4) + safe_yaml (1.0.4) sass (3.4.13) sass-rails (5.0.1) railties (>= 4.0.0, < 5.0) @@ -395,6 +399,7 @@ GEM kgio (~> 2.6) rack raindrops (~> 0.7) + vcr (3.0.1) virtus (1.0.5) axiom-types (~> 0.1) coercible (~> 1.0) @@ -407,6 +412,10 @@ GEM binding_of_caller (>= 0.7.2) railties (>= 4.0) sprockets-rails (>= 2.0, < 4.0) + webmock (1.24.2) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff PLATFORMS ruby @@ -475,7 +484,9 @@ DEPENDENCIES twitter-text uglifier (>= 1.3.0) unicorn + vcr web-console (~> 2.0) + webmock BUNDLED WITH 1.11.2 diff --git a/test/integration/reservations/create_as_admin_test.rb b/test/integration/reservations/create_as_admin_test.rb new file mode 100644 index 000000000..5d40a3d6b --- /dev/null +++ b/test/integration/reservations/create_as_admin_test.rb @@ -0,0 +1,11 @@ +# class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest +# setup do +# admin = User.with_role(:admin).first +# login_as(admin, scope: :user) +# end +# +# test "admin reserves a machine for a user" do +# availability = Availability.find(5) +# +# end +# end diff --git a/test/integration/reservations/create_test.rb b/test/integration/reservations/create_test.rb new file mode 100644 index 000000000..b83ff9288 --- /dev/null +++ b/test/integration/reservations/create_test.rb @@ -0,0 +1,60 @@ +module Reservations + class CreateTest < ActionDispatch::IntegrationTest + setup do + @user = User.with_role(:member).first + login_as(@user, scope: :user) + end + + test "user without plan reserves a machine with success" do + machine = Machine.find(6) + availability = machine.availabilities.first + + reservations_count = Reservation.count + invoice_items_count = InvoiceItem.count + + VCR.use_cassette("reservations_create_without_plan_success") do + token = Stripe::Token.create( + :card => { + :number => "4242424242424242", + :exp_month => 4, + :exp_year => 1.year.from_now.year, + :cvc => "314" + }, + ) + + post reservations_path, { reservation: { + user_id: @user.id, + reservable_id: machine.id, + reservable_type: machine.class.name, + card_token: token.id, + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, { 'Accept' => Mime::JSON, 'Content-Type' => Mime::JSON.to_s } + end + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_items_count + 1, InvoiceItem.count + + # reservation assertions + reservation = Reservation.last + + assert reservation.invoice + assert_equal 1, reservation.invoice.invoice_items.count + + # invoice_items + invoice_item = InvoiceItem.last + + assert invoice_item.stp_invoice_item_id + assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user.group_id).amount + + + p json_response(response.body) + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 4e951ee6f..8d78ee38d 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,13 +1,20 @@ ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' +require 'vcr' require 'sidekiq/testing' -Sidekiq::Testing.fake! - require 'minitest/reporters' + +VCR.configure do |config| + config.cassette_library_dir = "test/vcr_cassettes" + config.hook_into :webmock +end + +Sidekiq::Testing.inline! Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new({ color: true })] + class ActiveSupport::TestCase # Add more helper methods to be used by all tests here... diff --git a/test/vcr_cassettes/reservations_create_without_plan_success.yml b/test/vcr_cassettes/reservations_create_without_plan_success.yml new file mode 100644 index 000000000..5aa39bb1d --- /dev/null +++ b/test/vcr_cassettes/reservations_create_without_plan_success.yml @@ -0,0 +1,642 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 09:46:39 GMT + Content-Type: + - application/json + Content-Length: + - '778' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DeYuCEulJlrPp + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xDFD2sOmf47Nz9JD1vbrAJ", + "object": "token", + "card": { + "id": "card_17xDFD2sOmf47Nz9LbJShTlw", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "86.76.5.109", + "created": 1459935999, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Wed, 06 Apr 2016 09:46:39 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoiceitems + body: + encoding: UTF-8 + string: customer=cus_8CzAgnSeFbDuG2&amount=3200¤cy=eur&description=FORM1%2B+imprimante+3D+lundi+11+avril+2016+14h00+-+15%3A00 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '123' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 09:46:41 GMT + Content-Type: + - application/json + Content-Length: + - '471' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DeYBFB42AoW5m + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "ii_17xDFF2sOmf47Nz90VoIJ17e", + "object": "invoiceitem", + "amount": 3200, + "currency": "eur", + "customer": "cus_8CzAgnSeFbDuG2", + "date": 1459936001, + "description": "FORM1+ imprimante 3D lundi 11 avril 2016 14h00 - 15:00", + "discountable": true, + "invoice": null, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459936001, + "end": 1459936001 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 09:46:41 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8CzAgnSeFbDuG2 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 09:46:42 GMT + Content-Type: + - application/json + Content-Length: + - '649' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DeYGJn0xDlBIk + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8CzAgnSeFbDuG2", + "object": "customer", + "account_balance": 0, + "created": 1459782030, + "currency": "eur", + "default_source": null, + "delinquent": false, + "description": "Jean Dupont", + "discount": null, + "email": "jean.dupont@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "/v1/customers/cus_8CzAgnSeFbDuG2/sources" + }, + "subscriptions": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "/v1/customers/cus_8CzAgnSeFbDuG2/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 09:46:42 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8CzAgnSeFbDuG2/sources + body: + encoding: UTF-8 + string: card=tok_17xDFD2sOmf47Nz9JD1vbrAJ + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '33' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 09:46:42 GMT + Content-Type: + - application/json + Content-Length: + - '577' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DeYMzh7lG57bt + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "card_17xDFD2sOmf47Nz9LbJShTlw", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8CzAgnSeFbDuG2", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 09:46:42 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices + body: + encoding: UTF-8 + string: customer=cus_8CzAgnSeFbDuG2 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '27' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 09:46:43 GMT + Content-Type: + - application/json + Content-Length: + - '1428' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DeYs6PUiVx1DN + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xDFH2sOmf47Nz9DpUY5b3U", + "object": "invoice", + "amount_due": 3200, + "application_fee": null, + "attempt_count": 0, + "attempted": false, + "charge": null, + "closed": false, + "currency": "eur", + "customer": "cus_8CzAgnSeFbDuG2", + "date": 1459936003, + "description": null, + "discount": null, + "ending_balance": null, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xDFF2sOmf47Nz90VoIJ17e", + "object": "line_item", + "amount": 3200, + "currency": "eur", + "description": "FORM1+ imprimante 3D lundi 11 avril 2016 14h00 - 15:00", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459936001, + "end": 1459936001 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xDFH2sOmf47Nz9DpUY5b3U/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1459939603, + "paid": false, + "period_end": 1459936003, + "period_start": 1459936003, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 3200, + "tax": null, + "tax_percent": null, + "total": 3200, + "webhooks_delivered_at": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 09:46:43 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices/in_17xDFH2sOmf47Nz9DpUY5b3U/pay + body: + encoding: ASCII-8BIT + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '0' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 09:46:44 GMT + Content-Type: + - application/json + Content-Length: + - '1447' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DeYRzymQv71IY + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xDFH2sOmf47Nz9DpUY5b3U", + "object": "invoice", + "amount_due": 3200, + "application_fee": null, + "attempt_count": 1, + "attempted": true, + "charge": "ch_17xDFI2sOmf47Nz9KHMAQUmF", + "closed": true, + "currency": "eur", + "customer": "cus_8CzAgnSeFbDuG2", + "date": 1459936003, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xDFF2sOmf47Nz90VoIJ17e", + "object": "line_item", + "amount": 3200, + "currency": "eur", + "description": "FORM1+ imprimante 3D lundi 11 avril 2016 14h00 - 15:00", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459936001, + "end": 1459936001 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xDFH2sOmf47Nz9DpUY5b3U/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1459936003, + "period_start": 1459936003, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 3200, + "tax": null, + "tax_percent": null, + "total": 3200, + "webhooks_delivered_at": 1459936003 + } + http_version: + recorded_at: Wed, 06 Apr 2016 09:46:44 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8CzAgnSeFbDuG2/sources/card_17xDFD2sOmf47Nz9LbJShTlw + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOy + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 09:46:45 GMT + Content-Type: + - application/json + Content-Length: + - '63' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DeYSokbVz2FOu + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "deleted": true, + "id": "card_17xDFD2sOmf47Nz9LbJShTlw" + } + http_version: + recorded_at: Wed, 06 Apr 2016 09:46:45 GMT +recorded_with: VCR 3.0.1 From 2cd1127a09db08b998ef9f016a971eb727daa434 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Wed, 6 Apr 2016 15:22:32 +0200 Subject: [PATCH 18/64] updates tests to use test helpers --- test/integration/abuses_test.rb | 14 ++++---------- test/integration/reservations/create_test.rb | 16 ++-------------- test/test_helper.rb | 5 ++++- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/test/integration/abuses_test.rb b/test/integration/abuses_test.rb index 1d9820a22..8ed669a22 100644 --- a/test/integration/abuses_test.rb +++ b/test/integration/abuses_test.rb @@ -28,10 +28,7 @@ class AbusesTest < ActionDispatch::IntegrationTest message: 'This project is in infringement with the patent US5014921 A.' } }.to_json, - { - 'Accept' => Mime::JSON, - 'Content-Type' => Mime::JSON.to_s - } + default_headers # Check response format & status assert_equal 201, response.status, response.body @@ -66,13 +63,10 @@ class AbusesTest < ActionDispatch::IntegrationTest message: '' } }.to_json, - { - 'Accept' => Mime::JSON, - 'Content-Type' => Mime::JSON.to_s - } + default_headers assert_equal 422, response.status, response.body - assert_match /can't be blank/, response.body + assert_match /can't be blank|doit être rempli/, response.body end -end \ No newline at end of file +end diff --git a/test/integration/reservations/create_test.rb b/test/integration/reservations/create_test.rb index b83ff9288..d724d2a51 100644 --- a/test/integration/reservations/create_test.rb +++ b/test/integration/reservations/create_test.rb @@ -13,27 +13,18 @@ module Reservations invoice_items_count = InvoiceItem.count VCR.use_cassette("reservations_create_without_plan_success") do - token = Stripe::Token.create( - :card => { - :number => "4242424242424242", - :exp_month => 4, - :exp_year => 1.year.from_now.year, - :cvc => "314" - }, - ) - post reservations_path, { reservation: { user_id: @user.id, reservable_id: machine.id, reservable_type: machine.class.name, - card_token: token.id, + card_token: stripe_card_token, slots_attributes: [ { start_at: availability.start_at.to_s(:iso8601), end_at: (availability.start_at + 1.hour).to_s(:iso8601), availability_id: availability.id } ] - }}.to_json, { 'Accept' => Mime::JSON, 'Content-Type' => Mime::JSON.to_s } + }}.to_json, default_headers end # general assertions @@ -52,9 +43,6 @@ module Reservations assert invoice_item.stp_invoice_item_id assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user.group_id).amount - - - p json_response(response.body) end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 752f882f0..138f8b50f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -13,7 +13,6 @@ end Sidekiq::Testing.inline! Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new({ color: true })] -require "stripe" @@ -26,6 +25,10 @@ class ActiveSupport::TestCase JSON.parse(body, symbolize_names: true) end + def default_headers + { 'Accept' => Mime::JSON, 'Content-Type' => Mime::JSON.to_s } + end + def stripe_card_token Stripe::Token.create( :card => { From baa692dfb9f6bbe7e19edac0ea8141dd23b2f956 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 15:23:13 +0200 Subject: [PATCH 19/64] fix subscription test --- test/fixtures/users.yml | 168 ++++++++++++------------- test/integration/subscriptions_test.rb | 3 +- 2 files changed, 85 insertions(+), 86 deletions(-) diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index e84e28270..02edd418c 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -1,57 +1,57 @@ user_2: id: 2 - username: jdupont - email: jean.dupont@gmail.com + username: jdupond + email: jean.dupond@gmail.com encrypted_password: "$2a$10$M41moTmI.I4xNVeOPzS1JeplUM0B5b0KfQqBZ./fgHZVn7BcIAY.m" - reset_password_token: - reset_password_sent_at: - remember_created_at: + reset_password_token: + reset_password_sent_at: + remember_created_at: sign_in_count: 1 current_sign_in_at: 2016-04-04 15:00:29.439018000 Z last_sign_in_at: 2016-04-04 15:00:29.439018000 Z current_sign_in_ip: 127.0.0.1 last_sign_in_ip: 127.0.0.1 - confirmation_token: + confirmation_token: confirmed_at: 2016-04-04 15:00:43.555678000 Z confirmation_sent_at: 2016-04-04 15:00:29.424011000 Z - unconfirmed_email: + unconfirmed_email: failed_attempts: 0 - unlock_token: - locked_at: + unlock_token: + locked_at: created_at: 2016-04-04 15:00:29.107434000 Z updated_at: 2016-04-04 15:00:43.556308000 Z is_allow_contact: true group_id: 1 - stp_customer_id: cus_8CzAgnSeFbDuG2 - slug: jdupont + stp_customer_id: cus_8Di1wjdVktv5kt + slug: jdupond is_active: true invoicing_disabled: false - provider: - uid: - auth_token: - merged_at: + provider: + uid: + auth_token: + merged_at: user_4: id: 4 username: kdumas email: kevin.dumas@orange.fr encrypted_password: "$2a$10$N6Q4SHkkUtwlnMNFvN6nF.rkmLFTIPsARk7xEuR1Dws7Dy2sSrSOW" - reset_password_token: - reset_password_sent_at: - remember_created_at: + reset_password_token: + reset_password_sent_at: + remember_created_at: sign_in_count: 0 - current_sign_in_at: - last_sign_in_at: - current_sign_in_ip: - last_sign_in_ip: - confirmation_token: + current_sign_in_at: + last_sign_in_at: + current_sign_in_ip: + last_sign_in_ip: + confirmation_token: confirmed_at: 2016-04-04 15:11:02.968494000 Z confirmation_sent_at: 2016-04-04 15:10:42.376191000 Z - unconfirmed_email: + unconfirmed_email: failed_attempts: 0 - unlock_token: - locked_at: + unlock_token: + locked_at: created_at: 2016-04-04 15:10:42.340868000 Z updated_at: 2016-04-04 15:11:02.969182000 Z is_allow_contact: true @@ -59,32 +59,32 @@ user_4: stp_customer_id: cus_8CzKe50I0J1gaI slug: kdumas is_active: true - invoicing_disabled: - provider: - uid: - auth_token: - merged_at: + invoicing_disabled: + provider: + uid: + auth_token: + merged_at: user_6: id: 6 username: GilbertPartenaire email: gilbert.partenaire@nicolas.com encrypted_password: "$2a$10$UtWcIYMd2aOtQjw6OFL4cuMV1MB20Bfs/opzJDqWXqu8woUo.2cLu" - reset_password_token: - reset_password_sent_at: - remember_created_at: + reset_password_token: + reset_password_sent_at: + remember_created_at: sign_in_count: 0 - current_sign_in_at: - last_sign_in_at: - current_sign_in_ip: - last_sign_in_ip: - confirmation_token: - confirmed_at: - confirmation_sent_at: - unconfirmed_email: + current_sign_in_at: + last_sign_in_at: + current_sign_in_ip: + last_sign_in_ip: + confirmation_token: + confirmed_at: + confirmation_sent_at: + unconfirmed_email: failed_attempts: 0 - unlock_token: - locked_at: + unlock_token: + locked_at: created_at: 2016-04-04 15:17:12.522028000 Z updated_at: 2016-04-04 15:17:12.522028000 Z is_allow_contact: true @@ -93,31 +93,31 @@ user_6: slug: gilbertpartenaire is_active: true invoicing_disabled: false - provider: - uid: - auth_token: - merged_at: + provider: + uid: + auth_token: + merged_at: user_5: id: 5 username: vlonchamp email: vanessa.lonchamp@sfr.fr encrypted_password: "$2a$10$HOEk.QyGwpd9nsk2gVXGSuAxig9jMrNFHVqYMW1.Sp41EtN7rdBbG" - reset_password_token: - reset_password_sent_at: - remember_created_at: + reset_password_token: + reset_password_sent_at: + remember_created_at: sign_in_count: 1 current_sign_in_at: 2016-04-04 15:34:23.343596000 Z last_sign_in_at: 2016-04-04 15:34:23.343596000 Z current_sign_in_ip: 127.0.0.1 last_sign_in_ip: 127.0.0.1 confirmation_token: 59cfd407491c4e1d95a9f91f81e710a62a83a6fd7171ad22823b4c4395312c4d - confirmed_at: + confirmed_at: confirmation_sent_at: 2016-04-04 15:14:08.599603000 Z - unconfirmed_email: + unconfirmed_email: failed_attempts: 0 - unlock_token: - locked_at: + unlock_token: + locked_at: created_at: 2016-04-04 15:14:08.563152000 Z updated_at: 2016-04-04 15:34:23.344613000 Z is_allow_contact: true @@ -125,32 +125,32 @@ user_5: stp_customer_id: cus_8CzNtM08NVlSGN slug: vlonchamp is_active: true - invoicing_disabled: - provider: - uid: - auth_token: - merged_at: + invoicing_disabled: + provider: + uid: + auth_token: + merged_at: user_3: id: 3 username: pdurand email: paulette.durand@hotmail.fr encrypted_password: "$2a$10$Ri5kcxmonFsZDDWLxjVUy.KoM2coBmB.W6ED11KDDaAuaBV8dVsim" - reset_password_token: - reset_password_sent_at: - remember_created_at: + reset_password_token: + reset_password_sent_at: + remember_created_at: sign_in_count: 2 current_sign_in_at: 2016-04-05 08:35:05.676918000 Z last_sign_in_at: 2016-04-04 15:07:46.733781000 Z current_sign_in_ip: 127.0.0.1 last_sign_in_ip: 127.0.0.1 - confirmation_token: + confirmation_token: confirmed_at: 2016-04-04 15:08:00.893381000 Z confirmation_sent_at: 2016-04-04 15:07:46.726886000 Z - unconfirmed_email: + unconfirmed_email: failed_attempts: 0 - unlock_token: - locked_at: + unlock_token: + locked_at: created_at: 2016-04-04 15:07:46.675613000 Z updated_at: 2016-04-05 08:35:05.678582000 Z is_allow_contact: false @@ -159,31 +159,31 @@ user_3: slug: pdurand is_active: true invoicing_disabled: false - provider: - uid: - auth_token: - merged_at: + provider: + uid: + auth_token: + merged_at: user_1: id: 1 username: admin email: admin@fab-manager.com encrypted_password: "$2a$10$LtQ2OggropcXpmcsPTEPruuGZrwuFYGOo8qjh.po91YDna/K4/Bbe" - reset_password_token: - reset_password_sent_at: - remember_created_at: + reset_password_token: + reset_password_sent_at: + remember_created_at: sign_in_count: 8 current_sign_in_at: 2016-04-05 08:36:08.361260000 Z last_sign_in_at: 2016-04-05 08:34:28.227054000 Z current_sign_in_ip: 127.0.0.1 last_sign_in_ip: 127.0.0.1 - confirmation_token: - confirmed_at: - confirmation_sent_at: - unconfirmed_email: + confirmation_token: + confirmed_at: + confirmation_sent_at: + unconfirmed_email: failed_attempts: 0 - unlock_token: - locked_at: + unlock_token: + locked_at: created_at: 2016-04-04 14:11:33.852719000 Z updated_at: 2016-04-05 08:36:08.362215000 Z is_allow_contact: true @@ -192,7 +192,7 @@ user_1: slug: admin is_active: true invoicing_disabled: false - provider: - uid: - auth_token: - merged_at: + provider: + uid: + auth_token: + merged_at: diff --git a/test/integration/subscriptions_test.rb b/test/integration/subscriptions_test.rb index 249b3c63b..bd4055bbd 100644 --- a/test/integration/subscriptions_test.rb +++ b/test/integration/subscriptions_test.rb @@ -2,12 +2,11 @@ class SubscriptionsTest < ActionDispatch::IntegrationTest setup do - @user = User.find_by_username('jdupont') + @user = User.find_by_username('jdupond') login_as(@user, scope: :user) end test "user take a subscription" do - skip plan = Plan.where(group_id: @user.group.id, type: 'Plan').first post '/api/subscriptions', From 1e39c53d0d4ee734f18655e8fc3e0d786ec7ff3d Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 15:55:56 +0200 Subject: [PATCH 20/64] configure secrets for tests --- config/secrets.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/config/secrets.yml b/config/secrets.yml index ce1b803dc..49512691b 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -30,23 +30,23 @@ development: elasticsearch_language_analyzer: <%= ENV["ELASTICSEARCH_LANGUAGE_ANALYZER"] %> test: - secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> + secret_key_base: 83daf5e7b80d990f037407bab78dff9904aaf3c195a50f84fa8695a22287e707dfbd9524b403b1dcf116ae1d8c06844c3d7ed942564e5b46be6ae3ead93a9d30 stripe_api_key: <%= ENV["STRIPE_API_KEY"] %> stripe_publishable_key: <%= ENV["STRIPE_PUBLISHABLE_KEY"] %> - stripe_currency: <%= ENV["STRIPE_CURRENCY"] %> - disqus_shortname: <%= ENV["DISQUS_SHORTNAME"] %> - fablab_without_plans: <%= ENV["FABLAB_WITHOUT_PLANS"] %> - time_zone: <%= ENV["TIME_ZONE"] %> - week_starting_day: <%= ENV["WEEK_STARTING_DAY"] %> - d3_date_format: <%= ENV["D3_DATE_FORMAT"].dump %> - uib_date_format: <%= ENV["UIB_DATE_FORMAT"] %> - rails_locale: <%= ENV["RAILS_LOCALE"] %> - moment_locale: <%= ENV["MOMENT_LOCALE"] %> - summernote_locale: <%= ENV["SUMMERNOTE_LOCALE"] %> - angular_locale: <%= ENV["ANGULAR_LOCALE"] %> - messageformat_locale: <%= ENV["MESSAGEFORMAT_LOCALE"] %> - fullcalendar_locale: <%= ENV["FULLCALENDAR_LOCALE"] %> - elasticsearch_language_analyzer: <%= ENV["ELASTICSEARCH_LANGUAGE_ANALYZER"] %> + stripe_currency: usd + disqus_shortname: fablab-sleede + fablab_without_plans: false + time_zone: Paris + week_starting_day: monday + d3_date_format: %d/%m/%y + uib_date_format: dd/MM/yyyy + rails_locale: en + moment_locale: en + summernote_locale: en-US + angular_locale: en-us + messageformat_locale: en + fullcalendar_locale: en + elasticsearch_language_analyzer: french staging: From 43f076191cc666b3ec7c50e4cb20d7eabe654902 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 15:57:27 +0200 Subject: [PATCH 21/64] using VCR in subscription test --- test/integration/subscriptions_test.rb | 22 +- .../subscriptions_user_create_success.yml | 828 ++++++++++++++++++ 2 files changed, 838 insertions(+), 12 deletions(-) create mode 100644 test/vcr_cassettes/subscriptions_user_create_success.yml diff --git a/test/integration/subscriptions_test.rb b/test/integration/subscriptions_test.rb index bd4055bbd..a52e06442 100644 --- a/test/integration/subscriptions_test.rb +++ b/test/integration/subscriptions_test.rb @@ -9,18 +9,16 @@ class SubscriptionsTest < ActionDispatch::IntegrationTest test "user take a subscription" do plan = Plan.where(group_id: @user.group.id, type: 'Plan').first - post '/api/subscriptions', - { - subscription: { - plan_id: plan.id, - user_id: @user.id, - card_token: stripe_card_token - } - }.to_json, - { - 'Accept' => Mime::JSON, - 'Content-Type' => Mime::JSON.to_s - } + VCR.use_cassette("subscriptions_user_create_success") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: @user.id, + card_token: stripe_card_token + } + }.to_json, default_headers + end assert_equal 201, response.status, response.body assert_equal Mime::JSON, response.content_type diff --git a/test/vcr_cassettes/subscriptions_user_create_success.yml b/test/vcr_cassettes/subscriptions_user_create_success.yml new file mode 100644 index 000000000..7f76d38ae --- /dev/null +++ b/test/vcr_cassettes/subscriptions_user_create_success.yml @@ -0,0 +1,828 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 13:29:57 GMT + Content-Type: + - application/json + Content-Length: + - '780' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Di9AmOR7uXw9z + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xGjJ2sOmf47Nz9PLqUZge2", + "object": "token", + "card": { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "90.52.157.226", + "created": 1459949397, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Wed, 06 Apr 2016 13:29:57 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 13:29:58 GMT + Content-Type: + - application/json + Content-Length: + - '2437' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Di9uNBvnRw9C0 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGcM2sOmf47Nz9CxYGRvdo", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGcM2sOmf47Nz9CxYGRvdo", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 13:29:58 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions + body: + encoding: UTF-8 + string: plan=mensuel-standard-month-20160404171519&card=tok_17xGjJ2sOmf47Nz9PLqUZge2 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '76' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 13:29:59 GMT + Content-Type: + - application/json + Content-Length: + - '821' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Di9LpzecLQFba + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 13:29:59 GMT +- request: + method: get + uri: https://api.stripe.com/v1/invoices?customer=cus_8Di1wjdVktv5kt&limit=1 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 13:30:00 GMT + Content-Type: + - application/json + Content-Length: + - '2207' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Di9FX8V833C25 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "object": "list", + "data": [ + { + "id": "in_17xGjL2sOmf47Nz976QQJRnZ", + "object": "invoice", + "amount_due": 3000, + "application_fee": null, + "attempt_count": 1, + "attempted": true, + "charge": "ch_17xGjL2sOmf47Nz9H8wfSmBa", + "closed": true, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459949399, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "line_item", + "amount": 3000, + "currency": "usd", + "description": null, + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459949399, + "end": 1462541399 + }, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "proration": false, + "quantity": 1, + "subscription": null, + "type": "subscription" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xGjL2sOmf47Nz976QQJRnZ/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1459949399, + "period_start": 1459948968, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": "sub_8Di9gqPLwt5IIC", + "subtotal": 3000, + "tax": null, + "tax_percent": null, + "total": 3000, + "webhooks_delivered_at": 1459949399 + } + ], + "has_more": true, + "url": "/v1/invoices" + } + http_version: + recorded_at: Wed, 06 Apr 2016 13:30:00 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 13:30:02 GMT + Content-Type: + - application/json + Content-Length: + - '3457' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Di9aIVqbT9ubZ + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 13:30:02 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8Di9gqPLwt5IIC + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 13:30:03 GMT + Content-Type: + - application/json + Content-Length: + - '821' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Di9AyPG0FJYAw + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 13:30:03 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8Di9gqPLwt5IIC?at_period_end=true + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 13:30:04 GMT + Content-Type: + - application/json + Content-Length: + - '826' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Di9ujL9MyuuZS + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 13:30:04 GMT +recorded_with: VCR 3.0.1 From 2e2f25ce4700b536ceaee3ec6ea53e4d8b484ae7 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 16:01:59 +0200 Subject: [PATCH 22/64] fix D3 date format for test --- config/secrets.yml | 2 +- test/integration/abuses_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/secrets.yml b/config/secrets.yml index 49512691b..946b82794 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -38,7 +38,7 @@ test: fablab_without_plans: false time_zone: Paris week_starting_day: monday - d3_date_format: %d/%m/%y + d3_date_format: '%d/%m/%y' uib_date_format: dd/MM/yyyy rails_locale: en moment_locale: en diff --git a/test/integration/abuses_test.rb b/test/integration/abuses_test.rb index 8ed669a22..fd3b4a27d 100644 --- a/test/integration/abuses_test.rb +++ b/test/integration/abuses_test.rb @@ -66,7 +66,7 @@ class AbusesTest < ActionDispatch::IntegrationTest default_headers assert_equal 422, response.status, response.body - assert_match /can't be blank|doit être rempli/, response.body + assert_match /can't be blank/, response.body end end From f334f76ef8d4417399a8ab144b2f488482dcd13c Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Wed, 6 Apr 2016 16:26:45 +0200 Subject: [PATCH 23/64] improves stripe_card_token test helper --- test/test_helper.rb | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index 138f8b50f..881b40e8e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -29,14 +29,31 @@ class ActiveSupport::TestCase { 'Accept' => Mime::JSON, 'Content-Type' => Mime::JSON.to_s } end - def stripe_card_token - Stripe::Token.create( - :card => { - :number => "4242424242424242", - :exp_month => 4, - :exp_year => DateTime.now.next_year.year, - :cvc => "314" - }, + def stripe_card_token(error: nil) + number = "4242424242424242" + exp_month = 4 + exp_year = DateTime.now.next_year.year + cvc = "314" + + case error + when /card_declined/ + number = "4000000000000002" + when /incorrect_number/ + number = "4242424242424241" + when /invalid_expiry_month/ + exp_month = 15 + when /invalid_expiry_year/ + exp_year = 1964 + when /invalid_cvc/ + cvc = "99" + end + + Stripe::Token.create(card: { + number: number, + exp_month: exp_month, + exp_year: exp_year, + cvc: cvc + }, ).id end end From 5ed9090df8f40c77730b5ed6de50dfa5e0ec79de Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 17:10:15 +0200 Subject: [PATCH 24/64] completed subscription test for user --- .../subscriptions/create_as_user_test.rb | 59 +++++++++++++++++++ test/integration/subscriptions_test.rb | 31 ---------- 2 files changed, 59 insertions(+), 31 deletions(-) create mode 100644 test/integration/subscriptions/create_as_user_test.rb delete mode 100644 test/integration/subscriptions_test.rb diff --git a/test/integration/subscriptions/create_as_user_test.rb b/test/integration/subscriptions/create_as_user_test.rb new file mode 100644 index 000000000..630973ee2 --- /dev/null +++ b/test/integration/subscriptions/create_as_user_test.rb @@ -0,0 +1,59 @@ +class CreateAsUserTest < ActionDispatch::IntegrationTest + + + setup do + @user = User.find_by_username('jdupond') + login_as(@user, scope: :user) + end + + test "user takes a subscription" do + plan = Plan.find_by(group_id: @user.group.id, type: 'Plan', base_name: 'Mensuel') + + VCR.use_cassette("subscriptions_user_create_success") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: @user.id, + card_token: stripe_card_token + } + }.to_json, default_headers + end + + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the correct plan was subscribed + subscription = json_response(response.body) + assert_equal plan.id, subscription[:plan_id], 'subscribed plan does not match' + + # Check that the user has the correct subscription + assert_not_nil @user.subscription, "user's subscription was not found" + assert_not_nil @user.subscription.plan, "user's subscribed plan was not found" + assert_equal plan.id, @user.subscription.plan_id, "user's plan does not match" + + # Check that the training credits were set correctly + assert_empty @user.training_credits, 'training credits were not reset' + assert_equal @user.subscription.plan.training_credit_nb, plan.training_credit_nb, 'trainings credits were not allocated' + + # Check that the user benefit from prices of his plan + printer = Machine.find_by_slug('imprimante-3d') + assert_equal 15, (printer.prices.find_by(group_id: @user.group_id, plan_id: @user.subscription.plan_id).amount / 100), 'machine hourly price does not match' + + # Check notifications were sent for every admins + notifications = Notification.where(notification_type_id: NotificationType.find_by_name('notify_admin_subscribed_plan'), attached_object_type: 'Subscription', attached_object_id: subscription[:id]) + assert_not_empty notifications, 'no notifications were created' + notified_users_ids = notifications.map {|n| n.receiver_id } + User.admins.each do |adm| + assert_includes notified_users_ids, adm.id, "Admin #{adm.id} was not notified" + end + + # Check generated invoice + invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) + assert_not_nil invoice, 'Invoice was not created' + assert File.exist?(invoice.file), 'Invoice PDF was not generated' + assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' + end + +end \ No newline at end of file diff --git a/test/integration/subscriptions_test.rb b/test/integration/subscriptions_test.rb deleted file mode 100644 index a52e06442..000000000 --- a/test/integration/subscriptions_test.rb +++ /dev/null @@ -1,31 +0,0 @@ -class SubscriptionsTest < ActionDispatch::IntegrationTest - - - setup do - @user = User.find_by_username('jdupond') - login_as(@user, scope: :user) - end - - test "user take a subscription" do - plan = Plan.where(group_id: @user.group.id, type: 'Plan').first - - VCR.use_cassette("subscriptions_user_create_success") do - post '/api/subscriptions', - { - subscription: { - plan_id: plan.id, - user_id: @user.id, - card_token: stripe_card_token - } - }.to_json, default_headers - end - - assert_equal 201, response.status, response.body - assert_equal Mime::JSON, response.content_type - - subscription = json_response(response.body) - assert_equal plan.id, subscription[:plan_id] - - end - -end \ No newline at end of file From 2a4ff82a154c797562e3df978a457d0b89a0e904 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Apr 2016 18:17:33 +0200 Subject: [PATCH 25/64] test admin create subscription --- .../subscriptions/create_as_admin_test.rb | 57 ++ .../subscriptions/create_as_user_test.rb | 2 +- .../subscriptions_admin_create_success.yml | 802 ++++++++++++++++++ 3 files changed, 860 insertions(+), 1 deletion(-) create mode 100644 test/integration/subscriptions/create_as_admin_test.rb create mode 100644 test/vcr_cassettes/subscriptions_admin_create_success.yml diff --git a/test/integration/subscriptions/create_as_admin_test.rb b/test/integration/subscriptions/create_as_admin_test.rb new file mode 100644 index 000000000..7438977a0 --- /dev/null +++ b/test/integration/subscriptions/create_as_admin_test.rb @@ -0,0 +1,57 @@ +class CreateAsUserTest < ActionDispatch::IntegrationTest + + + setup do + @admin = User.find_by_username('admin') + login_as(@admin, scope: :user) + end + + test "admin takes a subscription for a user" do + user = User.find_by_username('jdupond') + plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Mensuel') + + VCR.use_cassette("subscriptions_admin_create_success") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: user.id + } + }.to_json, default_headers + end + + + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the correct plan was subscribed + subscription = json_response(response.body) + assert_equal plan.id, subscription[:plan_id], 'subscribed plan does not match' + + # Check that the user has the correct subscription + assert_not_nil user.subscription, "user's subscription was not found" + assert_not_nil user.subscription.plan, "user's subscribed plan was not found" + assert_equal plan.id, user.subscription.plan_id, "user's plan does not match" + + # Check that the training credits were set correctly + assert_empty user.training_credits, 'training credits were not reset' + assert_equal user.subscription.plan.training_credit_nb, plan.training_credit_nb, 'trainings credits were not allocated' + + # Check that the user benefit from prices of his plan + printer = Machine.find_by_slug('imprimante-3d') + assert_equal 15, (printer.prices.find_by(group_id: user.group_id, plan_id: user.subscription.plan_id).amount / 100), 'machine hourly price does not match' + + # Check notification was sent to the user + notification = Notification.find_by(notification_type_id: NotificationType.find_by_name('notify_member_subscribed_plan'), attached_object_type: 'Subscription', attached_object_id: subscription[:id]) + assert_not_nil notification, 'user notification was not created' + assert_equal user.id, notification.receiver_id, 'wrong user notified' + + # Check generated invoice + invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) + assert_not_nil invoice, 'Invoice was not created' + assert File.exist?(invoice.file), 'Invoice PDF was not generated' + assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' + end + +end \ No newline at end of file diff --git a/test/integration/subscriptions/create_as_user_test.rb b/test/integration/subscriptions/create_as_user_test.rb index 630973ee2..122bb45f2 100644 --- a/test/integration/subscriptions/create_as_user_test.rb +++ b/test/integration/subscriptions/create_as_user_test.rb @@ -18,7 +18,7 @@ class CreateAsUserTest < ActionDispatch::IntegrationTest card_token: stripe_card_token } }.to_json, default_headers - end + end # Check response format & status assert_equal 201, response.status, response.body diff --git a/test/vcr_cassettes/subscriptions_admin_create_success.yml b/test/vcr_cassettes/subscriptions_admin_create_success.yml new file mode 100644 index 000000000..11fca6153 --- /dev/null +++ b/test/vcr_cassettes/subscriptions_admin_create_success.yml @@ -0,0 +1,802 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 16:16:21 GMT + Content-Type: + - application/json + Content-Length: + - '3462' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dkq2KtxZyjTlS + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 16:16:21 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions + body: + encoding: UTF-8 + string: plan=mensuel-standard-month-20160404171519 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '42' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 16:16:22 GMT + Content-Type: + - application/json + Content-Length: + - '821' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dkqxbz3ZxvmBy + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8DkqBcR1bQvr5G", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462551382, + "current_period_start": 1459959382, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459959382, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 16:16:22 GMT +- request: + method: get + uri: https://api.stripe.com/v1/invoices?customer=cus_8Di1wjdVktv5kt&limit=1 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 16:16:24 GMT + Content-Type: + - application/json + Content-Length: + - '2207' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DkqeZjTLH22XJ + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "object": "list", + "data": [ + { + "id": "in_17xJKM2sOmf47Nz9wOmb9YSB", + "object": "invoice", + "amount_due": 3000, + "application_fee": null, + "attempt_count": 1, + "attempted": true, + "charge": "ch_17xJKM2sOmf47Nz9huANudcu", + "closed": true, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459959382, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "sub_8DkqBcR1bQvr5G", + "object": "line_item", + "amount": 3000, + "currency": "usd", + "description": null, + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459959382, + "end": 1462551382 + }, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "proration": false, + "quantity": 1, + "subscription": null, + "type": "subscription" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xJKM2sOmf47Nz9wOmb9YSB/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1459959382, + "period_start": 1459948968, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": "sub_8DkqBcR1bQvr5G", + "subtotal": 3000, + "tax": null, + "tax_percent": null, + "total": 3000, + "webhooks_delivered_at": 1459959382 + } + ], + "has_more": true, + "url": "/v1/invoices" + } + http_version: + recorded_at: Wed, 06 Apr 2016 16:16:23 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 16:16:25 GMT + Content-Type: + - application/json + Content-Length: + - '4482' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dkq9n5NEnaqj7 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8DkqBcR1bQvr5G", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462551382, + "current_period_start": 1459959382, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459959382, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 3, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 16:16:25 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8DkqBcR1bQvr5G + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 16:16:26 GMT + Content-Type: + - application/json + Content-Length: + - '821' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DkqSt9TNkbCet + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8DkqBcR1bQvr5G", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462551382, + "current_period_start": 1459959382, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459959382, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 16:16:25 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8DkqBcR1bQvr5G?at_period_end=true + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 16:16:26 GMT + Content-Type: + - application/json + Content-Length: + - '826' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DkqQmbuyBCYqr + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8DkqBcR1bQvr5G", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459959386, + "current_period_end": 1462551382, + "current_period_start": 1459959382, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459959382, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 16:16:26 GMT +recorded_with: VCR 3.0.1 From f12646aaf9b65ff6eac9d95e3f07d8b3141ea12f Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Wed, 6 Apr 2016 18:23:32 +0200 Subject: [PATCH 26/64] adds integration tests for reservation --- app/models/user.rb | 2 + test/fixtures/credits.yml | 29 +- test/integration/reservations/create_test.rb | 173 +++- ...for_machine_with_subscription_success.yml} | 314 ++++-- ...for_machine_without_subscription_error.yml | 480 +++++++++ ...r_machine_without_subscription_success.yml | 941 ++++++++++++++++++ ..._training_without_subscription_success.yml | 941 ++++++++++++++++++ 7 files changed, 2766 insertions(+), 114 deletions(-) rename test/vcr_cassettes/{reservations_create_without_plan_success.yml => reservations_create_for_machine_with_subscription_success.yml} (66%) create mode 100644 test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml create mode 100644 test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml create mode 100644 test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml diff --git a/app/models/user.rb b/app/models/user.rb index 752ef5a7a..c3522a747 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -65,6 +65,8 @@ class User < ActiveRecord::Base validates :username, presence: true, uniqueness: true, length: { maximum: 30 } scope :active, -> { where(is_active: true) } + scope :without_subscription, -> { includes(:subscriptions).where(subscriptions: { user_id: nil }) } + scope :with_subscription, -> { joins(:subscriptions) } def to_builder Jbuilder.new do |json| diff --git a/test/fixtures/credits.yml b/test/fixtures/credits.yml index 6f80545a8..5b602a86d 100644 --- a/test/fixtures/credits.yml +++ b/test/fixtures/credits.yml @@ -4,7 +4,7 @@ credit_1: creditable_id: 2 creditable_type: Training plan_id: 1 - hours: + hours: created_at: 2016-04-04 15:19:28.414019000 Z updated_at: 2016-04-04 15:19:28.414019000 Z @@ -13,7 +13,7 @@ credit_2: creditable_id: 3 creditable_type: Training plan_id: 1 - hours: + hours: created_at: 2016-04-04 15:19:28.449511000 Z updated_at: 2016-04-04 15:19:28.449511000 Z @@ -22,7 +22,7 @@ credit_3: creditable_id: 1 creditable_type: Training plan_id: 1 - hours: + hours: created_at: 2016-04-04 15:19:28.495141000 Z updated_at: 2016-04-04 15:19:28.495141000 Z @@ -31,7 +31,7 @@ credit_5: creditable_id: 2 creditable_type: Training plan_id: 2 - hours: + hours: created_at: 2016-04-04 15:19:39.416054000 Z updated_at: 2016-04-04 15:19:39.416054000 Z @@ -40,7 +40,7 @@ credit_7: creditable_id: 4 creditable_type: Training plan_id: 2 - hours: + hours: created_at: 2016-04-04 15:19:39.486949000 Z updated_at: 2016-04-04 15:19:39.486949000 Z @@ -49,7 +49,7 @@ credit_8: creditable_id: 1 creditable_type: Training plan_id: 2 - hours: + hours: created_at: 2016-04-04 15:19:39.521993000 Z updated_at: 2016-04-04 15:19:39.521993000 Z @@ -58,7 +58,7 @@ credit_9: creditable_id: 3 creditable_type: Training plan_id: 2 - hours: + hours: created_at: 2016-04-04 15:19:39.553519000 Z updated_at: 2016-04-04 15:19:39.553519000 Z @@ -67,7 +67,7 @@ credit_10: creditable_id: 2 creditable_type: Training plan_id: 3 - hours: + hours: created_at: 2016-04-04 15:21:35.437032000 Z updated_at: 2016-04-04 15:21:35.437032000 Z @@ -76,7 +76,7 @@ credit_11: creditable_id: 1 creditable_type: Training plan_id: 3 - hours: + hours: created_at: 2016-04-04 15:21:35.470423000 Z updated_at: 2016-04-04 15:21:35.470423000 Z @@ -85,7 +85,7 @@ credit_12: creditable_id: 3 creditable_type: Training plan_id: 3 - hours: + hours: created_at: 2016-04-04 15:21:35.547043000 Z updated_at: 2016-04-04 15:21:35.547043000 Z @@ -97,3 +97,12 @@ credit_13: hours: 1 created_at: 2016-04-04 15:21:57.547939000 Z updated_at: 2016-04-04 15:21:57.547939000 Z + +credit_14: + id: 14 + creditable_id: 6 + creditable_type: Machine + plan_id: 3 + hours: 1 + created_at: 2016-04-04 15:21:57.547939000 Z + updated_at: 2016-04-04 15:21:57.547939000 Z diff --git a/test/integration/reservations/create_test.rb b/test/integration/reservations/create_test.rb index d724d2a51..e1a5f0a97 100644 --- a/test/integration/reservations/create_test.rb +++ b/test/integration/reservations/create_test.rb @@ -1,20 +1,24 @@ module Reservations class CreateTest < ActionDispatch::IntegrationTest setup do - @user = User.with_role(:member).first - login_as(@user, scope: :user) + @user_without_subscription = User.with_role(:member).without_subscription.first + @user_with_subscription = User.with_role(:member).with_subscription.second end - test "user without plan reserves a machine with success" do + test "user without subscription reserves a machine with success" do + login_as(@user_without_subscription, scope: :user) + machine = Machine.find(6) availability = machine.availabilities.first reservations_count = Reservation.count + invoice_count = Invoice.count invoice_items_count = InvoiceItem.count + users_credit_count = UsersCredit.count - VCR.use_cassette("reservations_create_without_plan_success") do + VCR.use_cassette("reservations_create_for_machine_without_subscription_success") do post reservations_path, { reservation: { - user_id: @user.id, + user_id: @user_without_subscription.id, reservable_id: machine.id, reservable_type: machine.class.name, card_token: stripe_card_token, @@ -30,19 +34,176 @@ module Reservations # general assertions assert_equal 201, response.status assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count + 1, Invoice.count + assert_equal invoice_items_count + 1, InvoiceItem.count + assert_equal users_credit_count, UsersCredit.count + + # reservation assertions + reservation = Reservation.last + + assert reservation.invoice + refute reservation.stp_invoice_id.blank? + assert_equal 1, reservation.invoice.invoice_items.count + + # invoice assertions + invoice = reservation.invoice + + refute invoice.stp_invoice_id.blank? + refute invoice.total.blank? + + # invoice_items assertions + invoice_item = InvoiceItem.last + + assert invoice_item.stp_invoice_item_id + assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id).amount + end + + test "user without subscription reserves a machine with error" do + login_as(@user_without_subscription, scope: :user) + + machine = Machine.find(6) + availability = machine.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + + VCR.use_cassette("reservations_create_for_machine_without_subscription_error") do + post reservations_path, { reservation: { + user_id: @user_without_subscription.id, + reservable_id: machine.id, + reservable_type: machine.class.name, + card_token: stripe_card_token(error: :card_declined), + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + end + + # general assertions + assert_equal 422, response.status + assert_equal reservations_count, Reservation.count + assert_equal invoice_count, Invoice.count + assert_equal invoice_items_count, InvoiceItem.count + end + + test "user without subscription reserves a training with success" do + login_as(@user_without_subscription, scope: :user) + + training = Training.first + availability = training.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + + VCR.use_cassette("reservations_create_for_training_without_subscription_success") do + post reservations_path, { reservation: { + user_id: @user_without_subscription.id, + reservable_id: training.id, + reservable_type: training.class.name, + card_token: stripe_card_token, + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + end + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count + 1, Invoice.count assert_equal invoice_items_count + 1, InvoiceItem.count # reservation assertions reservation = Reservation.last assert reservation.invoice + refute reservation.stp_invoice_id.blank? assert_equal 1, reservation.invoice.invoice_items.count + # invoice assertions + invoice = reservation.invoice + + refute invoice.stp_invoice_id.blank? + refute invoice.total.blank? # invoice_items invoice_item = InvoiceItem.last assert invoice_item.stp_invoice_item_id - assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user.group_id).amount + assert_equal invoice_item.amount, training.amount_by_group(@user_without_subscription.group_id).amount + end + + test "user with subscription reserves a machine with success" do + login_as(@user_with_subscription, scope: :user) + + plan = @user_with_subscription.subscribed_plan + machine = Machine.find(6) + availability = machine.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + users_credit_count = UsersCredit.count + + VCR.use_cassette("reservations_create_for_machine_with_subscription_success") do + post reservations_path, { reservation: { + user_id: @user_with_subscription.id, + reservable_id: machine.id, + reservable_type: machine.class.name, + card_token: stripe_card_token, + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + }, + { start_at: (availability.start_at + 1.hour).to_s(:iso8601), + end_at: (availability.start_at + 2.hours).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + end + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count + 1, Invoice.count + assert_equal invoice_items_count + 2, InvoiceItem.count + assert_equal users_credit_count + 1, UsersCredit.count + + # reservation assertions + reservation = Reservation.last + + assert reservation.invoice + refute reservation.stp_invoice_id.blank? + assert_equal 2, reservation.invoice.invoice_items.count + + # invoice assertions + invoice = reservation.invoice + + refute invoice.stp_invoice_id.blank? + refute invoice.total.blank? + + # invoice_items assertions + invoice_items = InvoiceItem.last(2) + machine_price = machine.prices.find_by(group_id: @user_with_subscription.group_id, plan_id: plan.id).amount + + assert invoice_items.any? { |invoice| invoice.amount == 0 } + assert invoice_items.any? { |invoice| invoice.amount == machine_price } + assert invoice_items.all? { |invoice| invoice.stp_invoice_item_id } + + # users_credits assertions + users_credit = UsersCredit.last + + assert_equal @user_with_subscription, users_credit.user + assert_equal [reservation.slots.count, plan.machine_credits.find_by(creditable_id: machine.id).hours].min, users_credit.hours_used end end end diff --git a/test/vcr_cassettes/reservations_create_without_plan_success.yml b/test/vcr_cassettes/reservations_create_for_machine_with_subscription_success.yml similarity index 66% rename from test/vcr_cassettes/reservations_create_without_plan_success.yml rename to test/vcr_cassettes/reservations_create_for_machine_with_subscription_success.yml index 5aa39bb1d..f1273017f 100644 --- a/test/vcr_cassettes/reservations_create_without_plan_success.yml +++ b/test/vcr_cassettes/reservations_create_for_machine_with_subscription_success.yml @@ -31,7 +31,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 09:46:39 GMT + - Wed, 06 Apr 2016 15:22:24 GMT Content-Type: - application/json Content-Length: @@ -49,7 +49,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DeYuCEulJlrPp + - req_8DjynFP8DZtkjQ Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -58,10 +58,10 @@ http_interactions: encoding: UTF-8 string: | { - "id": "tok_17xDFD2sOmf47Nz9JD1vbrAJ", + "id": "tok_17xIU82sOmf47Nz9lhdbMB7A", "object": "token", "card": { - "id": "card_17xDFD2sOmf47Nz9LbJShTlw", + "id": "card_17xIU82sOmf47Nz94aVn3WmU", "object": "card", "address_city": null, "address_country": null, @@ -85,19 +85,19 @@ http_interactions: "tokenization_method": null }, "client_ip": "86.76.5.109", - "created": 1459935999, + "created": 1459956144, "livemode": false, "type": "card", "used": false } - http_version: - recorded_at: Wed, 06 Apr 2016 09:46:39 GMT + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:24 GMT - request: method: post uri: https://api.stripe.com/v1/invoiceitems body: encoding: UTF-8 - string: customer=cus_8CzAgnSeFbDuG2&amount=3200¤cy=eur&description=FORM1%2B+imprimante+3D+lundi+11+avril+2016+14h00+-+15%3A00 + string: customer=cus_8CzKe50I0J1gaI&amount=0¤cy=usd&description=FORM1%2B+imprimante+3D+April+11%2C+2016+14%3A00+-+03%3A00+PM headers: Accept: - "*/*; q=0.5, application/xml" @@ -114,7 +114,7 @@ http_interactions: MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' Content-Length: - - '123' + - '122' response: status: code: 200 @@ -123,11 +123,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 09:46:41 GMT + - Wed, 06 Apr 2016 15:22:25 GMT Content-Type: - application/json Content-Length: - - '471' + - '466' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -141,7 +141,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DeYBFB42AoW5m + - req_8DjyDxNWUBoDuT Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -150,31 +150,111 @@ http_interactions: encoding: UTF-8 string: | { - "id": "ii_17xDFF2sOmf47Nz90VoIJ17e", + "id": "ii_17xIU92sOmf47Nz9JiLpXlHs", "object": "invoiceitem", - "amount": 3200, - "currency": "eur", - "customer": "cus_8CzAgnSeFbDuG2", - "date": 1459936001, - "description": "FORM1+ imprimante 3D lundi 11 avril 2016 14h00 - 15:00", + "amount": 0, + "currency": "usd", + "customer": "cus_8CzKe50I0J1gaI", + "date": 1459956145, + "description": "FORM1+ imprimante 3D April 11, 2016 14:00 - 03:00 PM", "discountable": true, "invoice": null, "livemode": false, "metadata": {}, "period": { - "start": 1459936001, - "end": 1459936001 + "start": 1459956145, + "end": 1459956145 }, "plan": null, "proration": false, "quantity": null, "subscription": null } - http_version: - recorded_at: Wed, 06 Apr 2016 09:46:41 GMT + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:25 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoiceitems + body: + encoding: UTF-8 + string: customer=cus_8CzKe50I0J1gaI&amount=1000¤cy=usd&description=FORM1%2B+imprimante+3D+April+11%2C+2016+15%3A00+-+04%3A00+PM + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '125' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 15:22:25 GMT + Content-Type: + - application/json + Content-Length: + - '469' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Djyoqd7RfPgqy + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "ii_17xIU92sOmf47Nz98bi7Z01X", + "object": "invoiceitem", + "amount": 1000, + "currency": "usd", + "customer": "cus_8CzKe50I0J1gaI", + "date": 1459956145, + "description": "FORM1+ imprimante 3D April 11, 2016 15:00 - 04:00 PM", + "discountable": true, + "invoice": null, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459956145, + "end": 1459956145 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:26 GMT - request: method: get - uri: https://api.stripe.com/v1/customers/cus_8CzAgnSeFbDuG2 + uri: https://api.stripe.com/v1/customers/cus_8CzKe50I0J1gaI body: encoding: US-ASCII string: '' @@ -201,7 +281,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 09:46:42 GMT + - Wed, 06 Apr 2016 15:22:26 GMT Content-Type: - application/json Content-Length: @@ -219,7 +299,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DeYGJn0xDlBIk + - req_8DjyndnI54v1Uz Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -228,16 +308,16 @@ http_interactions: encoding: UTF-8 string: | { - "id": "cus_8CzAgnSeFbDuG2", + "id": "cus_8CzKe50I0J1gaI", "object": "customer", "account_balance": 0, - "created": 1459782030, - "currency": "eur", + "created": 1459782643, + "currency": "usd", "default_source": null, "delinquent": false, - "description": "Jean Dupont", + "description": "Kevin Dumas", "discount": null, - "email": "jean.dupont@gmail.com", + "email": "kevin.dumas@orange.fr", "livemode": false, "metadata": {}, "shipping": null, @@ -246,24 +326,24 @@ http_interactions: "data": [], "has_more": false, "total_count": 0, - "url": "/v1/customers/cus_8CzAgnSeFbDuG2/sources" + "url": "/v1/customers/cus_8CzKe50I0J1gaI/sources" }, "subscriptions": { "object": "list", "data": [], "has_more": false, "total_count": 0, - "url": "/v1/customers/cus_8CzAgnSeFbDuG2/subscriptions" + "url": "/v1/customers/cus_8CzKe50I0J1gaI/subscriptions" } } - http_version: - recorded_at: Wed, 06 Apr 2016 09:46:42 GMT + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:26 GMT - request: method: post - uri: https://api.stripe.com/v1/customers/cus_8CzAgnSeFbDuG2/sources + uri: https://api.stripe.com/v1/customers/cus_8CzKe50I0J1gaI/sources body: encoding: UTF-8 - string: card=tok_17xDFD2sOmf47Nz9JD1vbrAJ + string: card=tok_17xIU82sOmf47Nz9lhdbMB7A headers: Accept: - "*/*; q=0.5, application/xml" @@ -289,7 +369,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 09:46:42 GMT + - Wed, 06 Apr 2016 15:22:27 GMT Content-Type: - application/json Content-Length: @@ -307,7 +387,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DeYMzh7lG57bt + - req_8DjyrgeP2PYiHp Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -316,7 +396,7 @@ http_interactions: encoding: UTF-8 string: | { - "id": "card_17xDFD2sOmf47Nz9LbJShTlw", + "id": "card_17xIU82sOmf47Nz94aVn3WmU", "object": "card", "address_city": null, "address_country": null, @@ -328,7 +408,7 @@ http_interactions: "address_zip_check": null, "brand": "Visa", "country": "US", - "customer": "cus_8CzAgnSeFbDuG2", + "customer": "cus_8CzKe50I0J1gaI", "cvc_check": "pass", "dynamic_last4": null, "exp_month": 4, @@ -340,14 +420,14 @@ http_interactions: "name": null, "tokenization_method": null } - http_version: - recorded_at: Wed, 06 Apr 2016 09:46:42 GMT + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:27 GMT - request: method: post uri: https://api.stripe.com/v1/invoices body: encoding: UTF-8 - string: customer=cus_8CzAgnSeFbDuG2 + string: customer=cus_8CzKe50I0J1gaI headers: Accept: - "*/*; q=0.5, application/xml" @@ -373,11 +453,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 09:46:43 GMT + - Wed, 06 Apr 2016 15:22:28 GMT Content-Type: - application/json Content-Length: - - '1428' + - '1953' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -391,7 +471,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DeYs6PUiVx1DN + - req_8DjyPqF2AowT93 Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -400,17 +480,17 @@ http_interactions: encoding: UTF-8 string: | { - "id": "in_17xDFH2sOmf47Nz9DpUY5b3U", + "id": "in_17xIUC2sOmf47Nz9RmCbPPpz", "object": "invoice", - "amount_due": 3200, + "amount_due": 1000, "application_fee": null, "attempt_count": 0, "attempted": false, "charge": null, "closed": false, - "currency": "eur", - "customer": "cus_8CzAgnSeFbDuG2", - "date": 1459936003, + "currency": "usd", + "customer": "cus_8CzKe50I0J1gaI", + "date": 1459956148, "description": null, "discount": null, "ending_balance": null, @@ -419,17 +499,36 @@ http_interactions: "object": "list", "data": [ { - "id": "ii_17xDFF2sOmf47Nz90VoIJ17e", + "id": "ii_17xIU92sOmf47Nz98bi7Z01X", "object": "line_item", - "amount": 3200, - "currency": "eur", - "description": "FORM1+ imprimante 3D lundi 11 avril 2016 14h00 - 15:00", + "amount": 1000, + "currency": "usd", + "description": "FORM1+ imprimante 3D April 11, 2016 15:00 - 04:00 PM", "discountable": true, "livemode": false, "metadata": {}, "period": { - "start": 1459936001, - "end": 1459936001 + "start": 1459956145, + "end": 1459956145 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + }, + { + "id": "ii_17xIU92sOmf47Nz9JiLpXlHs", + "object": "line_item", + "amount": 0, + "currency": "usd", + "description": "FORM1+ imprimante 3D April 11, 2016 14:00 - 03:00 PM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459956145, + "end": 1459956145 }, "plan": null, "proration": false, @@ -439,30 +538,30 @@ http_interactions: } ], "has_more": false, - "total_count": 1, - "url": "/v1/invoices/in_17xDFH2sOmf47Nz9DpUY5b3U/lines" + "total_count": 2, + "url": "/v1/invoices/in_17xIUC2sOmf47Nz9RmCbPPpz/lines" }, "livemode": false, "metadata": {}, - "next_payment_attempt": 1459939603, + "next_payment_attempt": 1459959748, "paid": false, - "period_end": 1459936003, - "period_start": 1459936003, + "period_end": 1459956148, + "period_start": 1459956148, "receipt_number": null, "starting_balance": 0, "statement_descriptor": null, "subscription": null, - "subtotal": 3200, + "subtotal": 1000, "tax": null, "tax_percent": null, - "total": 3200, + "total": 1000, "webhooks_delivered_at": null } - http_version: - recorded_at: Wed, 06 Apr 2016 09:46:43 GMT + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:28 GMT - request: method: post - uri: https://api.stripe.com/v1/invoices/in_17xDFH2sOmf47Nz9DpUY5b3U/pay + uri: https://api.stripe.com/v1/invoices/in_17xIUC2sOmf47Nz9RmCbPPpz/pay body: encoding: ASCII-8BIT string: '' @@ -491,11 +590,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 09:46:44 GMT + - Wed, 06 Apr 2016 15:22:29 GMT Content-Type: - application/json Content-Length: - - '1447' + - '1972' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -509,7 +608,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DeYRzymQv71IY + - req_8DjynUtcAbsRqG Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -518,17 +617,17 @@ http_interactions: encoding: UTF-8 string: | { - "id": "in_17xDFH2sOmf47Nz9DpUY5b3U", + "id": "in_17xIUC2sOmf47Nz9RmCbPPpz", "object": "invoice", - "amount_due": 3200, + "amount_due": 1000, "application_fee": null, "attempt_count": 1, "attempted": true, - "charge": "ch_17xDFI2sOmf47Nz9KHMAQUmF", + "charge": "ch_17xIUD2sOmf47Nz9ScdFhmGL", "closed": true, - "currency": "eur", - "customer": "cus_8CzAgnSeFbDuG2", - "date": 1459936003, + "currency": "usd", + "customer": "cus_8CzKe50I0J1gaI", + "date": 1459956148, "description": null, "discount": null, "ending_balance": 0, @@ -537,17 +636,36 @@ http_interactions: "object": "list", "data": [ { - "id": "ii_17xDFF2sOmf47Nz90VoIJ17e", + "id": "ii_17xIU92sOmf47Nz98bi7Z01X", "object": "line_item", - "amount": 3200, - "currency": "eur", - "description": "FORM1+ imprimante 3D lundi 11 avril 2016 14h00 - 15:00", + "amount": 1000, + "currency": "usd", + "description": "FORM1+ imprimante 3D April 11, 2016 15:00 - 04:00 PM", "discountable": true, "livemode": false, "metadata": {}, "period": { - "start": 1459936001, - "end": 1459936001 + "start": 1459956145, + "end": 1459956145 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + }, + { + "id": "ii_17xIU92sOmf47Nz9JiLpXlHs", + "object": "line_item", + "amount": 0, + "currency": "usd", + "description": "FORM1+ imprimante 3D April 11, 2016 14:00 - 03:00 PM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459956145, + "end": 1459956145 }, "plan": null, "proration": false, @@ -557,30 +675,30 @@ http_interactions: } ], "has_more": false, - "total_count": 1, - "url": "/v1/invoices/in_17xDFH2sOmf47Nz9DpUY5b3U/lines" + "total_count": 2, + "url": "/v1/invoices/in_17xIUC2sOmf47Nz9RmCbPPpz/lines" }, "livemode": false, "metadata": {}, "next_payment_attempt": null, "paid": true, - "period_end": 1459936003, - "period_start": 1459936003, + "period_end": 1459956148, + "period_start": 1459956148, "receipt_number": null, "starting_balance": 0, "statement_descriptor": null, "subscription": null, - "subtotal": 3200, + "subtotal": 1000, "tax": null, "tax_percent": null, - "total": 3200, - "webhooks_delivered_at": 1459936003 + "total": 1000, + "webhooks_delivered_at": 1459956148 } - http_version: - recorded_at: Wed, 06 Apr 2016 09:46:44 GMT + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:29 GMT - request: method: delete - uri: https://api.stripe.com/v1/customers/cus_8CzAgnSeFbDuG2/sources/card_17xDFD2sOmf47Nz9LbJShTlw + uri: https://api.stripe.com/v1/customers/cus_8CzKe50I0J1gaI/sources/card_17xIU82sOmf47Nz94aVn3WmU body: encoding: US-ASCII string: '' @@ -592,7 +710,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOy + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -607,7 +725,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 09:46:45 GMT + - Wed, 06 Apr 2016 15:22:30 GMT Content-Type: - application/json Content-Length: @@ -625,7 +743,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DeYSokbVz2FOu + - req_8DjyJ9JQVHnxT0 Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -635,8 +753,8 @@ http_interactions: string: | { "deleted": true, - "id": "card_17xDFD2sOmf47Nz9LbJShTlw" + "id": "card_17xIU82sOmf47Nz94aVn3WmU" } - http_version: - recorded_at: Wed, 06 Apr 2016 09:46:45 GMT + http_version: + recorded_at: Wed, 06 Apr 2016 15:22:30 GMT recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml new file mode 100644 index 000000000..18ff86370 --- /dev/null +++ b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml @@ -0,0 +1,480 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4000000000000002&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:31:05 GMT + Content-Type: + - application/json + Content-Length: + - '778' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dj8hOci59D4xC + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xHgT2sOmf47Nz962TaLtD7", + "object": "token", + "card": { + "id": "card_17xHgT2sOmf47Nz98eSsgCfX", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "xsVM9Mfv9kfwhRSL", + "funding": "credit", + "last4": "0002", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "86.76.5.109", + "created": 1459953065, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:31:05 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoiceitems + body: + encoding: UTF-8 + string: customer=cus_8Di1wjdVktv5kt&amount=3200¤cy=usd&description=FORM1%2B+imprimante+3D+April+11%2C+2016+14%3A00+-+03%3A00+PM + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '125' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:31:06 GMT + Content-Type: + - application/json + Content-Length: + - '469' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dj87wp0RJ3Z71 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "ii_17xHgU2sOmf47Nz9Pp3l4ZAA", + "object": "invoiceitem", + "amount": 3200, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459953066, + "description": "FORM1+ imprimante 3D April 11, 2016 14:00 - 03:00 PM", + "discountable": true, + "invoice": null, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459953066, + "end": 1459953066 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:31:06 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:31:07 GMT + Content-Type: + - application/json + Content-Length: + - '3462' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dj8aOsnrVp2zU + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:31:07 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources + body: + encoding: UTF-8 + string: card=tok_17xHgT2sOmf47Nz962TaLtD7 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '33' + response: + status: + code: 402 + message: Payment Required + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:31:09 GMT + Content-Type: + - application/json + Content-Length: + - '134' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dj8Q0yiZoox2F + Stripe-Version: + - '2015-10-16' + body: + encoding: UTF-8 + string: | + { + "error": { + "message": "Your card was declined.", + "type": "card_error", + "param": "", + "code": "card_declined" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:31:09 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/invoiceitems/ii_17xHgU2sOmf47Nz9Pp3l4ZAA + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:31:09 GMT + Content-Type: + - application/json + Content-Length: + - '61' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dj86hW0UVRjBL + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "deleted": true, + "id": "ii_17xHgU2sOmf47Nz9Pp3l4ZAA" + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:31:09 GMT +recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml new file mode 100644 index 000000000..9249aa5fc --- /dev/null +++ b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml @@ -0,0 +1,941 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:58 GMT + Content-Type: + - application/json + Content-Length: + - '778' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigzZOUKbFLP8 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xHFG2sOmf47Nz9pZ4CafpU", + "object": "token", + "card": { + "id": "card_17xHFG2sOmf47Nz95yErDQbL", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "86.76.5.109", + "created": 1459951378, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:58 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoiceitems + body: + encoding: UTF-8 + string: customer=cus_8Di1wjdVktv5kt&amount=3200¤cy=usd&description=FORM1%2B+imprimante+3D+April+11%2C+2016+14%3A00+-+03%3A00+PM + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '125' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:58 GMT + Content-Type: + - application/json + Content-Length: + - '469' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigTaKJ04PVMc + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "ii_17xHFG2sOmf47Nz9hhIaJZtF", + "object": "invoiceitem", + "amount": 3200, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459951378, + "description": "FORM1+ imprimante 3D April 11, 2016 14:00 - 03:00 PM", + "discountable": true, + "invoice": null, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459951378, + "end": 1459951378 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:58 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:59 GMT + Content-Type: + - application/json + Content-Length: + - '3462' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Digc2V3aKSGrn + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:59 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources + body: + encoding: UTF-8 + string: card=tok_17xHFG2sOmf47Nz9pZ4CafpU + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '33' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:03:00 GMT + Content-Type: + - application/json + Content-Length: + - '577' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigAxuQClwx3A + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "card_17xHFG2sOmf47Nz95yErDQbL", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:03:00 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: UTF-8 + string: default_source=card_17xHFG2sOmf47Nz95yErDQbL + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '44' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:03:01 GMT + Content-Type: + - application/json + Content-Length: + - '4190' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dig1Js3cBEeqQ + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xHFG2sOmf47Nz95yErDQbL", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xHFG2sOmf47Nz95yErDQbL", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:03:01 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices + body: + encoding: UTF-8 + string: customer=cus_8Di1wjdVktv5kt + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '27' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:03:02 GMT + Content-Type: + - application/json + Content-Length: + - '1426' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigRXqOIStdA0 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xHFK2sOmf47Nz9jegPFlNt", + "object": "invoice", + "amount_due": 3200, + "application_fee": null, + "attempt_count": 0, + "attempted": false, + "charge": null, + "closed": false, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459951382, + "description": null, + "discount": null, + "ending_balance": null, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xHFG2sOmf47Nz9hhIaJZtF", + "object": "line_item", + "amount": 3200, + "currency": "usd", + "description": "FORM1+ imprimante 3D April 11, 2016 14:00 - 03:00 PM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459951378, + "end": 1459951378 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xHFK2sOmf47Nz9jegPFlNt/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1459954982, + "paid": false, + "period_end": 1459951382, + "period_start": 1459948968, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 3200, + "tax": null, + "tax_percent": null, + "total": 3200, + "webhooks_delivered_at": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:03:02 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices/in_17xHFK2sOmf47Nz9jegPFlNt/pay + body: + encoding: ASCII-8BIT + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '0' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:03:03 GMT + Content-Type: + - application/json + Content-Length: + - '1445' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigckzVuj8MLI + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xHFK2sOmf47Nz9jegPFlNt", + "object": "invoice", + "amount_due": 3200, + "application_fee": null, + "attempt_count": 1, + "attempted": true, + "charge": "ch_17xHFL2sOmf47Nz9FCQ0BJKc", + "closed": true, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459951382, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xHFG2sOmf47Nz9hhIaJZtF", + "object": "line_item", + "amount": 3200, + "currency": "usd", + "description": "FORM1+ imprimante 3D April 11, 2016 14:00 - 03:00 PM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459951378, + "end": 1459951378 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xHFK2sOmf47Nz9jegPFlNt/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1459951382, + "period_start": 1459948968, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 3200, + "tax": null, + "tax_percent": null, + "total": 3200, + "webhooks_delivered_at": 1459951382 + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:03:03 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources/card_17xHFG2sOmf47Nz95yErDQbL + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:03:04 GMT + Content-Type: + - application/json + Content-Length: + - '63' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8Dig3VHawFrxab + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "deleted": true, + "id": "card_17xHFG2sOmf47Nz95yErDQbL" + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:03:04 GMT +recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml new file mode 100644 index 000000000..1b1c55b7b --- /dev/null +++ b/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml @@ -0,0 +1,941 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:49 GMT + Content-Type: + - application/json + Content-Length: + - '778' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigcYeFhS0WA0 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xHF72sOmf47Nz9gTjKt9Pb", + "object": "token", + "card": { + "id": "card_17xHF72sOmf47Nz9pOYRMYdO", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "86.76.5.109", + "created": 1459951369, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:49 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoiceitems + body: + encoding: UTF-8 + string: customer=cus_8Di1wjdVktv5kt&amount=5100¤cy=usd&description=Formation+Imprimante+3D+April+12%2C+2016+08%3A00+-+09%3A00+AM + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '126' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:50 GMT + Content-Type: + - application/json + Content-Length: + - '472' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigyU1U3fnul5 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "ii_17xHF82sOmf47Nz9QT6BnkAZ", + "object": "invoiceitem", + "amount": 5100, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459951370, + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 09:00 AM", + "discountable": true, + "invoice": null, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459951370, + "end": 1459951370 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:50 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:51 GMT + Content-Type: + - application/json + Content-Length: + - '3462' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigzPm4VAhhnA + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:51 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources + body: + encoding: UTF-8 + string: card=tok_17xHF72sOmf47Nz9gTjKt9Pb + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '33' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:52 GMT + Content-Type: + - application/json + Content-Length: + - '577' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigYDBbu9Qzcj + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "card_17xHF72sOmf47Nz9pOYRMYdO", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:52 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: UTF-8 + string: default_source=card_17xHF72sOmf47Nz9pOYRMYdO + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '44' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:53 GMT + Content-Type: + - application/json + Content-Length: + - '4190' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigPEpOnL3MYw + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xHF72sOmf47Nz9pOYRMYdO", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xHF72sOmf47Nz9pOYRMYdO", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:53 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices + body: + encoding: UTF-8 + string: customer=cus_8Di1wjdVktv5kt + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '27' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:54 GMT + Content-Type: + - application/json + Content-Length: + - '1429' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DiggAW17hqwsf + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xHFC2sOmf47Nz9ZZeO0yST", + "object": "invoice", + "amount_due": 5100, + "application_fee": null, + "attempt_count": 0, + "attempted": false, + "charge": null, + "closed": false, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459951374, + "description": null, + "discount": null, + "ending_balance": null, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xHF82sOmf47Nz9QT6BnkAZ", + "object": "line_item", + "amount": 5100, + "currency": "usd", + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 09:00 AM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459951370, + "end": 1459951370 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xHFC2sOmf47Nz9ZZeO0yST/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1459954974, + "paid": false, + "period_end": 1459951374, + "period_start": 1459948968, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 5100, + "tax": null, + "tax_percent": null, + "total": 5100, + "webhooks_delivered_at": null + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:54 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices/in_17xHFC2sOmf47Nz9ZZeO0yST/pay + body: + encoding: ASCII-8BIT + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '0' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:55 GMT + Content-Type: + - application/json + Content-Length: + - '1448' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigSwPCrF5F8H + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xHFC2sOmf47Nz9ZZeO0yST", + "object": "invoice", + "amount_due": 5100, + "application_fee": null, + "attempt_count": 1, + "attempted": true, + "charge": "ch_17xHFD2sOmf47Nz97SA1n7nn", + "closed": true, + "currency": "usd", + "customer": "cus_8Di1wjdVktv5kt", + "date": 1459951374, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xHF82sOmf47Nz9QT6BnkAZ", + "object": "line_item", + "amount": 5100, + "currency": "usd", + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 09:00 AM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1459951370, + "end": 1459951370 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xHFC2sOmf47Nz9ZZeO0yST/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1459951374, + "period_start": 1459948968, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 5100, + "tax": null, + "tax_percent": null, + "total": 5100, + "webhooks_delivered_at": 1459951374 + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:55 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources/card_17xHF72sOmf47Nz9pOYRMYdO + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Wed, 06 Apr 2016 14:02:56 GMT + Content-Type: + - application/json + Content-Length: + - '63' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8DigPHaDWfrkLV + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "deleted": true, + "id": "card_17xHF72sOmf47Nz9pOYRMYdO" + } + http_version: + recorded_at: Wed, 06 Apr 2016 14:02:56 GMT +recorded_with: VCR 3.0.1 From 44fcb2e089a419299d83829251844e3134330d52 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Wed, 6 Apr 2016 18:24:26 +0200 Subject: [PATCH 27/64] draft a service to handle users credits --- app/services/users_credit_manager.rb | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 app/services/users_credit_manager.rb diff --git a/app/services/users_credit_manager.rb b/app/services/users_credit_manager.rb new file mode 100644 index 000000000..1372e814c --- /dev/null +++ b/app/services/users_credit_manager.rb @@ -0,0 +1,82 @@ +class UsersCreditManager + attr_reader :manager + + def initialize(reservation) + if reservation.reservable_type == "Training" + @manager = Training.new(reservation) + elsif reservation.reservable_type == "Machine" + @manager = Machine.new(reservation) + end + end + + class Machine < Manager + def will_use_credits? + end + + def credited_hours_number + end + + def update + super + end + + private + def _will_use_credits? + end + end + + class Training < Manager + def will_use_credits? + _will_use_credits?[0] + end + + def update + super + will_use_credits, training_credit = _will_use_credits? + if will_use_credits + user.credits << training_credit # we create a new UsersCredit object + end + end + + private + def _will_use_credits? + # if there is a training_credit defined for this plan and this training + if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id) + # if user has not used all the plan credits + if user.training_credits.count < plan.training_credit_nb + return true, training_credit + end + end + return false, nil + end + end + + private + class Manager + attr_reader :reservation + + def initialize(reservation) + @reservation = reservation + @already_updated = false + end + + def plan + user.subscribed_plan + end + + def user + reservation.user + end + + def update + if @already_updated + raise AlreadyUpdated, "update credit is not idempotent ! do not try to update twice." + else + @already_updated = true + end + end + end + + class AlreadyUpdated < StandardError + end +end From 28fcd121b4e4739186903b4b77646d133c597a5b Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Wed, 6 Apr 2016 18:26:02 +0200 Subject: [PATCH 28/64] renames service of users credits manager --- .../{users_credit_manager.rb => users_credits_manager.rb} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename app/services/{users_credit_manager.rb => users_credits_manager.rb} (98%) diff --git a/app/services/users_credit_manager.rb b/app/services/users_credits_manager.rb similarity index 98% rename from app/services/users_credit_manager.rb rename to app/services/users_credits_manager.rb index 1372e814c..76f228417 100644 --- a/app/services/users_credit_manager.rb +++ b/app/services/users_credits_manager.rb @@ -1,4 +1,4 @@ -class UsersCreditManager +class UsersCreditsManager attr_reader :manager def initialize(reservation) From b72609c072f6bcbb30fcae3863c8492d4b3263aa Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 7 Apr 2016 12:28:25 +0200 Subject: [PATCH 29/64] test and validation from plan group --- app/models/subscription.rb | 1 + .../subscription_group_validator.rb | 7 + .../subscriptions/create_as_user_test.rb | 31 +- .../subscriptions_user_create_failed.yml | 829 ++++++++++++++++++ 4 files changed, 867 insertions(+), 1 deletion(-) create mode 100644 app/validators/subscription_group_validator.rb create mode 100644 test/vcr_cassettes/subscriptions_user_create_failed.yml diff --git a/app/models/subscription.rb b/app/models/subscription.rb index d6a11b378..b41fac740 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -8,6 +8,7 @@ class Subscription < ActiveRecord::Base has_many :offer_days, dependent: :destroy validates_presence_of :plan_id + validates_with SubscriptionGroupValidator attr_accessor :card_token diff --git a/app/validators/subscription_group_validator.rb b/app/validators/subscription_group_validator.rb new file mode 100644 index 000000000..f53ea16cb --- /dev/null +++ b/app/validators/subscription_group_validator.rb @@ -0,0 +1,7 @@ +class SubscriptionGroupValidator < ActiveModel::Validator + def validate(record) + if record.user.group != record.plan.group + record.errors[:plan_id] << "This plan is not compatible with the current user's group" + end + end +end \ No newline at end of file diff --git a/test/integration/subscriptions/create_as_user_test.rb b/test/integration/subscriptions/create_as_user_test.rb index 122bb45f2..841e6a606 100644 --- a/test/integration/subscriptions/create_as_user_test.rb +++ b/test/integration/subscriptions/create_as_user_test.rb @@ -6,7 +6,7 @@ class CreateAsUserTest < ActionDispatch::IntegrationTest login_as(@user, scope: :user) end - test "user takes a subscription" do + test 'user takes a subscription successfully' do plan = Plan.find_by(group_id: @user.group.id, type: 'Plan', base_name: 'Mensuel') VCR.use_cassette("subscriptions_user_create_success") do @@ -56,4 +56,33 @@ class CreateAsUserTest < ActionDispatch::IntegrationTest assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' end + + + test 'user takes a subscription with error' do + # get plan for wrong group + plan = Plan.where.not(group_id: @user.group.id).first + + VCR.use_cassette("subscriptions_user_create_failed") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: @user.id, + card_token: stripe_card_token + } + }.to_json, default_headers + end + + # Check response format & status + assert_equal 422, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the error was handled + subscription = json_response(response.body) + assert_match /plan is not compatible/, response.body + + # Check that the user has no subscription + assert_nil @user.subscription, "user's subscription was found" + end + end \ No newline at end of file diff --git a/test/vcr_cassettes/subscriptions_user_create_failed.yml b/test/vcr_cassettes/subscriptions_user_create_failed.yml new file mode 100644 index 000000000..5475de74e --- /dev/null +++ b/test/vcr_cassettes/subscriptions_user_create_failed.yml @@ -0,0 +1,829 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 09:34:23 GMT + Content-Type: + - application/json + Content-Length: + - '780' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E1aDuJqtjQOj4 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xZWt2sOmf47Nz906Kkg4Q3", + "object": "token", + "card": { + "id": "card_17xZWt2sOmf47Nz9eVUCi53A", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "90.52.157.226", + "created": 1460021663, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Thu, 07 Apr 2016 09:34:23 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 09:34:24 GMT + Content-Type: + - application/json + Content-Length: + - '4487' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E1aHv4p7a59Gy + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8Di1wjdVktv5kt", + "object": "customer", + "account_balance": 0, + "created": 1459948888, + "currency": "usd", + "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "delinquent": false, + "description": "Jean Dupond", + "discount": null, + "email": "jean.dupond@gmail.com", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8Di1wjdVktv5kt", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8DkqBcR1bQvr5G", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459959386, + "current_period_end": 1462551382, + "current_period_start": 1459959382, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459959382, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di9gqPLwt5IIC", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459949404, + "current_period_end": 1462541399, + "current_period_start": 1459949399, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459949399, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8Di2VadRvr7A99", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1459948972, + "current_period_end": 1462540968, + "current_period_start": 1459948968, + "customer": "cus_8Di1wjdVktv5kt", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1459948968, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 3, + "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" + } + } + http_version: + recorded_at: Thu, 07 Apr 2016 09:34:24 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions + body: + encoding: UTF-8 + string: plan=mensuel-tarif-reduit-student-month-20160404171827&card=tok_17xZWt2sOmf47Nz906Kkg4Q3 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '88' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 09:34:25 GMT + Content-Type: + - application/json + Content-Length: + - '880' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E1ac4ihRJHesp + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJzdWJfOEUxYWZrVEJuMmRjMUQiLAogICJvYmplY3QiOiAi + c3Vic2NyaXB0aW9uIiwKICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQiOiBu + dWxsLAogICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IGZhbHNlLAogICJjYW5j + ZWxlZF9hdCI6IG51bGwsCiAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI2 + MTM2NjUsCiAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ2MDAyMTY2NSwK + ICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAiZGlzY291 + bnQiOiBudWxsLAogICJlbmRlZF9hdCI6IG51bGwsCiAgIm1ldGFkYXRhIjog + e30sCiAgInBsYW4iOiB7CiAgICAiaWQiOiAibWVuc3VlbC10YXJpZi1yZWR1 + aXQtc3R1ZGVudC1tb250aC0yMDE2MDQwNDE3MTgyNyIsCiAgICAib2JqZWN0 + IjogInBsYW4iLAogICAgImFtb3VudCI6IDIwMDAsCiAgICAiY3JlYXRlZCI6 + IDE0NTk3ODMxMDgsCiAgICAiY3VycmVuY3kiOiAidXNkIiwKICAgICJpbnRl + cnZhbCI6ICJtb250aCIsCiAgICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAg + ImxpdmVtb2RlIjogZmFsc2UsCiAgICAibWV0YWRhdGEiOiB7fSwKICAgICJu + YW1lIjogIk1lbnN1ZWwgdGFyaWYgcsOpZHVpdCAtIMOpdHVkaWFudCwgLSBk + ZSAyNSBhbnMsIGVuc2VpZ25hbnQsIGRlbWFuZGV1ciBkJ2VtcGxvaSAtIG1v + bnRoIiwKICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAi + dHJpYWxfcGVyaW9kX2RheXMiOiBudWxsCiAgfSwKICAicXVhbnRpdHkiOiAx + LAogICJzdGFydCI6IDE0NjAwMjE2NjUsCiAgInN0YXR1cyI6ICJhY3RpdmUi + LAogICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgInRyaWFsX2VuZCI6IG51bGws + CiAgInRyaWFsX3N0YXJ0IjogbnVsbAp9Cg== + http_version: + recorded_at: Thu, 07 Apr 2016 09:34:26 GMT +- request: + method: get + uri: https://api.stripe.com/v1/invoices?customer=cus_8Di1wjdVktv5kt&limit=1 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 09:34:27 GMT + Content-Type: + - application/json + Content-Length: + - '2266' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E1aqh5kH5Jx71 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: ASCII-8BIT + string: !binary |- + ewogICJvYmplY3QiOiAibGlzdCIsCiAgImRhdGEiOiBbCiAgICB7CiAgICAg + ICJpZCI6ICJpbl8xN3haV3Yyc09tZjQ3Tno5UVZ5UG8zWHYiLAogICAgICAi + b2JqZWN0IjogImludm9pY2UiLAogICAgICAiYW1vdW50X2R1ZSI6IDIwMDAs + CiAgICAgICJhcHBsaWNhdGlvbl9mZWUiOiBudWxsLAogICAgICAiYXR0ZW1w + dF9jb3VudCI6IDEsCiAgICAgICJhdHRlbXB0ZWQiOiB0cnVlLAogICAgICAi + Y2hhcmdlIjogImNoXzE3eFpXdjJzT21mNDdOejlFOWtIUTV5OCIsCiAgICAg + ICJjbG9zZWQiOiB0cnVlLAogICAgICAiY3VycmVuY3kiOiAidXNkIiwKICAg + ICAgImN1c3RvbWVyIjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAgICJk + YXRlIjogMTQ2MDAyMTY2NSwKICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwK + ICAgICAgImRpc2NvdW50IjogbnVsbCwKICAgICAgImVuZGluZ19iYWxhbmNl + IjogMCwKICAgICAgImZvcmdpdmVuIjogZmFsc2UsCiAgICAgICJsaW5lcyI6 + IHsKICAgICAgICAib2JqZWN0IjogImxpc3QiLAogICAgICAgICJkYXRhIjog + WwogICAgICAgICAgewogICAgICAgICAgICAiaWQiOiAic3ViXzhFMWFma1RC + bjJkYzFEIiwKICAgICAgICAgICAgIm9iamVjdCI6ICJsaW5lX2l0ZW0iLAog + ICAgICAgICAgICAiYW1vdW50IjogMjAwMCwKICAgICAgICAgICAgImN1cnJl + bmN5IjogInVzZCIsCiAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6IG51bGws + CiAgICAgICAgICAgICJkaXNjb3VudGFibGUiOiB0cnVlLAogICAgICAgICAg + ICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICAgICAgICAgIm1ldGFkYXRhIjog + e30sCiAgICAgICAgICAgICJwZXJpb2QiOiB7CiAgICAgICAgICAgICAgInN0 + YXJ0IjogMTQ2MDAyMTY2NSwKICAgICAgICAgICAgICAiZW5kIjogMTQ2MjYx + MzY2NQogICAgICAgICAgICB9LAogICAgICAgICAgICAicGxhbiI6IHsKICAg + ICAgICAgICAgICAiaWQiOiAibWVuc3VlbC10YXJpZi1yZWR1aXQtc3R1ZGVu + dC1tb250aC0yMDE2MDQwNDE3MTgyNyIsCiAgICAgICAgICAgICAgIm9iamVj + dCI6ICJwbGFuIiwKICAgICAgICAgICAgICAiYW1vdW50IjogMjAwMCwKICAg + ICAgICAgICAgICAiY3JlYXRlZCI6IDE0NTk3ODMxMDgsCiAgICAgICAgICAg + ICAgImN1cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAgICAgImludGVydmFs + IjogIm1vbnRoIiwKICAgICAgICAgICAgICAiaW50ZXJ2YWxfY291bnQiOiAx + LAogICAgICAgICAgICAgICJsaXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAg + ICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICAgICAgICJuYW1lIjogIk1l + bnN1ZWwgdGFyaWYgcsOpZHVpdCAtIMOpdHVkaWFudCwgLSBkZSAyNSBhbnMs + IGVuc2VpZ25hbnQsIGRlbWFuZGV1ciBkJ2VtcGxvaSAtIG1vbnRoIiwKICAg + ICAgICAgICAgICAic3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAogICAg + ICAgICAgICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwKICAgICAgICAg + ICAgfSwKICAgICAgICAgICAgInByb3JhdGlvbiI6IGZhbHNlLAogICAgICAg + ICAgICAicXVhbnRpdHkiOiAxLAogICAgICAgICAgICAic3Vic2NyaXB0aW9u + IjogbnVsbCwKICAgICAgICAgICAgInR5cGUiOiAic3Vic2NyaXB0aW9uIgog + ICAgICAgICAgfQogICAgICAgIF0sCiAgICAgICAgImhhc19tb3JlIjogZmFs + c2UsCiAgICAgICAgInRvdGFsX2NvdW50IjogMSwKICAgICAgICAidXJsIjog + Ii92MS9pbnZvaWNlcy9pbl8xN3haV3Yyc09tZjQ3Tno5UVZ5UG8zWHYvbGlu + ZXMiCiAgICAgIH0sCiAgICAgICJsaXZlbW9kZSI6IGZhbHNlLAogICAgICAi + bWV0YWRhdGEiOiB7fSwKICAgICAgIm5leHRfcGF5bWVudF9hdHRlbXB0Ijog + bnVsbCwKICAgICAgInBhaWQiOiB0cnVlLAogICAgICAicGVyaW9kX2VuZCI6 + IDE0NjAwMjE2NjUsCiAgICAgICJwZXJpb2Rfc3RhcnQiOiAxNDU5OTQ4OTY4 + LAogICAgICAicmVjZWlwdF9udW1iZXIiOiBudWxsLAogICAgICAic3RhcnRp + bmdfYmFsYW5jZSI6IDAsCiAgICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6 + IG51bGwsCiAgICAgICJzdWJzY3JpcHRpb24iOiAic3ViXzhFMWFma1RCbjJk + YzFEIiwKICAgICAgInN1YnRvdGFsIjogMjAwMCwKICAgICAgInRheCI6IG51 + bGwsCiAgICAgICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgICAgICJ0b3RhbCI6 + IDIwMDAsCiAgICAgICJ3ZWJob29rc19kZWxpdmVyZWRfYXQiOiAxNDYwMDIx + NjY1CiAgICB9CiAgXSwKICAiaGFzX21vcmUiOiB0cnVlLAogICJ1cmwiOiAi + L3YxL2ludm9pY2VzIgp9Cg== + http_version: + recorded_at: Thu, 07 Apr 2016 09:34:27 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 09:34:28 GMT + Content-Type: + - application/json + Content-Length: + - '5566' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E1a2ZYS5iN1tJ + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJvYmplY3QiOiAi + Y3VzdG9tZXIiLAogICJhY2NvdW50X2JhbGFuY2UiOiAwLAogICJjcmVhdGVk + IjogMTQ1OTk0ODg4OCwKICAiY3VycmVuY3kiOiAidXNkIiwKICAiZGVmYXVs + dF9zb3VyY2UiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1M0EiLAog + ICJkZWxpbnF1ZW50IjogZmFsc2UsCiAgImRlc2NyaXB0aW9uIjogIkplYW4g + RHVwb25kIiwKICAiZGlzY291bnQiOiBudWxsLAogICJlbWFpbCI6ICJqZWFu + LmR1cG9uZEBnbWFpbC5jb20iLAogICJsaXZlbW9kZSI6IGZhbHNlLAogICJt + ZXRhZGF0YSI6IHt9LAogICJzaGlwcGluZyI6IG51bGwsCiAgInNvdXJjZXMi + OiB7CiAgICAib2JqZWN0IjogImxpc3QiLAogICAgImRhdGEiOiBbCiAgICAg + IHsKICAgICAgICAiaWQiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1 + M0EiLAogICAgICAgICJvYmplY3QiOiAiY2FyZCIsCiAgICAgICAgImFkZHJl + c3NfY2l0eSI6IG51bGwsCiAgICAgICAgImFkZHJlc3NfY291bnRyeSI6IG51 + bGwsCiAgICAgICAgImFkZHJlc3NfbGluZTEiOiBudWxsLAogICAgICAgICJh + ZGRyZXNzX2xpbmUxX2NoZWNrIjogbnVsbCwKICAgICAgICAiYWRkcmVzc19s + aW5lMiI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nfc3RhdGUiOiBudWxsLAog + ICAgICAgICJhZGRyZXNzX3ppcCI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nf + emlwX2NoZWNrIjogbnVsbCwKICAgICAgICAiYnJhbmQiOiAiVmlzYSIsCiAg + ICAgICAgImNvdW50cnkiOiAiVVMiLAogICAgICAgICJjdXN0b21lciI6ICJj + dXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJjdmNfY2hlY2siOiAicGFz + cyIsCiAgICAgICAgImR5bmFtaWNfbGFzdDQiOiBudWxsLAogICAgICAgICJl + eHBfbW9udGgiOiA0LAogICAgICAgICJleHBfeWVhciI6IDIwMTcsCiAgICAg + ICAgImZpbmdlcnByaW50IjogIm81Mmp5YlI3Ym5tTm42QVQiLAogICAgICAg + ICJmdW5kaW5nIjogImNyZWRpdCIsCiAgICAgICAgImxhc3Q0IjogIjQyNDIi + LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJuYW1lIjogbnVs + bCwKICAgICAgICAidG9rZW5pemF0aW9uX21ldGhvZCI6IG51bGwKICAgICAg + fQogICAgXSwKICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRvdGFsX2Nv + dW50IjogMSwKICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNfOERpMXdq + ZFZrdHY1a3Qvc291cmNlcyIKICB9LAogICJzdWJzY3JpcHRpb25zIjogewog + ICAgIm9iamVjdCI6ICJsaXN0IiwKICAgICJkYXRhIjogWwogICAgICB7CiAg + ICAgICAgImlkIjogInN1Yl84RTFhZmtUQm4yZGMxRCIsCiAgICAgICAgIm9i + amVjdCI6ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9m + ZWVfcGVyY2VudCI6IG51bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2Rf + ZW5kIjogZmFsc2UsCiAgICAgICAgImNhbmNlbGVkX2F0IjogbnVsbCwKICAg + ICAgICAiY3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjYxMzY2NSwKICAgICAg + ICAiY3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDYwMDIxNjY1LAogICAgICAg + ICJjdXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJk + aXNjb3VudCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0IjogbnVsbCwKICAg + ICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6IHsKICAgICAg + ICAgICJpZCI6ICJtZW5zdWVsLXRhcmlmLXJlZHVpdC1zdHVkZW50LW1vbnRo + LTIwMTYwNDA0MTcxODI3IiwKICAgICAgICAgICJvYmplY3QiOiAicGxhbiIs + CiAgICAgICAgICAiYW1vdW50IjogMjAwMCwKICAgICAgICAgICJjcmVhdGVk + IjogMTQ1OTc4MzEwOCwKICAgICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAog + ICAgICAgICAgImludGVydmFsIjogIm1vbnRoIiwKICAgICAgICAgICJpbnRl + cnZhbF9jb3VudCI6IDEsCiAgICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwK + ICAgICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAi + TWVuc3VlbCB0YXJpZiByw6lkdWl0IC0gw6l0dWRpYW50LCAtIGRlIDI1IGFu + cywgZW5zZWlnbmFudCwgZGVtYW5kZXVyIGQnZW1wbG9pIC0gbW9udGgiLAog + ICAgICAgICAgInN0YXRlbWVudF9kZXNjcmlwdG9yIjogbnVsbCwKICAgICAg + ICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwKICAgICAgICB9LAogICAg + ICAgICJxdWFudGl0eSI6IDEsCiAgICAgICAgInN0YXJ0IjogMTQ2MDAyMTY2 + NSwKICAgICAgICAic3RhdHVzIjogImFjdGl2ZSIsCiAgICAgICAgInRheF9w + ZXJjZW50IjogbnVsbCwKICAgICAgICAidHJpYWxfZW5kIjogbnVsbCwKICAg + ICAgICAidHJpYWxfc3RhcnQiOiBudWxsCiAgICAgIH0sCiAgICAgIHsKICAg + ICAgICAiaWQiOiAic3ViXzhEa3FCY1IxYlF2cjVHIiwKICAgICAgICAib2Jq + ZWN0IjogInN1YnNjcmlwdGlvbiIsCiAgICAgICAgImFwcGxpY2F0aW9uX2Zl + ZV9wZXJjZW50IjogbnVsbCwKICAgICAgICAiY2FuY2VsX2F0X3BlcmlvZF9l + bmQiOiB0cnVlLAogICAgICAgICJjYW5jZWxlZF9hdCI6IDE0NTk5NTkzODYs + CiAgICAgICAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI1NTEzODIsCiAg + ICAgICAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ1OTk1OTM4MiwKICAg + ICAgICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAgICAg + ICAiZGlzY291bnQiOiBudWxsLAogICAgICAgICJlbmRlZF9hdCI6IG51bGws + CiAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgInBsYW4iOiB7CiAg + ICAgICAgICAiaWQiOiAibWVuc3VlbC1zdGFuZGFyZC1tb250aC0yMDE2MDQw + NDE3MTUxOSIsCiAgICAgICAgICAib2JqZWN0IjogInBsYW4iLAogICAgICAg + ICAgImFtb3VudCI6IDMwMDAsCiAgICAgICAgICAiY3JlYXRlZCI6IDE0NTk3 + ODI5MjEsCiAgICAgICAgICAiY3VycmVuY3kiOiAidXNkIiwKICAgICAgICAg + ICJpbnRlcnZhbCI6ICJtb250aCIsCiAgICAgICAgICAiaW50ZXJ2YWxfY291 + bnQiOiAxLAogICAgICAgICAgImxpdmVtb2RlIjogZmFsc2UsCiAgICAgICAg + ICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAgICJuYW1lIjogIk1lbnN1ZWwg + LSBzdGFuZGFyZCwgYXNzb2NpYXRpb24gLSBtb250aCIsCiAgICAgICAgICAi + c3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAogICAgICAgICAgInRyaWFs + X3BlcmlvZF9kYXlzIjogbnVsbAogICAgICAgIH0sCiAgICAgICAgInF1YW50 + aXR5IjogMSwKICAgICAgICAic3RhcnQiOiAxNDU5OTU5MzgyLAogICAgICAg + ICJzdGF0dXMiOiAiYWN0aXZlIiwKICAgICAgICAidGF4X3BlcmNlbnQiOiBu + dWxsLAogICAgICAgICJ0cmlhbF9lbmQiOiBudWxsLAogICAgICAgICJ0cmlh + bF9zdGFydCI6IG51bGwKICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6 + ICJzdWJfOERpOWdxUEx3dDVJSUMiLAogICAgICAgICJvYmplY3QiOiAic3Vi + c2NyaXB0aW9uIiwKICAgICAgICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQi + OiBudWxsLAogICAgICAgICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IHRydWUs + CiAgICAgICAgImNhbmNlbGVkX2F0IjogMTQ1OTk0OTQwNCwKICAgICAgICAi + Y3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjU0MTM5OSwKICAgICAgICAiY3Vy + cmVudF9wZXJpb2Rfc3RhcnQiOiAxNDU5OTQ5Mzk5LAogICAgICAgICJjdXN0 + b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJkaXNjb3Vu + dCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0IjogbnVsbCwKICAgICAgICAi + bWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6IHsKICAgICAgICAgICJp + ZCI6ICJtZW5zdWVsLXN0YW5kYXJkLW1vbnRoLTIwMTYwNDA0MTcxNTE5IiwK + ICAgICAgICAgICJvYmplY3QiOiAicGxhbiIsCiAgICAgICAgICAiYW1vdW50 + IjogMzAwMCwKICAgICAgICAgICJjcmVhdGVkIjogMTQ1OTc4MjkyMSwKICAg + ICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAgICAgICAgImludGVydmFs + IjogIm1vbnRoIiwKICAgICAgICAgICJpbnRlcnZhbF9jb3VudCI6IDEsCiAg + ICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICAgICAgICJtZXRhZGF0 + YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAiTWVuc3VlbCAtIHN0YW5kYXJk + LCBhc3NvY2lhdGlvbiAtIG1vbnRoIiwKICAgICAgICAgICJzdGF0ZW1lbnRf + ZGVzY3JpcHRvciI6IG51bGwsCiAgICAgICAgICAidHJpYWxfcGVyaW9kX2Rh + eXMiOiBudWxsCiAgICAgICAgfSwKICAgICAgICAicXVhbnRpdHkiOiAxLAog + ICAgICAgICJzdGFydCI6IDE0NTk5NDkzOTksCiAgICAgICAgInN0YXR1cyI6 + ICJhY3RpdmUiLAogICAgICAgICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgICAg + ICAgInRyaWFsX2VuZCI6IG51bGwsCiAgICAgICAgInRyaWFsX3N0YXJ0Ijog + bnVsbAogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogInN1Yl84RGky + VmFkUnZyN0E5OSIsCiAgICAgICAgIm9iamVjdCI6ICJzdWJzY3JpcHRpb24i + LAogICAgICAgICJhcHBsaWNhdGlvbl9mZWVfcGVyY2VudCI6IG51bGwsCiAg + ICAgICAgImNhbmNlbF9hdF9wZXJpb2RfZW5kIjogdHJ1ZSwKICAgICAgICAi + Y2FuY2VsZWRfYXQiOiAxNDU5OTQ4OTcyLAogICAgICAgICJjdXJyZW50X3Bl + cmlvZF9lbmQiOiAxNDYyNTQwOTY4LAogICAgICAgICJjdXJyZW50X3Blcmlv + ZF9zdGFydCI6IDE0NTk5NDg5NjgsCiAgICAgICAgImN1c3RvbWVyIjogImN1 + c184RGkxd2pkVmt0djVrdCIsCiAgICAgICAgImRpc2NvdW50IjogbnVsbCwK + ICAgICAgICAiZW5kZWRfYXQiOiBudWxsLAogICAgICAgICJtZXRhZGF0YSI6 + IHt9LAogICAgICAgICJwbGFuIjogewogICAgICAgICAgImlkIjogIm1lbnN1 + ZWwtc3RhbmRhcmQtbW9udGgtMjAxNjA0MDQxNzE1MTkiLAogICAgICAgICAg + Im9iamVjdCI6ICJwbGFuIiwKICAgICAgICAgICJhbW91bnQiOiAzMDAwLAog + ICAgICAgICAgImNyZWF0ZWQiOiAxNDU5NzgyOTIxLAogICAgICAgICAgImN1 + cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAiaW50ZXJ2YWwiOiAibW9udGgi + LAogICAgICAgICAgImludGVydmFsX2NvdW50IjogMSwKICAgICAgICAgICJs + aXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAgIm1ldGFkYXRhIjoge30sCiAg + ICAgICAgICAibmFtZSI6ICJNZW5zdWVsIC0gc3RhbmRhcmQsIGFzc29jaWF0 + aW9uIC0gbW9udGgiLAogICAgICAgICAgInN0YXRlbWVudF9kZXNjcmlwdG9y + IjogbnVsbCwKICAgICAgICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwK + ICAgICAgICB9LAogICAgICAgICJxdWFudGl0eSI6IDEsCiAgICAgICAgInN0 + YXJ0IjogMTQ1OTk0ODk2OCwKICAgICAgICAic3RhdHVzIjogImFjdGl2ZSIs + CiAgICAgICAgInRheF9wZXJjZW50IjogbnVsbCwKICAgICAgICAidHJpYWxf + ZW5kIjogbnVsbCwKICAgICAgICAidHJpYWxfc3RhcnQiOiBudWxsCiAgICAg + IH0KICAgIF0sCiAgICAiaGFzX21vcmUiOiBmYWxzZSwKICAgICJ0b3RhbF9j + b3VudCI6IDQsCiAgICAidXJsIjogIi92MS9jdXN0b21lcnMvY3VzXzhEaTF3 + amRWa3R2NWt0L3N1YnNjcmlwdGlvbnMiCiAgfQp9Cg== + http_version: + recorded_at: Thu, 07 Apr 2016 09:34:28 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8E1afkTBn2dc1D + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 09:34:29 GMT + Content-Type: + - application/json + Content-Length: + - '880' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E1a72YcNQrLBo + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJzdWJfOEUxYWZrVEJuMmRjMUQiLAogICJvYmplY3QiOiAi + c3Vic2NyaXB0aW9uIiwKICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQiOiBu + dWxsLAogICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IGZhbHNlLAogICJjYW5j + ZWxlZF9hdCI6IG51bGwsCiAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI2 + MTM2NjUsCiAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ2MDAyMTY2NSwK + ICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAiZGlzY291 + bnQiOiBudWxsLAogICJlbmRlZF9hdCI6IG51bGwsCiAgIm1ldGFkYXRhIjog + e30sCiAgInBsYW4iOiB7CiAgICAiaWQiOiAibWVuc3VlbC10YXJpZi1yZWR1 + aXQtc3R1ZGVudC1tb250aC0yMDE2MDQwNDE3MTgyNyIsCiAgICAib2JqZWN0 + IjogInBsYW4iLAogICAgImFtb3VudCI6IDIwMDAsCiAgICAiY3JlYXRlZCI6 + IDE0NTk3ODMxMDgsCiAgICAiY3VycmVuY3kiOiAidXNkIiwKICAgICJpbnRl + cnZhbCI6ICJtb250aCIsCiAgICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAg + ImxpdmVtb2RlIjogZmFsc2UsCiAgICAibWV0YWRhdGEiOiB7fSwKICAgICJu + YW1lIjogIk1lbnN1ZWwgdGFyaWYgcsOpZHVpdCAtIMOpdHVkaWFudCwgLSBk + ZSAyNSBhbnMsIGVuc2VpZ25hbnQsIGRlbWFuZGV1ciBkJ2VtcGxvaSAtIG1v + bnRoIiwKICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAi + dHJpYWxfcGVyaW9kX2RheXMiOiBudWxsCiAgfSwKICAicXVhbnRpdHkiOiAx + LAogICJzdGFydCI6IDE0NjAwMjE2NjUsCiAgInN0YXR1cyI6ICJhY3RpdmUi + LAogICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgInRyaWFsX2VuZCI6IG51bGws + CiAgInRyaWFsX3N0YXJ0IjogbnVsbAp9Cg== + http_version: + recorded_at: Thu, 07 Apr 2016 09:34:29 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8E1afkTBn2dc1D?at_period_end=true + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 09:34:30 GMT + Content-Type: + - application/json + Content-Length: + - '885' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E1aMVW98tCB7l + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJzdWJfOEUxYWZrVEJuMmRjMUQiLAogICJvYmplY3QiOiAi + c3Vic2NyaXB0aW9uIiwKICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQiOiBu + dWxsLAogICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IHRydWUsCiAgImNhbmNl + bGVkX2F0IjogMTQ2MDAyMTY3MCwKICAiY3VycmVudF9wZXJpb2RfZW5kIjog + MTQ2MjYxMzY2NSwKICAiY3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDYwMDIx + NjY1LAogICJjdXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJk + aXNjb3VudCI6IG51bGwsCiAgImVuZGVkX2F0IjogbnVsbCwKICAibWV0YWRh + dGEiOiB7fSwKICAicGxhbiI6IHsKICAgICJpZCI6ICJtZW5zdWVsLXRhcmlm + LXJlZHVpdC1zdHVkZW50LW1vbnRoLTIwMTYwNDA0MTcxODI3IiwKICAgICJv + YmplY3QiOiAicGxhbiIsCiAgICAiYW1vdW50IjogMjAwMCwKICAgICJjcmVh + dGVkIjogMTQ1OTc4MzEwOCwKICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAg + ImludGVydmFsIjogIm1vbnRoIiwKICAgICJpbnRlcnZhbF9jb3VudCI6IDEs + CiAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICJtZXRhZGF0YSI6IHt9LAog + ICAgIm5hbWUiOiAiTWVuc3VlbCB0YXJpZiByw6lkdWl0IC0gw6l0dWRpYW50 + LCAtIGRlIDI1IGFucywgZW5zZWlnbmFudCwgZGVtYW5kZXVyIGQnZW1wbG9p + IC0gbW9udGgiLAogICAgInN0YXRlbWVudF9kZXNjcmlwdG9yIjogbnVsbCwK + ICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwKICB9LAogICJxdWFudGl0 + eSI6IDEsCiAgInN0YXJ0IjogMTQ2MDAyMTY2NSwKICAic3RhdHVzIjogImFj + dGl2ZSIsCiAgInRheF9wZXJjZW50IjogbnVsbCwKICAidHJpYWxfZW5kIjog + bnVsbCwKICAidHJpYWxfc3RhcnQiOiBudWxsCn0K + http_version: + recorded_at: Thu, 07 Apr 2016 09:34:30 GMT +recorded_with: VCR 3.0.1 From 823b4c5e1d5603011287359a3b3e66ccd16cc697 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 12:57:08 +0200 Subject: [PATCH 30/64] updates users_credits module and manager and adds tests --- app/services/users_credits/manager.rb | 136 ++++++++++++++++ app/services/users_credits_manager.rb | 82 ---------- test/services/users_credits_manager_test.rb | 162 ++++++++++++++++++++ 3 files changed, 298 insertions(+), 82 deletions(-) create mode 100644 app/services/users_credits/manager.rb delete mode 100644 app/services/users_credits_manager.rb create mode 100644 test/services/users_credits_manager_test.rb diff --git a/app/services/users_credits/manager.rb b/app/services/users_credits/manager.rb new file mode 100644 index 000000000..451b825ab --- /dev/null +++ b/app/services/users_credits/manager.rb @@ -0,0 +1,136 @@ +require 'forwardable' + +module UsersCredits + class AlreadyUpdatedError < StandardError;end; + + class Manager + extend Forwardable + attr_reader :manager + + def initialize(reservation: nil, user: nil) + if user + @manager = Managers::User.new(user) + elsif reservation + if reservation.reservable_type == "Training" + @manager = Managers::Training.new(reservation) + elsif reservation.reservable_type == "Machine" + @manager = Managers::Machine.new(reservation) + end + end + end + + def_delegators :@manager, :will_use_credits?, :free_hours_count, :update_credits, :reset_credits + end + + module Managers + class User + attr_reader :user + + def initialize(user) + @user = user + end + + def reset_credits + user.users_credits.destroy_all + end + end + + class Reservation + attr_reader :reservation + + def initialize(reservation) + @reservation = reservation + @already_updated = false + end + + def plan + user.subscribed_plan + end + + def user + reservation.user + end + + def update_credits + if @already_updated + raise AlreadyUpdatedError, "update credit is not idempotent ! you can't invoke update_credits method twice." + else + @already_updated = true + end + end + end + private_constant :Reservation + + + class Machine < Reservation + def will_use_credits? + _will_use_credits?[0] + end + + def free_hours_count + _will_use_credits?[1] + end + + def update_credits + super + + will_use_credits, free_hours_count, machine_credit = _will_use_credits? + if will_use_credits + users_credit = user.users_credits.find_or_initialize_by(credit_id: machine_credit.id) + + if users_credit.new_record? + users_credit.hours_used = free_hours_count + else + users_credit.hours_used += free_hours_count + end + users_credit.save! + end + end + + private + def _will_use_credits? + if machine_credit = plan.machine_credits.find_by(creditable_id: reservation.reservable_id) + users_credit = user.users_credits.find_by(credit_id: machine_credit.id) + already_used_hours = users_credit ? users_credit.hours_used : 0 + + remaining_hours = machine_credit.hours - already_used_hours + + free_hours_count = [remaining_hours, reservation.slots.size].min + + if free_hours_count > 0 + return true, free_hours_count, machine_credit + else + return false, free_hours_count, machine_credit + end + end + return false, 0 + end + end + + class Training < Reservation + def will_use_credits? + _will_use_credits?[0] + end + + def update_credits + super + will_use_credits, training_credit = _will_use_credits? + if will_use_credits + user.credits << training_credit # we create a new UsersCredit object + end + end + + private + def _will_use_credits? + # if there is a training_credit defined for this plan and this training + if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id) + # if user has not used all the plan credits + if user.training_credits.count < plan.training_credit_nb + return true, training_credit + end + end + return false, nil + end + end + end +end diff --git a/app/services/users_credits_manager.rb b/app/services/users_credits_manager.rb deleted file mode 100644 index 76f228417..000000000 --- a/app/services/users_credits_manager.rb +++ /dev/null @@ -1,82 +0,0 @@ -class UsersCreditsManager - attr_reader :manager - - def initialize(reservation) - if reservation.reservable_type == "Training" - @manager = Training.new(reservation) - elsif reservation.reservable_type == "Machine" - @manager = Machine.new(reservation) - end - end - - class Machine < Manager - def will_use_credits? - end - - def credited_hours_number - end - - def update - super - end - - private - def _will_use_credits? - end - end - - class Training < Manager - def will_use_credits? - _will_use_credits?[0] - end - - def update - super - will_use_credits, training_credit = _will_use_credits? - if will_use_credits - user.credits << training_credit # we create a new UsersCredit object - end - end - - private - def _will_use_credits? - # if there is a training_credit defined for this plan and this training - if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id) - # if user has not used all the plan credits - if user.training_credits.count < plan.training_credit_nb - return true, training_credit - end - end - return false, nil - end - end - - private - class Manager - attr_reader :reservation - - def initialize(reservation) - @reservation = reservation - @already_updated = false - end - - def plan - user.subscribed_plan - end - - def user - reservation.user - end - - def update - if @already_updated - raise AlreadyUpdated, "update credit is not idempotent ! do not try to update twice." - else - @already_updated = true - end - end - end - - class AlreadyUpdated < StandardError - end -end diff --git a/test/services/users_credits_manager_test.rb b/test/services/users_credits_manager_test.rb new file mode 100644 index 000000000..aa69eab83 --- /dev/null +++ b/test/services/users_credits_manager_test.rb @@ -0,0 +1,162 @@ +require 'test_helper' + +class UsersCreditsManagerTest < ActiveSupport::TestCase + setup do + @machine = Machine.find(6) + @training = Training.find(2) + @plan = Plan.find(3) + @user = User.joins(:subscriptions).find_by(subscriptions: { plan: @plan }) + @availability = @machine.availabilities.first + @reservation_machine = Reservation.new(user: @user, reservable: @machine) + @reservation_training = Reservation.new(user: @user, reservable: @training) + end + + ## context machine reservation + + test "machine reservation without credit associated" do + Credit.where(creditable: @machine).destroy_all + + @reservation_machine.assign_attributes(slots_attributes: [{ + start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id + }]) + manager = UsersCredits::Manager.new(reservation: @reservation_machine) + + assert_equal false, manager.will_use_credits? + assert_equal 0, manager.free_hours_count + + assert_no_difference 'UsersCredit.count' do + manager.update_credits + end + + assert_raise UsersCredits::AlreadyUpdatedError do + manager.update_credits + end + end + + test "machine reservation with credit associated and user never used his credit" do + credit = Credit.find_by!(creditable: @machine, plan: @plan) + credit.update!(hours: 2) + @user.users_credits.destroy_all + + @reservation_machine.assign_attributes(slots_attributes: [{ + start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id + }]) + manager = UsersCredits::Manager.new(reservation: @reservation_machine) + + assert_equal true, manager.will_use_credits? + assert_equal 1, manager.free_hours_count + + assert_difference 'UsersCredit.count' do + manager.update_credits + end + + assert_raise UsersCredits::AlreadyUpdatedError do + manager.update_credits + end + end + + test "machine reservation with credit associated and user already used partially his credit" do + credit = Credit.find_by!(creditable: @machine, plan: @plan) + credit.update!(hours: 2) + users_credit = @user.users_credits.create!(credit: credit, hours_used: 1) + + @reservation_machine.assign_attributes(slots_attributes: [ + { start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id }, + { start_at: @availability.start_at + 1.hour, end_at: @availability.start_at + 2.hour, availability_id: @availability.id } + ]) + + manager = UsersCredits::Manager.new(reservation: @reservation_machine) + + assert_equal true, manager.will_use_credits? + assert_equal 1, manager.free_hours_count + + assert_no_difference 'UsersCredit.count' do + manager.update_credits + end + + users_credit.reload + assert_equal 2, users_credit.hours_used + end + + test "machine reservation with credit associated and user already used all credit" do + credit = Credit.find_by!(creditable: @machine, plan: @plan) + users_credit = @user.users_credits.create!(credit: credit, hours_used: 1) + + @reservation_machine.assign_attributes(slots_attributes: [ + { start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id }, + { start_at: @availability.start_at + 1.hour, end_at: @availability.start_at + 2.hour, availability_id: @availability.id } + ]) + manager = UsersCredits::Manager.new(reservation: @reservation_machine) + + assert_equal false, manager.will_use_credits? + assert_equal 0, manager.free_hours_count + + assert_no_difference 'UsersCredit.count' do + manager.update_credits + end + + users_credit.reload + assert_equal 1, users_credit.hours_used + end + + # context training reservation + + test "training reservation without credit associated" do + Credit.where(creditable: @training).destroy_all + + manager = UsersCredits::Manager.new(reservation: @reservation_training) + + assert_equal false, manager.will_use_credits? + + assert_no_difference 'UsersCredit.count' do + manager.update_credits + end + + assert_raise UsersCredits::AlreadyUpdatedError do + manager.update_credits + end + end + + test "training reservation with credit associated and user didnt use his credit yet" do + credit = Credit.find_or_create_by!(creditable: @training, plan: @plan) + @user.users_credits.destroy_all + + manager = UsersCredits::Manager.new(reservation: @reservation_training) + + assert_equal true, manager.will_use_credits? + + assert_difference 'UsersCredit.count' do + manager.update_credits + end + end + + test "training reservation with credit associated but user already used all his credits" do + @user.users_credits.destroy_all + another_training = Training.where.not(id: @training.id).first + credit = Credit.find_or_create_by!(creditable: another_training, plan: @plan) + @user.users_credits.find_or_create_by!(credit: credit) + @plan.update(training_credit_nb: 1) + + manager = UsersCredits::Manager.new(reservation: @reservation_training) + + assert_equal false, manager.will_use_credits? + + assert_no_difference 'UsersCredit.count' do + manager.update_credits + end + end + + # context reset user credits + + test "use UsersCredit::Manager to reset users_credits" do + credit = Credit.find_by!(creditable: @machine, plan: @plan) + users_credit = @user.users_credits.create!(credit: credit, hours_used: 1) + + assert_not_empty @user.users_credits + + manager = UsersCredits::Manager.new(user: @user) + manager.reset_credits + + assert_empty @user.users_credits.reload + end +end From 2ab8d04a689d51fb36e7b211001933465bdd9d2d Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 16:00:12 +0200 Subject: [PATCH 31/64] adds comment to model invoice_item --- app/models/invoice_item.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/invoice_item.rb b/app/models/invoice_item.rb index 68c8193f8..23eeeeaa6 100644 --- a/app/models/invoice_item.rb +++ b/app/models/invoice_item.rb @@ -2,5 +2,5 @@ class InvoiceItem < ActiveRecord::Base belongs_to :invoice belongs_to :subscription - has_one :invoice_item + has_one :invoice_item # to associated invoice_items of an invoice to invoice_items of an avoir end From 02b56ed6a7b8ebd07b3ccb4471f87175e1652d33 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 16:01:31 +0200 Subject: [PATCH 32/64] users_credits/manager service, handle the case if user does not have a plan --- app/services/users_credits/manager.rb | 4 +++ test/services/users_credits_manager_test.rb | 28 +++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/app/services/users_credits/manager.rb b/app/services/users_credits/manager.rb index 451b825ab..35a1d2dca 100644 --- a/app/services/users_credits/manager.rb +++ b/app/services/users_credits/manager.rb @@ -89,6 +89,8 @@ module UsersCredits private def _will_use_credits? + return false, 0 unless plan + if machine_credit = plan.machine_credits.find_by(creditable_id: reservation.reservable_id) users_credit = user.users_credits.find_by(credit_id: machine_credit.id) already_used_hours = users_credit ? users_credit.hours_used : 0 @@ -122,6 +124,8 @@ module UsersCredits private def _will_use_credits? + return false, nil unless plan + # if there is a training_credit defined for this plan and this training if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id) # if user has not used all the plan credits diff --git a/test/services/users_credits_manager_test.rb b/test/services/users_credits_manager_test.rb index aa69eab83..f8a3c72c0 100644 --- a/test/services/users_credits_manager_test.rb +++ b/test/services/users_credits_manager_test.rb @@ -6,12 +6,28 @@ class UsersCreditsManagerTest < ActiveSupport::TestCase @training = Training.find(2) @plan = Plan.find(3) @user = User.joins(:subscriptions).find_by(subscriptions: { plan: @plan }) + @user.users_credits.destroy_all @availability = @machine.availabilities.first @reservation_machine = Reservation.new(user: @user, reservable: @machine) @reservation_training = Reservation.new(user: @user, reservable: @training) end ## context machine reservation + test "machine reservation from user without subscribed plan" do + @user.subscriptions.destroy_all + + @reservation_machine.assign_attributes(slots_attributes: [{ + start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id + }]) + manager = UsersCredits::Manager.new(reservation: @reservation_machine) + + assert_equal false, manager.will_use_credits? + assert_equal 0, manager.free_hours_count + + assert_no_difference 'UsersCredit.count' do + manager.update_credits + end + end test "machine reservation without credit associated" do Credit.where(creditable: @machine).destroy_all @@ -101,6 +117,18 @@ class UsersCreditsManagerTest < ActiveSupport::TestCase # context training reservation + test "training reservation from user without subscribed plan" do + @user.subscriptions.destroy_all + + manager = UsersCredits::Manager.new(reservation: @reservation_training) + + assert_equal false, manager.will_use_credits? + + assert_no_difference 'UsersCredit.count' do + manager.update_credits + end + end + test "training reservation without credit associated" do Credit.where(creditable: @training).destroy_all From 7748d601f82029b67469c64f4dd7254bc15c5eda Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 16:02:09 +0200 Subject: [PATCH 33/64] uses users_credits/manager service in models reservation and subscription, and adds integration tests --- app/models/reservation.rb | 114 +++------- app/models/subscription.rb | 10 +- .../reservations/create_as_admin_test.rb | 199 +++++++++++++++++- test/integration/reservations/create_test.rb | 26 +++ 4 files changed, 246 insertions(+), 103 deletions(-) diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 48b93ad8f..04e493c37 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -45,68 +45,36 @@ class Reservation < ActiveRecord::Base # === Machine reservation === when Machine base_amount = reservable.prices.find_by(group_id: user.group_id, plan_id: plan.try(:id)).amount - if plan - machine_credit = plan.machine_credits.select {|credit| credit.creditable_id == reservable_id}.first - if machine_credit - hours_available = machine_credit.hours - if !new_plan_being_bought - user_credit = user.users_credits.find_by_credit_id(machine_credit.id) - if user_credit - hours_available = machine_credit.hours - user_credit.hours_used - end - end - slots.each_with_index do |slot, index| - description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}" - ii_amount = (index < hours_available ? 0 : base_amount) - ii_amount = 0 if (slot.offered and on_site) - unless on_site - ii = Stripe::InvoiceItem.create( - customer: user.stp_customer_id, - amount: ii_amount, - currency: Rails.application.secrets.stripe_currency, - description: description - ) - invoice_items << ii - end - self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description) - end - else - slots.each do |slot| - description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}" - ii_amount = base_amount - ii_amount = 0 if (slot.offered and on_site) - unless on_site - ii = Stripe::InvoiceItem.create( - customer: user.stp_customer_id, - amount: ii_amount, - currency: Rails.application.secrets.stripe_currency, - description: description - ) - invoice_items << ii - end - self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description) - end + users_credits_manager = UsersCredits::Manager.new(reservation: self) + + slots.each_with_index do |slot, index| + description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}" + + ii_amount = base_amount # ii_amount default to base_amount + + if users_credits_manager.will_use_credits? + ii_amount = (index < users_credits_manager.free_hours_count) ? 0 : base_amount end - else - slots.each do |slot| - description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}" - ii_amount = base_amount - ii_amount = 0 if (slot.offered and on_site) - unless on_site - ii = Stripe::InvoiceItem.create( - customer: user.stp_customer_id, - amount: ii_amount, - currency: Rails.application.secrets.stripe_currency, - description: description - ) - invoice_items << ii - end - self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description) + + ii_amount = 0 if slot.offered and on_site # if it's a local payment and slot is offered free + + unless on_site # if it's local payment then do not create Stripe::InvoiceItem + ii = Stripe::InvoiceItem.create( + customer: user.stp_customer_id, + amount: ii_amount, + currency: Rails.application.secrets.stripe_currency, + description: description + ) + invoice_items << ii end + self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description) end + # === Training reservation === when Training + # TO BE REFACTORED WHEN PLAN PURCHASE AND RESERVATION PURCHASE WILL BE DECOUPLED + base_amount = reservable.amount_by_group(user.group_id).amount if plan # Return True if the subscription link a training credit for training reserved by the user @@ -176,32 +144,6 @@ class Reservation < ActiveRecord::Base invoice_items end - def update_users_credits - if user.subscribed_plan - if reservable_type == 'Machine' - machine_credit = user.subscribed_plan.machine_credits.select {|credit| credit.creditable_id == reservable_id}.first - if machine_credit - hours_available = machine_credit.hours - user_credit = user.users_credits.find_or_initialize_by(credit_id: machine_credit.id) - user_credit.hours_used ||= 0 - hours_available = machine_credit.hours - user_credit.hours_used - if hours_available >= slots.size - user_credit.hours_used = user_credit.hours_used + slots.size - else - user_credit.hours_used = machine_credit.hours - end - user_credit.save - end - elsif reservable_type == 'Training' - training_credit = user.subscribed_plan.training_credits.select {|credit| credit.creditable_id == reservable_id}.first - if user.training_credits.size < user.subscribed_plan.training_credit_nb and training_credit - user.credits << training_credit - end - end - end - return self - end - def save_with_payment build_invoice(user: user) invoice_items = generate_invoice_items @@ -286,7 +228,8 @@ class Reservation < ActiveRecord::Base end end - update_users_credits + UsersCredits::Manager.new(reservation: self).update_credits + return true end end @@ -318,7 +261,7 @@ class Reservation < ActiveRecord::Base if user.invoicing_disabled? if valid? save! - update_users_credits + UsersCredits::Manager.new(reservation: self).update_credits return true end else @@ -345,7 +288,8 @@ class Reservation < ActiveRecord::Base save! end - update_users_credits + UsersCredits::Manager.new(reservation: self).update_credits + return true end end diff --git a/app/models/subscription.rb b/app/models/subscription.rb index b41fac740..dfd0bd5e2 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -28,7 +28,7 @@ class Subscription < ActiveRecord::Base self.expired_at = Time.at(new_subscription.current_period_end) save! - reset_users_credits if expired_date_changed + UsersCredits::Manager.new(user: self.user).reset_credits if expired_date_changed # generate invoice stp_invoice = Stripe::Invoice.all(customer: user.stp_customer_id, limit: 1).data.first @@ -77,7 +77,7 @@ class Subscription < ActiveRecord::Base self.canceled_at = nil set_expired_at save! - reset_users_credits if expired_date_changed + UsersCredits::Manager.new(user: self.user).reset_credits if expired_date_changed generate_invoice.save if invoice return true else @@ -140,7 +140,7 @@ class Subscription < ActiveRecord::Base self.expired_at = expired_at if save - reset_users_credits if !free_days + UsersCredits::Manager.new(user: self.user).reset_credits if !free_days notify_subscription_extended(free_days) return true end @@ -215,10 +215,6 @@ class Subscription < ActiveRecord::Base p_value.to_date != expired_at.to_date and expired_at > p_value end - def reset_users_credits - user.users_credits.destroy_all - end - # def is_being_extended? # !expired_at_was.nil? and expired_at_changed? # end diff --git a/test/integration/reservations/create_as_admin_test.rb b/test/integration/reservations/create_as_admin_test.rb index 5d40a3d6b..6383c93fd 100644 --- a/test/integration/reservations/create_as_admin_test.rb +++ b/test/integration/reservations/create_as_admin_test.rb @@ -1,11 +1,188 @@ -# class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest -# setup do -# admin = User.with_role(:admin).first -# login_as(admin, scope: :user) -# end -# -# test "admin reserves a machine for a user" do -# availability = Availability.find(5) -# -# end -# end +module Reservations + class CreateAsAdminTest < ActionDispatch::IntegrationTest + setup do + @user_without_subscription = User.with_role(:member).without_subscription.first + @user_with_subscription = User.with_role(:member).with_subscription.second + @admin = User.with_role(:admin).first + login_as(@admin, scope: :user) + end + + test "user without subscription reserves a machine with success" do + machine = Machine.find(6) + availability = machine.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + users_credit_count = UsersCredit.count + + post reservations_path, { reservation: { + user_id: @user_without_subscription.id, + reservable_id: machine.id, + reservable_type: machine.class.name, + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count + 1, Invoice.count + assert_equal invoice_items_count + 1, InvoiceItem.count + assert_equal users_credit_count, UsersCredit.count + + # reservation assertions + reservation = Reservation.last + + assert reservation.invoice + assert reservation.stp_invoice_id.blank? + assert_equal 1, reservation.invoice.invoice_items.count + + # invoice assertions + invoice = reservation.invoice + + assert invoice.stp_invoice_id.blank? + refute invoice.total.blank? + + # invoice_items assertions + invoice_item = InvoiceItem.last + + refute invoice_item.stp_invoice_item_id + assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id).amount + + # invoice assertions + invoice = Invoice.find_by(invoiced: reservation) + assert invoice + assert File.exist?(invoice.file) + + # notification + assert_not_empty Notification.where(attached_object: reservation) + end + + test "user without subscription reserves a training with success" do + training = Training.first + availability = training.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + + post reservations_path, { reservation: { + user_id: @user_without_subscription.id, + reservable_id: training.id, + reservable_type: training.class.name, + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count + 1, Invoice.count + assert_equal invoice_items_count + 1, InvoiceItem.count + + # reservation assertions + reservation = Reservation.last + + assert reservation.invoice + assert reservation.stp_invoice_id.blank? + assert_equal 1, reservation.invoice.invoice_items.count + + # invoice assertions + invoice = reservation.invoice + + assert invoice.stp_invoice_id.blank? + refute invoice.total.blank? + # invoice_items + invoice_item = InvoiceItem.last + + refute invoice_item.stp_invoice_item_id + assert_equal invoice_item.amount, training.amount_by_group(@user_without_subscription.group_id).amount + + # invoice assertions + invoice = Invoice.find_by(invoiced: reservation) + assert invoice + assert File.exist?(invoice.file) + + # notification + assert_not_empty Notification.where(attached_object: reservation) + end + + test "user with subscription reserves a machine with success" do + plan = @user_with_subscription.subscribed_plan + machine = Machine.find(6) + availability = machine.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + users_credit_count = UsersCredit.count + + post reservations_path, { reservation: { + user_id: @user_with_subscription.id, + reservable_id: machine.id, + reservable_type: machine.class.name, + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + }, + { start_at: (availability.start_at + 1.hour).to_s(:iso8601), + end_at: (availability.start_at + 2.hours).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count + 1, Invoice.count + assert_equal invoice_items_count + 2, InvoiceItem.count + assert_equal users_credit_count + 1, UsersCredit.count + + # reservation assertions + reservation = Reservation.last + + assert reservation.invoice + assert reservation.stp_invoice_id.blank? + assert_equal 2, reservation.invoice.invoice_items.count + + # invoice assertions + invoice = reservation.invoice + + assert invoice.stp_invoice_id.blank? + refute invoice.total.blank? + + # invoice_items assertions + invoice_items = InvoiceItem.last(2) + machine_price = machine.prices.find_by(group_id: @user_with_subscription.group_id, plan_id: plan.id).amount + + assert invoice_items.any? { |invoice| invoice.amount == 0 } + assert invoice_items.any? { |invoice| invoice.amount == machine_price } + assert invoice_items.all? { |invoice| invoice.stp_invoice_item_id.blank? } + + # users_credits assertions + users_credit = UsersCredit.last + + assert_equal @user_with_subscription, users_credit.user + assert_equal [reservation.slots.count, plan.machine_credits.find_by(creditable_id: machine.id).hours].min, users_credit.hours_used + + # invoice assertions + invoice = Invoice.find_by(invoiced: reservation) + assert invoice + assert File.exist?(invoice.file) + + # notification + assert_not_empty Notification.where(attached_object: reservation) + end + end +end diff --git a/test/integration/reservations/create_test.rb b/test/integration/reservations/create_test.rb index e1a5f0a97..e3c6dd29c 100644 --- a/test/integration/reservations/create_test.rb +++ b/test/integration/reservations/create_test.rb @@ -56,6 +56,14 @@ module Reservations assert invoice_item.stp_invoice_item_id assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id).amount + + # invoice assertions + invoice = Invoice.find_by(invoiced: reservation) + assert invoice + assert File.exist?(invoice.file) + + # notification + assert_not_empty Notification.where(attached_object: reservation) end test "user without subscription reserves a machine with error" do @@ -67,6 +75,7 @@ module Reservations reservations_count = Reservation.count invoice_count = Invoice.count invoice_items_count = InvoiceItem.count + notifications_count = Notification.count VCR.use_cassette("reservations_create_for_machine_without_subscription_error") do post reservations_path, { reservation: { @@ -88,6 +97,7 @@ module Reservations assert_equal reservations_count, Reservation.count assert_equal invoice_count, Invoice.count assert_equal invoice_items_count, InvoiceItem.count + assert_equal notifications_count, Notification.count end test "user without subscription reserves a training with success" do @@ -138,6 +148,14 @@ module Reservations assert invoice_item.stp_invoice_item_id assert_equal invoice_item.amount, training.amount_by_group(@user_without_subscription.group_id).amount + + # invoice assertions + invoice = Invoice.find_by(invoiced: reservation) + assert invoice + assert File.exist?(invoice.file) + + # notification + assert_not_empty Notification.where(attached_object: reservation) end test "user with subscription reserves a machine with success" do @@ -204,6 +222,14 @@ module Reservations assert_equal @user_with_subscription, users_credit.user assert_equal [reservation.slots.count, plan.machine_credits.find_by(creditable_id: machine.id).hours].min, users_credit.hours_used + + # invoice assertions + invoice = Invoice.find_by(invoiced: reservation) + assert invoice + assert File.exist?(invoice.file) + + # notification + assert_not_empty Notification.where(attached_object: reservation) end end end From e0dca6c74473630a75bf23b396c05aa15352d752 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 7 Apr 2016 17:46:23 +0200 Subject: [PATCH 34/64] [ongoing] renew subscription test --- test/fixtures/availabilities.yml | 32 +- test/fixtures/credits.yml | 13 +- test/fixtures/invoice_items.yml | 30 +- test/fixtures/invoices.yml | 61 +- test/fixtures/machines.yml | 4 +- test/fixtures/plans.yml | 16 +- test/fixtures/profiles.yml | 21 +- test/fixtures/reservations.yml | 12 + test/fixtures/slots.yml | 13 + test/fixtures/subscriptions.yml | 15 +- test/fixtures/trainings.yml | 24 +- test/fixtures/users.yml | 48 +- test/fixtures/users_credits.yml | 8 + .../subscriptions/create_as_admin_test.rb | 90 +- .../subscriptions/create_as_user_test.rb | 7 +- .../subscriptions/renew_as_user_test.rb | 83 ++ test/test_helper.rb | 4 +- .../subscriptions_user_renew_failed.yml | 246 +++++ .../subscriptions_user_renew_success.yml | 894 ++++++++++++++++++ 19 files changed, 1508 insertions(+), 113 deletions(-) create mode 100644 test/integration/subscriptions/renew_as_user_test.rb create mode 100644 test/vcr_cassettes/subscriptions_user_renew_failed.yml create mode 100644 test/vcr_cassettes/subscriptions_user_renew_success.yml diff --git a/test/fixtures/availabilities.yml b/test/fixtures/availabilities.yml index e1ba699de..7e3e00131 100644 --- a/test/fixtures/availabilities.yml +++ b/test/fixtures/availabilities.yml @@ -6,7 +6,7 @@ availability_1: available_type: training created_at: 2016-04-04 15:24:01.517486000 Z updated_at: 2016-04-04 15:24:01.517486000 Z - nb_total_places: + nb_total_places: destroying: false availability_2: @@ -16,7 +16,7 @@ availability_2: available_type: training created_at: 2016-04-04 15:24:09.169364000 Z updated_at: 2016-04-04 15:24:09.169364000 Z - nb_total_places: + nb_total_places: destroying: false availability_3: @@ -26,7 +26,7 @@ availability_3: available_type: machines created_at: 2016-04-04 15:24:27.587583000 Z updated_at: 2016-04-04 15:24:27.587583000 Z - nb_total_places: + nb_total_places: destroying: false availability_4: @@ -36,7 +36,7 @@ availability_4: available_type: machines created_at: 2016-04-04 15:24:44.044908000 Z updated_at: 2016-04-04 15:24:44.044908000 Z - nb_total_places: + nb_total_places: destroying: false availability_5: @@ -46,7 +46,7 @@ availability_5: available_type: machines created_at: 2016-04-04 15:25:48.584444000 Z updated_at: 2016-04-04 15:25:48.584444000 Z - nb_total_places: + nb_total_places: destroying: false availability_6: @@ -56,7 +56,7 @@ availability_6: available_type: machines created_at: 2016-04-04 15:26:17.953216000 Z updated_at: 2016-04-04 15:26:17.953216000 Z - nb_total_places: + nb_total_places: destroying: false availability_7: @@ -66,7 +66,7 @@ availability_7: available_type: machines created_at: 2016-04-04 15:26:39.278627000 Z updated_at: 2016-04-04 15:26:39.278627000 Z - nb_total_places: + nb_total_places: destroying: false availability_8: @@ -76,7 +76,7 @@ availability_8: available_type: training created_at: 2016-04-04 15:26:49.572724000 Z updated_at: 2016-04-04 15:26:49.572724000 Z - nb_total_places: + nb_total_places: destroying: false availability_9: @@ -86,7 +86,7 @@ availability_9: available_type: event created_at: 2016-04-04 15:44:02.228661000 Z updated_at: 2016-04-04 15:44:02.228661000 Z - nb_total_places: + nb_total_places: destroying: false availability_10: @@ -96,7 +96,7 @@ availability_10: available_type: event created_at: 2016-04-04 15:44:03.156629000 Z updated_at: 2016-04-04 15:44:03.156629000 Z - nb_total_places: + nb_total_places: destroying: false availability_11: @@ -106,5 +106,15 @@ availability_11: available_type: event created_at: 2016-04-04 15:44:04.023557000 Z updated_at: 2016-04-04 15:44:04.023557000 Z - nb_total_places: + nb_total_places: destroying: false + +availability_12: + id: 12 + start_at: 2012-04-11 06:00:00.000000000 Z + end_at: 2012-04-11 10:00:00.000000000 Z + available_type: training + created_at: 2012-04-04 15:24:01.517486000 Z + updated_at: 2012-04-04 15:24:01.517486000 Z + nb_total_places: + destroying: false \ No newline at end of file diff --git a/test/fixtures/credits.yml b/test/fixtures/credits.yml index 5b602a86d..c4661431a 100644 --- a/test/fixtures/credits.yml +++ b/test/fixtures/credits.yml @@ -5,8 +5,8 @@ credit_1: creditable_type: Training plan_id: 1 hours: - created_at: 2016-04-04 15:19:28.414019000 Z - updated_at: 2016-04-04 15:19:28.414019000 Z + created_at: 2001-01-01 14:11:33.852721000 Z + updated_at: 2001-01-01 14:11:33.852721000 Z credit_2: id: 2 @@ -106,3 +106,12 @@ credit_14: hours: 1 created_at: 2016-04-04 15:21:57.547939000 Z updated_at: 2016-04-04 15:21:57.547939000 Z + +credit_15: + id: 15 + creditable_id: 4 + creditable_type: Machine + plan_id: 1 + hours: 1 + created_at: 2001-01-01 14:11:33.852721000 Z + updated_at: 2001-01-01 14:11:33.852721000 Z diff --git a/test/fixtures/invoice_items.yml b/test/fixtures/invoice_items.yml index babd3946f..cc531e736 100644 --- a/test/fixtures/invoice_items.yml +++ b/test/fixtures/invoice_items.yml @@ -8,16 +8,40 @@ invoice_item_1: updated_at: 2016-04-05 08:35:52.934725000 Z description: Sleede - standard, association - month subscription_id: 1 - invoice_item_id: + invoice_item_id: invoice_item_2: id: 2 invoice_id: 2 - stp_invoice_item_id: + stp_invoice_item_id: amount: 2000 created_at: 2016-04-05 08:36:46.856021000 Z updated_at: 2016-04-05 08:36:46.856021000 Z description: Mensuel tarif réduit - étudiant, - de 25 ans, enseignant, demandeur d'emploi - month subscription_id: 2 - invoice_item_id: + invoice_item_id: + +invoice_item_3: + id: 3 + invoice_id: 3 + stp_invoice_item_id: + amount: 3000 + created_at: 2012-03-12 11:03:31.651441000 Z + updated_at: 2012-03-12 11:03:31.651441000 Z + description: Mensuel - standard, association - month + subscription_id: 3 + invoice_item_id: + + +invoice_item_4: + id: 4 + invoice_id: 4 + stp_invoice_item_id: + amount: 0 + created_at: 2012-03-12 13:40:22.342717000 Z + updated_at: 2012-03-12 13:40:22.342717000 Z + description: Formation Laser / Vinyle April 11, 2012 08:00 - 12:00 PM + subscription_id: + invoice_item_id: + diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index da9488003..ec8b24552 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -9,26 +9,61 @@ invoice_1: updated_at: 2016-04-05 08:35:52.931187000 Z user_id: 3 reference: 1604001/VL - avoir_mode: - avoir_date: - invoice_id: - type: - subscription_to_expire: - description: + avoir_mode: + avoir_date: + invoice_id: + type: + subscription_to_expire: + description: invoice_2: id: 2 invoiced_id: 2 invoiced_type: Subscription - stp_invoice_id: + stp_invoice_id: total: 2000 created_at: 2016-04-05 08:36:46.853368000 Z updated_at: 2016-04-05 08:36:46.853368000 Z user_id: 4 reference: '1604002' - avoir_mode: - avoir_date: - invoice_id: - type: - subscription_to_expire: - description: + avoir_mode: + avoir_date: + invoice_id: + type: + subscription_to_expire: + description: + +invoice_3: + id: 3 + invoiced_id: 3 + invoiced_type: Subscription + stp_invoice_id: + total: 3000 + created_at: 2012-03-12 11:03:31.651441000 Z + updated_at: 2012-03-12 11:03:31.651441000 Z + user_id: 7 + reference: '1203001' + avoir_mode: + avoir_date: + invoice_id: + type: + subscription_to_expire: + description: + + +invoice_4: + id: 4 + invoiced_id: 1 + invoiced_type: Reservation + stp_invoice_id: + total: 0 + created_at: 2012-03-12 13:40:22.342717000 Z + updated_at: 2012-03-12 13:40:22.342717000 Z + user_id: 7 + reference: '1203002' + avoir_mode: + avoir_date: + invoice_id: + type: + subscription_to_expire: + description: \ No newline at end of file diff --git a/test/fixtures/machines.yml b/test/fixtures/machines.yml index 8f5876290..527ea6ca2 100644 --- a/test/fixtures/machines.yml +++ b/test/fixtures/machines.yml @@ -64,8 +64,8 @@ machine_4: spec: "Surface maximale de travail: 210x210x220mm \r\nRésolution méchanique: 0,02 mm \r\nPrécision de position: +/- 0,05 \r\nLogiciel utilisé: Cura\r\nFormats de fichier acceptés: STL \r\nMatériaux utilisés: PLA (en stock)." - created_at: 2016-04-04 14:11:34.341810000 Z - updated_at: 2016-04-04 14:11:34.341810000 Z + created_at: 2001-01-01 14:11:34.341810000 Z + updated_at: 2001-01-01 14:11:34.341810000 Z slug: imprimante-3d machine_5: diff --git a/test/fixtures/plans.yml b/test/fixtures/plans.yml index 18a9e1379..af996e226 100644 --- a/test/fixtures/plans.yml +++ b/test/fixtures/plans.yml @@ -6,11 +6,11 @@ plan_1: interval: month group_id: 1 stp_plan_id: mensuel-standard-month-20160404171519 - created_at: 2016-04-04 15:15:19.860064000 Z - updated_at: 2016-04-04 15:19:28.367161000 Z + created_at: 2001-01-01 15:15:19.860064000 Z + updated_at: 2001-01-01 15:19:28.367161000 Z training_credit_nb: 1 - is_rolling: - description: + is_rolling: + description: type: Plan base_name: Mensuel ui_weight: 1 @@ -26,8 +26,8 @@ plan_2: created_at: 2016-04-04 15:17:24.026385000 Z updated_at: 2016-04-04 15:19:39.357636000 Z training_credit_nb: 2 - is_rolling: - description: + is_rolling: + description: type: PartnerPlan base_name: Sleede ui_weight: 5 @@ -44,8 +44,8 @@ plan_3: created_at: 2016-04-04 15:18:27.734657000 Z updated_at: 2016-04-04 15:21:35.501739000 Z training_credit_nb: 1 - is_rolling: - description: + is_rolling: + description: type: Plan base_name: Mensuel tarif réduit ui_weight: 0 diff --git a/test/fixtures/profiles.yml b/test/fixtures/profiles.yml index 96ccdb0e6..610e272d5 100644 --- a/test/fixtures/profiles.yml +++ b/test/fixtures/profiles.yml @@ -7,8 +7,8 @@ profile_1: gender: true birthday: 2016-04-04 phone: 0123456789 - interest: - software_mastered: + interest: + software_mastered: created_at: 2016-04-04 14:11:33.858015000 Z updated_at: 2016-04-04 14:11:33.858015000 Z @@ -59,8 +59,8 @@ profile_6: gender: true birthday: 2016-04-04 phone: '0000000000' - interest: - software_mastered: + interest: + software_mastered: created_at: 2016-04-04 15:17:12.535971000 Z updated_at: 2016-04-04 15:17:12.535971000 Z @@ -76,3 +76,16 @@ profile_3: software_mastered: '' created_at: 2016-04-04 15:07:46.687390000 Z updated_at: 2016-04-05 08:35:18.580745000 Z + +profile_7: + id: 7 + user_id: 7 + first_name: Lucile + last_name: Seguin + gender: false + birthday: 1969-02-03 + phone: '0241853679' + interest: + software_mastered: + created_at: 2012-03-12 11:00:21.411067000 Z + updated_at: 2016-04-07 11:00:37.643112000 Z diff --git a/test/fixtures/reservations.yml b/test/fixtures/reservations.yml index e69de29bb..45c898f07 100644 --- a/test/fixtures/reservations.yml +++ b/test/fixtures/reservations.yml @@ -0,0 +1,12 @@ + +reservation_1: + id: 1 + user_id: 7 + message: + created_at: 2012-03-12 11:03:31.651441000 Z + updated_at: 2012-03-12 11:03:31.651441000 Z + reservable_id: 2 + reservable_type: Training + stp_invoice_id: + nb_reserve_places: + nb_reserve_reduced_places: \ No newline at end of file diff --git a/test/fixtures/slots.yml b/test/fixtures/slots.yml index e69de29bb..ace3405fb 100644 --- a/test/fixtures/slots.yml +++ b/test/fixtures/slots.yml @@ -0,0 +1,13 @@ + +slot_1: + id: 1 + start_at: 2012-04-11 06:00:00.000000000 Z + end_at: 2012-04-11 10:00:00.000000000 Z + reservation_id: 12 + created_at: 2012-03-12 13:40:22.342717000 Z + updated_at: 2012-03-12 13:40:22.342717000 Z + availability_id: 1 + ex_start_at: + canceled_at: + ex_end_at: + offered: \ No newline at end of file diff --git a/test/fixtures/subscriptions.yml b/test/fixtures/subscriptions.yml index ed5e346aa..0eca46fdd 100644 --- a/test/fixtures/subscriptions.yml +++ b/test/fixtures/subscriptions.yml @@ -13,8 +13,19 @@ subscription_2: id: 2 plan_id: 3 user_id: 4 - stp_subscription_id: + stp_subscription_id: created_at: 2016-04-05 08:36:46.829879000 Z updated_at: 2016-04-05 08:36:46.829879000 Z expired_at: 2016-05-05 08:36:46.828332000 Z - canceled_at: + canceled_at: + +# subscription has expired (do not change dates) +subscription_3: + id: 3 + plan_id: 1 + user_id: 7 + stp_subscription_id: + created_at: 2012-03-12 11:03:31.651441000 Z + updated_at: 2012-03-12 11:03:31.651441000 Z + expired_at: 2012-04-12 11:03:31.648274000 Z + canceled_at: diff --git a/test/fixtures/trainings.yml b/test/fixtures/trainings.yml index 150996ec7..a25c18e82 100644 --- a/test/fixtures/trainings.yml +++ b/test/fixtures/trainings.yml @@ -4,42 +4,42 @@ training_1: name: Formation Imprimante 3D created_at: 2016-04-04 14:11:34.033464000 Z updated_at: 2016-04-04 14:11:34.033464000 Z - nb_total_places: + nb_total_places: slug: formation-imprimante-3d - description: + description: training_2: id: 2 name: Formation Laser / Vinyle - created_at: 2016-04-04 14:11:34.075249000 Z - updated_at: 2016-04-04 14:11:34.075249000 Z - nb_total_places: + created_at: 2001-01-01 14:11:33.852721000 Z + updated_at: 2001-01-01 14:11:34.075249000 Z + nb_total_places: slug: formation-laser-vinyle - description: + description: training_3: id: 3 name: Formation Petite fraiseuse numerique created_at: 2016-04-04 14:11:34.103077000 Z updated_at: 2016-04-04 14:11:34.103077000 Z - nb_total_places: + nb_total_places: slug: formation-petite-fraiseuse-numerique - description: + description: training_4: id: 4 name: Formation Shopbot Grande Fraiseuse created_at: 2016-04-04 14:11:34.132899000 Z updated_at: 2016-04-04 14:11:34.132899000 Z - nb_total_places: + nb_total_places: slug: formation-shopbot-grande-fraiseuse - description: + description: training_5: id: 5 name: Formation logiciel 2D created_at: 2016-04-04 14:11:34.152000000 Z updated_at: 2016-04-04 14:11:34.152000000 Z - nb_total_places: + nb_total_places: slug: formation-logiciel-2d - description: + description: diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 02edd418c..0984b0311 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -10,8 +10,8 @@ user_2: sign_in_count: 1 current_sign_in_at: 2016-04-04 15:00:29.439018000 Z last_sign_in_at: 2016-04-04 15:00:29.439018000 Z - current_sign_in_ip: 127.0.0.1 - last_sign_in_ip: 127.0.0.1 + current_sign_in_ip: 5.196.0.99 + last_sign_in_ip: 5.196.0.99 confirmation_token: confirmed_at: 2016-04-04 15:00:43.555678000 Z confirmation_sent_at: 2016-04-04 15:00:29.424011000 Z @@ -109,8 +109,8 @@ user_5: sign_in_count: 1 current_sign_in_at: 2016-04-04 15:34:23.343596000 Z last_sign_in_at: 2016-04-04 15:34:23.343596000 Z - current_sign_in_ip: 127.0.0.1 - last_sign_in_ip: 127.0.0.1 + current_sign_in_ip: 37.64.230.6 + last_sign_in_ip: 37.67.211.2 confirmation_token: 59cfd407491c4e1d95a9f91f81e710a62a83a6fd7171ad22823b4c4395312c4d confirmed_at: confirmation_sent_at: 2016-04-04 15:14:08.599603000 Z @@ -142,8 +142,8 @@ user_3: sign_in_count: 2 current_sign_in_at: 2016-04-05 08:35:05.676918000 Z last_sign_in_at: 2016-04-04 15:07:46.733781000 Z - current_sign_in_ip: 127.0.0.1 - last_sign_in_ip: 127.0.0.1 + current_sign_in_ip: 81.45.10.6 + last_sign_in_ip: 81.45.10.6 confirmation_token: confirmed_at: 2016-04-04 15:08:00.893381000 Z confirmation_sent_at: 2016-04-04 15:07:46.726886000 Z @@ -184,7 +184,7 @@ user_1: failed_attempts: 0 unlock_token: locked_at: - created_at: 2016-04-04 14:11:33.852719000 Z + created_at: 2001-01-01 14:11:33.852719000 Z updated_at: 2016-04-05 08:36:08.362215000 Z is_allow_contact: true group_id: 1 @@ -196,3 +196,37 @@ user_1: uid: auth_token: merged_at: + + +user_7: + id: 7 + username: lseguin + email: lucile.seguin@live.fr + encrypted_password: $2a$10$5dThoeez738sWt6sILHs7eqlOMHSa0M3GXo6VL05DPu.Kdyxl.Qdm + reset_password_token: + reset_password_sent_at: + remember_created_at: + sign_in_count: 1 + current_sign_in_at: 2016-04-07 11:00:21.779594000 Z + last_sign_in_at: 2016-04-07 11:00:21.779594000 Z + current_sign_in_ip: 37.72.235.1 + last_sign_in_ip: 37.72.199.5 + confirmation_token: + confirmed_at: 2012-03-12 11:00:37.642349000 Z + confirmation_sent_at: 2012-03-12 11:00:21.762686000 Z + unconfirmed_email: + failed_attempts: 0 + unlock_token: + locked_at: + created_at: 2012-03-12 11:00:21.411067000 Z + updated_at: 2016-04-07 11:00:37.643112000 Z + is_allow_contact: true + group_id: 1 + stp_customer_id: cus_8E2ys9zDZgetWX + slug: lseguin + is_active: true + invoicing_disabled: false + provider: + uid: + auth_token: + merged_at: diff --git a/test/fixtures/users_credits.yml b/test/fixtures/users_credits.yml index e69de29bb..e73c369af 100644 --- a/test/fixtures/users_credits.yml +++ b/test/fixtures/users_credits.yml @@ -0,0 +1,8 @@ + +users_credits_1: + id: 1 + user_id: 7 + credit_id: 1 + hours_used: + created_at: 2012-03-12 11:03:31.651441000 Z + updated_at: 2012-03-12 11:03:31.651441000 Z \ No newline at end of file diff --git a/test/integration/subscriptions/create_as_admin_test.rb b/test/integration/subscriptions/create_as_admin_test.rb index 7438977a0..e14eab456 100644 --- a/test/integration/subscriptions/create_as_admin_test.rb +++ b/test/integration/subscriptions/create_as_admin_test.rb @@ -1,57 +1,59 @@ -class CreateAsUserTest < ActionDispatch::IntegrationTest +module Subscriptions + class CreateAsAdminTest < ActionDispatch::IntegrationTest - setup do - @admin = User.find_by_username('admin') - login_as(@admin, scope: :user) - end - - test "admin takes a subscription for a user" do - user = User.find_by_username('jdupond') - plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Mensuel') - - VCR.use_cassette("subscriptions_admin_create_success") do - post '/api/subscriptions', - { - subscription: { - plan_id: plan.id, - user_id: user.id - } - }.to_json, default_headers + setup do + @admin = User.find_by_username('admin') + login_as(@admin, scope: :user) end + test "admin successfully takes a subscription for a user" do + user = User.find_by_username('jdupond') + plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Mensuel') - # Check response format & status - assert_equal 201, response.status, response.body - assert_equal Mime::JSON, response.content_type + VCR.use_cassette("subscriptions_admin_create_success") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: user.id + } + }.to_json, default_headers + end - # Check the correct plan was subscribed - subscription = json_response(response.body) - assert_equal plan.id, subscription[:plan_id], 'subscribed plan does not match' - # Check that the user has the correct subscription - assert_not_nil user.subscription, "user's subscription was not found" - assert_not_nil user.subscription.plan, "user's subscribed plan was not found" - assert_equal plan.id, user.subscription.plan_id, "user's plan does not match" + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type - # Check that the training credits were set correctly - assert_empty user.training_credits, 'training credits were not reset' - assert_equal user.subscription.plan.training_credit_nb, plan.training_credit_nb, 'trainings credits were not allocated' + # Check the correct plan was subscribed + subscription = json_response(response.body) + assert_equal plan.id, subscription[:plan_id], 'subscribed plan does not match' - # Check that the user benefit from prices of his plan - printer = Machine.find_by_slug('imprimante-3d') - assert_equal 15, (printer.prices.find_by(group_id: user.group_id, plan_id: user.subscription.plan_id).amount / 100), 'machine hourly price does not match' + # Check that the user has the correct subscription + assert_not_nil user.subscription, "user's subscription was not found" + assert_not_nil user.subscription.plan, "user's subscribed plan was not found" + assert_equal plan.id, user.subscription.plan_id, "user's plan does not match" - # Check notification was sent to the user - notification = Notification.find_by(notification_type_id: NotificationType.find_by_name('notify_member_subscribed_plan'), attached_object_type: 'Subscription', attached_object_id: subscription[:id]) - assert_not_nil notification, 'user notification was not created' - assert_equal user.id, notification.receiver_id, 'wrong user notified' + # Check that the training credits were set correctly + assert_empty user.training_credits, 'training credits were not reset' + assert_equal user.subscription.plan.training_credit_nb, plan.training_credit_nb, 'trainings credits were not allocated' + + # Check that the user benefit from prices of his plan + printer = Machine.find_by_slug('imprimante-3d') + assert_equal 15, (printer.prices.find_by(group_id: user.group_id, plan_id: user.subscription.plan_id).amount / 100), 'machine hourly price does not match' + + # Check notification was sent to the user + notification = Notification.find_by(notification_type_id: NotificationType.find_by_name('notify_member_subscribed_plan'), attached_object_type: 'Subscription', attached_object_id: subscription[:id]) + assert_not_nil notification, 'user notification was not created' + assert_equal user.id, notification.receiver_id, 'wrong user notified' + + # Check generated invoice + invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) + assert_not_nil invoice, 'Invoice was not created' + assert File.exist?(invoice.file), 'Invoice PDF was not generated' + assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' + end - # Check generated invoice - invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) - assert_not_nil invoice, 'Invoice was not created' - assert File.exist?(invoice.file), 'Invoice PDF was not generated' - assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' end - end \ No newline at end of file diff --git a/test/integration/subscriptions/create_as_user_test.rb b/test/integration/subscriptions/create_as_user_test.rb index 841e6a606..92822388c 100644 --- a/test/integration/subscriptions/create_as_user_test.rb +++ b/test/integration/subscriptions/create_as_user_test.rb @@ -1,4 +1,4 @@ -class CreateAsUserTest < ActionDispatch::IntegrationTest +class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest setup do @@ -6,7 +6,7 @@ class CreateAsUserTest < ActionDispatch::IntegrationTest login_as(@user, scope: :user) end - test 'user takes a subscription successfully' do + test 'user successfully takes a subscription' do plan = Plan.find_by(group_id: @user.group.id, type: 'Plan', base_name: 'Mensuel') VCR.use_cassette("subscriptions_user_create_success") do @@ -58,7 +58,7 @@ class CreateAsUserTest < ActionDispatch::IntegrationTest - test 'user takes a subscription with error' do + test 'user fails to take a subscription' do # get plan for wrong group plan = Plan.where.not(group_id: @user.group.id).first @@ -78,7 +78,6 @@ class CreateAsUserTest < ActionDispatch::IntegrationTest assert_equal Mime::JSON, response.content_type # Check the error was handled - subscription = json_response(response.body) assert_match /plan is not compatible/, response.body # Check that the user has no subscription diff --git a/test/integration/subscriptions/renew_as_user_test.rb b/test/integration/subscriptions/renew_as_user_test.rb new file mode 100644 index 000000000..240bbc10b --- /dev/null +++ b/test/integration/subscriptions/renew_as_user_test.rb @@ -0,0 +1,83 @@ +class Subscriptions::RenewAsUserTest < ActionDispatch::IntegrationTest + + + setup do + @user = User.find_by_username('lseguin') + login_as(@user, scope: :user) + end + + test 'user successfully renew a subscription after it has ended' do + plan = Plan.find_by(group_id: @user.group.id, type: 'Plan', base_name: 'Mensuel') + + VCR.use_cassette("subscriptions_user_renew_success") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: @user.id, + card_token: stripe_card_token + } + }.to_json, default_headers + end + + # Check response format & status + assert_equal 201, response.status, "API does not return the expected status."+response.body + assert_equal Mime::JSON, response.content_type + + # Check the correct plan was subscribed + subscription = json_response(response.body) + assert_equal plan.id, subscription[:plan_id], 'subscribed plan does not match' + + # Check that the user has the correct subscription + assert_not_nil @user.subscription, "user's subscription was not found" + assert (@user.subscription.expired_at > DateTime.now), "user's subscription expiration was not updated" + assert_in_delta 5, (DateTime.now.to_i - @user.subscription.updated_at.to_i), 10, "user's subscription was not updated recently" + + # Check that the credits were reset correctly + assert_empty @user.users_credits, 'credits were not reset' + + # Check notifications were sent for every admins + notifications = Notification.where(notification_type_id: NotificationType.find_by_name('notify_admin_subscribed_plan'), attached_object_type: 'Subscription', attached_object_id: subscription[:id]) + assert_not_empty notifications, 'no notifications were created' + notified_users_ids = notifications.map {|n| n.receiver_id } + User.admins.each do |adm| + assert_includes notified_users_ids, adm.id, "Admin #{adm.id} was not notified" + end + + # Check generated invoice + invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) + assert_not_nil invoice, 'Invoice was not created' + #FIXME assert File.exist?(invoice.file), 'Invoice PDF was not generated' + assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' + end + + + + test 'user fails to renew a subscription' do + plan = Plan.find_by(group_id: @user.group.id, type: 'Plan', base_name: 'Mensuel') + + previous_expiration = @user.subscription.expired_at.to_i + + VCR.use_cassette("subscriptions_user_renew_failed") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: @user.id, + card_token: 'invalid_card_token' + } + }.to_json, default_headers + end + + # Check response format & status + assert_equal 422, response.status, "API does not return the expected status."+response.body + assert_equal Mime::JSON, response.content_type + + # Check the error was handled + assert_match /No such token/, response.body + + # Check that the user's subscription has not changed + #FIXME assert_equal previous_expiration, @user.subscription.expired_at.to_i, "user's subscription has changed" + end + +end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 881b40e8e..c222a602b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -10,7 +10,9 @@ VCR.configure do |config| config.hook_into :webmock end -Sidekiq::Testing.inline! +Sidekiq::Testing.inline! do |pp| + puts pp +end Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new({ color: true })] diff --git a/test/vcr_cassettes/subscriptions_user_renew_failed.yml b/test/vcr_cassettes/subscriptions_user_renew_failed.yml new file mode 100644 index 000000000..5fb22c749 --- /dev/null +++ b/test/vcr_cassettes/subscriptions_user_renew_failed.yml @@ -0,0 +1,246 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:18:06 GMT + Content-Type: + - application/json + Content-Length: + - '3454' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E69echXR3qGGa + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8E2ys9zDZgetWX", + "object": "customer", + "account_balance": 0, + "created": 1460026822, + "currency": "usd", + "default_source": "card_17xdxN2sOmf47Nz9eyRuY12a", + "delinquent": false, + "description": "Lucile Seguin", + "discount": null, + "email": "lucile.seguin@live.fr", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xdxN2sOmf47Nz9eyRuY12a", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8E2ys9zDZgetWX", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8E694MZ1FBtXBg", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630683, + "current_period_start": 1460038683, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038683, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E67Z0lSjjVxBn", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630527, + "current_period_start": 1460038527, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038527, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/subscriptions" + } + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:18:06 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions + body: + encoding: UTF-8 + string: plan=mensuel-standard-month-20160404171519&card=invalid_card_token + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '66' + response: + status: + code: 400 + message: Bad Request + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:18:07 GMT + Content-Type: + - application/json + Content-Length: + - '130' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E69jMRCeshYc1 + Stripe-Version: + - '2015-10-16' + body: + encoding: UTF-8 + string: | + { + "error": { + "type": "invalid_request_error", + "message": "No such token: invalid_card_token", + "param": "card" + } + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:18:07 GMT +recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/subscriptions_user_renew_success.yml b/test/vcr_cassettes/subscriptions_user_renew_success.yml new file mode 100644 index 000000000..eb3cdfa25 --- /dev/null +++ b/test/vcr_cassettes/subscriptions_user_renew_success.yml @@ -0,0 +1,894 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:57:45 GMT + Content-Type: + - application/json + Content-Length: + - '780' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6ntokZYBap5o + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xeZp2sOmf47Nz9U7isup9R", + "object": "token", + "card": { + "id": "card_17xeZp2sOmf47Nz9Nw38pLma", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "90.52.157.226", + "created": 1460041065, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:57:45 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:57:46 GMT + Content-Type: + - application/json + Content-Length: + - '3454' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6nN7HdnY2Zr2 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8E2ys9zDZgetWX", + "object": "customer", + "account_balance": 0, + "created": 1460026822, + "currency": "usd", + "default_source": "card_17xdxN2sOmf47Nz9eyRuY12a", + "delinquent": false, + "description": "Lucile Seguin", + "discount": null, + "email": "lucile.seguin@live.fr", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xdxN2sOmf47Nz9eyRuY12a", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8E2ys9zDZgetWX", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8E694MZ1FBtXBg", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630683, + "current_period_start": 1460038683, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038683, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E67Z0lSjjVxBn", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630527, + "current_period_start": 1460038527, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038527, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 2, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/subscriptions" + } + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:57:46 GMT +- request: + method: post + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions + body: + encoding: UTF-8 + string: plan=mensuel-standard-month-20160404171519&card=tok_17xeZp2sOmf47Nz9U7isup9R + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + Content-Length: + - '76' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:57:47 GMT + Content-Type: + - application/json + Content-Length: + - '821' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6nkvdYjkxZ3A + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8E6nlabIu0FNDK", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462633067, + "current_period_start": 1460041067, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460041067, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:57:47 GMT +- request: + method: get + uri: https://api.stripe.com/v1/invoices?customer=cus_8E2ys9zDZgetWX&limit=1 + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:57:48 GMT + Content-Type: + - application/json + Content-Length: + - '2207' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6nsHStsgJ8uR + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "object": "list", + "data": [ + { + "id": "in_17xeZr2sOmf47Nz9JTOtgIXv", + "object": "invoice", + "amount_due": 3000, + "application_fee": null, + "attempt_count": 1, + "attempted": true, + "charge": "ch_17xeZr2sOmf47Nz9KgHCuwK0", + "closed": true, + "currency": "usd", + "customer": "cus_8E2ys9zDZgetWX", + "date": 1460041067, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "sub_8E6nlabIu0FNDK", + "object": "line_item", + "amount": 3000, + "currency": "usd", + "description": null, + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1460041067, + "end": 1462633067 + }, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "proration": false, + "quantity": 1, + "subscription": null, + "type": "subscription" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xeZr2sOmf47Nz9JTOtgIXv/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1460041067, + "period_start": 1460038527, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": "sub_8E6nlabIu0FNDK", + "subtotal": 3000, + "tax": null, + "tax_percent": null, + "total": 3000, + "webhooks_delivered_at": 1460041067 + } + ], + "has_more": true, + "url": "/v1/invoices" + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:57:48 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:57:49 GMT + Content-Type: + - application/json + Content-Length: + - '4474' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6nTDGRZ4k0vh + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8E2ys9zDZgetWX", + "object": "customer", + "account_balance": 0, + "created": 1460026822, + "currency": "usd", + "default_source": "card_17xeZp2sOmf47Nz9Nw38pLma", + "delinquent": false, + "description": "Lucile Seguin", + "discount": null, + "email": "lucile.seguin@live.fr", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17xeZp2sOmf47Nz9Nw38pLma", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8E2ys9zDZgetWX", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8E6nlabIu0FNDK", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462633067, + "current_period_start": 1460041067, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460041067, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E694MZ1FBtXBg", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630683, + "current_period_start": 1460038683, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038683, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E67Z0lSjjVxBn", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630527, + "current_period_start": 1460038527, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038527, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 3, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/subscriptions" + } + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:57:49 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions/sub_8E6nlabIu0FNDK + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:57:50 GMT + Content-Type: + - application/json + Content-Length: + - '821' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6nOZSSSXyv3E + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8E6nlabIu0FNDK", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462633067, + "current_period_start": 1460041067, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460041067, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:57:50 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions/sub_8E6nlabIu0FNDK?at_period_end=true + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) + ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 14:57:51 GMT + Content-Type: + - application/json + Content-Length: + - '826' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6nip0fkOtET5 + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8E6nlabIu0FNDK", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1460041071, + "current_period_end": 1462633067, + "current_period_start": 1460041067, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460041067, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Thu, 07 Apr 2016 14:57:51 GMT +recorded_with: VCR 3.0.1 From 8c3f2d2862059e8d52ce219e370d44cb2c3e6faf Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 17:55:36 +0200 Subject: [PATCH 35/64] implements a service to handle subscription extension after reservation, comes with tests --- ...ubscription_extension_after_reservation.rb | 26 ++++++++++ ...iption_extension_after_reservation_test.rb | 50 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 app/services/subscription_extension_after_reservation.rb create mode 100644 test/services/subscription_extension_after_reservation_test.rb diff --git a/app/services/subscription_extension_after_reservation.rb b/app/services/subscription_extension_after_reservation.rb new file mode 100644 index 000000000..a11490d77 --- /dev/null +++ b/app/services/subscription_extension_after_reservation.rb @@ -0,0 +1,26 @@ +class SubscriptionExtensionAfterReservation + attr_accessor :user, :reservation + + def initialize(reservation) + @user, @reservation = reservation.user, reservation + end + + def extend_subscription_if_eligible + extend_subscription if eligible_to_extension? + end + + def eligible_to_extension? + return false unless reservation.reservable_type == 'Training' + return false if user.reservations.where(reservable_type: 'Training').count != 1 + return false unless user.subscription + return false if user.subscription.is_expired? + return false unless user.subscribed_plan.is_rolling + return true + end + + def extend_subscription + user.subscription.update_columns( + expired_at: reservation.slots.first.start_at + user.subscribed_plan.duration + ) + end +end diff --git a/test/services/subscription_extension_after_reservation_test.rb b/test/services/subscription_extension_after_reservation_test.rb new file mode 100644 index 000000000..6da433bf0 --- /dev/null +++ b/test/services/subscription_extension_after_reservation_test.rb @@ -0,0 +1,50 @@ +require 'test_helper' + +class SubscriptionExtensionAfterReservationTest < ActiveSupport::TestCase + setup do + @machine = Machine.find(6) + @training = Training.find(2) + + @plan = Plan.find(3) + @plan.update!(is_rolling: true) + + @user = User.joins(:subscriptions).find_by(subscriptions: { plan: @plan }) + + @user.reservations.destroy_all # ensure no reservations + + @availability = @machine.availabilities.first + slot = Slot.new(start_at: @availability.start_at, end_at: @availability.end_at, availability_id: @availability.id) + @reservation_machine = Reservation.new(user: @user, reservable: @machine, slots: [slot]) + @reservation_training = Reservation.new(user: @user, reservable: @training, slots: [slot]) + @reservation_training.save! + end + + test "is eligible for extension because all conditions are met by default (test setup)" do + assert SubscriptionExtensionAfterReservation.new(@reservation_training).eligible_to_extension? + end + + test "not eligible if reservable is a machine" do + @reservation_machine.save! + refute SubscriptionExtensionAfterReservation.new(@reservation_machine).eligible_to_extension? + end + + test "not eligible if user doesn't have subscription" do + @user.subscriptions.destroy_all + refute SubscriptionExtensionAfterReservation.new(@reservation_training).eligible_to_extension? + end + + test "not eligible if subscription is expired" do + @user.subscription.update!(expired_at: 10.years.ago) + refute SubscriptionExtensionAfterReservation.new(@reservation_training).eligible_to_extension? + end + + test "not eligible if plan attribute 'is_rolling' is false/nil" do + @plan.update!(is_rolling: false) + refute SubscriptionExtensionAfterReservation.new(@reservation_training).eligible_to_extension? + end + + test "method extend_subscription" do + SubscriptionExtensionAfterReservation.new(@reservation_training).extend_subscription + assert_equal @reservation_training.slots.first.start_at + @plan.duration, @user.subscription.expired_at + end +end From 7a523a1cf806d7d1f3ec52ff731089cc8cacd98c Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 17:56:54 +0200 Subject: [PATCH 36/64] adds reservation integration test to test subscription extension when plan is_rolling true --- test/integration/reservations/create_test.rb | 69 +- ...for_training_with_subscription_success.yml | 497 +++++++++++++ ..._training_without_subscription_success.yml | 661 +++++++++--------- 3 files changed, 892 insertions(+), 335 deletions(-) create mode 100644 test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml diff --git a/test/integration/reservations/create_test.rb b/test/integration/reservations/create_test.rb index e3c6dd29c..8b7f16a42 100644 --- a/test/integration/reservations/create_test.rb +++ b/test/integration/reservations/create_test.rb @@ -117,8 +117,9 @@ module Reservations reservable_type: training.class.name, card_token: stripe_card_token, slots_attributes: [ - { start_at: availability.start_at.to_s(:iso8601), - end_at: (availability.start_at + 1.hour).to_s(:iso8601), + { + start_at: availability.start_at.to_s(:iso8601), + end_at: availability.end_at.to_s(:iso8601), availability_id: availability.id } ] @@ -231,5 +232,69 @@ module Reservations # notification assert_not_empty Notification.where(attached_object: reservation) end + + test "user with subscription reserves the FIRST training with success" do + login_as(@user_with_subscription, scope: :user) + plan = @user_with_subscription.subscribed_plan + plan.update!(is_rolling: true) + + training = Training.joins(credits: :plan).where(credits: { plan: plan }).first + availability = training.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + + VCR.use_cassette("reservations_create_for_training_with_subscription_success") do + post reservations_path, { reservation: { + user_id: @user_with_subscription.id, + reservable_id: training.id, + reservable_type: training.class.name, + card_token: stripe_card_token, + slots_attributes: [ + { + start_at: availability.start_at.to_s(:iso8601), + end_at: availability.end_at.to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + end + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count + 1, Invoice.count + assert_equal invoice_items_count + 1, InvoiceItem.count + + # reservation assertions + reservation = Reservation.last + + assert reservation.invoice + refute reservation.stp_invoice_id.blank? + assert_equal 1, reservation.invoice.invoice_items.count + + # invoice assertions + invoice = reservation.invoice + + refute invoice.stp_invoice_id.blank? + refute invoice.total.blank? + # invoice_items + invoice_item = InvoiceItem.last + + assert invoice_item.stp_invoice_item_id + assert_equal 0, invoice_item.amount # amount is 0 because this training is a credited training with that plan + + # invoice assertions + invoice = Invoice.find_by(invoiced: reservation) + assert invoice + assert File.exist?(invoice.file) + + # notification + assert_not_empty Notification.where(attached_object: reservation) + + # check that user subscription were extended + assert_equal reservation.slots.first.start_at + plan.duration, @user_with_subscription.subscription.expired_at + end end end diff --git a/test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml new file mode 100644 index 000000000..7cb903c66 --- /dev/null +++ b/test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml @@ -0,0 +1,497 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.stripe.com/v1/tokens + body: + encoding: UTF-8 + string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314 + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '81' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 15:06:59 GMT + Content-Type: + - application/json + Content-Length: + - '778' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6w5td6P3FMmw + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17xeil2sOmf47Nz9hPGrY38H", + "object": "token", + "card": { + "id": "card_17xeil2sOmf47Nz9K3lr9AIc", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "86.76.5.109", + "created": 1460041619, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Thu, 07 Apr 2016 15:06:59 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoiceitems + body: + encoding: UTF-8 + string: customer=cus_8CzKe50I0J1gaI&amount=0¤cy=usd&description=Formation+Imprimante+3D+April+12%2C+2016+08%3A00+-+12%3A00+PM + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '123' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 15:07:00 GMT + Content-Type: + - application/json + Content-Length: + - '469' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6wDLVEcvrNew + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "ii_17xeim2sOmf47Nz9aoVFuMOo", + "object": "invoiceitem", + "amount": 0, + "currency": "usd", + "customer": "cus_8CzKe50I0J1gaI", + "date": 1460041620, + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 12:00 PM", + "discountable": true, + "invoice": null, + "livemode": false, + "metadata": {}, + "period": { + "start": 1460041620, + "end": 1460041620 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null + } + http_version: + recorded_at: Thu, 07 Apr 2016 15:07:00 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8CzKe50I0J1gaI + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 15:07:02 GMT + Content-Type: + - application/json + Content-Length: + - '649' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6wKVkDbddbOI + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8CzKe50I0J1gaI", + "object": "customer", + "account_balance": 0, + "created": 1459782643, + "currency": "usd", + "default_source": null, + "delinquent": false, + "description": "Kevin Dumas", + "discount": null, + "email": "kevin.dumas@orange.fr", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "/v1/customers/cus_8CzKe50I0J1gaI/sources" + }, + "subscriptions": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "/v1/customers/cus_8CzKe50I0J1gaI/subscriptions" + } + } + http_version: + recorded_at: Thu, 07 Apr 2016 15:07:01 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices + body: + encoding: UTF-8 + string: customer=cus_8CzKe50I0J1gaI + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '27' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 15:07:03 GMT + Content-Type: + - application/json + Content-Length: + - '1417' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6wYV4WPn7r3p + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xeip2sOmf47Nz9kf2GTiaS", + "object": "invoice", + "amount_due": 0, + "application_fee": null, + "attempt_count": 0, + "attempted": false, + "charge": null, + "closed": false, + "currency": "usd", + "customer": "cus_8CzKe50I0J1gaI", + "date": 1460041623, + "description": null, + "discount": null, + "ending_balance": null, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xeim2sOmf47Nz9aoVFuMOo", + "object": "line_item", + "amount": 0, + "currency": "usd", + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 12:00 PM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1460041620, + "end": 1460041620 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xeip2sOmf47Nz9kf2GTiaS/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1460045223, + "paid": false, + "period_end": 1460041623, + "period_start": 1460041623, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 0, + "tax": null, + "tax_percent": null, + "total": 0, + "webhooks_delivered_at": null + } + http_version: + recorded_at: Thu, 07 Apr 2016 15:07:02 GMT +- request: + method: post + uri: https://api.stripe.com/v1/invoices/in_17xeip2sOmf47Nz9kf2GTiaS/pay + body: + encoding: ASCII-8BIT + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-darwin14","engine":"ruby","publisher":"stripe","uname":"Darwin + MBP-sleede-Nicolas.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 + PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64","hostname":"MBP-sleede-Nicolas.local"}' + Content-Length: + - '0' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 07 Apr 2016 15:07:04 GMT + Content-Type: + - application/json + Content-Length: + - '1411' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8E6w2oGfDSiKDf + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "in_17xeip2sOmf47Nz9kf2GTiaS", + "object": "invoice", + "amount_due": 0, + "application_fee": null, + "attempt_count": 0, + "attempted": true, + "charge": null, + "closed": true, + "currency": "usd", + "customer": "cus_8CzKe50I0J1gaI", + "date": 1460041623, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "ii_17xeim2sOmf47Nz9aoVFuMOo", + "object": "line_item", + "amount": 0, + "currency": "usd", + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 12:00 PM", + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1460041620, + "end": 1460041620 + }, + "plan": null, + "proration": false, + "quantity": null, + "subscription": null, + "type": "invoiceitem" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17xeip2sOmf47Nz9kf2GTiaS/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1460041623, + "period_start": 1460041623, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": null, + "subtotal": 0, + "tax": null, + "tax_percent": null, + "total": 0, + "webhooks_delivered_at": 1460041623 + } + http_version: + recorded_at: Thu, 07 Apr 2016 15:07:04 GMT +recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml index 1b1c55b7b..f33512801 100644 --- a/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml +++ b/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml @@ -31,7 +31,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:49 GMT + - Thu, 07 Apr 2016 15:02:21 GMT Content-Type: - application/json Content-Length: @@ -49,7 +49,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DigcYeFhS0WA0 + - req_8E6s5qX3Z71ouH Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -58,10 +58,10 @@ http_interactions: encoding: UTF-8 string: | { - "id": "tok_17xHF72sOmf47Nz9gTjKt9Pb", + "id": "tok_17xeeH2sOmf47Nz9fhi24LcM", "object": "token", "card": { - "id": "card_17xHF72sOmf47Nz9pOYRMYdO", + "id": "card_17xeeH2sOmf47Nz9qkD2jaiS", "object": "card", "address_city": null, "address_country": null, @@ -85,19 +85,19 @@ http_interactions: "tokenization_method": null }, "client_ip": "86.76.5.109", - "created": 1459951369, + "created": 1460041341, "livemode": false, "type": "card", "used": false } http_version: - recorded_at: Wed, 06 Apr 2016 14:02:49 GMT + recorded_at: Thu, 07 Apr 2016 15:02:21 GMT - request: method: post uri: https://api.stripe.com/v1/invoiceitems body: encoding: UTF-8 - string: customer=cus_8Di1wjdVktv5kt&amount=5100¤cy=usd&description=Formation+Imprimante+3D+April+12%2C+2016+08%3A00+-+09%3A00+AM + string: customer=cus_8Di1wjdVktv5kt&amount=5100¤cy=usd&description=Formation+Imprimante+3D+April+12%2C+2016+08%3A00+-+12%3A00+PM headers: Accept: - "*/*; q=0.5, application/xml" @@ -123,7 +123,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:50 GMT + - Thu, 07 Apr 2016 15:02:22 GMT Content-Type: - application/json Content-Length: @@ -141,7 +141,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DigyU1U3fnul5 + - req_8E6sbtrP1o0eL7 Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -150,20 +150,20 @@ http_interactions: encoding: UTF-8 string: | { - "id": "ii_17xHF82sOmf47Nz9QT6BnkAZ", + "id": "ii_17xeeI2sOmf47Nz9qEhwu9J6", "object": "invoiceitem", "amount": 5100, "currency": "usd", "customer": "cus_8Di1wjdVktv5kt", - "date": 1459951370, - "description": "Formation Imprimante 3D April 12, 2016 08:00 - 09:00 AM", + "date": 1460041342, + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 12:00 PM", "discountable": true, "invoice": null, "livemode": false, "metadata": {}, "period": { - "start": 1459951370, - "end": 1459951370 + "start": 1460041342, + "end": 1460041342 }, "plan": null, "proration": false, @@ -171,7 +171,7 @@ http_interactions: "subscription": null } http_version: - recorded_at: Wed, 06 Apr 2016 14:02:50 GMT + recorded_at: Thu, 07 Apr 2016 15:02:22 GMT - request: method: get uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt @@ -201,11 +201,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:51 GMT + - Thu, 07 Apr 2016 15:02:23 GMT Content-Type: - application/json Content-Length: - - '3462' + - '5571' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -219,144 +219,146 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DigzPm4VAhhnA + - req_8E6sNFUC3vntgP Stripe-Version: - '2015-10-16' Strict-Transport-Security: - max-age=31556926; includeSubDomains body: - encoding: UTF-8 - string: | - { - "id": "cus_8Di1wjdVktv5kt", - "object": "customer", - "account_balance": 0, - "created": 1459948888, - "currency": "usd", - "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", - "delinquent": false, - "description": "Jean Dupond", - "discount": null, - "email": "jean.dupond@gmail.com", - "livemode": false, - "metadata": {}, - "shipping": null, - "sources": { - "object": "list", - "data": [ - { - "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", - "object": "card", - "address_city": null, - "address_country": null, - "address_line1": null, - "address_line1_check": null, - "address_line2": null, - "address_state": null, - "address_zip": null, - "address_zip_check": null, - "brand": "Visa", - "country": "US", - "customer": "cus_8Di1wjdVktv5kt", - "cvc_check": "pass", - "dynamic_last4": null, - "exp_month": 4, - "exp_year": 2017, - "fingerprint": "o52jybR7bnmNn6AT", - "funding": "credit", - "last4": "4242", - "metadata": {}, - "name": null, - "tokenization_method": null - } - ], - "has_more": false, - "total_count": 1, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" - }, - "subscriptions": { - "object": "list", - "data": [ - { - "id": "sub_8Di9gqPLwt5IIC", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459949404, - "current_period_end": 1462541399, - "current_period_start": 1459949399, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459949399, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - }, - { - "id": "sub_8Di2VadRvr7A99", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459948972, - "current_period_end": 1462540968, - "current_period_start": 1459948968, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459948968, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - } - ], - "has_more": false, - "total_count": 2, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" - } - } + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJvYmplY3QiOiAi + Y3VzdG9tZXIiLAogICJhY2NvdW50X2JhbGFuY2UiOiAwLAogICJjcmVhdGVk + IjogMTQ1OTk0ODg4OCwKICAiY3VycmVuY3kiOiAidXNkIiwKICAiZGVmYXVs + dF9zb3VyY2UiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1M0EiLAog + ICJkZWxpbnF1ZW50IjogZmFsc2UsCiAgImRlc2NyaXB0aW9uIjogIkplYW4g + RHVwb25kIiwKICAiZGlzY291bnQiOiBudWxsLAogICJlbWFpbCI6ICJqZWFu + LmR1cG9uZEBnbWFpbC5jb20iLAogICJsaXZlbW9kZSI6IGZhbHNlLAogICJt + ZXRhZGF0YSI6IHt9LAogICJzaGlwcGluZyI6IG51bGwsCiAgInNvdXJjZXMi + OiB7CiAgICAib2JqZWN0IjogImxpc3QiLAogICAgImRhdGEiOiBbCiAgICAg + IHsKICAgICAgICAiaWQiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1 + M0EiLAogICAgICAgICJvYmplY3QiOiAiY2FyZCIsCiAgICAgICAgImFkZHJl + c3NfY2l0eSI6IG51bGwsCiAgICAgICAgImFkZHJlc3NfY291bnRyeSI6IG51 + bGwsCiAgICAgICAgImFkZHJlc3NfbGluZTEiOiBudWxsLAogICAgICAgICJh + ZGRyZXNzX2xpbmUxX2NoZWNrIjogbnVsbCwKICAgICAgICAiYWRkcmVzc19s + aW5lMiI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nfc3RhdGUiOiBudWxsLAog + ICAgICAgICJhZGRyZXNzX3ppcCI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nf + emlwX2NoZWNrIjogbnVsbCwKICAgICAgICAiYnJhbmQiOiAiVmlzYSIsCiAg + ICAgICAgImNvdW50cnkiOiAiVVMiLAogICAgICAgICJjdXN0b21lciI6ICJj + dXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJjdmNfY2hlY2siOiAicGFz + cyIsCiAgICAgICAgImR5bmFtaWNfbGFzdDQiOiBudWxsLAogICAgICAgICJl + eHBfbW9udGgiOiA0LAogICAgICAgICJleHBfeWVhciI6IDIwMTcsCiAgICAg + ICAgImZpbmdlcnByaW50IjogIm81Mmp5YlI3Ym5tTm42QVQiLAogICAgICAg + ICJmdW5kaW5nIjogImNyZWRpdCIsCiAgICAgICAgImxhc3Q0IjogIjQyNDIi + LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJuYW1lIjogbnVs + bCwKICAgICAgICAidG9rZW5pemF0aW9uX21ldGhvZCI6IG51bGwKICAgICAg + fQogICAgXSwKICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRvdGFsX2Nv + dW50IjogMSwKICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNfOERpMXdq + ZFZrdHY1a3Qvc291cmNlcyIKICB9LAogICJzdWJzY3JpcHRpb25zIjogewog + ICAgIm9iamVjdCI6ICJsaXN0IiwKICAgICJkYXRhIjogWwogICAgICB7CiAg + ICAgICAgImlkIjogInN1Yl84RTFhZmtUQm4yZGMxRCIsCiAgICAgICAgIm9i + amVjdCI6ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9m + ZWVfcGVyY2VudCI6IG51bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2Rf + ZW5kIjogdHJ1ZSwKICAgICAgICAiY2FuY2VsZWRfYXQiOiAxNDYwMDIxNjcw + LAogICAgICAgICJjdXJyZW50X3BlcmlvZF9lbmQiOiAxNDYyNjEzNjY1LAog + ICAgICAgICJjdXJyZW50X3BlcmlvZF9zdGFydCI6IDE0NjAwMjE2NjUsCiAg + ICAgICAgImN1c3RvbWVyIjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAg + ICAgImRpc2NvdW50IjogbnVsbCwKICAgICAgICAiZW5kZWRfYXQiOiBudWxs + LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJwbGFuIjogewog + ICAgICAgICAgImlkIjogIm1lbnN1ZWwtdGFyaWYtcmVkdWl0LXN0dWRlbnQt + bW9udGgtMjAxNjA0MDQxNzE4MjciLAogICAgICAgICAgIm9iamVjdCI6ICJw + bGFuIiwKICAgICAgICAgICJhbW91bnQiOiAyMDAwLAogICAgICAgICAgImNy + ZWF0ZWQiOiAxNDU5NzgzMTA4LAogICAgICAgICAgImN1cnJlbmN5IjogInVz + ZCIsCiAgICAgICAgICAiaW50ZXJ2YWwiOiAibW9udGgiLAogICAgICAgICAg + ImludGVydmFsX2NvdW50IjogMSwKICAgICAgICAgICJsaXZlbW9kZSI6IGZh + bHNlLAogICAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgICAibmFt + ZSI6ICJNZW5zdWVsIHRhcmlmIHLDqWR1aXQgLSDDqXR1ZGlhbnQsIC0gZGUg + MjUgYW5zLCBlbnNlaWduYW50LCBkZW1hbmRldXIgZCdlbXBsb2kgLSBtb250 + aCIsCiAgICAgICAgICAic3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAog + ICAgICAgICAgInRyaWFsX3BlcmlvZF9kYXlzIjogbnVsbAogICAgICAgIH0s + CiAgICAgICAgInF1YW50aXR5IjogMSwKICAgICAgICAic3RhcnQiOiAxNDYw + MDIxNjY1LAogICAgICAgICJzdGF0dXMiOiAiYWN0aXZlIiwKICAgICAgICAi + dGF4X3BlcmNlbnQiOiBudWxsLAogICAgICAgICJ0cmlhbF9lbmQiOiBudWxs + LAogICAgICAgICJ0cmlhbF9zdGFydCI6IG51bGwKICAgICAgfSwKICAgICAg + ewogICAgICAgICJpZCI6ICJzdWJfOERrcUJjUjFiUXZyNUciLAogICAgICAg + ICJvYmplY3QiOiAic3Vic2NyaXB0aW9uIiwKICAgICAgICAiYXBwbGljYXRp + b25fZmVlX3BlcmNlbnQiOiBudWxsLAogICAgICAgICJjYW5jZWxfYXRfcGVy + aW9kX2VuZCI6IHRydWUsCiAgICAgICAgImNhbmNlbGVkX2F0IjogMTQ1OTk1 + OTM4NiwKICAgICAgICAiY3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjU1MTM4 + MiwKICAgICAgICAiY3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDU5OTU5Mzgy + LAogICAgICAgICJjdXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAog + ICAgICAgICJkaXNjb3VudCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0Ijog + bnVsbCwKICAgICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6 + IHsKICAgICAgICAgICJpZCI6ICJtZW5zdWVsLXN0YW5kYXJkLW1vbnRoLTIw + MTYwNDA0MTcxNTE5IiwKICAgICAgICAgICJvYmplY3QiOiAicGxhbiIsCiAg + ICAgICAgICAiYW1vdW50IjogMzAwMCwKICAgICAgICAgICJjcmVhdGVkIjog + MTQ1OTc4MjkyMSwKICAgICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAg + ICAgICAgImludGVydmFsIjogIm1vbnRoIiwKICAgICAgICAgICJpbnRlcnZh + bF9jb3VudCI6IDEsCiAgICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAg + ICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAiTWVu + c3VlbCAtIHN0YW5kYXJkLCBhc3NvY2lhdGlvbiAtIG1vbnRoIiwKICAgICAg + ICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAgICAgICAi + dHJpYWxfcGVyaW9kX2RheXMiOiBudWxsCiAgICAgICAgfSwKICAgICAgICAi + cXVhbnRpdHkiOiAxLAogICAgICAgICJzdGFydCI6IDE0NTk5NTkzODIsCiAg + ICAgICAgInN0YXR1cyI6ICJhY3RpdmUiLAogICAgICAgICJ0YXhfcGVyY2Vu + dCI6IG51bGwsCiAgICAgICAgInRyaWFsX2VuZCI6IG51bGwsCiAgICAgICAg + InRyaWFsX3N0YXJ0IjogbnVsbAogICAgICB9LAogICAgICB7CiAgICAgICAg + ImlkIjogInN1Yl84RGk5Z3FQTHd0NUlJQyIsCiAgICAgICAgIm9iamVjdCI6 + ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9mZWVfcGVy + Y2VudCI6IG51bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2RfZW5kIjog + dHJ1ZSwKICAgICAgICAiY2FuY2VsZWRfYXQiOiAxNDU5OTQ5NDA0LAogICAg + ICAgICJjdXJyZW50X3BlcmlvZF9lbmQiOiAxNDYyNTQxMzk5LAogICAgICAg + ICJjdXJyZW50X3BlcmlvZF9zdGFydCI6IDE0NTk5NDkzOTksCiAgICAgICAg + ImN1c3RvbWVyIjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAgICAgImRp + c2NvdW50IjogbnVsbCwKICAgICAgICAiZW5kZWRfYXQiOiBudWxsLAogICAg + ICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJwbGFuIjogewogICAgICAg + ICAgImlkIjogIm1lbnN1ZWwtc3RhbmRhcmQtbW9udGgtMjAxNjA0MDQxNzE1 + MTkiLAogICAgICAgICAgIm9iamVjdCI6ICJwbGFuIiwKICAgICAgICAgICJh + bW91bnQiOiAzMDAwLAogICAgICAgICAgImNyZWF0ZWQiOiAxNDU5NzgyOTIx + LAogICAgICAgICAgImN1cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAiaW50 + ZXJ2YWwiOiAibW9udGgiLAogICAgICAgICAgImludGVydmFsX2NvdW50Ijog + MSwKICAgICAgICAgICJsaXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAgIm1l + dGFkYXRhIjoge30sCiAgICAgICAgICAibmFtZSI6ICJNZW5zdWVsIC0gc3Rh + bmRhcmQsIGFzc29jaWF0aW9uIC0gbW9udGgiLAogICAgICAgICAgInN0YXRl + bWVudF9kZXNjcmlwdG9yIjogbnVsbCwKICAgICAgICAgICJ0cmlhbF9wZXJp + b2RfZGF5cyI6IG51bGwKICAgICAgICB9LAogICAgICAgICJxdWFudGl0eSI6 + IDEsCiAgICAgICAgInN0YXJ0IjogMTQ1OTk0OTM5OSwKICAgICAgICAic3Rh + dHVzIjogImFjdGl2ZSIsCiAgICAgICAgInRheF9wZXJjZW50IjogbnVsbCwK + ICAgICAgICAidHJpYWxfZW5kIjogbnVsbCwKICAgICAgICAidHJpYWxfc3Rh + cnQiOiBudWxsCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiaWQiOiAic3Vi + XzhEaTJWYWRSdnI3QTk5IiwKICAgICAgICAib2JqZWN0IjogInN1YnNjcmlw + dGlvbiIsCiAgICAgICAgImFwcGxpY2F0aW9uX2ZlZV9wZXJjZW50IjogbnVs + bCwKICAgICAgICAiY2FuY2VsX2F0X3BlcmlvZF9lbmQiOiB0cnVlLAogICAg + ICAgICJjYW5jZWxlZF9hdCI6IDE0NTk5NDg5NzIsCiAgICAgICAgImN1cnJl + bnRfcGVyaW9kX2VuZCI6IDE0NjI1NDA5NjgsCiAgICAgICAgImN1cnJlbnRf + cGVyaW9kX3N0YXJ0IjogMTQ1OTk0ODk2OCwKICAgICAgICAiY3VzdG9tZXIi + OiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAgICAgICAiZGlzY291bnQiOiBu + dWxsLAogICAgICAgICJlbmRlZF9hdCI6IG51bGwsCiAgICAgICAgIm1ldGFk + YXRhIjoge30sCiAgICAgICAgInBsYW4iOiB7CiAgICAgICAgICAiaWQiOiAi + bWVuc3VlbC1zdGFuZGFyZC1tb250aC0yMDE2MDQwNDE3MTUxOSIsCiAgICAg + ICAgICAib2JqZWN0IjogInBsYW4iLAogICAgICAgICAgImFtb3VudCI6IDMw + MDAsCiAgICAgICAgICAiY3JlYXRlZCI6IDE0NTk3ODI5MjEsCiAgICAgICAg + ICAiY3VycmVuY3kiOiAidXNkIiwKICAgICAgICAgICJpbnRlcnZhbCI6ICJt + b250aCIsCiAgICAgICAgICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAgICAg + ICAgImxpdmVtb2RlIjogZmFsc2UsCiAgICAgICAgICAibWV0YWRhdGEiOiB7 + fSwKICAgICAgICAgICJuYW1lIjogIk1lbnN1ZWwgLSBzdGFuZGFyZCwgYXNz + b2NpYXRpb24gLSBtb250aCIsCiAgICAgICAgICAic3RhdGVtZW50X2Rlc2Ny + aXB0b3IiOiBudWxsLAogICAgICAgICAgInRyaWFsX3BlcmlvZF9kYXlzIjog + bnVsbAogICAgICAgIH0sCiAgICAgICAgInF1YW50aXR5IjogMSwKICAgICAg + ICAic3RhcnQiOiAxNDU5OTQ4OTY4LAogICAgICAgICJzdGF0dXMiOiAiYWN0 + aXZlIiwKICAgICAgICAidGF4X3BlcmNlbnQiOiBudWxsLAogICAgICAgICJ0 + cmlhbF9lbmQiOiBudWxsLAogICAgICAgICJ0cmlhbF9zdGFydCI6IG51bGwK + ICAgICAgfQogICAgXSwKICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRv + dGFsX2NvdW50IjogNCwKICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNf + OERpMXdqZFZrdHY1a3Qvc3Vic2NyaXB0aW9ucyIKICB9Cn0K http_version: - recorded_at: Wed, 06 Apr 2016 14:02:51 GMT + recorded_at: Thu, 07 Apr 2016 15:02:23 GMT - request: method: post uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources body: encoding: UTF-8 - string: card=tok_17xHF72sOmf47Nz9gTjKt9Pb + string: card=tok_17xeeH2sOmf47Nz9fhi24LcM headers: Accept: - "*/*; q=0.5, application/xml" @@ -382,7 +384,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:52 GMT + - Thu, 07 Apr 2016 15:02:24 GMT Content-Type: - application/json Content-Length: @@ -400,7 +402,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DigYDBbu9Qzcj + - req_8E6s96LPZP4cCo Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -409,7 +411,7 @@ http_interactions: encoding: UTF-8 string: | { - "id": "card_17xHF72sOmf47Nz9pOYRMYdO", + "id": "card_17xeeH2sOmf47Nz9qkD2jaiS", "object": "card", "address_city": null, "address_country": null, @@ -434,13 +436,13 @@ http_interactions: "tokenization_method": null } http_version: - recorded_at: Wed, 06 Apr 2016 14:02:52 GMT + recorded_at: Thu, 07 Apr 2016 15:02:24 GMT - request: method: post uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt body: encoding: UTF-8 - string: default_source=card_17xHF72sOmf47Nz9pOYRMYdO + string: default_source=card_17xeeH2sOmf47Nz9qkD2jaiS headers: Accept: - "*/*; q=0.5, application/xml" @@ -466,11 +468,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:53 GMT + - Thu, 07 Apr 2016 15:02:25 GMT Content-Type: - application/json Content-Length: - - '4190' + - '6299' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -484,163 +486,156 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DigPEpOnL3MYw + - req_8E6shlISPAIWMP Stripe-Version: - '2015-10-16' Strict-Transport-Security: - max-age=31556926; includeSubDomains body: - encoding: UTF-8 - string: | - { - "id": "cus_8Di1wjdVktv5kt", - "object": "customer", - "account_balance": 0, - "created": 1459948888, - "currency": "usd", - "default_source": "card_17xHF72sOmf47Nz9pOYRMYdO", - "delinquent": false, - "description": "Jean Dupond", - "discount": null, - "email": "jean.dupond@gmail.com", - "livemode": false, - "metadata": {}, - "shipping": null, - "sources": { - "object": "list", - "data": [ - { - "id": "card_17xHF72sOmf47Nz9pOYRMYdO", - "object": "card", - "address_city": null, - "address_country": null, - "address_line1": null, - "address_line1_check": null, - "address_line2": null, - "address_state": null, - "address_zip": null, - "address_zip_check": null, - "brand": "Visa", - "country": "US", - "customer": "cus_8Di1wjdVktv5kt", - "cvc_check": "pass", - "dynamic_last4": null, - "exp_month": 4, - "exp_year": 2017, - "fingerprint": "o52jybR7bnmNn6AT", - "funding": "credit", - "last4": "4242", - "metadata": {}, - "name": null, - "tokenization_method": null - }, - { - "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", - "object": "card", - "address_city": null, - "address_country": null, - "address_line1": null, - "address_line1_check": null, - "address_line2": null, - "address_state": null, - "address_zip": null, - "address_zip_check": null, - "brand": "Visa", - "country": "US", - "customer": "cus_8Di1wjdVktv5kt", - "cvc_check": "pass", - "dynamic_last4": null, - "exp_month": 4, - "exp_year": 2017, - "fingerprint": "o52jybR7bnmNn6AT", - "funding": "credit", - "last4": "4242", - "metadata": {}, - "name": null, - "tokenization_method": null - } - ], - "has_more": false, - "total_count": 2, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" - }, - "subscriptions": { - "object": "list", - "data": [ - { - "id": "sub_8Di9gqPLwt5IIC", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459949404, - "current_period_end": 1462541399, - "current_period_start": 1459949399, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459949399, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - }, - { - "id": "sub_8Di2VadRvr7A99", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459948972, - "current_period_end": 1462540968, - "current_period_start": 1459948968, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459948968, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - } - ], - "has_more": false, - "total_count": 2, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" - } - } + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJvYmplY3QiOiAi + Y3VzdG9tZXIiLAogICJhY2NvdW50X2JhbGFuY2UiOiAwLAogICJjcmVhdGVk + IjogMTQ1OTk0ODg4OCwKICAiY3VycmVuY3kiOiAidXNkIiwKICAiZGVmYXVs + dF9zb3VyY2UiOiAiY2FyZF8xN3hlZUgyc09tZjQ3Tno5cWtEMmphaVMiLAog + ICJkZWxpbnF1ZW50IjogZmFsc2UsCiAgImRlc2NyaXB0aW9uIjogIkplYW4g + RHVwb25kIiwKICAiZGlzY291bnQiOiBudWxsLAogICJlbWFpbCI6ICJqZWFu + LmR1cG9uZEBnbWFpbC5jb20iLAogICJsaXZlbW9kZSI6IGZhbHNlLAogICJt + ZXRhZGF0YSI6IHt9LAogICJzaGlwcGluZyI6IG51bGwsCiAgInNvdXJjZXMi + OiB7CiAgICAib2JqZWN0IjogImxpc3QiLAogICAgImRhdGEiOiBbCiAgICAg + IHsKICAgICAgICAiaWQiOiAiY2FyZF8xN3hlZUgyc09tZjQ3Tno5cWtEMmph + aVMiLAogICAgICAgICJvYmplY3QiOiAiY2FyZCIsCiAgICAgICAgImFkZHJl + c3NfY2l0eSI6IG51bGwsCiAgICAgICAgImFkZHJlc3NfY291bnRyeSI6IG51 + bGwsCiAgICAgICAgImFkZHJlc3NfbGluZTEiOiBudWxsLAogICAgICAgICJh + ZGRyZXNzX2xpbmUxX2NoZWNrIjogbnVsbCwKICAgICAgICAiYWRkcmVzc19s + aW5lMiI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nfc3RhdGUiOiBudWxsLAog + ICAgICAgICJhZGRyZXNzX3ppcCI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nf + emlwX2NoZWNrIjogbnVsbCwKICAgICAgICAiYnJhbmQiOiAiVmlzYSIsCiAg + ICAgICAgImNvdW50cnkiOiAiVVMiLAogICAgICAgICJjdXN0b21lciI6ICJj + dXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJjdmNfY2hlY2siOiAicGFz + cyIsCiAgICAgICAgImR5bmFtaWNfbGFzdDQiOiBudWxsLAogICAgICAgICJl + eHBfbW9udGgiOiA0LAogICAgICAgICJleHBfeWVhciI6IDIwMTcsCiAgICAg + ICAgImZpbmdlcnByaW50IjogIm81Mmp5YlI3Ym5tTm42QVQiLAogICAgICAg + ICJmdW5kaW5nIjogImNyZWRpdCIsCiAgICAgICAgImxhc3Q0IjogIjQyNDIi + LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJuYW1lIjogbnVs + bCwKICAgICAgICAidG9rZW5pemF0aW9uX21ldGhvZCI6IG51bGwKICAgICAg + fSwKICAgICAgewogICAgICAgICJpZCI6ICJjYXJkXzE3eFpXdDJzT21mNDdO + ejllVlVDaTUzQSIsCiAgICAgICAgIm9iamVjdCI6ICJjYXJkIiwKICAgICAg + ICAiYWRkcmVzc19jaXR5IjogbnVsbCwKICAgICAgICAiYWRkcmVzc19jb3Vu + dHJ5IjogbnVsbCwKICAgICAgICAiYWRkcmVzc19saW5lMSI6IG51bGwsCiAg + ICAgICAgImFkZHJlc3NfbGluZTFfY2hlY2siOiBudWxsLAogICAgICAgICJh + ZGRyZXNzX2xpbmUyIjogbnVsbCwKICAgICAgICAiYWRkcmVzc19zdGF0ZSI6 + IG51bGwsCiAgICAgICAgImFkZHJlc3NfemlwIjogbnVsbCwKICAgICAgICAi + YWRkcmVzc196aXBfY2hlY2siOiBudWxsLAogICAgICAgICJicmFuZCI6ICJW + aXNhIiwKICAgICAgICAiY291bnRyeSI6ICJVUyIsCiAgICAgICAgImN1c3Rv + bWVyIjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAgICAgImN2Y19jaGVj + ayI6ICJwYXNzIiwKICAgICAgICAiZHluYW1pY19sYXN0NCI6IG51bGwsCiAg + ICAgICAgImV4cF9tb250aCI6IDQsCiAgICAgICAgImV4cF95ZWFyIjogMjAx + NywKICAgICAgICAiZmluZ2VycHJpbnQiOiAibzUyanliUjdibm1ObjZBVCIs + CiAgICAgICAgImZ1bmRpbmciOiAiY3JlZGl0IiwKICAgICAgICAibGFzdDQi + OiAiNDI0MiIsCiAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgIm5h + bWUiOiBudWxsLAogICAgICAgICJ0b2tlbml6YXRpb25fbWV0aG9kIjogbnVs + bAogICAgICB9CiAgICBdLAogICAgImhhc19tb3JlIjogZmFsc2UsCiAgICAi + dG90YWxfY291bnQiOiAyLAogICAgInVybCI6ICIvdjEvY3VzdG9tZXJzL2N1 + c184RGkxd2pkVmt0djVrdC9zb3VyY2VzIgogIH0sCiAgInN1YnNjcmlwdGlv + bnMiOiB7CiAgICAib2JqZWN0IjogImxpc3QiLAogICAgImRhdGEiOiBbCiAg + ICAgIHsKICAgICAgICAiaWQiOiAic3ViXzhFMWFma1RCbjJkYzFEIiwKICAg + ICAgICAib2JqZWN0IjogInN1YnNjcmlwdGlvbiIsCiAgICAgICAgImFwcGxp + Y2F0aW9uX2ZlZV9wZXJjZW50IjogbnVsbCwKICAgICAgICAiY2FuY2VsX2F0 + X3BlcmlvZF9lbmQiOiB0cnVlLAogICAgICAgICJjYW5jZWxlZF9hdCI6IDE0 + NjAwMjE2NzAsCiAgICAgICAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI2 + MTM2NjUsCiAgICAgICAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ2MDAy + MTY2NSwKICAgICAgICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0 + IiwKICAgICAgICAiZGlzY291bnQiOiBudWxsLAogICAgICAgICJlbmRlZF9h + dCI6IG51bGwsCiAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgInBs + YW4iOiB7CiAgICAgICAgICAiaWQiOiAibWVuc3VlbC10YXJpZi1yZWR1aXQt + c3R1ZGVudC1tb250aC0yMDE2MDQwNDE3MTgyNyIsCiAgICAgICAgICAib2Jq + ZWN0IjogInBsYW4iLAogICAgICAgICAgImFtb3VudCI6IDIwMDAsCiAgICAg + ICAgICAiY3JlYXRlZCI6IDE0NTk3ODMxMDgsCiAgICAgICAgICAiY3VycmVu + Y3kiOiAidXNkIiwKICAgICAgICAgICJpbnRlcnZhbCI6ICJtb250aCIsCiAg + ICAgICAgICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAgICAgICAgImxpdmVt + b2RlIjogZmFsc2UsCiAgICAgICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAg + ICAgICJuYW1lIjogIk1lbnN1ZWwgdGFyaWYgcsOpZHVpdCAtIMOpdHVkaWFu + dCwgLSBkZSAyNSBhbnMsIGVuc2VpZ25hbnQsIGRlbWFuZGV1ciBkJ2VtcGxv + aSAtIG1vbnRoIiwKICAgICAgICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6 + IG51bGwsCiAgICAgICAgICAidHJpYWxfcGVyaW9kX2RheXMiOiBudWxsCiAg + ICAgICAgfSwKICAgICAgICAicXVhbnRpdHkiOiAxLAogICAgICAgICJzdGFy + dCI6IDE0NjAwMjE2NjUsCiAgICAgICAgInN0YXR1cyI6ICJhY3RpdmUiLAog + ICAgICAgICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgICAgICAgInRyaWFsX2Vu + ZCI6IG51bGwsCiAgICAgICAgInRyaWFsX3N0YXJ0IjogbnVsbAogICAgICB9 + LAogICAgICB7CiAgICAgICAgImlkIjogInN1Yl84RGtxQmNSMWJRdnI1RyIs + CiAgICAgICAgIm9iamVjdCI6ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJh + cHBsaWNhdGlvbl9mZWVfcGVyY2VudCI6IG51bGwsCiAgICAgICAgImNhbmNl + bF9hdF9wZXJpb2RfZW5kIjogdHJ1ZSwKICAgICAgICAiY2FuY2VsZWRfYXQi + OiAxNDU5OTU5Mzg2LAogICAgICAgICJjdXJyZW50X3BlcmlvZF9lbmQiOiAx + NDYyNTUxMzgyLAogICAgICAgICJjdXJyZW50X3BlcmlvZF9zdGFydCI6IDE0 + NTk5NTkzODIsCiAgICAgICAgImN1c3RvbWVyIjogImN1c184RGkxd2pkVmt0 + djVrdCIsCiAgICAgICAgImRpc2NvdW50IjogbnVsbCwKICAgICAgICAiZW5k + ZWRfYXQiOiBudWxsLAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAg + ICJwbGFuIjogewogICAgICAgICAgImlkIjogIm1lbnN1ZWwtc3RhbmRhcmQt + bW9udGgtMjAxNjA0MDQxNzE1MTkiLAogICAgICAgICAgIm9iamVjdCI6ICJw + bGFuIiwKICAgICAgICAgICJhbW91bnQiOiAzMDAwLAogICAgICAgICAgImNy + ZWF0ZWQiOiAxNDU5NzgyOTIxLAogICAgICAgICAgImN1cnJlbmN5IjogInVz + ZCIsCiAgICAgICAgICAiaW50ZXJ2YWwiOiAibW9udGgiLAogICAgICAgICAg + ImludGVydmFsX2NvdW50IjogMSwKICAgICAgICAgICJsaXZlbW9kZSI6IGZh + bHNlLAogICAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgICAibmFt + ZSI6ICJNZW5zdWVsIC0gc3RhbmRhcmQsIGFzc29jaWF0aW9uIC0gbW9udGgi + LAogICAgICAgICAgInN0YXRlbWVudF9kZXNjcmlwdG9yIjogbnVsbCwKICAg + ICAgICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwKICAgICAgICB9LAog + ICAgICAgICJxdWFudGl0eSI6IDEsCiAgICAgICAgInN0YXJ0IjogMTQ1OTk1 + OTM4MiwKICAgICAgICAic3RhdHVzIjogImFjdGl2ZSIsCiAgICAgICAgInRh + eF9wZXJjZW50IjogbnVsbCwKICAgICAgICAidHJpYWxfZW5kIjogbnVsbCwK + ICAgICAgICAidHJpYWxfc3RhcnQiOiBudWxsCiAgICAgIH0sCiAgICAgIHsK + ICAgICAgICAiaWQiOiAic3ViXzhEaTlncVBMd3Q1SUlDIiwKICAgICAgICAi + b2JqZWN0IjogInN1YnNjcmlwdGlvbiIsCiAgICAgICAgImFwcGxpY2F0aW9u + X2ZlZV9wZXJjZW50IjogbnVsbCwKICAgICAgICAiY2FuY2VsX2F0X3Blcmlv + ZF9lbmQiOiB0cnVlLAogICAgICAgICJjYW5jZWxlZF9hdCI6IDE0NTk5NDk0 + MDQsCiAgICAgICAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI1NDEzOTks + CiAgICAgICAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ1OTk0OTM5OSwK + ICAgICAgICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAg + ICAgICAiZGlzY291bnQiOiBudWxsLAogICAgICAgICJlbmRlZF9hdCI6IG51 + bGwsCiAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgInBsYW4iOiB7 + CiAgICAgICAgICAiaWQiOiAibWVuc3VlbC1zdGFuZGFyZC1tb250aC0yMDE2 + MDQwNDE3MTUxOSIsCiAgICAgICAgICAib2JqZWN0IjogInBsYW4iLAogICAg + ICAgICAgImFtb3VudCI6IDMwMDAsCiAgICAgICAgICAiY3JlYXRlZCI6IDE0 + NTk3ODI5MjEsCiAgICAgICAgICAiY3VycmVuY3kiOiAidXNkIiwKICAgICAg + ICAgICJpbnRlcnZhbCI6ICJtb250aCIsCiAgICAgICAgICAiaW50ZXJ2YWxf + Y291bnQiOiAxLAogICAgICAgICAgImxpdmVtb2RlIjogZmFsc2UsCiAgICAg + ICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAgICJuYW1lIjogIk1lbnN1 + ZWwgLSBzdGFuZGFyZCwgYXNzb2NpYXRpb24gLSBtb250aCIsCiAgICAgICAg + ICAic3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAogICAgICAgICAgInRy + aWFsX3BlcmlvZF9kYXlzIjogbnVsbAogICAgICAgIH0sCiAgICAgICAgInF1 + YW50aXR5IjogMSwKICAgICAgICAic3RhcnQiOiAxNDU5OTQ5Mzk5LAogICAg + ICAgICJzdGF0dXMiOiAiYWN0aXZlIiwKICAgICAgICAidGF4X3BlcmNlbnQi + OiBudWxsLAogICAgICAgICJ0cmlhbF9lbmQiOiBudWxsLAogICAgICAgICJ0 + cmlhbF9zdGFydCI6IG51bGwKICAgICAgfSwKICAgICAgewogICAgICAgICJp + ZCI6ICJzdWJfOERpMlZhZFJ2cjdBOTkiLAogICAgICAgICJvYmplY3QiOiAi + c3Vic2NyaXB0aW9uIiwKICAgICAgICAiYXBwbGljYXRpb25fZmVlX3BlcmNl + bnQiOiBudWxsLAogICAgICAgICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IHRy + dWUsCiAgICAgICAgImNhbmNlbGVkX2F0IjogMTQ1OTk0ODk3MiwKICAgICAg + ICAiY3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjU0MDk2OCwKICAgICAgICAi + Y3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDU5OTQ4OTY4LAogICAgICAgICJj + dXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJkaXNj + b3VudCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0IjogbnVsbCwKICAgICAg + ICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6IHsKICAgICAgICAg + ICJpZCI6ICJtZW5zdWVsLXN0YW5kYXJkLW1vbnRoLTIwMTYwNDA0MTcxNTE5 + IiwKICAgICAgICAgICJvYmplY3QiOiAicGxhbiIsCiAgICAgICAgICAiYW1v + dW50IjogMzAwMCwKICAgICAgICAgICJjcmVhdGVkIjogMTQ1OTc4MjkyMSwK + ICAgICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAgICAgICAgImludGVy + dmFsIjogIm1vbnRoIiwKICAgICAgICAgICJpbnRlcnZhbF9jb3VudCI6IDEs + CiAgICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICAgICAgICJtZXRh + ZGF0YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAiTWVuc3VlbCAtIHN0YW5k + YXJkLCBhc3NvY2lhdGlvbiAtIG1vbnRoIiwKICAgICAgICAgICJzdGF0ZW1l + bnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAgICAgICAidHJpYWxfcGVyaW9k + X2RheXMiOiBudWxsCiAgICAgICAgfSwKICAgICAgICAicXVhbnRpdHkiOiAx + LAogICAgICAgICJzdGFydCI6IDE0NTk5NDg5NjgsCiAgICAgICAgInN0YXR1 + cyI6ICJhY3RpdmUiLAogICAgICAgICJ0YXhfcGVyY2VudCI6IG51bGwsCiAg + ICAgICAgInRyaWFsX2VuZCI6IG51bGwsCiAgICAgICAgInRyaWFsX3N0YXJ0 + IjogbnVsbAogICAgICB9CiAgICBdLAogICAgImhhc19tb3JlIjogZmFsc2Us + CiAgICAidG90YWxfY291bnQiOiA0LAogICAgInVybCI6ICIvdjEvY3VzdG9t + ZXJzL2N1c184RGkxd2pkVmt0djVrdC9zdWJzY3JpcHRpb25zIgogIH0KfQo= http_version: - recorded_at: Wed, 06 Apr 2016 14:02:53 GMT + recorded_at: Thu, 07 Apr 2016 15:02:25 GMT - request: method: post uri: https://api.stripe.com/v1/invoices @@ -672,7 +667,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:54 GMT + - Thu, 07 Apr 2016 15:02:26 GMT Content-Type: - application/json Content-Length: @@ -690,7 +685,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DiggAW17hqwsf + - req_8E6spkK6V9UkUW Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -699,7 +694,7 @@ http_interactions: encoding: UTF-8 string: | { - "id": "in_17xHFC2sOmf47Nz9ZZeO0yST", + "id": "in_17xeeM2sOmf47Nz9kzn0pC8f", "object": "invoice", "amount_due": 5100, "application_fee": null, @@ -709,7 +704,7 @@ http_interactions: "closed": false, "currency": "usd", "customer": "cus_8Di1wjdVktv5kt", - "date": 1459951374, + "date": 1460041346, "description": null, "discount": null, "ending_balance": null, @@ -718,17 +713,17 @@ http_interactions: "object": "list", "data": [ { - "id": "ii_17xHF82sOmf47Nz9QT6BnkAZ", + "id": "ii_17xeeI2sOmf47Nz9qEhwu9J6", "object": "line_item", "amount": 5100, "currency": "usd", - "description": "Formation Imprimante 3D April 12, 2016 08:00 - 09:00 AM", + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 12:00 PM", "discountable": true, "livemode": false, "metadata": {}, "period": { - "start": 1459951370, - "end": 1459951370 + "start": 1460041342, + "end": 1460041342 }, "plan": null, "proration": false, @@ -739,13 +734,13 @@ http_interactions: ], "has_more": false, "total_count": 1, - "url": "/v1/invoices/in_17xHFC2sOmf47Nz9ZZeO0yST/lines" + "url": "/v1/invoices/in_17xeeM2sOmf47Nz9kzn0pC8f/lines" }, "livemode": false, "metadata": {}, - "next_payment_attempt": 1459954974, + "next_payment_attempt": 1460044946, "paid": false, - "period_end": 1459951374, + "period_end": 1460041346, "period_start": 1459948968, "receipt_number": null, "starting_balance": 0, @@ -758,10 +753,10 @@ http_interactions: "webhooks_delivered_at": null } http_version: - recorded_at: Wed, 06 Apr 2016 14:02:54 GMT + recorded_at: Thu, 07 Apr 2016 15:02:26 GMT - request: method: post - uri: https://api.stripe.com/v1/invoices/in_17xHFC2sOmf47Nz9ZZeO0yST/pay + uri: https://api.stripe.com/v1/invoices/in_17xeeM2sOmf47Nz9kzn0pC8f/pay body: encoding: ASCII-8BIT string: '' @@ -790,7 +785,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:55 GMT + - Thu, 07 Apr 2016 15:02:28 GMT Content-Type: - application/json Content-Length: @@ -808,7 +803,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DigSwPCrF5F8H + - req_8E6srau28jSd0F Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -817,17 +812,17 @@ http_interactions: encoding: UTF-8 string: | { - "id": "in_17xHFC2sOmf47Nz9ZZeO0yST", + "id": "in_17xeeM2sOmf47Nz9kzn0pC8f", "object": "invoice", "amount_due": 5100, "application_fee": null, "attempt_count": 1, "attempted": true, - "charge": "ch_17xHFD2sOmf47Nz97SA1n7nn", + "charge": "ch_17xeeN2sOmf47Nz9bPRkhlte", "closed": true, "currency": "usd", "customer": "cus_8Di1wjdVktv5kt", - "date": 1459951374, + "date": 1460041346, "description": null, "discount": null, "ending_balance": 0, @@ -836,17 +831,17 @@ http_interactions: "object": "list", "data": [ { - "id": "ii_17xHF82sOmf47Nz9QT6BnkAZ", + "id": "ii_17xeeI2sOmf47Nz9qEhwu9J6", "object": "line_item", "amount": 5100, "currency": "usd", - "description": "Formation Imprimante 3D April 12, 2016 08:00 - 09:00 AM", + "description": "Formation Imprimante 3D April 12, 2016 08:00 - 12:00 PM", "discountable": true, "livemode": false, "metadata": {}, "period": { - "start": 1459951370, - "end": 1459951370 + "start": 1460041342, + "end": 1460041342 }, "plan": null, "proration": false, @@ -857,13 +852,13 @@ http_interactions: ], "has_more": false, "total_count": 1, - "url": "/v1/invoices/in_17xHFC2sOmf47Nz9ZZeO0yST/lines" + "url": "/v1/invoices/in_17xeeM2sOmf47Nz9kzn0pC8f/lines" }, "livemode": false, "metadata": {}, "next_payment_attempt": null, "paid": true, - "period_end": 1459951374, + "period_end": 1460041346, "period_start": 1459948968, "receipt_number": null, "starting_balance": 0, @@ -873,13 +868,13 @@ http_interactions: "tax": null, "tax_percent": null, "total": 5100, - "webhooks_delivered_at": 1459951374 + "webhooks_delivered_at": 1460041346 } http_version: - recorded_at: Wed, 06 Apr 2016 14:02:55 GMT + recorded_at: Thu, 07 Apr 2016 15:02:27 GMT - request: method: delete - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources/card_17xHF72sOmf47Nz9pOYRMYdO + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources/card_17xeeH2sOmf47Nz9qkD2jaiS body: encoding: US-ASCII string: '' @@ -906,7 +901,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 14:02:56 GMT + - Thu, 07 Apr 2016 15:02:29 GMT Content-Type: - application/json Content-Length: @@ -924,7 +919,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8DigPHaDWfrkLV + - req_8E6saiNl2MPHRO Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -934,8 +929,8 @@ http_interactions: string: | { "deleted": true, - "id": "card_17xHF72sOmf47Nz9pOYRMYdO" + "id": "card_17xeeH2sOmf47Nz9qkD2jaiS" } http_version: - recorded_at: Wed, 06 Apr 2016 14:02:56 GMT + recorded_at: Thu, 07 Apr 2016 15:02:28 GMT recorded_with: VCR 3.0.1 From 7649e953e4152c0a257f4ec181ba04f0dfd15e90 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 17:57:48 +0200 Subject: [PATCH 37/64] refacto subscription extension with first training using a service --- app/controllers/api/reservations_controller.rb | 10 ++-------- app/controllers/api/slots_controller.rb | 9 +-------- app/models/subscription.rb | 6 ------ 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/app/controllers/api/reservations_controller.rb b/app/controllers/api/reservations_controller.rb index 08cee38a5..f7332d0aa 100644 --- a/app/controllers/api/reservations_controller.rb +++ b/app/controllers/api/reservations_controller.rb @@ -28,10 +28,8 @@ class API::ReservationsController < API::ApiController is_reserve = @reservation.save_with_payment end if is_reserve - reservation_user = @reservation.user - if @reservation.reservable_type == 'Training' and is_first_training_and_active_subscription(reservation_user) - reservation_user.subscription.update_expired_date_with_first_training(@reservation.slots.first.start_at) - end + SubscriptionExtensionAfterReservation.new(@reservation).extend_subscription_if_eligible + render :show, status: :created, location: @reservation else render json: @reservation.errors, status: :unprocessable_entity @@ -57,8 +55,4 @@ class API::ReservationsController < API::ApiController :nb_reserve_places, :nb_reserve_reduced_places, slots_attributes: [:id, :start_at, :end_at, :availability_id, :offered]) end - - def is_first_training_and_active_subscription(user) - user.reservations.where(reservable_type: 'Training').size == 1 and user.subscription and !user.subscription.is_expired? - end end diff --git a/app/controllers/api/slots_controller.rb b/app/controllers/api/slots_controller.rb index 5e5179afe..1d315cd24 100644 --- a/app/controllers/api/slots_controller.rb +++ b/app/controllers/api/slots_controller.rb @@ -6,10 +6,7 @@ class API::SlotsController < API::ApiController def update authorize @slot if @slot.update(slot_params) - reservation_user = @slot.reservation.user - if @slot.reservation.reservable_type == 'Training' and is_first_training_and_active_subscription(reservation_user) - reservation_user.subscription.update_expired_date_with_first_training(@slot.start_at) - end + SubscriptionExtensionAfterReservation.new(@slot.reservation).extend_subscription_if_eligible render :show, status: :created, location: @slot else render json: @slot.errors, status: :unprocessable_entity @@ -29,8 +26,4 @@ class API::SlotsController < API::ApiController def slot_params params.require(:slot).permit(:start_at, :end_at, :availability_id) end - - def is_first_training_and_active_subscription(user) - user.reservations.where(reservable_type: 'Training').size == 1 and user.subscription and !user.subscription.is_expired? - end end diff --git a/app/models/subscription.rb b/app/models/subscription.rb index dfd0bd5e2..1d9ccd240 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -102,12 +102,6 @@ class Subscription < ActiveRecord::Base invoice.save end - def update_expired_date_with_first_training(training_start_at) - if plan.is_rolling? - update_columns(expired_at: training_start_at + plan.duration) - end - end - def cancel if stp_subscription_id.present? stp_subscription = stripe_subscription From 9bfd5e03626addb3c5fc505bd358d151d5086771 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Apr 2016 18:05:23 +0200 Subject: [PATCH 38/64] removes block from Sidekiq::Testing setup in test_helper unless tests don't pass anymore --- test/test_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index c222a602b..1f030b920 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -10,9 +10,9 @@ VCR.configure do |config| config.hook_into :webmock end -Sidekiq::Testing.inline! do |pp| - puts pp -end +Sidekiq::Testing.inline!# do |pp| + #puts pp +#end Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new({ color: true })] From 74e2d170bf704cbf3b60fcb94e97df573d901551 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 10:02:45 +0200 Subject: [PATCH 39/64] adds integration test for reservations for user with invoicing disabled --- .../reservations/create_as_admin_test.rb | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/integration/reservations/create_as_admin_test.rb b/test/integration/reservations/create_as_admin_test.rb index 6383c93fd..ebd66a5a1 100644 --- a/test/integration/reservations/create_as_admin_test.rb +++ b/test/integration/reservations/create_as_admin_test.rb @@ -7,6 +7,45 @@ module Reservations login_as(@admin, scope: :user) end + test "user without subscription and with invoicing disabled reserves a machine with success" do + @user_without_subscription.update!(invoicing_disabled: true) + machine = Machine.find(6) + availability = machine.availabilities.first + + reservations_count = Reservation.count + invoice_count = Invoice.count + invoice_items_count = InvoiceItem.count + users_credit_count = UsersCredit.count + + post reservations_path, { reservation: { + user_id: @user_without_subscription.id, + reservable_id: machine.id, + reservable_type: machine.class.name, + slots_attributes: [ + { start_at: availability.start_at.to_s(:iso8601), + end_at: (availability.start_at + 1.hour).to_s(:iso8601), + availability_id: availability.id + } + ] + }}.to_json, default_headers + + # general assertions + assert_equal 201, response.status + assert_equal reservations_count + 1, Reservation.count + assert_equal invoice_count, Invoice.count + assert_equal invoice_items_count, InvoiceItem.count + assert_equal users_credit_count, UsersCredit.count + + # reservation assertions + reservation = Reservation.last + + refute reservation.invoice + assert reservation.stp_invoice_id.blank? + + # notification + assert_not_empty Notification.where(attached_object: reservation) + end + test "user without subscription reserves a machine with success" do machine = Machine.find(6) availability = machine.availabilities.first From aee814604014dca1b4783ea7ca99c6ed0dbf3fdc Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 10:33:50 +0200 Subject: [PATCH 40/64] users_credits/manager service: initializing service, you can pass a plan to simulate that user have that plan --- app/services/users_credits/manager.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/services/users_credits/manager.rb b/app/services/users_credits/manager.rb index 35a1d2dca..eec89155a 100644 --- a/app/services/users_credits/manager.rb +++ b/app/services/users_credits/manager.rb @@ -7,14 +7,14 @@ module UsersCredits extend Forwardable attr_reader :manager - def initialize(reservation: nil, user: nil) + def initialize(reservation: nil, user: nil, plan: nil) if user @manager = Managers::User.new(user) elsif reservation if reservation.reservable_type == "Training" - @manager = Managers::Training.new(reservation) + @manager = Managers::Training.new(reservation, plan) elsif reservation.reservable_type == "Machine" - @manager = Managers::Machine.new(reservation) + @manager = Managers::Machine.new(reservation, plan) end end end @@ -38,13 +38,14 @@ module UsersCredits class Reservation attr_reader :reservation - def initialize(reservation) + def initialize(reservation, plan) @reservation = reservation @already_updated = false + @plan = plan end def plan - user.subscribed_plan + @plan || user.subscribed_plan end def user @@ -129,7 +130,7 @@ module UsersCredits # if there is a training_credit defined for this plan and this training if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id) # if user has not used all the plan credits - if user.training_credits.count < plan.training_credit_nb + if user.training_credits.where(plan: plan).count < plan.training_credit_nb return true, training_credit end end From dbe8d4266368b885eb6c00aacdc561d72f50ab7e Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 11:10:36 +0200 Subject: [PATCH 41/64] adds byebug to gemfile for group test --- Gemfile | 1 + Gemfile.lock | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index 50b95f0e7..4359d9755 100644 --- a/Gemfile +++ b/Gemfile @@ -60,6 +60,7 @@ group :test do gem 'minitest-reporters' gem 'webmock' gem 'vcr' + gem 'byebug' end group :production do diff --git a/Gemfile.lock b/Gemfile.lock index 7c1b4b090..7e86fbd04 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -59,6 +59,7 @@ GEM sass (>= 3.2.19) buftok (0.2.0) builder (3.2.2) + byebug (8.2.3) camertron-eprun (1.1.0) capistrano (2.15.5) highline @@ -426,6 +427,7 @@ DEPENDENCIES active_record_query_trace awesome_print bootstrap-sass + byebug capistrano capistrano-maintenance (= 0.0.5) capistrano-sidekiq From d22574dae4d3eb7511fe891b1604b0ea64ca8fa6 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 11:11:42 +0200 Subject: [PATCH 42/64] UsersCredits::Manager is more strict about arguments that have to be passed --- app/services/users_credits/manager.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/services/users_credits/manager.rb b/app/services/users_credits/manager.rb index eec89155a..4021d5676 100644 --- a/app/services/users_credits/manager.rb +++ b/app/services/users_credits/manager.rb @@ -15,7 +15,11 @@ module UsersCredits @manager = Managers::Training.new(reservation, plan) elsif reservation.reservable_type == "Machine" @manager = Managers::Machine.new(reservation, plan) + else + raise ArgumentError, "reservation.reservable_type must be Training or Machine" end + else + raise ArgumentError, "you have to pass either a reservation or a user to initialize a UsersCredits::Manager" end end From c78e010888b4672cc4586046687d96468464667b Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 11:12:03 +0200 Subject: [PATCH 43/64] refacto method generate_invoice_items using UsersCredits::Manager service --- app/models/reservation.rb | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 04e493c37..ea31b7158 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -73,28 +73,12 @@ class Reservation < ActiveRecord::Base # === Training reservation === when Training - # TO BE REFACTORED WHEN PLAN PURCHASE AND RESERVATION PURCHASE WILL BE DECOUPLED - base_amount = reservable.amount_by_group(user.group_id).amount - if plan - # Return True if the subscription link a training credit for training reserved by the user - training_is_creditable = plan.training_credits.select {|credit| credit.creditable_id == reservable.id}.size > 0 - # Training reserved by the user is free when : + # be careful, variable plan can be the user's plan OR the plan user is currently purchasing + users_credits_manager = UsersCredits::Manager.new(reservation: self, plan: plan) + base_amount = 0 if users_credits_manager.will_use_credits? - # |-> the user already has a current subscription and if training_is_creditable is true and has at least one credit available. - if !new_plan_being_bought - if user.training_credits.size < plan.training_credit_nb and training_is_creditable - base_amount = 0 - end - # |-> the user buys a new subscription and if training_is_creditable is true. - else - if training_is_creditable - base_amount = 0 - end - end - - end slots.each do |slot| description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}" ii_amount = base_amount From d104403af03a2e2c3631c31dce10d23461438235 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 11:17:52 +0200 Subject: [PATCH 44/64] little fix Reservation#generate_invoice_items take into account that plan can be purchased at the same time when reserving machine --- app/models/reservation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/reservation.rb b/app/models/reservation.rb index ea31b7158..4cbf36c03 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -45,7 +45,7 @@ class Reservation < ActiveRecord::Base # === Machine reservation === when Machine base_amount = reservable.prices.find_by(group_id: user.group_id, plan_id: plan.try(:id)).amount - users_credits_manager = UsersCredits::Manager.new(reservation: self) + users_credits_manager = UsersCredits::Manager.new(reservation: self, plan: plan) slots.each_with_index do |slot, index| description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}" From b46ee9177c25d9a03672041ca2b2907ebc0bef70 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 11:26:31 +0200 Subject: [PATCH 45/64] adds comments to service UsersCredits::Manager --- app/services/users_credits/manager.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/services/users_credits/manager.rb b/app/services/users_credits/manager.rb index 4021d5676..6fa9b7398 100644 --- a/app/services/users_credits/manager.rb +++ b/app/services/users_credits/manager.rb @@ -27,7 +27,7 @@ module UsersCredits end module Managers - class User + class User # that class is responsible for reseting users_credits of a user attr_reader :user def initialize(user) @@ -42,7 +42,7 @@ module UsersCredits class Reservation attr_reader :reservation - def initialize(reservation, plan) + def initialize(reservation, plan) # a plan can be passed to do a simulation (if user didn't have a subscription YET) @reservation = reservation @already_updated = false @plan = plan @@ -67,8 +67,8 @@ module UsersCredits private_constant :Reservation - class Machine < Reservation - def will_use_credits? + class Machine < Reservation # that class is responsible for knowing how to update users_credit of a given user for a given reservation + def will_use_credits? # to known if a credit will be used in the context of the given reservation _will_use_credits?[0] end @@ -114,7 +114,7 @@ module UsersCredits end end - class Training < Reservation + class Training < Reservation # same as class Machine but for Training reservation def will_use_credits? _will_use_credits?[0] end From fa64fd7a2e32545d0f474ac5e0caeaf4c00c18ec Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 16:58:46 +0200 Subject: [PATCH 46/64] remove useless method --- app/models/subscription.rb | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/models/subscription.rb b/app/models/subscription.rb index 1d9ccd240..04ecc8db3 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -142,18 +142,6 @@ class Subscription < ActiveRecord::Base end private - def update_payment - if stp_subscription_id.present? - stp_subscription = stripe_subscription - stp_subscription.plan = plan.stp_plan_id - stp_subscription.prorate = false - stp_subscription.save - else - # TODO: implement stripe payment if member update subscription - # must have a card - end - end - def notify_member_subscribed_plan NotificationCenter.call type: 'notify_member_subscribed_plan', receiver: user, From 1344e09f9681f9890b652bfe40d7635952d525d1 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Fri, 8 Apr 2016 16:59:09 +0200 Subject: [PATCH 47/64] adds comments to model reservation --- app/models/reservation.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 4cbf36c03..2c4359064 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -144,6 +144,10 @@ class Reservation < ActiveRecord::Base total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+) self.invoice.total = total save! + # + # IMPORTANT NOTE: here, we don't have to create a stripe::invoice and pay it + # because subscription.create (in subscription.rb) will pay all waiting stripe invoice items + # else # error handling invoice_items.each(&:delete) @@ -163,6 +167,9 @@ class Reservation < ActiveRecord::Base customer.save end end + # + # IMPORTANT NOTE: here, we have to create an invoice manually and pay it to pay all waiting stripe invoice items + # invoice = Stripe::Invoice.create( customer: user.stp_customer_id, ) From 91025019694c9f3e8b1eadb9b5014297849998a0 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 11 Apr 2016 09:06:04 +0200 Subject: [PATCH 48/64] fix typo in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cbfc21824..cd92670c4 100644 --- a/README.md +++ b/README.md @@ -524,7 +524,7 @@ After modifying any values concerning the localisation, restart the application ## Known issues - When browsing a machine page, you may encounter an "InterceptError" in the console and the loading bar will stop loading before reaching its ending. - This may append if the machine was created through a seed file without any image. + This may happen if the machine was created through a seed file without any image. To solve this, simply add an image to the machine's profile and refresh the web page. - When starting the Ruby on Rails server (eg. `foreman s`) you may receive the following error: @@ -533,7 +533,7 @@ After modifying any values concerning the localisation, restart the application web.1 | Exiting worker.1 | ...lib/redis/client.rb...:in `_parse_options' - This may happens when the `application.yml` file is missing. + This may happen when the `application.yml` file is missing. To solve this issue copy `config/application.yml.default` to `config/application.yml`. This is required before the first start. From 1d36ffce17c6e6f65328459e93acada125b0fdf2 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 11 Apr 2016 09:38:09 +0200 Subject: [PATCH 49/64] add infos about Postgre config for tests --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index cd92670c4..3d030c234 100644 --- a/README.md +++ b/README.md @@ -539,6 +539,24 @@ After modifying any values concerning the localisation, restart the application - Due to a stripe limitation, you won't be ble to create plans longer than one year. +- When running the tests suite with `rake test`, all tests may fail with errors similar to the following: + + Error: + ... + ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "..." violates foreign key constraint "fk_rails_..." + DETAIL: Key (group_id)=(1) is not present in table "groups". + : ... + test_after_commit (1.0.0) lib/test_after_commit/database_statements.rb:11:in `block in transaction' + test_after_commit (1.0.0) lib/test_after_commit/database_statements.rb:5:in `transaction' + + This is due to an ActiveRecord behavior witch disable referential integrity in PostgreSQL to load the fixtures. + PostgreSQL will prevent any users to disable referential integrity on the fly if they doesn't have the `SUPERUSER` role. + To fix that, logon as the `postgres` user and run the PostgreSQL shell (see [Setup the FabManager database in PostgreSQL](#setup-fabmanager-in-postgresql) for an example). + Then, run the following command (replace `sleede` with your test database user, as specified in your database.yml): + + ALTER ROLE sleede WITH SUPERUSER; + + DO NOT do this in a production environment, as this would lead to a serious security issue. ## Related Documentation From 5c7d52a6f3e68e62417337a7d8c648a9aa107d0c Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 11 Apr 2016 11:31:32 +0200 Subject: [PATCH 50/64] mails translations in english --- config/application.rb | 2 +- config/locales/mails.en.yml | 208 ++++++++++++++++++------------------ 2 files changed, 105 insertions(+), 105 deletions(-) diff --git a/config/application.rb b/config/application.rb index 8bc56fb5a..a48a2d29e 100644 --- a/config/application.rb +++ b/config/application.rb @@ -30,7 +30,7 @@ module Fablab # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # - # /!\ ALL locales above SHOULD be configured accordingly with this locale. /!\ + # /!\ ALL locales SHOULD be configured accordingly with this locale. /!\ # config.i18n.default_locale = Rails.application.secrets.rails_locale diff --git a/config/locales/mails.en.yml b/config/locales/mails.en.yml index f811d455b..8ec076374 100644 --- a/config/locales/mails.en.yml +++ b/config/locales/mails.en.yml @@ -1,244 +1,244 @@ en: layouts: - notifications_mailer: - see_you_later: - sincerely: - signature: - do_not_reply: + notifications_mailer: + see_you_later: "See you soon on {GENDER, select, other{the}}" # messageFormat interpolation + sincerely: "Sincerely," + signature: "The Fab Lab team." + do_not_reply: "Please do not reply to this email." users_mailer: notify_user_account_created: subject: "Your FabLab account has been successfully created" body: hello: "Hello %{NAME}," - intro: "The FabLab team has just created an account for you, on the {FABLAB} site:" # messageFormat interpolation + intro: "The FabLab team has just created an account for you, on the {FABLAB} website:" # messageFormat interpolation connection_parameters: "Here are your connection parameters:" account_name: "Account name:" password: "Password:" - temporary_password: - keep_advantages: - thanks_to_: - logon_or_login: - token_if_link_problem: + temporary_password: "This is a temporary password, you can modify it in your «My account» screen." + keep_advantages: "With this account, you keep all the advantages linked to your Fab Lab user profile (trainings, subscriptions plans)." + thanks_to_: "To use the website, please" + logon_or_login: "create a new account or log in by clicking here" + token_if_link_problem: "If you experience issues with the link, you can enter the following code at your first connection attempt:" notifications_mailer: notify_user_user_group_changed: - subject: "Your group has changed" + subject: "Your have changed group" body: - warning: + warning: "You have changed group. Inspections can be conducted at the lab to verify the legitimacy of this change." notify_admin_user_group_changed: - subject: "A member has changed his group" + subject: "A member has changed group" body: - user_changed_group_html: - previous_group: - new_group: + user_changed_group_html: "User %{NAME} has changed group." + previous_group: "Previous group:" + new_group: "New group:" notify_admin_subscription_extended: subject: "A subscription has been extended" body: - subscription_extended_html: + subscription_extended_html: "Subscription {PLAN} for user {NAME} has been extended {FREE, select, true{for free} other{}} until {DATE}." # messageFormat interpolation notify_member_subscription_extended: - subject: "Your subscription has been extended" + subject: "Your subscription plan has been extended" body: - your_plan: - has_been_extended: - free: - until: + your_plan: "Your subscription plan" + has_been_extended: "has been extended" + free: "for free" + until: "until" notify_partner_subscribed_plan: - subject: "A subscription has been purchased" + subject: "A subscription plan has been purchased" body: - a_plan: - was_purchased_by_member: + a_plan: "A subscription plan" + was_purchased_by_member: "has been purchased by user" notify_admin_when_project_published: subject: "A project has been published" body: - new_project_published: + new_project_published: "A new project has been published:" notify_project_collaborator_to_valid: - subject: "Invitation to take part in a project" + subject: "Invitation to collaborate on a project" body: - your_are_invited_to_take_part_in_a_project: - to_accept_the_invitation_click_on_following_link: + your_are_invited_to_take_part_in_a_project: "You are invited to join this project:" + to_accept_the_invitation_click_on_following_link: "To accept this invitation, please click on the following link:" notify_project_author_when_collaborator_valid: subject: "New collaborator in your project" body: - the_member: - accepted_your_invitation_to_take_part_in_the_project: + the_member: "the user" + accepted_your_invitation_to_take_part_in_the_project: "has accepted your invitation to join your project:" notify_user_training_valid: subject: "Your training has been validated" body: - your_training: - has_been_validated: + your_training: "Your training" + has_been_validated: "has been validated" notify_member_subscribed_plan: subject: "Your subscription has been successfully purchased" body: - plan_subscribed_html: - subscription_stops_on: + plan_subscribed_html: "You have subscribed the plan: %{PLAN}." + subscription_stops_on: "Your subscription plan will end on %{DATE}" notify_member_create_reservation: - subject: "Your réservation has been successfully saved" + subject: "Your reservation has been successfully saved" body: - reservation_saved_html: - your_reserved_slots: + reservation_saved_html: "You reservation %{RESERVATION} has been successfully saved" + your_reserved_slots: "Your reserved slots are:" notify_member_subscribed_plan_is_changed: subject: "Your subscription has been updated" body: - new_plan_html: + new_plan_html: "You have changed your plan to %{PLAN}." notify_admin_member_create_reservation: subject: "New reservation" body: - member_reserved_html: - reserved_slots: + member_reserved_html: "User %{NAME} has reserved %{RESERVABLE}." + reserved_slots: "Reserved slots are:" notify_member_slot_is_modified: subject: "Your reservation slot has been successfully changed" body: - reservation_changed_to: - previous_date: + reservation_changed_to: "Your reservation slot has been changed to:" + previous_date: "Previous date:" notify_admin_slot_is_modified: - subject: + subject: "A reservation slot has been modified" body: - slot_modified: - new_date: - old_date: + slot_modified: "User %{NAME} had modified his reservation slot" + new_date: "New slot" + old_date: "Previous slot" notify_admin_when_user_is_created: subject: "A user account has been created" body: - new_account_created: - invoicing_disabled_html: + new_account_created: "A new user account has been created on the website:" + invoicing_disabled_html: "Invoicing generation is disabled for this user." notify_admin_subscribed_plan: subject: "A subscription has been purchased" body: - plan_subscribed_html: + plan_subscribed_html: "A plan %{PLAN} has been subscribed by user %{NAME}." notify_member_invoice_ready: subject: "Your FabLab's invoice" body: - please_find_attached_html: - invoice_in_your_dashboard_html: - your_dashboard: + please_find_attached_html: "Please find as attached file your invoice from {DATE}, with an amount of {AMOUNT} concerning your {TYPE, select, Reservation{reservation} other{subscription}}." # messageFormat interpolation + invoice_in_your_dashboard_html: "You can access your invoice in %{DASHBOARD} on the Fab Lab website." + your_dashboard: "your dashboard" notify_member_avoir_ready: subject: "Your FabLab's refund invoice" body: - please_find_attached_html: - invoice_in_your_dashboard_html: - your_dashboard: + please_find_attached_html: "Please find as attached file your refund invoice from {DATE}, with an amount of {AMOUNT} concerning your {TYPE, select, Reservation{reservation} other{subscription}}." # messageFormat interpolation + invoice_in_your_dashboard_html: "You can access your refund invoice in %{DASHBOARD} on the Fab Lab website." + your_dashboard: "your dashboard" notify_member_subscription_will_expire_in_7_days: subject: "Your subscription expires in 7 days" body: - your_plan: - expires_in_7_days: - to_renew_your_plan_follow_the_link: + your_plan: "you plan" + expires_in_7_days: "will expire in 7 days." + to_renew_your_plan_follow_the_link: "Please, follow this link to renew your plan" notify_member_subscription_is_expired: subject: "Your subscription has expired" body: - your_plan: - has_expired: - you_can_go_to: - to_renew_your_plan: + your_plan: "You plan" + has_expired: "has expired." + you_can_go_to: "Please go to" + to_renew_your_plan: "to renew you plan" notify_admin_subscription_will_expire_in_7_days: subject: "A member subscription expires in 7 days" body: - subscription_will_expire_html: + subscription_will_expire_html: "Subscription plan for user %{NAME} %{PLAN} will expire in 7 days." notify_admin_subscription_is_expired: subject: "A member subscription has expired" body: - subscription_expired_html: + subscription_expired_html: "Subscription plan for user %{NAME} %{PLAN} is now expired." notify_admin_subscription_canceled: - subject: "A member subscription has been canceled" + subject: "A member subscription has been cancelled" body: - subscription_canceled_html: + subscription_canceled_html: "Subscription %{PLAN} for user %{NAME} has been cancelled." notify_member_subscription_canceled: - subject: "Your subscription has been canceled" + subject: "Your subscription has been cancelled" body: - your_plan_was_canceled: - your_plan: - end_at: + your_plan_was_canceled: "Your subscription plan has been cancelled." + your_plan: "your subscription plan" + end_at: "ends on" notify_member_slot_is_canceled: subject: "Your reservation has been canceled" body: - reservation_canceled: + reservation_canceled: "Your reservation for %{RESERVABLE} has been canceled" notify_admin_slot_is_canceled: - subject: "A reservation has been canceled" + subject: "A reservation has been cancelled" body: - member_cancelled: - item_details: - generate_refund: + member_cancelled: "User %{NAME} has cancelled his reservation" + item_details: "%{START} - %{END}, concerning %{RESERVABLE}" + generate_refund: "Do not forget to generate a credit note or a refund for this cancellation." notify_admin_when_user_is_imported: subject: "A user account has been imported from the SSO" body: - new_account_imported: - provider_uid: - known_informations: - address_already_used: - no_more_info_available: + new_account_imported: "A new user account (ID: %{ID}) has been imported to the website via %{PROVIDER}." + provider_uid: "its provider ID is: " + known_informations: "Here is what we know about this provider:" + address_already_used: "This address is already associated with another user" + no_more_info_available: "No other info about this user can be provided before he completes his profile." notify_user_profile_complete: - subject: "You now have access to the entire platform" + subject: "You now have access to the whole website" body: - message: + message: "Your account informations has been correctly updated, you now have access to the whole website." notify_user_auth_migration: subject: "Important change to your FabLab account" body: - the_platform: - is_changing_its_auth_system_and_will_now_use: - instead_of: - consequence_of_the_modification: - to_use_the_platform_thanks_for: - create_an_account_on: - or_use_an_existing_account_clicking_here: - in_case_of_problem_enter_the_following_code: + the_platform: "the website" + is_changing_its_auth_system_and_will_now_use: "is actually changing its user identification system and will use" + instead_of: "instead of" + consequence_of_the_modification: "Because of this change you won't be able to login to the website with your actual usernames" + to_use_the_platform_thanks_for: "to keep on using the website, please" + create_an_account_on: "create an account on" + or_use_an_existing_account_clicking_here: "or use an existing account by clicking here" + in_case_of_problem_enter_the_following_code: "In case of problem with this link, you can enter the following code at your first connection attempt in order to migrate your actual account into the new authentification system:" notify_admin_user_merged: subject: "An imported account has been merged with an existing account" body: - imported_account_merged: - provider_uid: + imported_account_merged: "A previously imported user account via %{PROVIDER) has been merged with the existing account %{NAME}" + provider_uid: "its provider ID is:" notify_admin_profile_complete: subject: "An imported account has completed its profile" body: - account_completed: - provider_id: + account_completed: "A previously imported user account via %{PROVIDER} has completed its profile:" + provider_id: "its provider ID is:" notify_admin_abuse_reported: subject: "An abusive content has been reported" body: - intro: - signaled_content: - signaled_by: - signaled_on: - message: + intro: "A user has flagged a content as abusive" + signaled_content: "flagged content:" + signaled_by: "flagged by:" + signaled_on: "flagged on:" + message: "Message:" notify_admin_invoicing_changed: subject: "An invoicing parameter has been changed" body: - generation_status_html: - disabled: - enabled: + generation_status_html: "Invoicing issuing has been {STATUS, select, true{disabled} other{enabled}} for the user {NAME}." # messageFormat interpolation + disabled: "From now on, no invoice will be issued when the user pays at the reception." + enabled: "From now on, all payments made by this user at the reception will lead to invoicing issuing. " shared: hello: "Hello %{user_name}" From 31ee15180973bb759a937a18202ba18b3261197d Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 11 Apr 2016 15:31:25 +0200 Subject: [PATCH 51/64] reproductible tests for invoice generation --- .../reservations/create_as_admin_test.rb | 9 +++------ test/integration/reservations/create_test.rb | 12 ++++-------- .../subscriptions/create_as_admin_test.rb | 3 +-- .../subscriptions/create_as_user_test.rb | 3 +-- .../subscriptions/renew_as_user_test.rb | 3 +-- test/test_helper.rb | 18 +++++++++++++++--- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/test/integration/reservations/create_as_admin_test.rb b/test/integration/reservations/create_as_admin_test.rb index ebd66a5a1..69c114904 100644 --- a/test/integration/reservations/create_as_admin_test.rb +++ b/test/integration/reservations/create_as_admin_test.rb @@ -95,8 +95,7 @@ module Reservations # invoice assertions invoice = Invoice.find_by(invoiced: reservation) - assert invoice - assert File.exist?(invoice.file) + assert_invoice_pdf invoice # notification assert_not_empty Notification.where(attached_object: reservation) @@ -148,8 +147,7 @@ module Reservations # invoice assertions invoice = Invoice.find_by(invoiced: reservation) - assert invoice - assert File.exist?(invoice.file) + assert_invoice_pdf invoice # notification assert_not_empty Notification.where(attached_object: reservation) @@ -217,8 +215,7 @@ module Reservations # invoice assertions invoice = Invoice.find_by(invoiced: reservation) - assert invoice - assert File.exist?(invoice.file) + assert_invoice_pdf invoice # notification assert_not_empty Notification.where(attached_object: reservation) diff --git a/test/integration/reservations/create_test.rb b/test/integration/reservations/create_test.rb index 8b7f16a42..08658e918 100644 --- a/test/integration/reservations/create_test.rb +++ b/test/integration/reservations/create_test.rb @@ -59,8 +59,7 @@ module Reservations # invoice assertions invoice = Invoice.find_by(invoiced: reservation) - assert invoice - assert File.exist?(invoice.file) + assert_invoice_pdf invoice # notification assert_not_empty Notification.where(attached_object: reservation) @@ -152,8 +151,7 @@ module Reservations # invoice assertions invoice = Invoice.find_by(invoiced: reservation) - assert invoice - assert File.exist?(invoice.file) + assert_invoice_pdf invoice # notification assert_not_empty Notification.where(attached_object: reservation) @@ -226,8 +224,7 @@ module Reservations # invoice assertions invoice = Invoice.find_by(invoiced: reservation) - assert invoice - assert File.exist?(invoice.file) + assert_invoice_pdf invoice # notification assert_not_empty Notification.where(attached_object: reservation) @@ -287,8 +284,7 @@ module Reservations # invoice assertions invoice = Invoice.find_by(invoiced: reservation) - assert invoice - assert File.exist?(invoice.file) + assert_invoice_pdf invoice # notification assert_not_empty Notification.where(attached_object: reservation) diff --git a/test/integration/subscriptions/create_as_admin_test.rb b/test/integration/subscriptions/create_as_admin_test.rb index e14eab456..c23e3ccd4 100644 --- a/test/integration/subscriptions/create_as_admin_test.rb +++ b/test/integration/subscriptions/create_as_admin_test.rb @@ -50,8 +50,7 @@ module Subscriptions # Check generated invoice invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) - assert_not_nil invoice, 'Invoice was not created' - assert File.exist?(invoice.file), 'Invoice PDF was not generated' + assert_invoice_pdf invoice assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' end diff --git a/test/integration/subscriptions/create_as_user_test.rb b/test/integration/subscriptions/create_as_user_test.rb index 92822388c..fd1882bca 100644 --- a/test/integration/subscriptions/create_as_user_test.rb +++ b/test/integration/subscriptions/create_as_user_test.rb @@ -51,8 +51,7 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest # Check generated invoice invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) - assert_not_nil invoice, 'Invoice was not created' - assert File.exist?(invoice.file), 'Invoice PDF was not generated' + assert_invoice_pdf invoice assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' end diff --git a/test/integration/subscriptions/renew_as_user_test.rb b/test/integration/subscriptions/renew_as_user_test.rb index 240bbc10b..4def40e4e 100644 --- a/test/integration/subscriptions/renew_as_user_test.rb +++ b/test/integration/subscriptions/renew_as_user_test.rb @@ -46,8 +46,7 @@ class Subscriptions::RenewAsUserTest < ActionDispatch::IntegrationTest # Check generated invoice invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) - assert_not_nil invoice, 'Invoice was not created' - #FIXME assert File.exist?(invoice.file), 'Invoice PDF was not generated' + assert_invoice_pdf invoice assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' end diff --git a/test/test_helper.rb b/test/test_helper.rb index 1f030b920..ef130913f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -10,9 +10,7 @@ VCR.configure do |config| config.hook_into :webmock end -Sidekiq::Testing.inline!# do |pp| - #puts pp -#end +Sidekiq::Testing.fake! Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new({ color: true })] @@ -58,6 +56,20 @@ class ActiveSupport::TestCase }, ).id end + + # Force the invoice generation worker to run NOW and check the resulting file generated. + # Delete the file afterwards. + # @param invoice {Invoice} + def assert_invoice_pdf(invoice) + assert_not_nil invoice, 'Invoice was not created' + + invoice_worker = InvoiceWorker.new + invoice_worker.perform(invoice.id) + + assert File.exist?(invoice.file), 'Invoice PDF was not generated' + + File.delete(invoice.file) + end end class ActionDispatch::IntegrationTest From f9628b4989ea726f5c299748cb16b300032c61b5 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 11 Apr 2016 18:37:06 +0200 Subject: [PATCH 52/64] prevent subscription creation/modification if card_token is invalid --- .../api/subscriptions_controller.rb | 22 +- app/pdfs/pdf/invoice.rb | 4 +- app/validators/stripe_card_token_validator.rb | 15 + .../subscriptions/renew_as_user_test.rb | 2 +- .../subscriptions_user_create_failed.yml | 738 +------------- .../subscriptions_user_create_success.yml | 716 +++++++------ .../subscriptions_user_renew_failed.yml | 156 ++- .../subscriptions_user_renew_success.yml | 948 ++++++++++-------- 8 files changed, 1209 insertions(+), 1392 deletions(-) create mode 100644 app/validators/stripe_card_token_validator.rb diff --git a/app/controllers/api/subscriptions_controller.rb b/app/controllers/api/subscriptions_controller.rb index 368286558..20bcdc709 100644 --- a/app/controllers/api/subscriptions_controller.rb +++ b/app/controllers/api/subscriptions_controller.rb @@ -14,16 +14,18 @@ class API::SubscriptionsController < API::ApiController else if current_user.is_admin? @subscription = Subscription.find_or_initialize_by(user_id: subscription_params[:user_id]) - # @subscription.expired_at = nil @subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important @subscription.attributes = subscription_params is_subscribe = @subscription.save_with_local_payment(!User.find(subscription_params[:user_id]).invoicing_disabled?) else @subscription = Subscription.find_or_initialize_by(user_id: current_user.id) - # @subscription.expired_at = nil - @subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important - @subscription.attributes = subscription_params.merge(user_id: current_user.id) - is_subscribe = @subscription.save_with_payment + if valid_card_token?(subscription_params[:card_token]) + @subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important + @subscription.attributes = subscription_params.merge(user_id: current_user.id) + is_subscribe = @subscription.save_with_payment + else + is_subscribe = false + end end if is_subscribe render :show, status: :created, location: @subscription @@ -61,4 +63,14 @@ class API::SubscriptionsController < API::ApiController def subscription_update_params params.require(:subscription).permit(:expired_at) end + + # TODO refactor subscriptions logic and move this in model/validator + def valid_card_token?(token) + begin + Stripe::Token.retrieve(token) + rescue Stripe::InvalidRequestError => e + @subscription.errors[:card_token] << e.message + false + end + end end diff --git a/app/pdfs/pdf/invoice.rb b/app/pdfs/pdf/invoice.rb index ce890dad0..6e2120159 100644 --- a/app/pdfs/pdf/invoice.rb +++ b/app/pdfs/pdf/invoice.rb @@ -139,8 +139,8 @@ module PDF vat_rate = Setting.find_by({name: 'invoice_VAT-rate'}).value.to_f vat = total / (vat_rate / 100 + 1) - data += [ [I18n.t('invoices.including_VAT_RATE', RATE: vat_rate), number_to_currency(vat)] ] - data += [ [I18n.t('invoices.including_total_excluding_taxes'), number_to_currency(total-vat)] ] + data += [ [I18n.t('invoices.including_VAT_RATE', RATE: vat_rate), number_to_currency(total-vat)] ] + data += [ [I18n.t('invoices.including_total_excluding_taxes'), number_to_currency(vat)] ] data += [ [I18n.t('invoices.including_amount_payed_on_ordering'), number_to_currency(total)] ] # checking the round number diff --git a/app/validators/stripe_card_token_validator.rb b/app/validators/stripe_card_token_validator.rb new file mode 100644 index 000000000..1d7a78165 --- /dev/null +++ b/app/validators/stripe_card_token_validator.rb @@ -0,0 +1,15 @@ + +class StripeCardTokenValidator + def validate(record) + if options[:token] + begin + res = Stripe::Token.retrieve(options[:token]) + if res[:id] != options[:token] + record.errors[:card_token] << "A problem occurred while retrieving the card with the specified token: #{res.id}" + end + rescue Stripe::InvalidRequestError => e + record.errors[:card_token] << e + end + end + end +end \ No newline at end of file diff --git a/test/integration/subscriptions/renew_as_user_test.rb b/test/integration/subscriptions/renew_as_user_test.rb index 4def40e4e..d534776ab 100644 --- a/test/integration/subscriptions/renew_as_user_test.rb +++ b/test/integration/subscriptions/renew_as_user_test.rb @@ -76,7 +76,7 @@ class Subscriptions::RenewAsUserTest < ActionDispatch::IntegrationTest assert_match /No such token/, response.body # Check that the user's subscription has not changed - #FIXME assert_equal previous_expiration, @user.subscription.expired_at.to_i, "user's subscription has changed" + assert_equal previous_expiration, @user.subscription.expired_at.to_i, "user's subscription has changed" end end \ No newline at end of file diff --git a/test/vcr_cassettes/subscriptions_user_create_failed.yml b/test/vcr_cassettes/subscriptions_user_create_failed.yml index 5475de74e..bce52ebeb 100644 --- a/test/vcr_cassettes/subscriptions_user_create_failed.yml +++ b/test/vcr_cassettes/subscriptions_user_create_failed.yml @@ -19,8 +19,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' Content-Length: - '81' response: @@ -31,11 +31,11 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 09:34:23 GMT + - Mon, 11 Apr 2016 15:43:39 GMT Content-Type: - application/json Content-Length: - - '780' + - '779' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -49,7 +49,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E1aDuJqtjQOj4 + - req_8FcRQTmptYozzo Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -58,10 +58,10 @@ http_interactions: encoding: UTF-8 string: | { - "id": "tok_17xZWt2sOmf47Nz906Kkg4Q3", + "id": "tok_17z7CR2sOmf47Nz9uppKBmeh", "object": "token", "card": { - "id": "card_17xZWt2sOmf47Nz9eVUCi53A", + "id": "card_17z7CR2sOmf47Nz9ruv5qwpH", "object": "card", "address_city": null, "address_country": null, @@ -84,17 +84,17 @@ http_interactions: "name": null, "tokenization_method": null }, - "client_ip": "90.52.157.226", - "created": 1460021663, + "client_ip": "90.42.87.235", + "created": 1460389419, "livemode": false, "type": "card", "used": false } http_version: - recorded_at: Thu, 07 Apr 2016 09:34:23 GMT + recorded_at: Mon, 11 Apr 2016 15:43:39 GMT - request: method: get - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt + uri: https://api.stripe.com/v1/tokens/tok_17z7CR2sOmf47Nz9uppKBmeh body: encoding: US-ASCII string: '' @@ -111,8 +111,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -121,11 +121,11 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 09:34:24 GMT + - Mon, 11 Apr 2016 15:43:40 GMT Content-Type: - application/json Content-Length: - - '4487' + - '779' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -139,7 +139,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E1aHv4p7a59Gy + - req_8FcRRKMMyEf0bI Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -148,682 +148,38 @@ http_interactions: encoding: UTF-8 string: | { - "id": "cus_8Di1wjdVktv5kt", - "object": "customer", - "account_balance": 0, - "created": 1459948888, - "currency": "usd", - "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", - "delinquent": false, - "description": "Jean Dupond", - "discount": null, - "email": "jean.dupond@gmail.com", - "livemode": false, - "metadata": {}, - "shipping": null, - "sources": { - "object": "list", - "data": [ - { - "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", - "object": "card", - "address_city": null, - "address_country": null, - "address_line1": null, - "address_line1_check": null, - "address_line2": null, - "address_state": null, - "address_zip": null, - "address_zip_check": null, - "brand": "Visa", - "country": "US", - "customer": "cus_8Di1wjdVktv5kt", - "cvc_check": "pass", - "dynamic_last4": null, - "exp_month": 4, - "exp_year": 2017, - "fingerprint": "o52jybR7bnmNn6AT", - "funding": "credit", - "last4": "4242", - "metadata": {}, - "name": null, - "tokenization_method": null - } - ], - "has_more": false, - "total_count": 1, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" + "id": "tok_17z7CR2sOmf47Nz9uppKBmeh", + "object": "token", + "card": { + "id": "card_17z7CR2sOmf47Nz9ruv5qwpH", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null }, - "subscriptions": { - "object": "list", - "data": [ - { - "id": "sub_8DkqBcR1bQvr5G", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459959386, - "current_period_end": 1462551382, - "current_period_start": 1459959382, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459959382, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - }, - { - "id": "sub_8Di9gqPLwt5IIC", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459949404, - "current_period_end": 1462541399, - "current_period_start": 1459949399, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459949399, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - }, - { - "id": "sub_8Di2VadRvr7A99", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459948972, - "current_period_end": 1462540968, - "current_period_start": 1459948968, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459948968, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - } - ], - "has_more": false, - "total_count": 3, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" - } + "client_ip": "90.42.87.235", + "created": 1460389419, + "livemode": false, + "type": "card", + "used": false } http_version: - recorded_at: Thu, 07 Apr 2016 09:34:24 GMT -- request: - method: post - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions - body: - encoding: UTF-8 - string: plan=mensuel-tarif-reduit-student-month-20160404171827&card=tok_17xZWt2sOmf47Nz906Kkg4Q3 - headers: - Accept: - - "*/*; q=0.5, application/xml" - Accept-Encoding: - - gzip, deflate - User-Agent: - - Stripe/v1 RubyBindings/1.30.2 - Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE - Content-Type: - - application/x-www-form-urlencoded - X-Stripe-Client-User-Agent: - - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' - Content-Length: - - '88' - response: - status: - code: 200 - message: OK - headers: - Server: - - nginx - Date: - - Thu, 07 Apr 2016 09:34:25 GMT - Content-Type: - - application/json - Content-Length: - - '880' - Connection: - - keep-alive - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Allow-Methods: - - GET, POST, HEAD, OPTIONS, DELETE - Access-Control-Allow-Origin: - - "*" - Access-Control-Max-Age: - - '300' - Cache-Control: - - no-cache, no-store - Request-Id: - - req_8E1ac4ihRJHesp - Stripe-Version: - - '2015-10-16' - Strict-Transport-Security: - - max-age=31556926; includeSubDomains - body: - encoding: ASCII-8BIT - string: !binary |- - ewogICJpZCI6ICJzdWJfOEUxYWZrVEJuMmRjMUQiLAogICJvYmplY3QiOiAi - c3Vic2NyaXB0aW9uIiwKICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQiOiBu - dWxsLAogICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IGZhbHNlLAogICJjYW5j - ZWxlZF9hdCI6IG51bGwsCiAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI2 - MTM2NjUsCiAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ2MDAyMTY2NSwK - ICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAiZGlzY291 - bnQiOiBudWxsLAogICJlbmRlZF9hdCI6IG51bGwsCiAgIm1ldGFkYXRhIjog - e30sCiAgInBsYW4iOiB7CiAgICAiaWQiOiAibWVuc3VlbC10YXJpZi1yZWR1 - aXQtc3R1ZGVudC1tb250aC0yMDE2MDQwNDE3MTgyNyIsCiAgICAib2JqZWN0 - IjogInBsYW4iLAogICAgImFtb3VudCI6IDIwMDAsCiAgICAiY3JlYXRlZCI6 - IDE0NTk3ODMxMDgsCiAgICAiY3VycmVuY3kiOiAidXNkIiwKICAgICJpbnRl - cnZhbCI6ICJtb250aCIsCiAgICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAg - ImxpdmVtb2RlIjogZmFsc2UsCiAgICAibWV0YWRhdGEiOiB7fSwKICAgICJu - YW1lIjogIk1lbnN1ZWwgdGFyaWYgcsOpZHVpdCAtIMOpdHVkaWFudCwgLSBk - ZSAyNSBhbnMsIGVuc2VpZ25hbnQsIGRlbWFuZGV1ciBkJ2VtcGxvaSAtIG1v - bnRoIiwKICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAi - dHJpYWxfcGVyaW9kX2RheXMiOiBudWxsCiAgfSwKICAicXVhbnRpdHkiOiAx - LAogICJzdGFydCI6IDE0NjAwMjE2NjUsCiAgInN0YXR1cyI6ICJhY3RpdmUi - LAogICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgInRyaWFsX2VuZCI6IG51bGws - CiAgInRyaWFsX3N0YXJ0IjogbnVsbAp9Cg== - http_version: - recorded_at: Thu, 07 Apr 2016 09:34:26 GMT -- request: - method: get - uri: https://api.stripe.com/v1/invoices?customer=cus_8Di1wjdVktv5kt&limit=1 - body: - encoding: US-ASCII - string: '' - headers: - Accept: - - "*/*; q=0.5, application/xml" - Accept-Encoding: - - gzip, deflate - User-Agent: - - Stripe/v1 RubyBindings/1.30.2 - Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE - Content-Type: - - application/x-www-form-urlencoded - X-Stripe-Client-User-Agent: - - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' - response: - status: - code: 200 - message: OK - headers: - Server: - - nginx - Date: - - Thu, 07 Apr 2016 09:34:27 GMT - Content-Type: - - application/json - Content-Length: - - '2266' - Connection: - - keep-alive - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Allow-Methods: - - GET, POST, HEAD, OPTIONS, DELETE - Access-Control-Allow-Origin: - - "*" - Access-Control-Max-Age: - - '300' - Cache-Control: - - no-cache, no-store - Request-Id: - - req_8E1aqh5kH5Jx71 - Stripe-Version: - - '2015-10-16' - Strict-Transport-Security: - - max-age=31556926; includeSubDomains - body: - encoding: ASCII-8BIT - string: !binary |- - ewogICJvYmplY3QiOiAibGlzdCIsCiAgImRhdGEiOiBbCiAgICB7CiAgICAg - ICJpZCI6ICJpbl8xN3haV3Yyc09tZjQ3Tno5UVZ5UG8zWHYiLAogICAgICAi - b2JqZWN0IjogImludm9pY2UiLAogICAgICAiYW1vdW50X2R1ZSI6IDIwMDAs - CiAgICAgICJhcHBsaWNhdGlvbl9mZWUiOiBudWxsLAogICAgICAiYXR0ZW1w - dF9jb3VudCI6IDEsCiAgICAgICJhdHRlbXB0ZWQiOiB0cnVlLAogICAgICAi - Y2hhcmdlIjogImNoXzE3eFpXdjJzT21mNDdOejlFOWtIUTV5OCIsCiAgICAg - ICJjbG9zZWQiOiB0cnVlLAogICAgICAiY3VycmVuY3kiOiAidXNkIiwKICAg - ICAgImN1c3RvbWVyIjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAgICJk - YXRlIjogMTQ2MDAyMTY2NSwKICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwK - ICAgICAgImRpc2NvdW50IjogbnVsbCwKICAgICAgImVuZGluZ19iYWxhbmNl - IjogMCwKICAgICAgImZvcmdpdmVuIjogZmFsc2UsCiAgICAgICJsaW5lcyI6 - IHsKICAgICAgICAib2JqZWN0IjogImxpc3QiLAogICAgICAgICJkYXRhIjog - WwogICAgICAgICAgewogICAgICAgICAgICAiaWQiOiAic3ViXzhFMWFma1RC - bjJkYzFEIiwKICAgICAgICAgICAgIm9iamVjdCI6ICJsaW5lX2l0ZW0iLAog - ICAgICAgICAgICAiYW1vdW50IjogMjAwMCwKICAgICAgICAgICAgImN1cnJl - bmN5IjogInVzZCIsCiAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6IG51bGws - CiAgICAgICAgICAgICJkaXNjb3VudGFibGUiOiB0cnVlLAogICAgICAgICAg - ICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICAgICAgICAgIm1ldGFkYXRhIjog - e30sCiAgICAgICAgICAgICJwZXJpb2QiOiB7CiAgICAgICAgICAgICAgInN0 - YXJ0IjogMTQ2MDAyMTY2NSwKICAgICAgICAgICAgICAiZW5kIjogMTQ2MjYx - MzY2NQogICAgICAgICAgICB9LAogICAgICAgICAgICAicGxhbiI6IHsKICAg - ICAgICAgICAgICAiaWQiOiAibWVuc3VlbC10YXJpZi1yZWR1aXQtc3R1ZGVu - dC1tb250aC0yMDE2MDQwNDE3MTgyNyIsCiAgICAgICAgICAgICAgIm9iamVj - dCI6ICJwbGFuIiwKICAgICAgICAgICAgICAiYW1vdW50IjogMjAwMCwKICAg - ICAgICAgICAgICAiY3JlYXRlZCI6IDE0NTk3ODMxMDgsCiAgICAgICAgICAg - ICAgImN1cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAgICAgImludGVydmFs - IjogIm1vbnRoIiwKICAgICAgICAgICAgICAiaW50ZXJ2YWxfY291bnQiOiAx - LAogICAgICAgICAgICAgICJsaXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAg - ICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICAgICAgICJuYW1lIjogIk1l - bnN1ZWwgdGFyaWYgcsOpZHVpdCAtIMOpdHVkaWFudCwgLSBkZSAyNSBhbnMs - IGVuc2VpZ25hbnQsIGRlbWFuZGV1ciBkJ2VtcGxvaSAtIG1vbnRoIiwKICAg - ICAgICAgICAgICAic3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAogICAg - ICAgICAgICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwKICAgICAgICAg - ICAgfSwKICAgICAgICAgICAgInByb3JhdGlvbiI6IGZhbHNlLAogICAgICAg - ICAgICAicXVhbnRpdHkiOiAxLAogICAgICAgICAgICAic3Vic2NyaXB0aW9u - IjogbnVsbCwKICAgICAgICAgICAgInR5cGUiOiAic3Vic2NyaXB0aW9uIgog - ICAgICAgICAgfQogICAgICAgIF0sCiAgICAgICAgImhhc19tb3JlIjogZmFs - c2UsCiAgICAgICAgInRvdGFsX2NvdW50IjogMSwKICAgICAgICAidXJsIjog - Ii92MS9pbnZvaWNlcy9pbl8xN3haV3Yyc09tZjQ3Tno5UVZ5UG8zWHYvbGlu - ZXMiCiAgICAgIH0sCiAgICAgICJsaXZlbW9kZSI6IGZhbHNlLAogICAgICAi - bWV0YWRhdGEiOiB7fSwKICAgICAgIm5leHRfcGF5bWVudF9hdHRlbXB0Ijog - bnVsbCwKICAgICAgInBhaWQiOiB0cnVlLAogICAgICAicGVyaW9kX2VuZCI6 - IDE0NjAwMjE2NjUsCiAgICAgICJwZXJpb2Rfc3RhcnQiOiAxNDU5OTQ4OTY4 - LAogICAgICAicmVjZWlwdF9udW1iZXIiOiBudWxsLAogICAgICAic3RhcnRp - bmdfYmFsYW5jZSI6IDAsCiAgICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6 - IG51bGwsCiAgICAgICJzdWJzY3JpcHRpb24iOiAic3ViXzhFMWFma1RCbjJk - YzFEIiwKICAgICAgInN1YnRvdGFsIjogMjAwMCwKICAgICAgInRheCI6IG51 - bGwsCiAgICAgICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgICAgICJ0b3RhbCI6 - IDIwMDAsCiAgICAgICJ3ZWJob29rc19kZWxpdmVyZWRfYXQiOiAxNDYwMDIx - NjY1CiAgICB9CiAgXSwKICAiaGFzX21vcmUiOiB0cnVlLAogICJ1cmwiOiAi - L3YxL2ludm9pY2VzIgp9Cg== - http_version: - recorded_at: Thu, 07 Apr 2016 09:34:27 GMT -- request: - method: get - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt - body: - encoding: US-ASCII - string: '' - headers: - Accept: - - "*/*; q=0.5, application/xml" - Accept-Encoding: - - gzip, deflate - User-Agent: - - Stripe/v1 RubyBindings/1.30.2 - Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE - Content-Type: - - application/x-www-form-urlencoded - X-Stripe-Client-User-Agent: - - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' - response: - status: - code: 200 - message: OK - headers: - Server: - - nginx - Date: - - Thu, 07 Apr 2016 09:34:28 GMT - Content-Type: - - application/json - Content-Length: - - '5566' - Connection: - - keep-alive - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Allow-Methods: - - GET, POST, HEAD, OPTIONS, DELETE - Access-Control-Allow-Origin: - - "*" - Access-Control-Max-Age: - - '300' - Cache-Control: - - no-cache, no-store - Request-Id: - - req_8E1a2ZYS5iN1tJ - Stripe-Version: - - '2015-10-16' - Strict-Transport-Security: - - max-age=31556926; includeSubDomains - body: - encoding: ASCII-8BIT - string: !binary |- - ewogICJpZCI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJvYmplY3QiOiAi - Y3VzdG9tZXIiLAogICJhY2NvdW50X2JhbGFuY2UiOiAwLAogICJjcmVhdGVk - IjogMTQ1OTk0ODg4OCwKICAiY3VycmVuY3kiOiAidXNkIiwKICAiZGVmYXVs - dF9zb3VyY2UiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1M0EiLAog - ICJkZWxpbnF1ZW50IjogZmFsc2UsCiAgImRlc2NyaXB0aW9uIjogIkplYW4g - RHVwb25kIiwKICAiZGlzY291bnQiOiBudWxsLAogICJlbWFpbCI6ICJqZWFu - LmR1cG9uZEBnbWFpbC5jb20iLAogICJsaXZlbW9kZSI6IGZhbHNlLAogICJt - ZXRhZGF0YSI6IHt9LAogICJzaGlwcGluZyI6IG51bGwsCiAgInNvdXJjZXMi - OiB7CiAgICAib2JqZWN0IjogImxpc3QiLAogICAgImRhdGEiOiBbCiAgICAg - IHsKICAgICAgICAiaWQiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1 - M0EiLAogICAgICAgICJvYmplY3QiOiAiY2FyZCIsCiAgICAgICAgImFkZHJl - c3NfY2l0eSI6IG51bGwsCiAgICAgICAgImFkZHJlc3NfY291bnRyeSI6IG51 - bGwsCiAgICAgICAgImFkZHJlc3NfbGluZTEiOiBudWxsLAogICAgICAgICJh - ZGRyZXNzX2xpbmUxX2NoZWNrIjogbnVsbCwKICAgICAgICAiYWRkcmVzc19s - aW5lMiI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nfc3RhdGUiOiBudWxsLAog - ICAgICAgICJhZGRyZXNzX3ppcCI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nf - emlwX2NoZWNrIjogbnVsbCwKICAgICAgICAiYnJhbmQiOiAiVmlzYSIsCiAg - ICAgICAgImNvdW50cnkiOiAiVVMiLAogICAgICAgICJjdXN0b21lciI6ICJj - dXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJjdmNfY2hlY2siOiAicGFz - cyIsCiAgICAgICAgImR5bmFtaWNfbGFzdDQiOiBudWxsLAogICAgICAgICJl - eHBfbW9udGgiOiA0LAogICAgICAgICJleHBfeWVhciI6IDIwMTcsCiAgICAg - ICAgImZpbmdlcnByaW50IjogIm81Mmp5YlI3Ym5tTm42QVQiLAogICAgICAg - ICJmdW5kaW5nIjogImNyZWRpdCIsCiAgICAgICAgImxhc3Q0IjogIjQyNDIi - LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJuYW1lIjogbnVs - bCwKICAgICAgICAidG9rZW5pemF0aW9uX21ldGhvZCI6IG51bGwKICAgICAg - fQogICAgXSwKICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRvdGFsX2Nv - dW50IjogMSwKICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNfOERpMXdq - ZFZrdHY1a3Qvc291cmNlcyIKICB9LAogICJzdWJzY3JpcHRpb25zIjogewog - ICAgIm9iamVjdCI6ICJsaXN0IiwKICAgICJkYXRhIjogWwogICAgICB7CiAg - ICAgICAgImlkIjogInN1Yl84RTFhZmtUQm4yZGMxRCIsCiAgICAgICAgIm9i - amVjdCI6ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9m - ZWVfcGVyY2VudCI6IG51bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2Rf - ZW5kIjogZmFsc2UsCiAgICAgICAgImNhbmNlbGVkX2F0IjogbnVsbCwKICAg - ICAgICAiY3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjYxMzY2NSwKICAgICAg - ICAiY3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDYwMDIxNjY1LAogICAgICAg - ICJjdXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJk - aXNjb3VudCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0IjogbnVsbCwKICAg - ICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6IHsKICAgICAg - ICAgICJpZCI6ICJtZW5zdWVsLXRhcmlmLXJlZHVpdC1zdHVkZW50LW1vbnRo - LTIwMTYwNDA0MTcxODI3IiwKICAgICAgICAgICJvYmplY3QiOiAicGxhbiIs - CiAgICAgICAgICAiYW1vdW50IjogMjAwMCwKICAgICAgICAgICJjcmVhdGVk - IjogMTQ1OTc4MzEwOCwKICAgICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAog - ICAgICAgICAgImludGVydmFsIjogIm1vbnRoIiwKICAgICAgICAgICJpbnRl - cnZhbF9jb3VudCI6IDEsCiAgICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwK - ICAgICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAi - TWVuc3VlbCB0YXJpZiByw6lkdWl0IC0gw6l0dWRpYW50LCAtIGRlIDI1IGFu - cywgZW5zZWlnbmFudCwgZGVtYW5kZXVyIGQnZW1wbG9pIC0gbW9udGgiLAog - ICAgICAgICAgInN0YXRlbWVudF9kZXNjcmlwdG9yIjogbnVsbCwKICAgICAg - ICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwKICAgICAgICB9LAogICAg - ICAgICJxdWFudGl0eSI6IDEsCiAgICAgICAgInN0YXJ0IjogMTQ2MDAyMTY2 - NSwKICAgICAgICAic3RhdHVzIjogImFjdGl2ZSIsCiAgICAgICAgInRheF9w - ZXJjZW50IjogbnVsbCwKICAgICAgICAidHJpYWxfZW5kIjogbnVsbCwKICAg - ICAgICAidHJpYWxfc3RhcnQiOiBudWxsCiAgICAgIH0sCiAgICAgIHsKICAg - ICAgICAiaWQiOiAic3ViXzhEa3FCY1IxYlF2cjVHIiwKICAgICAgICAib2Jq - ZWN0IjogInN1YnNjcmlwdGlvbiIsCiAgICAgICAgImFwcGxpY2F0aW9uX2Zl - ZV9wZXJjZW50IjogbnVsbCwKICAgICAgICAiY2FuY2VsX2F0X3BlcmlvZF9l - bmQiOiB0cnVlLAogICAgICAgICJjYW5jZWxlZF9hdCI6IDE0NTk5NTkzODYs - CiAgICAgICAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI1NTEzODIsCiAg - ICAgICAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ1OTk1OTM4MiwKICAg - ICAgICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAgICAg - ICAiZGlzY291bnQiOiBudWxsLAogICAgICAgICJlbmRlZF9hdCI6IG51bGws - CiAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgInBsYW4iOiB7CiAg - ICAgICAgICAiaWQiOiAibWVuc3VlbC1zdGFuZGFyZC1tb250aC0yMDE2MDQw - NDE3MTUxOSIsCiAgICAgICAgICAib2JqZWN0IjogInBsYW4iLAogICAgICAg - ICAgImFtb3VudCI6IDMwMDAsCiAgICAgICAgICAiY3JlYXRlZCI6IDE0NTk3 - ODI5MjEsCiAgICAgICAgICAiY3VycmVuY3kiOiAidXNkIiwKICAgICAgICAg - ICJpbnRlcnZhbCI6ICJtb250aCIsCiAgICAgICAgICAiaW50ZXJ2YWxfY291 - bnQiOiAxLAogICAgICAgICAgImxpdmVtb2RlIjogZmFsc2UsCiAgICAgICAg - ICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAgICJuYW1lIjogIk1lbnN1ZWwg - LSBzdGFuZGFyZCwgYXNzb2NpYXRpb24gLSBtb250aCIsCiAgICAgICAgICAi - c3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAogICAgICAgICAgInRyaWFs - X3BlcmlvZF9kYXlzIjogbnVsbAogICAgICAgIH0sCiAgICAgICAgInF1YW50 - aXR5IjogMSwKICAgICAgICAic3RhcnQiOiAxNDU5OTU5MzgyLAogICAgICAg - ICJzdGF0dXMiOiAiYWN0aXZlIiwKICAgICAgICAidGF4X3BlcmNlbnQiOiBu - dWxsLAogICAgICAgICJ0cmlhbF9lbmQiOiBudWxsLAogICAgICAgICJ0cmlh - bF9zdGFydCI6IG51bGwKICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6 - ICJzdWJfOERpOWdxUEx3dDVJSUMiLAogICAgICAgICJvYmplY3QiOiAic3Vi - c2NyaXB0aW9uIiwKICAgICAgICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQi - OiBudWxsLAogICAgICAgICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IHRydWUs - CiAgICAgICAgImNhbmNlbGVkX2F0IjogMTQ1OTk0OTQwNCwKICAgICAgICAi - Y3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjU0MTM5OSwKICAgICAgICAiY3Vy - cmVudF9wZXJpb2Rfc3RhcnQiOiAxNDU5OTQ5Mzk5LAogICAgICAgICJjdXN0 - b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJkaXNjb3Vu - dCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0IjogbnVsbCwKICAgICAgICAi - bWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6IHsKICAgICAgICAgICJp - ZCI6ICJtZW5zdWVsLXN0YW5kYXJkLW1vbnRoLTIwMTYwNDA0MTcxNTE5IiwK - ICAgICAgICAgICJvYmplY3QiOiAicGxhbiIsCiAgICAgICAgICAiYW1vdW50 - IjogMzAwMCwKICAgICAgICAgICJjcmVhdGVkIjogMTQ1OTc4MjkyMSwKICAg - ICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAgICAgICAgImludGVydmFs - IjogIm1vbnRoIiwKICAgICAgICAgICJpbnRlcnZhbF9jb3VudCI6IDEsCiAg - ICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICAgICAgICJtZXRhZGF0 - YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAiTWVuc3VlbCAtIHN0YW5kYXJk - LCBhc3NvY2lhdGlvbiAtIG1vbnRoIiwKICAgICAgICAgICJzdGF0ZW1lbnRf - ZGVzY3JpcHRvciI6IG51bGwsCiAgICAgICAgICAidHJpYWxfcGVyaW9kX2Rh - eXMiOiBudWxsCiAgICAgICAgfSwKICAgICAgICAicXVhbnRpdHkiOiAxLAog - ICAgICAgICJzdGFydCI6IDE0NTk5NDkzOTksCiAgICAgICAgInN0YXR1cyI6 - ICJhY3RpdmUiLAogICAgICAgICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgICAg - ICAgInRyaWFsX2VuZCI6IG51bGwsCiAgICAgICAgInRyaWFsX3N0YXJ0Ijog - bnVsbAogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogInN1Yl84RGky - VmFkUnZyN0E5OSIsCiAgICAgICAgIm9iamVjdCI6ICJzdWJzY3JpcHRpb24i - LAogICAgICAgICJhcHBsaWNhdGlvbl9mZWVfcGVyY2VudCI6IG51bGwsCiAg - ICAgICAgImNhbmNlbF9hdF9wZXJpb2RfZW5kIjogdHJ1ZSwKICAgICAgICAi - Y2FuY2VsZWRfYXQiOiAxNDU5OTQ4OTcyLAogICAgICAgICJjdXJyZW50X3Bl - cmlvZF9lbmQiOiAxNDYyNTQwOTY4LAogICAgICAgICJjdXJyZW50X3Blcmlv - ZF9zdGFydCI6IDE0NTk5NDg5NjgsCiAgICAgICAgImN1c3RvbWVyIjogImN1 - c184RGkxd2pkVmt0djVrdCIsCiAgICAgICAgImRpc2NvdW50IjogbnVsbCwK - ICAgICAgICAiZW5kZWRfYXQiOiBudWxsLAogICAgICAgICJtZXRhZGF0YSI6 - IHt9LAogICAgICAgICJwbGFuIjogewogICAgICAgICAgImlkIjogIm1lbnN1 - ZWwtc3RhbmRhcmQtbW9udGgtMjAxNjA0MDQxNzE1MTkiLAogICAgICAgICAg - Im9iamVjdCI6ICJwbGFuIiwKICAgICAgICAgICJhbW91bnQiOiAzMDAwLAog - ICAgICAgICAgImNyZWF0ZWQiOiAxNDU5NzgyOTIxLAogICAgICAgICAgImN1 - cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAiaW50ZXJ2YWwiOiAibW9udGgi - LAogICAgICAgICAgImludGVydmFsX2NvdW50IjogMSwKICAgICAgICAgICJs - aXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAgIm1ldGFkYXRhIjoge30sCiAg - ICAgICAgICAibmFtZSI6ICJNZW5zdWVsIC0gc3RhbmRhcmQsIGFzc29jaWF0 - aW9uIC0gbW9udGgiLAogICAgICAgICAgInN0YXRlbWVudF9kZXNjcmlwdG9y - IjogbnVsbCwKICAgICAgICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwK - ICAgICAgICB9LAogICAgICAgICJxdWFudGl0eSI6IDEsCiAgICAgICAgInN0 - YXJ0IjogMTQ1OTk0ODk2OCwKICAgICAgICAic3RhdHVzIjogImFjdGl2ZSIs - CiAgICAgICAgInRheF9wZXJjZW50IjogbnVsbCwKICAgICAgICAidHJpYWxf - ZW5kIjogbnVsbCwKICAgICAgICAidHJpYWxfc3RhcnQiOiBudWxsCiAgICAg - IH0KICAgIF0sCiAgICAiaGFzX21vcmUiOiBmYWxzZSwKICAgICJ0b3RhbF9j - b3VudCI6IDQsCiAgICAidXJsIjogIi92MS9jdXN0b21lcnMvY3VzXzhEaTF3 - amRWa3R2NWt0L3N1YnNjcmlwdGlvbnMiCiAgfQp9Cg== - http_version: - recorded_at: Thu, 07 Apr 2016 09:34:28 GMT -- request: - method: get - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8E1afkTBn2dc1D - body: - encoding: US-ASCII - string: '' - headers: - Accept: - - "*/*; q=0.5, application/xml" - Accept-Encoding: - - gzip, deflate - User-Agent: - - Stripe/v1 RubyBindings/1.30.2 - Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE - Content-Type: - - application/x-www-form-urlencoded - X-Stripe-Client-User-Agent: - - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' - response: - status: - code: 200 - message: OK - headers: - Server: - - nginx - Date: - - Thu, 07 Apr 2016 09:34:29 GMT - Content-Type: - - application/json - Content-Length: - - '880' - Connection: - - keep-alive - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Allow-Methods: - - GET, POST, HEAD, OPTIONS, DELETE - Access-Control-Allow-Origin: - - "*" - Access-Control-Max-Age: - - '300' - Cache-Control: - - no-cache, no-store - Request-Id: - - req_8E1a72YcNQrLBo - Stripe-Version: - - '2015-10-16' - Strict-Transport-Security: - - max-age=31556926; includeSubDomains - body: - encoding: ASCII-8BIT - string: !binary |- - ewogICJpZCI6ICJzdWJfOEUxYWZrVEJuMmRjMUQiLAogICJvYmplY3QiOiAi - c3Vic2NyaXB0aW9uIiwKICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQiOiBu - dWxsLAogICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IGZhbHNlLAogICJjYW5j - ZWxlZF9hdCI6IG51bGwsCiAgImN1cnJlbnRfcGVyaW9kX2VuZCI6IDE0NjI2 - MTM2NjUsCiAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0IjogMTQ2MDAyMTY2NSwK - ICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAiZGlzY291 - bnQiOiBudWxsLAogICJlbmRlZF9hdCI6IG51bGwsCiAgIm1ldGFkYXRhIjog - e30sCiAgInBsYW4iOiB7CiAgICAiaWQiOiAibWVuc3VlbC10YXJpZi1yZWR1 - aXQtc3R1ZGVudC1tb250aC0yMDE2MDQwNDE3MTgyNyIsCiAgICAib2JqZWN0 - IjogInBsYW4iLAogICAgImFtb3VudCI6IDIwMDAsCiAgICAiY3JlYXRlZCI6 - IDE0NTk3ODMxMDgsCiAgICAiY3VycmVuY3kiOiAidXNkIiwKICAgICJpbnRl - cnZhbCI6ICJtb250aCIsCiAgICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAg - ImxpdmVtb2RlIjogZmFsc2UsCiAgICAibWV0YWRhdGEiOiB7fSwKICAgICJu - YW1lIjogIk1lbnN1ZWwgdGFyaWYgcsOpZHVpdCAtIMOpdHVkaWFudCwgLSBk - ZSAyNSBhbnMsIGVuc2VpZ25hbnQsIGRlbWFuZGV1ciBkJ2VtcGxvaSAtIG1v - bnRoIiwKICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAi - dHJpYWxfcGVyaW9kX2RheXMiOiBudWxsCiAgfSwKICAicXVhbnRpdHkiOiAx - LAogICJzdGFydCI6IDE0NjAwMjE2NjUsCiAgInN0YXR1cyI6ICJhY3RpdmUi - LAogICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgInRyaWFsX2VuZCI6IG51bGws - CiAgInRyaWFsX3N0YXJ0IjogbnVsbAp9Cg== - http_version: - recorded_at: Thu, 07 Apr 2016 09:34:29 GMT -- request: - method: delete - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8E1afkTBn2dc1D?at_period_end=true - body: - encoding: US-ASCII - string: '' - headers: - Accept: - - "*/*; q=0.5, application/xml" - Accept-Encoding: - - gzip, deflate - User-Agent: - - Stripe/v1 RubyBindings/1.30.2 - Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE - Content-Type: - - application/x-www-form-urlencoded - X-Stripe-Client-User-Agent: - - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' - response: - status: - code: 200 - message: OK - headers: - Server: - - nginx - Date: - - Thu, 07 Apr 2016 09:34:30 GMT - Content-Type: - - application/json - Content-Length: - - '885' - Connection: - - keep-alive - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Allow-Methods: - - GET, POST, HEAD, OPTIONS, DELETE - Access-Control-Allow-Origin: - - "*" - Access-Control-Max-Age: - - '300' - Cache-Control: - - no-cache, no-store - Request-Id: - - req_8E1aMVW98tCB7l - Stripe-Version: - - '2015-10-16' - Strict-Transport-Security: - - max-age=31556926; includeSubDomains - body: - encoding: ASCII-8BIT - string: !binary |- - ewogICJpZCI6ICJzdWJfOEUxYWZrVEJuMmRjMUQiLAogICJvYmplY3QiOiAi - c3Vic2NyaXB0aW9uIiwKICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQiOiBu - dWxsLAogICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IHRydWUsCiAgImNhbmNl - bGVkX2F0IjogMTQ2MDAyMTY3MCwKICAiY3VycmVudF9wZXJpb2RfZW5kIjog - MTQ2MjYxMzY2NSwKICAiY3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDYwMDIx - NjY1LAogICJjdXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJk - aXNjb3VudCI6IG51bGwsCiAgImVuZGVkX2F0IjogbnVsbCwKICAibWV0YWRh - dGEiOiB7fSwKICAicGxhbiI6IHsKICAgICJpZCI6ICJtZW5zdWVsLXRhcmlm - LXJlZHVpdC1zdHVkZW50LW1vbnRoLTIwMTYwNDA0MTcxODI3IiwKICAgICJv - YmplY3QiOiAicGxhbiIsCiAgICAiYW1vdW50IjogMjAwMCwKICAgICJjcmVh - dGVkIjogMTQ1OTc4MzEwOCwKICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAg - ImludGVydmFsIjogIm1vbnRoIiwKICAgICJpbnRlcnZhbF9jb3VudCI6IDEs - CiAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICJtZXRhZGF0YSI6IHt9LAog - ICAgIm5hbWUiOiAiTWVuc3VlbCB0YXJpZiByw6lkdWl0IC0gw6l0dWRpYW50 - LCAtIGRlIDI1IGFucywgZW5zZWlnbmFudCwgZGVtYW5kZXVyIGQnZW1wbG9p - IC0gbW9udGgiLAogICAgInN0YXRlbWVudF9kZXNjcmlwdG9yIjogbnVsbCwK - ICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwKICB9LAogICJxdWFudGl0 - eSI6IDEsCiAgInN0YXJ0IjogMTQ2MDAyMTY2NSwKICAic3RhdHVzIjogImFj - dGl2ZSIsCiAgInRheF9wZXJjZW50IjogbnVsbCwKICAidHJpYWxfZW5kIjog - bnVsbCwKICAidHJpYWxfc3RhcnQiOiBudWxsCn0K - http_version: - recorded_at: Thu, 07 Apr 2016 09:34:30 GMT + recorded_at: Mon, 11 Apr 2016 15:43:40 GMT recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/subscriptions_user_create_success.yml b/test/vcr_cassettes/subscriptions_user_create_success.yml index 7f76d38ae..6f650ef27 100644 --- a/test/vcr_cassettes/subscriptions_user_create_success.yml +++ b/test/vcr_cassettes/subscriptions_user_create_success.yml @@ -19,8 +19,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' Content-Length: - '81' response: @@ -31,11 +31,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 13:29:57 GMT + - Mon, 11 Apr 2016 15:43:41 GMT Content-Type: - application/json Content-Length: - - '780' + - '779' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -49,7 +49,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8Di9AmOR7uXw9z + - req_8FcRwZhpRvOW2K Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -58,10 +58,10 @@ http_interactions: encoding: UTF-8 string: | { - "id": "tok_17xGjJ2sOmf47Nz9PLqUZge2", + "id": "tok_17z7CT2sOmf47Nz9bO1WBtba", "object": "token", "card": { - "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", + "id": "card_17z7CT2sOmf47Nz9wtWkhGor", "object": "card", "address_city": null, "address_country": null, @@ -84,14 +84,104 @@ http_interactions: "name": null, "tokenization_method": null }, - "client_ip": "90.52.157.226", - "created": 1459949397, + "client_ip": "90.42.87.235", + "created": 1460389421, "livemode": false, "type": "card", "used": false } http_version: - recorded_at: Wed, 06 Apr 2016 13:29:57 GMT + recorded_at: Mon, 11 Apr 2016 15:43:41 GMT +- request: + method: get + uri: https://api.stripe.com/v1/tokens/tok_17z7CT2sOmf47Nz9bO1WBtba + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 11 Apr 2016 15:43:41 GMT + Content-Type: + - application/json + Content-Length: + - '779' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8FcRgivvsrn6Jy + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "tok_17z7CT2sOmf47Nz9bO1WBtba", + "object": "token", + "card": { + "id": "card_17z7CT2sOmf47Nz9wtWkhGor", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + }, + "client_ip": "90.42.87.235", + "created": 1460389421, + "livemode": false, + "type": "card", + "used": false + } + http_version: + recorded_at: Mon, 11 Apr 2016 15:43:42 GMT - request: method: get uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt @@ -111,8 +201,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -121,11 +211,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 13:29:58 GMT + - Mon, 11 Apr 2016 15:43:42 GMT Content-Type: - application/json Content-Length: - - '2437' + - '5571' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -139,111 +229,146 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8Di9uNBvnRw9C0 + - req_8FcRWeqA3l7Zyc Stripe-Version: - '2015-10-16' Strict-Transport-Security: - max-age=31556926; includeSubDomains body: - encoding: UTF-8 - string: | - { - "id": "cus_8Di1wjdVktv5kt", - "object": "customer", - "account_balance": 0, - "created": 1459948888, - "currency": "usd", - "default_source": "card_17xGcM2sOmf47Nz9CxYGRvdo", - "delinquent": false, - "description": "Jean Dupond", - "discount": null, - "email": "jean.dupond@gmail.com", - "livemode": false, - "metadata": {}, - "shipping": null, - "sources": { - "object": "list", - "data": [ - { - "id": "card_17xGcM2sOmf47Nz9CxYGRvdo", - "object": "card", - "address_city": null, - "address_country": null, - "address_line1": null, - "address_line1_check": null, - "address_line2": null, - "address_state": null, - "address_zip": null, - "address_zip_check": null, - "brand": "Visa", - "country": "US", - "customer": "cus_8Di1wjdVktv5kt", - "cvc_check": "pass", - "dynamic_last4": null, - "exp_month": 4, - "exp_year": 2017, - "fingerprint": "o52jybR7bnmNn6AT", - "funding": "credit", - "last4": "4242", - "metadata": {}, - "name": null, - "tokenization_method": null - } - ], - "has_more": false, - "total_count": 1, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" - }, - "subscriptions": { - "object": "list", - "data": [ - { - "id": "sub_8Di2VadRvr7A99", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459948972, - "current_period_end": 1462540968, - "current_period_start": 1459948968, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459948968, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - } - ], - "has_more": false, - "total_count": 1, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" - } - } + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJvYmplY3QiOiAi + Y3VzdG9tZXIiLAogICJhY2NvdW50X2JhbGFuY2UiOiAwLAogICJjcmVhdGVk + IjogMTQ1OTk0ODg4OCwKICAiY3VycmVuY3kiOiAidXNkIiwKICAiZGVmYXVs + dF9zb3VyY2UiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1M0EiLAog + ICJkZWxpbnF1ZW50IjogZmFsc2UsCiAgImRlc2NyaXB0aW9uIjogIkplYW4g + RHVwb25kIiwKICAiZGlzY291bnQiOiBudWxsLAogICJlbWFpbCI6ICJqZWFu + LmR1cG9uZEBnbWFpbC5jb20iLAogICJsaXZlbW9kZSI6IGZhbHNlLAogICJt + ZXRhZGF0YSI6IHt9LAogICJzaGlwcGluZyI6IG51bGwsCiAgInNvdXJjZXMi + OiB7CiAgICAib2JqZWN0IjogImxpc3QiLAogICAgImRhdGEiOiBbCiAgICAg + IHsKICAgICAgICAiaWQiOiAiY2FyZF8xN3haV3Qyc09tZjQ3Tno5ZVZVQ2k1 + M0EiLAogICAgICAgICJvYmplY3QiOiAiY2FyZCIsCiAgICAgICAgImFkZHJl + c3NfY2l0eSI6IG51bGwsCiAgICAgICAgImFkZHJlc3NfY291bnRyeSI6IG51 + bGwsCiAgICAgICAgImFkZHJlc3NfbGluZTEiOiBudWxsLAogICAgICAgICJh + ZGRyZXNzX2xpbmUxX2NoZWNrIjogbnVsbCwKICAgICAgICAiYWRkcmVzc19s + aW5lMiI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nfc3RhdGUiOiBudWxsLAog + ICAgICAgICJhZGRyZXNzX3ppcCI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nf + emlwX2NoZWNrIjogbnVsbCwKICAgICAgICAiYnJhbmQiOiAiVmlzYSIsCiAg + ICAgICAgImNvdW50cnkiOiAiVVMiLAogICAgICAgICJjdXN0b21lciI6ICJj + dXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJjdmNfY2hlY2siOiAicGFz + cyIsCiAgICAgICAgImR5bmFtaWNfbGFzdDQiOiBudWxsLAogICAgICAgICJl + eHBfbW9udGgiOiA0LAogICAgICAgICJleHBfeWVhciI6IDIwMTcsCiAgICAg + ICAgImZpbmdlcnByaW50IjogIm81Mmp5YlI3Ym5tTm42QVQiLAogICAgICAg + ICJmdW5kaW5nIjogImNyZWRpdCIsCiAgICAgICAgImxhc3Q0IjogIjQyNDIi + LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJuYW1lIjogbnVs + bCwKICAgICAgICAidG9rZW5pemF0aW9uX21ldGhvZCI6IG51bGwKICAgICAg + fQogICAgXSwKICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRvdGFsX2Nv + dW50IjogMSwKICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNfOERpMXdq + ZFZrdHY1a3Qvc291cmNlcyIKICB9LAogICJzdWJzY3JpcHRpb25zIjogewog + ICAgIm9iamVjdCI6ICJsaXN0IiwKICAgICJkYXRhIjogWwogICAgICB7CiAg + ICAgICAgImlkIjogInN1Yl84RTFhZmtUQm4yZGMxRCIsCiAgICAgICAgIm9i + amVjdCI6ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9m + ZWVfcGVyY2VudCI6IG51bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2Rf + ZW5kIjogdHJ1ZSwKICAgICAgICAiY2FuY2VsZWRfYXQiOiAxNDYwMDIxNjcw + LAogICAgICAgICJjdXJyZW50X3BlcmlvZF9lbmQiOiAxNDYyNjEzNjY1LAog + ICAgICAgICJjdXJyZW50X3BlcmlvZF9zdGFydCI6IDE0NjAwMjE2NjUsCiAg + ICAgICAgImN1c3RvbWVyIjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAg + ICAgImRpc2NvdW50IjogbnVsbCwKICAgICAgICAiZW5kZWRfYXQiOiBudWxs + LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJwbGFuIjogewog + ICAgICAgICAgImlkIjogIm1lbnN1ZWwtdGFyaWYtcmVkdWl0LXN0dWRlbnQt + bW9udGgtMjAxNjA0MDQxNzE4MjciLAogICAgICAgICAgIm9iamVjdCI6ICJw + bGFuIiwKICAgICAgICAgICJhbW91bnQiOiAyMDAwLAogICAgICAgICAgImNy + ZWF0ZWQiOiAxNDU5NzgzMTA4LAogICAgICAgICAgImN1cnJlbmN5IjogInVz + ZCIsCiAgICAgICAgICAiaW50ZXJ2YWwiOiAibW9udGgiLAogICAgICAgICAg + ImludGVydmFsX2NvdW50IjogMSwKICAgICAgICAgICJsaXZlbW9kZSI6IGZh + bHNlLAogICAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAgICAgICAibmFt + ZSI6ICJNZW5zdWVsIHRhcmlmIHLDqWR1aXQgLSDDqXR1ZGlhbnQsIC0gZGUg + MjUgYW5zLCBlbnNlaWduYW50LCBkZW1hbmRldXIgZCdlbXBsb2kgLSBtb250 + aCIsCiAgICAgICAgICAic3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAog + ICAgICAgICAgInRyaWFsX3BlcmlvZF9kYXlzIjogbnVsbAogICAgICAgIH0s + CiAgICAgICAgInF1YW50aXR5IjogMSwKICAgICAgICAic3RhcnQiOiAxNDYw + MDIxNjY1LAogICAgICAgICJzdGF0dXMiOiAiYWN0aXZlIiwKICAgICAgICAi + dGF4X3BlcmNlbnQiOiBudWxsLAogICAgICAgICJ0cmlhbF9lbmQiOiBudWxs + LAogICAgICAgICJ0cmlhbF9zdGFydCI6IG51bGwKICAgICAgfSwKICAgICAg + ewogICAgICAgICJpZCI6ICJzdWJfOERrcUJjUjFiUXZyNUciLAogICAgICAg + ICJvYmplY3QiOiAic3Vic2NyaXB0aW9uIiwKICAgICAgICAiYXBwbGljYXRp + b25fZmVlX3BlcmNlbnQiOiBudWxsLAogICAgICAgICJjYW5jZWxfYXRfcGVy + aW9kX2VuZCI6IHRydWUsCiAgICAgICAgImNhbmNlbGVkX2F0IjogMTQ1OTk1 + OTM4NiwKICAgICAgICAiY3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjU1MTM4 + MiwKICAgICAgICAiY3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDU5OTU5Mzgy + LAogICAgICAgICJjdXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAog + ICAgICAgICJkaXNjb3VudCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0Ijog + bnVsbCwKICAgICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6 + IHsKICAgICAgICAgICJpZCI6ICJtZW5zdWVsLXN0YW5kYXJkLW1vbnRoLTIw + MTYwNDA0MTcxNTE5IiwKICAgICAgICAgICJvYmplY3QiOiAicGxhbiIsCiAg + ICAgICAgICAiYW1vdW50IjogMzAwMCwKICAgICAgICAgICJjcmVhdGVkIjog + MTQ1OTc4MjkyMSwKICAgICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAg + ICAgICAgImludGVydmFsIjogIm1vbnRoIiwKICAgICAgICAgICJpbnRlcnZh + bF9jb3VudCI6IDEsCiAgICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAg + ICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAiTWVu + c3VlbCAtIHN0YW5kYXJkLCBhc3NvY2lhdGlvbiAtIG1vbnRoIiwKICAgICAg + ICAgICJzdGF0ZW1lbnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAgICAgICAi + dHJpYWxfcGVyaW9kX2RheXMiOiBudWxsCiAgICAgICAgfSwKICAgICAgICAi + cXVhbnRpdHkiOiAxLAogICAgICAgICJzdGFydCI6IDE0NTk5NTkzODIsCiAg + ICAgICAgInN0YXR1cyI6ICJhY3RpdmUiLAogICAgICAgICJ0YXhfcGVyY2Vu + dCI6IG51bGwsCiAgICAgICAgInRyaWFsX2VuZCI6IG51bGwsCiAgICAgICAg + InRyaWFsX3N0YXJ0IjogbnVsbAogICAgICB9LAogICAgICB7CiAgICAgICAg + ImlkIjogInN1Yl84RGk5Z3FQTHd0NUlJQyIsCiAgICAgICAgIm9iamVjdCI6 + ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9mZWVfcGVy + Y2VudCI6IG51bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2RfZW5kIjog + dHJ1ZSwKICAgICAgICAiY2FuY2VsZWRfYXQiOiAxNDU5OTQ5NDA0LAogICAg + ICAgICJjdXJyZW50X3BlcmlvZF9lbmQiOiAxNDYyNTQxMzk5LAogICAgICAg + ICJjdXJyZW50X3BlcmlvZF9zdGFydCI6IDE0NTk5NDkzOTksCiAgICAgICAg + ImN1c3RvbWVyIjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAgICAgImRp + c2NvdW50IjogbnVsbCwKICAgICAgICAiZW5kZWRfYXQiOiBudWxsLAogICAg + ICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJwbGFuIjogewogICAgICAg + ICAgImlkIjogIm1lbnN1ZWwtc3RhbmRhcmQtbW9udGgtMjAxNjA0MDQxNzE1 + MTkiLAogICAgICAgICAgIm9iamVjdCI6ICJwbGFuIiwKICAgICAgICAgICJh + bW91bnQiOiAzMDAwLAogICAgICAgICAgImNyZWF0ZWQiOiAxNDU5NzgyOTIx + LAogICAgICAgICAgImN1cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAiaW50 + ZXJ2YWwiOiAibW9udGgiLAogICAgICAgICAgImludGVydmFsX2NvdW50Ijog + MSwKICAgICAgICAgICJsaXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAgIm1l + dGFkYXRhIjoge30sCiAgICAgICAgICAibmFtZSI6ICJNZW5zdWVsIC0gc3Rh + bmRhcmQsIGFzc29jaWF0aW9uIC0gbW9udGgiLAogICAgICAgICAgInN0YXRl + bWVudF9kZXNjcmlwdG9yIjogbnVsbCwKICAgICAgICAgICJ0cmlhbF9wZXJp + b2RfZGF5cyI6IG51bGwKICAgICAgICB9LAogICAgICAgICJxdWFudGl0eSI6 + IDEsCiAgICAgICAgInN0YXJ0IjogMTQ1OTk0OTM5OSwKICAgICAgICAic3Rh + dHVzIjogImFjdGl2ZSIsCiAgICAgICAgInRheF9wZXJjZW50IjogbnVsbCwK + ICAgICAgICAidHJpYWxfZW5kIjogbnVsbCwKICAgICAgICAidHJpYWxfc3Rh + cnQiOiBudWxsCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiaWQiOiAic3Vi + XzhEaTJWYWRSdnI3QTk5IiwKICAgICAgICAib2JqZWN0IjogInN1YnNjcmlw + dGlvbiIsCiAgICAgICAgImFwcGxpY2F0aW9uX2ZlZV9wZXJjZW50IjogbnVs + bCwKICAgICAgICAiY2FuY2VsX2F0X3BlcmlvZF9lbmQiOiB0cnVlLAogICAg + ICAgICJjYW5jZWxlZF9hdCI6IDE0NTk5NDg5NzIsCiAgICAgICAgImN1cnJl + bnRfcGVyaW9kX2VuZCI6IDE0NjI1NDA5NjgsCiAgICAgICAgImN1cnJlbnRf + cGVyaW9kX3N0YXJ0IjogMTQ1OTk0ODk2OCwKICAgICAgICAiY3VzdG9tZXIi + OiAiY3VzXzhEaTF3amRWa3R2NWt0IiwKICAgICAgICAiZGlzY291bnQiOiBu + dWxsLAogICAgICAgICJlbmRlZF9hdCI6IG51bGwsCiAgICAgICAgIm1ldGFk + YXRhIjoge30sCiAgICAgICAgInBsYW4iOiB7CiAgICAgICAgICAiaWQiOiAi + bWVuc3VlbC1zdGFuZGFyZC1tb250aC0yMDE2MDQwNDE3MTUxOSIsCiAgICAg + ICAgICAib2JqZWN0IjogInBsYW4iLAogICAgICAgICAgImFtb3VudCI6IDMw + MDAsCiAgICAgICAgICAiY3JlYXRlZCI6IDE0NTk3ODI5MjEsCiAgICAgICAg + ICAiY3VycmVuY3kiOiAidXNkIiwKICAgICAgICAgICJpbnRlcnZhbCI6ICJt + b250aCIsCiAgICAgICAgICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAgICAg + ICAgImxpdmVtb2RlIjogZmFsc2UsCiAgICAgICAgICAibWV0YWRhdGEiOiB7 + fSwKICAgICAgICAgICJuYW1lIjogIk1lbnN1ZWwgLSBzdGFuZGFyZCwgYXNz + b2NpYXRpb24gLSBtb250aCIsCiAgICAgICAgICAic3RhdGVtZW50X2Rlc2Ny + aXB0b3IiOiBudWxsLAogICAgICAgICAgInRyaWFsX3BlcmlvZF9kYXlzIjog + bnVsbAogICAgICAgIH0sCiAgICAgICAgInF1YW50aXR5IjogMSwKICAgICAg + ICAic3RhcnQiOiAxNDU5OTQ4OTY4LAogICAgICAgICJzdGF0dXMiOiAiYWN0 + aXZlIiwKICAgICAgICAidGF4X3BlcmNlbnQiOiBudWxsLAogICAgICAgICJ0 + cmlhbF9lbmQiOiBudWxsLAogICAgICAgICJ0cmlhbF9zdGFydCI6IG51bGwK + ICAgICAgfQogICAgXSwKICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRv + dGFsX2NvdW50IjogNCwKICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNf + OERpMXdqZFZrdHY1a3Qvc3Vic2NyaXB0aW9ucyIKICB9Cn0K http_version: - recorded_at: Wed, 06 Apr 2016 13:29:58 GMT + recorded_at: Mon, 11 Apr 2016 15:43:42 GMT - request: method: post uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions body: encoding: UTF-8 - string: plan=mensuel-standard-month-20160404171519&card=tok_17xGjJ2sOmf47Nz9PLqUZge2 + string: plan=mensuel-standard-month-20160404171519&card=tok_17z7CT2sOmf47Nz9bO1WBtba headers: Accept: - "*/*; q=0.5, application/xml" @@ -257,8 +382,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' Content-Length: - '76' response: @@ -269,7 +394,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 13:29:59 GMT + - Mon, 11 Apr 2016 15:43:44 GMT Content-Type: - application/json Content-Length: @@ -287,7 +412,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8Di9LpzecLQFba + - req_8FcRItYpDN04OA Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -296,13 +421,13 @@ http_interactions: encoding: UTF-8 string: | { - "id": "sub_8Di9gqPLwt5IIC", + "id": "sub_8FcRar5XrAGnL0", "object": "subscription", "application_fee_percent": null, "cancel_at_period_end": false, "canceled_at": null, - "current_period_end": 1462541399, - "current_period_start": 1459949399, + "current_period_end": 1462981423, + "current_period_start": 1460389423, "customer": "cus_8Di1wjdVktv5kt", "discount": null, "ended_at": null, @@ -322,14 +447,14 @@ http_interactions: "trial_period_days": null }, "quantity": 1, - "start": 1459949399, + "start": 1460389423, "status": "active", "tax_percent": null, "trial_end": null, "trial_start": null } http_version: - recorded_at: Wed, 06 Apr 2016 13:29:59 GMT + recorded_at: Mon, 11 Apr 2016 15:43:44 GMT - request: method: get uri: https://api.stripe.com/v1/invoices?customer=cus_8Di1wjdVktv5kt&limit=1 @@ -349,8 +474,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -359,7 +484,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 13:30:00 GMT + - Mon, 11 Apr 2016 15:43:47 GMT Content-Type: - application/json Content-Length: @@ -377,7 +502,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8Di9FX8V833C25 + - req_8FcRkV7kaP4d74 Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -389,17 +514,17 @@ http_interactions: "object": "list", "data": [ { - "id": "in_17xGjL2sOmf47Nz976QQJRnZ", + "id": "in_17z7CV2sOmf47Nz9GowUoPMG", "object": "invoice", "amount_due": 3000, "application_fee": null, "attempt_count": 1, "attempted": true, - "charge": "ch_17xGjL2sOmf47Nz9H8wfSmBa", + "charge": "ch_17z7CV2sOmf47Nz9v4oKnmLc", "closed": true, "currency": "usd", "customer": "cus_8Di1wjdVktv5kt", - "date": 1459949399, + "date": 1460389423, "description": null, "discount": null, "ending_balance": 0, @@ -408,7 +533,7 @@ http_interactions: "object": "list", "data": [ { - "id": "sub_8Di9gqPLwt5IIC", + "id": "sub_8FcRar5XrAGnL0", "object": "line_item", "amount": 3000, "currency": "usd", @@ -417,8 +542,8 @@ http_interactions: "livemode": false, "metadata": {}, "period": { - "start": 1459949399, - "end": 1462541399 + "start": 1460389423, + "end": 1462981423 }, "plan": { "id": "mensuel-standard-month-20160404171519", @@ -442,30 +567,30 @@ http_interactions: ], "has_more": false, "total_count": 1, - "url": "/v1/invoices/in_17xGjL2sOmf47Nz976QQJRnZ/lines" + "url": "/v1/invoices/in_17z7CV2sOmf47Nz9GowUoPMG/lines" }, "livemode": false, "metadata": {}, "next_payment_attempt": null, "paid": true, - "period_end": 1459949399, + "period_end": 1460389423, "period_start": 1459948968, "receipt_number": null, "starting_balance": 0, "statement_descriptor": null, - "subscription": "sub_8Di9gqPLwt5IIC", + "subscription": "sub_8FcRar5XrAGnL0", "subtotal": 3000, "tax": null, "tax_percent": null, "total": 3000, - "webhooks_delivered_at": 1459949399 + "webhooks_delivered_at": 1460389424 } ], "has_more": true, "url": "/v1/invoices" } http_version: - recorded_at: Wed, 06 Apr 2016 13:30:00 GMT + recorded_at: Mon, 11 Apr 2016 15:43:47 GMT - request: method: get uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt @@ -485,8 +610,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -495,11 +620,11 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 13:30:02 GMT + - Mon, 11 Apr 2016 15:43:48 GMT Content-Type: - application/json Content-Length: - - '3457' + - '6591' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -513,141 +638,166 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8Di9aIVqbT9ubZ + - req_8FcRzywC1ZKG1q Stripe-Version: - '2015-10-16' Strict-Transport-Security: - max-age=31556926; includeSubDomains body: - encoding: UTF-8 - string: | - { - "id": "cus_8Di1wjdVktv5kt", - "object": "customer", - "account_balance": 0, - "created": 1459948888, - "currency": "usd", - "default_source": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", - "delinquent": false, - "description": "Jean Dupond", - "discount": null, - "email": "jean.dupond@gmail.com", - "livemode": false, - "metadata": {}, - "shipping": null, - "sources": { - "object": "list", - "data": [ - { - "id": "card_17xGjJ2sOmf47Nz9UrQOP8Cl", - "object": "card", - "address_city": null, - "address_country": null, - "address_line1": null, - "address_line1_check": null, - "address_line2": null, - "address_state": null, - "address_zip": null, - "address_zip_check": null, - "brand": "Visa", - "country": "US", - "customer": "cus_8Di1wjdVktv5kt", - "cvc_check": "pass", - "dynamic_last4": null, - "exp_month": 4, - "exp_year": 2017, - "fingerprint": "o52jybR7bnmNn6AT", - "funding": "credit", - "last4": "4242", - "metadata": {}, - "name": null, - "tokenization_method": null - } - ], - "has_more": false, - "total_count": 1, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/sources" - }, - "subscriptions": { - "object": "list", - "data": [ - { - "id": "sub_8Di9gqPLwt5IIC", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": false, - "canceled_at": null, - "current_period_end": 1462541399, - "current_period_start": 1459949399, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459949399, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - }, - { - "id": "sub_8Di2VadRvr7A99", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": true, - "canceled_at": 1459948972, - "current_period_end": 1462540968, - "current_period_start": 1459948968, - "customer": "cus_8Di1wjdVktv5kt", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1459948968, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - } - ], - "has_more": false, - "total_count": 2, - "url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions" - } - } + encoding: ASCII-8BIT + string: !binary |- + ewogICJpZCI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICJvYmplY3QiOiAi + Y3VzdG9tZXIiLAogICJhY2NvdW50X2JhbGFuY2UiOiAwLAogICJjcmVhdGVk + IjogMTQ1OTk0ODg4OCwKICAiY3VycmVuY3kiOiAidXNkIiwKICAiZGVmYXVs + dF9zb3VyY2UiOiAiY2FyZF8xN3o3Q1Qyc09tZjQ3Tno5d3RXa2hHb3IiLAog + ICJkZWxpbnF1ZW50IjogZmFsc2UsCiAgImRlc2NyaXB0aW9uIjogIkplYW4g + RHVwb25kIiwKICAiZGlzY291bnQiOiBudWxsLAogICJlbWFpbCI6ICJqZWFu + LmR1cG9uZEBnbWFpbC5jb20iLAogICJsaXZlbW9kZSI6IGZhbHNlLAogICJt + ZXRhZGF0YSI6IHt9LAogICJzaGlwcGluZyI6IG51bGwsCiAgInNvdXJjZXMi + OiB7CiAgICAib2JqZWN0IjogImxpc3QiLAogICAgImRhdGEiOiBbCiAgICAg + IHsKICAgICAgICAiaWQiOiAiY2FyZF8xN3o3Q1Qyc09tZjQ3Tno5d3RXa2hH + b3IiLAogICAgICAgICJvYmplY3QiOiAiY2FyZCIsCiAgICAgICAgImFkZHJl + c3NfY2l0eSI6IG51bGwsCiAgICAgICAgImFkZHJlc3NfY291bnRyeSI6IG51 + bGwsCiAgICAgICAgImFkZHJlc3NfbGluZTEiOiBudWxsLAogICAgICAgICJh + ZGRyZXNzX2xpbmUxX2NoZWNrIjogbnVsbCwKICAgICAgICAiYWRkcmVzc19s + aW5lMiI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nfc3RhdGUiOiBudWxsLAog + ICAgICAgICJhZGRyZXNzX3ppcCI6IG51bGwsCiAgICAgICAgImFkZHJlc3Nf + emlwX2NoZWNrIjogbnVsbCwKICAgICAgICAiYnJhbmQiOiAiVmlzYSIsCiAg + ICAgICAgImNvdW50cnkiOiAiVVMiLAogICAgICAgICJjdXN0b21lciI6ICJj + dXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJjdmNfY2hlY2siOiAicGFz + cyIsCiAgICAgICAgImR5bmFtaWNfbGFzdDQiOiBudWxsLAogICAgICAgICJl + eHBfbW9udGgiOiA0LAogICAgICAgICJleHBfeWVhciI6IDIwMTcsCiAgICAg + ICAgImZpbmdlcnByaW50IjogIm81Mmp5YlI3Ym5tTm42QVQiLAogICAgICAg + ICJmdW5kaW5nIjogImNyZWRpdCIsCiAgICAgICAgImxhc3Q0IjogIjQyNDIi + LAogICAgICAgICJtZXRhZGF0YSI6IHt9LAogICAgICAgICJuYW1lIjogbnVs + bCwKICAgICAgICAidG9rZW5pemF0aW9uX21ldGhvZCI6IG51bGwKICAgICAg + fQogICAgXSwKICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRvdGFsX2Nv + dW50IjogMSwKICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNfOERpMXdq + ZFZrdHY1a3Qvc291cmNlcyIKICB9LAogICJzdWJzY3JpcHRpb25zIjogewog + ICAgIm9iamVjdCI6ICJsaXN0IiwKICAgICJkYXRhIjogWwogICAgICB7CiAg + ICAgICAgImlkIjogInN1Yl84RmNSYXI1WHJBR25MMCIsCiAgICAgICAgIm9i + amVjdCI6ICJzdWJzY3JpcHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9m + ZWVfcGVyY2VudCI6IG51bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2Rf + ZW5kIjogZmFsc2UsCiAgICAgICAgImNhbmNlbGVkX2F0IjogbnVsbCwKICAg + ICAgICAiY3VycmVudF9wZXJpb2RfZW5kIjogMTQ2Mjk4MTQyMywKICAgICAg + ICAiY3VycmVudF9wZXJpb2Rfc3RhcnQiOiAxNDYwMzg5NDIzLAogICAgICAg + ICJjdXN0b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJk + aXNjb3VudCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0IjogbnVsbCwKICAg + ICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6IHsKICAgICAg + ICAgICJpZCI6ICJtZW5zdWVsLXN0YW5kYXJkLW1vbnRoLTIwMTYwNDA0MTcx + NTE5IiwKICAgICAgICAgICJvYmplY3QiOiAicGxhbiIsCiAgICAgICAgICAi + YW1vdW50IjogMzAwMCwKICAgICAgICAgICJjcmVhdGVkIjogMTQ1OTc4Mjky + MSwKICAgICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAgICAgICAgImlu + dGVydmFsIjogIm1vbnRoIiwKICAgICAgICAgICJpbnRlcnZhbF9jb3VudCI6 + IDEsCiAgICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICAgICAgICJt + ZXRhZGF0YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAiTWVuc3VlbCAtIHN0 + YW5kYXJkLCBhc3NvY2lhdGlvbiAtIG1vbnRoIiwKICAgICAgICAgICJzdGF0 + ZW1lbnRfZGVzY3JpcHRvciI6IG51bGwsCiAgICAgICAgICAidHJpYWxfcGVy + aW9kX2RheXMiOiBudWxsCiAgICAgICAgfSwKICAgICAgICAicXVhbnRpdHki + OiAxLAogICAgICAgICJzdGFydCI6IDE0NjAzODk0MjMsCiAgICAgICAgInN0 + YXR1cyI6ICJhY3RpdmUiLAogICAgICAgICJ0YXhfcGVyY2VudCI6IG51bGws + CiAgICAgICAgInRyaWFsX2VuZCI6IG51bGwsCiAgICAgICAgInRyaWFsX3N0 + YXJ0IjogbnVsbAogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogInN1 + Yl84RTFhZmtUQm4yZGMxRCIsCiAgICAgICAgIm9iamVjdCI6ICJzdWJzY3Jp + cHRpb24iLAogICAgICAgICJhcHBsaWNhdGlvbl9mZWVfcGVyY2VudCI6IG51 + bGwsCiAgICAgICAgImNhbmNlbF9hdF9wZXJpb2RfZW5kIjogdHJ1ZSwKICAg + ICAgICAiY2FuY2VsZWRfYXQiOiAxNDYwMDIxNjcwLAogICAgICAgICJjdXJy + ZW50X3BlcmlvZF9lbmQiOiAxNDYyNjEzNjY1LAogICAgICAgICJjdXJyZW50 + X3BlcmlvZF9zdGFydCI6IDE0NjAwMjE2NjUsCiAgICAgICAgImN1c3RvbWVy + IjogImN1c184RGkxd2pkVmt0djVrdCIsCiAgICAgICAgImRpc2NvdW50Ijog + bnVsbCwKICAgICAgICAiZW5kZWRfYXQiOiBudWxsLAogICAgICAgICJtZXRh + ZGF0YSI6IHt9LAogICAgICAgICJwbGFuIjogewogICAgICAgICAgImlkIjog + Im1lbnN1ZWwtdGFyaWYtcmVkdWl0LXN0dWRlbnQtbW9udGgtMjAxNjA0MDQx + NzE4MjciLAogICAgICAgICAgIm9iamVjdCI6ICJwbGFuIiwKICAgICAgICAg + ICJhbW91bnQiOiAyMDAwLAogICAgICAgICAgImNyZWF0ZWQiOiAxNDU5Nzgz + MTA4LAogICAgICAgICAgImN1cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAi + aW50ZXJ2YWwiOiAibW9udGgiLAogICAgICAgICAgImludGVydmFsX2NvdW50 + IjogMSwKICAgICAgICAgICJsaXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAg + Im1ldGFkYXRhIjoge30sCiAgICAgICAgICAibmFtZSI6ICJNZW5zdWVsIHRh + cmlmIHLDqWR1aXQgLSDDqXR1ZGlhbnQsIC0gZGUgMjUgYW5zLCBlbnNlaWdu + YW50LCBkZW1hbmRldXIgZCdlbXBsb2kgLSBtb250aCIsCiAgICAgICAgICAi + c3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAogICAgICAgICAgInRyaWFs + X3BlcmlvZF9kYXlzIjogbnVsbAogICAgICAgIH0sCiAgICAgICAgInF1YW50 + aXR5IjogMSwKICAgICAgICAic3RhcnQiOiAxNDYwMDIxNjY1LAogICAgICAg + ICJzdGF0dXMiOiAiYWN0aXZlIiwKICAgICAgICAidGF4X3BlcmNlbnQiOiBu + dWxsLAogICAgICAgICJ0cmlhbF9lbmQiOiBudWxsLAogICAgICAgICJ0cmlh + bF9zdGFydCI6IG51bGwKICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6 + ICJzdWJfOERrcUJjUjFiUXZyNUciLAogICAgICAgICJvYmplY3QiOiAic3Vi + c2NyaXB0aW9uIiwKICAgICAgICAiYXBwbGljYXRpb25fZmVlX3BlcmNlbnQi + OiBudWxsLAogICAgICAgICJjYW5jZWxfYXRfcGVyaW9kX2VuZCI6IHRydWUs + CiAgICAgICAgImNhbmNlbGVkX2F0IjogMTQ1OTk1OTM4NiwKICAgICAgICAi + Y3VycmVudF9wZXJpb2RfZW5kIjogMTQ2MjU1MTM4MiwKICAgICAgICAiY3Vy + cmVudF9wZXJpb2Rfc3RhcnQiOiAxNDU5OTU5MzgyLAogICAgICAgICJjdXN0 + b21lciI6ICJjdXNfOERpMXdqZFZrdHY1a3QiLAogICAgICAgICJkaXNjb3Vu + dCI6IG51bGwsCiAgICAgICAgImVuZGVkX2F0IjogbnVsbCwKICAgICAgICAi + bWV0YWRhdGEiOiB7fSwKICAgICAgICAicGxhbiI6IHsKICAgICAgICAgICJp + ZCI6ICJtZW5zdWVsLXN0YW5kYXJkLW1vbnRoLTIwMTYwNDA0MTcxNTE5IiwK + ICAgICAgICAgICJvYmplY3QiOiAicGxhbiIsCiAgICAgICAgICAiYW1vdW50 + IjogMzAwMCwKICAgICAgICAgICJjcmVhdGVkIjogMTQ1OTc4MjkyMSwKICAg + ICAgICAgICJjdXJyZW5jeSI6ICJ1c2QiLAogICAgICAgICAgImludGVydmFs + IjogIm1vbnRoIiwKICAgICAgICAgICJpbnRlcnZhbF9jb3VudCI6IDEsCiAg + ICAgICAgICAibGl2ZW1vZGUiOiBmYWxzZSwKICAgICAgICAgICJtZXRhZGF0 + YSI6IHt9LAogICAgICAgICAgIm5hbWUiOiAiTWVuc3VlbCAtIHN0YW5kYXJk + LCBhc3NvY2lhdGlvbiAtIG1vbnRoIiwKICAgICAgICAgICJzdGF0ZW1lbnRf + ZGVzY3JpcHRvciI6IG51bGwsCiAgICAgICAgICAidHJpYWxfcGVyaW9kX2Rh + eXMiOiBudWxsCiAgICAgICAgfSwKICAgICAgICAicXVhbnRpdHkiOiAxLAog + ICAgICAgICJzdGFydCI6IDE0NTk5NTkzODIsCiAgICAgICAgInN0YXR1cyI6 + ICJhY3RpdmUiLAogICAgICAgICJ0YXhfcGVyY2VudCI6IG51bGwsCiAgICAg + ICAgInRyaWFsX2VuZCI6IG51bGwsCiAgICAgICAgInRyaWFsX3N0YXJ0Ijog + bnVsbAogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogInN1Yl84RGk5 + Z3FQTHd0NUlJQyIsCiAgICAgICAgIm9iamVjdCI6ICJzdWJzY3JpcHRpb24i + LAogICAgICAgICJhcHBsaWNhdGlvbl9mZWVfcGVyY2VudCI6IG51bGwsCiAg + ICAgICAgImNhbmNlbF9hdF9wZXJpb2RfZW5kIjogdHJ1ZSwKICAgICAgICAi + Y2FuY2VsZWRfYXQiOiAxNDU5OTQ5NDA0LAogICAgICAgICJjdXJyZW50X3Bl + cmlvZF9lbmQiOiAxNDYyNTQxMzk5LAogICAgICAgICJjdXJyZW50X3Blcmlv + ZF9zdGFydCI6IDE0NTk5NDkzOTksCiAgICAgICAgImN1c3RvbWVyIjogImN1 + c184RGkxd2pkVmt0djVrdCIsCiAgICAgICAgImRpc2NvdW50IjogbnVsbCwK + ICAgICAgICAiZW5kZWRfYXQiOiBudWxsLAogICAgICAgICJtZXRhZGF0YSI6 + IHt9LAogICAgICAgICJwbGFuIjogewogICAgICAgICAgImlkIjogIm1lbnN1 + ZWwtc3RhbmRhcmQtbW9udGgtMjAxNjA0MDQxNzE1MTkiLAogICAgICAgICAg + Im9iamVjdCI6ICJwbGFuIiwKICAgICAgICAgICJhbW91bnQiOiAzMDAwLAog + ICAgICAgICAgImNyZWF0ZWQiOiAxNDU5NzgyOTIxLAogICAgICAgICAgImN1 + cnJlbmN5IjogInVzZCIsCiAgICAgICAgICAiaW50ZXJ2YWwiOiAibW9udGgi + LAogICAgICAgICAgImludGVydmFsX2NvdW50IjogMSwKICAgICAgICAgICJs + aXZlbW9kZSI6IGZhbHNlLAogICAgICAgICAgIm1ldGFkYXRhIjoge30sCiAg + ICAgICAgICAibmFtZSI6ICJNZW5zdWVsIC0gc3RhbmRhcmQsIGFzc29jaWF0 + aW9uIC0gbW9udGgiLAogICAgICAgICAgInN0YXRlbWVudF9kZXNjcmlwdG9y + IjogbnVsbCwKICAgICAgICAgICJ0cmlhbF9wZXJpb2RfZGF5cyI6IG51bGwK + ICAgICAgICB9LAogICAgICAgICJxdWFudGl0eSI6IDEsCiAgICAgICAgInN0 + YXJ0IjogMTQ1OTk0OTM5OSwKICAgICAgICAic3RhdHVzIjogImFjdGl2ZSIs + CiAgICAgICAgInRheF9wZXJjZW50IjogbnVsbCwKICAgICAgICAidHJpYWxf + ZW5kIjogbnVsbCwKICAgICAgICAidHJpYWxfc3RhcnQiOiBudWxsCiAgICAg + IH0sCiAgICAgIHsKICAgICAgICAiaWQiOiAic3ViXzhEaTJWYWRSdnI3QTk5 + IiwKICAgICAgICAib2JqZWN0IjogInN1YnNjcmlwdGlvbiIsCiAgICAgICAg + ImFwcGxpY2F0aW9uX2ZlZV9wZXJjZW50IjogbnVsbCwKICAgICAgICAiY2Fu + Y2VsX2F0X3BlcmlvZF9lbmQiOiB0cnVlLAogICAgICAgICJjYW5jZWxlZF9h + dCI6IDE0NTk5NDg5NzIsCiAgICAgICAgImN1cnJlbnRfcGVyaW9kX2VuZCI6 + IDE0NjI1NDA5NjgsCiAgICAgICAgImN1cnJlbnRfcGVyaW9kX3N0YXJ0Ijog + MTQ1OTk0ODk2OCwKICAgICAgICAiY3VzdG9tZXIiOiAiY3VzXzhEaTF3amRW + a3R2NWt0IiwKICAgICAgICAiZGlzY291bnQiOiBudWxsLAogICAgICAgICJl + bmRlZF9hdCI6IG51bGwsCiAgICAgICAgIm1ldGFkYXRhIjoge30sCiAgICAg + ICAgInBsYW4iOiB7CiAgICAgICAgICAiaWQiOiAibWVuc3VlbC1zdGFuZGFy + ZC1tb250aC0yMDE2MDQwNDE3MTUxOSIsCiAgICAgICAgICAib2JqZWN0Ijog + InBsYW4iLAogICAgICAgICAgImFtb3VudCI6IDMwMDAsCiAgICAgICAgICAi + Y3JlYXRlZCI6IDE0NTk3ODI5MjEsCiAgICAgICAgICAiY3VycmVuY3kiOiAi + dXNkIiwKICAgICAgICAgICJpbnRlcnZhbCI6ICJtb250aCIsCiAgICAgICAg + ICAiaW50ZXJ2YWxfY291bnQiOiAxLAogICAgICAgICAgImxpdmVtb2RlIjog + ZmFsc2UsCiAgICAgICAgICAibWV0YWRhdGEiOiB7fSwKICAgICAgICAgICJu + YW1lIjogIk1lbnN1ZWwgLSBzdGFuZGFyZCwgYXNzb2NpYXRpb24gLSBtb250 + aCIsCiAgICAgICAgICAic3RhdGVtZW50X2Rlc2NyaXB0b3IiOiBudWxsLAog + ICAgICAgICAgInRyaWFsX3BlcmlvZF9kYXlzIjogbnVsbAogICAgICAgIH0s + CiAgICAgICAgInF1YW50aXR5IjogMSwKICAgICAgICAic3RhcnQiOiAxNDU5 + OTQ4OTY4LAogICAgICAgICJzdGF0dXMiOiAiYWN0aXZlIiwKICAgICAgICAi + dGF4X3BlcmNlbnQiOiBudWxsLAogICAgICAgICJ0cmlhbF9lbmQiOiBudWxs + LAogICAgICAgICJ0cmlhbF9zdGFydCI6IG51bGwKICAgICAgfQogICAgXSwK + ICAgICJoYXNfbW9yZSI6IGZhbHNlLAogICAgInRvdGFsX2NvdW50IjogNSwK + ICAgICJ1cmwiOiAiL3YxL2N1c3RvbWVycy9jdXNfOERpMXdqZFZrdHY1a3Qv + c3Vic2NyaXB0aW9ucyIKICB9Cn0K http_version: - recorded_at: Wed, 06 Apr 2016 13:30:02 GMT + recorded_at: Mon, 11 Apr 2016 15:43:48 GMT - request: method: get - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8Di9gqPLwt5IIC + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8FcRar5XrAGnL0 body: encoding: US-ASCII string: '' @@ -664,8 +814,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -674,7 +824,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 13:30:03 GMT + - Mon, 11 Apr 2016 15:43:48 GMT Content-Type: - application/json Content-Length: @@ -692,7 +842,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8Di9AyPG0FJYAw + - req_8FcRg1EQDVfpku Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -701,13 +851,13 @@ http_interactions: encoding: UTF-8 string: | { - "id": "sub_8Di9gqPLwt5IIC", + "id": "sub_8FcRar5XrAGnL0", "object": "subscription", "application_fee_percent": null, "cancel_at_period_end": false, "canceled_at": null, - "current_period_end": 1462541399, - "current_period_start": 1459949399, + "current_period_end": 1462981423, + "current_period_start": 1460389423, "customer": "cus_8Di1wjdVktv5kt", "discount": null, "ended_at": null, @@ -727,17 +877,17 @@ http_interactions: "trial_period_days": null }, "quantity": 1, - "start": 1459949399, + "start": 1460389423, "status": "active", "tax_percent": null, "trial_end": null, "trial_start": null } http_version: - recorded_at: Wed, 06 Apr 2016 13:30:03 GMT + recorded_at: Mon, 11 Apr 2016 15:43:49 GMT - request: method: delete - uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8Di9gqPLwt5IIC?at_period_end=true + uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_8FcRar5XrAGnL0?at_period_end=true body: encoding: US-ASCII string: '' @@ -754,8 +904,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -764,7 +914,7 @@ http_interactions: Server: - nginx Date: - - Wed, 06 Apr 2016 13:30:04 GMT + - Mon, 11 Apr 2016 15:43:49 GMT Content-Type: - application/json Content-Length: @@ -782,7 +932,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8Di9ujL9MyuuZS + - req_8FcRvdzGhluZiD Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -791,13 +941,13 @@ http_interactions: encoding: UTF-8 string: | { - "id": "sub_8Di9gqPLwt5IIC", + "id": "sub_8FcRar5XrAGnL0", "object": "subscription", "application_fee_percent": null, "cancel_at_period_end": true, - "canceled_at": 1459949404, - "current_period_end": 1462541399, - "current_period_start": 1459949399, + "canceled_at": 1460389429, + "current_period_end": 1462981423, + "current_period_start": 1460389423, "customer": "cus_8Di1wjdVktv5kt", "discount": null, "ended_at": null, @@ -817,12 +967,12 @@ http_interactions: "trial_period_days": null }, "quantity": 1, - "start": 1459949399, + "start": 1460389423, "status": "active", "tax_percent": null, "trial_end": null, "trial_start": null } http_version: - recorded_at: Wed, 06 Apr 2016 13:30:04 GMT + recorded_at: Mon, 11 Apr 2016 15:43:50 GMT recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/subscriptions_user_renew_failed.yml b/test/vcr_cassettes/subscriptions_user_renew_failed.yml index 5fb22c749..4597cfc7b 100644 --- a/test/vcr_cassettes/subscriptions_user_renew_failed.yml +++ b/test/vcr_cassettes/subscriptions_user_renew_failed.yml @@ -1,5 +1,67 @@ --- http_interactions: +- request: + method: get + uri: https://api.stripe.com/v1/tokens/invalid_card_token + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' + response: + status: + code: 400 + message: Bad Request + headers: + Server: + - nginx + Date: + - Mon, 11 Apr 2016 15:47:34 GMT + Content-Type: + - application/json + Content-Length: + - '131' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8FcVweUogPiUZf + Stripe-Version: + - '2015-10-16' + body: + encoding: UTF-8 + string: | + { + "error": { + "type": "invalid_request_error", + "message": "No such token: invalid_card_token", + "param": "token" + } + } + http_version: + recorded_at: Mon, 11 Apr 2016 15:47:34 GMT - request: method: get uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX @@ -19,8 +81,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -29,11 +91,11 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 14:18:06 GMT + - Mon, 11 Apr 2016 15:47:35 GMT Content-Type: - application/json Content-Length: - - '3454' + - '5504' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -47,7 +109,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E69echXR3qGGa + - req_8FcV6gxRsSzUbZ Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -61,7 +123,7 @@ http_interactions: "account_balance": 0, "created": 1460026822, "currency": "usd", - "default_source": "card_17xdxN2sOmf47Nz9eyRuY12a", + "default_source": "card_17z7Ce2sOmf47Nz91IP2CV16", "delinquent": false, "description": "Lucile Seguin", "discount": null, @@ -73,7 +135,7 @@ http_interactions: "object": "list", "data": [ { - "id": "card_17xdxN2sOmf47Nz9eyRuY12a", + "id": "card_17z7Ce2sOmf47Nz91IP2CV16", "object": "card", "address_city": null, "address_country": null, @@ -105,6 +167,72 @@ http_interactions: "subscriptions": { "object": "list", "data": [ + { + "id": "sub_8FcRgFLyTO4ZeY", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1460389442, + "current_period_end": 1462981435, + "current_period_start": 1460389435, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460389435, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E6nlabIu0FNDK", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1460041071, + "current_period_end": 1462633067, + "current_period_start": 1460041067, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460041067, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, { "id": "sub_8E694MZ1FBtXBg", "object": "subscription", @@ -173,12 +301,12 @@ http_interactions: } ], "has_more": false, - "total_count": 2, + "total_count": 4, "url": "/v1/customers/cus_8E2ys9zDZgetWX/subscriptions" } } http_version: - recorded_at: Thu, 07 Apr 2016 14:18:06 GMT + recorded_at: Mon, 11 Apr 2016 15:47:35 GMT - request: method: post uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions @@ -198,8 +326,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' Content-Length: - '66' response: @@ -210,7 +338,7 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 14:18:07 GMT + - Mon, 11 Apr 2016 15:47:36 GMT Content-Type: - application/json Content-Length: @@ -228,7 +356,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E69jMRCeshYc1 + - req_8FcVzLJ4tiRJHF Stripe-Version: - '2015-10-16' body: @@ -242,5 +370,5 @@ http_interactions: } } http_version: - recorded_at: Thu, 07 Apr 2016 14:18:07 GMT + recorded_at: Mon, 11 Apr 2016 15:47:36 GMT recorded_with: VCR 3.0.1 diff --git a/test/vcr_cassettes/subscriptions_user_renew_success.yml b/test/vcr_cassettes/subscriptions_user_renew_success.yml index eb3cdfa25..f406f04f1 100644 --- a/test/vcr_cassettes/subscriptions_user_renew_success.yml +++ b/test/vcr_cassettes/subscriptions_user_renew_success.yml @@ -19,8 +19,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' Content-Length: - '81' response: @@ -31,11 +31,11 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 14:57:45 GMT + - Mon, 11 Apr 2016 15:43:52 GMT Content-Type: - application/json Content-Length: - - '780' + - '779' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -49,7 +49,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E6ntokZYBap5o + - req_8FcRua6xeSWJgP Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -58,10 +58,10 @@ http_interactions: encoding: UTF-8 string: | { - "id": "tok_17xeZp2sOmf47Nz9U7isup9R", + "id": "tok_17z7Ce2sOmf47Nz9tArxQ9hI", "object": "token", "card": { - "id": "card_17xeZp2sOmf47Nz9Nw38pLma", + "id": "card_17z7Ce2sOmf47Nz91IP2CV16", "object": "card", "address_city": null, "address_country": null, @@ -84,17 +84,17 @@ http_interactions: "name": null, "tokenization_method": null }, - "client_ip": "90.52.157.226", - "created": 1460041065, + "client_ip": "90.42.87.235", + "created": 1460389432, "livemode": false, "type": "card", "used": false } http_version: - recorded_at: Thu, 07 Apr 2016 14:57:45 GMT + recorded_at: Mon, 11 Apr 2016 15:43:52 GMT - request: method: get - uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX + uri: https://api.stripe.com/v1/tokens/tok_17z7Ce2sOmf47Nz9tArxQ9hI body: encoding: US-ASCII string: '' @@ -111,8 +111,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -121,11 +121,11 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 14:57:46 GMT + - Mon, 11 Apr 2016 15:43:53 GMT Content-Type: - application/json Content-Length: - - '3454' + - '779' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -139,7 +139,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E6nN7HdnY2Zr2 + - req_8FcRynHazNvAUI Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -148,357 +148,40 @@ http_interactions: encoding: UTF-8 string: | { - "id": "cus_8E2ys9zDZgetWX", - "object": "customer", - "account_balance": 0, - "created": 1460026822, - "currency": "usd", - "default_source": "card_17xdxN2sOmf47Nz9eyRuY12a", - "delinquent": false, - "description": "Lucile Seguin", - "discount": null, - "email": "lucile.seguin@live.fr", - "livemode": false, - "metadata": {}, - "shipping": null, - "sources": { - "object": "list", - "data": [ - { - "id": "card_17xdxN2sOmf47Nz9eyRuY12a", - "object": "card", - "address_city": null, - "address_country": null, - "address_line1": null, - "address_line1_check": null, - "address_line2": null, - "address_state": null, - "address_zip": null, - "address_zip_check": null, - "brand": "Visa", - "country": "US", - "customer": "cus_8E2ys9zDZgetWX", - "cvc_check": "pass", - "dynamic_last4": null, - "exp_month": 4, - "exp_year": 2017, - "fingerprint": "o52jybR7bnmNn6AT", - "funding": "credit", - "last4": "4242", - "metadata": {}, - "name": null, - "tokenization_method": null - } - ], - "has_more": false, - "total_count": 1, - "url": "/v1/customers/cus_8E2ys9zDZgetWX/sources" - }, - "subscriptions": { - "object": "list", - "data": [ - { - "id": "sub_8E694MZ1FBtXBg", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": false, - "canceled_at": null, - "current_period_end": 1462630683, - "current_period_start": 1460038683, - "customer": "cus_8E2ys9zDZgetWX", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1460038683, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - }, - { - "id": "sub_8E67Z0lSjjVxBn", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": false, - "canceled_at": null, - "current_period_end": 1462630527, - "current_period_start": 1460038527, - "customer": "cus_8E2ys9zDZgetWX", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "quantity": 1, - "start": 1460038527, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null - } - ], - "has_more": false, - "total_count": 2, - "url": "/v1/customers/cus_8E2ys9zDZgetWX/subscriptions" - } - } - http_version: - recorded_at: Thu, 07 Apr 2016 14:57:46 GMT -- request: - method: post - uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions - body: - encoding: UTF-8 - string: plan=mensuel-standard-month-20160404171519&card=tok_17xeZp2sOmf47Nz9U7isup9R - headers: - Accept: - - "*/*; q=0.5, application/xml" - Accept-Encoding: - - gzip, deflate - User-Agent: - - Stripe/v1 RubyBindings/1.30.2 - Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE - Content-Type: - - application/x-www-form-urlencoded - X-Stripe-Client-User-Agent: - - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' - Content-Length: - - '76' - response: - status: - code: 200 - message: OK - headers: - Server: - - nginx - Date: - - Thu, 07 Apr 2016 14:57:47 GMT - Content-Type: - - application/json - Content-Length: - - '821' - Connection: - - keep-alive - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Allow-Methods: - - GET, POST, HEAD, OPTIONS, DELETE - Access-Control-Allow-Origin: - - "*" - Access-Control-Max-Age: - - '300' - Cache-Control: - - no-cache, no-store - Request-Id: - - req_8E6nkvdYjkxZ3A - Stripe-Version: - - '2015-10-16' - Strict-Transport-Security: - - max-age=31556926; includeSubDomains - body: - encoding: UTF-8 - string: | - { - "id": "sub_8E6nlabIu0FNDK", - "object": "subscription", - "application_fee_percent": null, - "cancel_at_period_end": false, - "canceled_at": null, - "current_period_end": 1462633067, - "current_period_start": 1460041067, - "customer": "cus_8E2ys9zDZgetWX", - "discount": null, - "ended_at": null, - "metadata": {}, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, + "id": "tok_17z7Ce2sOmf47Nz9tArxQ9hI", + "object": "token", + "card": { + "id": "card_17z7Ce2sOmf47Nz91IP2CV16", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "cvc_check": "unchecked", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null + "name": null, + "tokenization_method": null }, - "quantity": 1, - "start": 1460041067, - "status": "active", - "tax_percent": null, - "trial_end": null, - "trial_start": null + "client_ip": "90.42.87.235", + "created": 1460389432, + "livemode": false, + "type": "card", + "used": false } http_version: - recorded_at: Thu, 07 Apr 2016 14:57:47 GMT -- request: - method: get - uri: https://api.stripe.com/v1/invoices?customer=cus_8E2ys9zDZgetWX&limit=1 - body: - encoding: US-ASCII - string: '' - headers: - Accept: - - "*/*; q=0.5, application/xml" - Accept-Encoding: - - gzip, deflate - User-Agent: - - Stripe/v1 RubyBindings/1.30.2 - Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE - Content-Type: - - application/x-www-form-urlencoded - X-Stripe-Client-User-Agent: - - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' - response: - status: - code: 200 - message: OK - headers: - Server: - - nginx - Date: - - Thu, 07 Apr 2016 14:57:48 GMT - Content-Type: - - application/json - Content-Length: - - '2207' - Connection: - - keep-alive - Access-Control-Allow-Credentials: - - 'true' - Access-Control-Allow-Methods: - - GET, POST, HEAD, OPTIONS, DELETE - Access-Control-Allow-Origin: - - "*" - Access-Control-Max-Age: - - '300' - Cache-Control: - - no-cache, no-store - Request-Id: - - req_8E6nsHStsgJ8uR - Stripe-Version: - - '2015-10-16' - Strict-Transport-Security: - - max-age=31556926; includeSubDomains - body: - encoding: UTF-8 - string: | - { - "object": "list", - "data": [ - { - "id": "in_17xeZr2sOmf47Nz9JTOtgIXv", - "object": "invoice", - "amount_due": 3000, - "application_fee": null, - "attempt_count": 1, - "attempted": true, - "charge": "ch_17xeZr2sOmf47Nz9KgHCuwK0", - "closed": true, - "currency": "usd", - "customer": "cus_8E2ys9zDZgetWX", - "date": 1460041067, - "description": null, - "discount": null, - "ending_balance": 0, - "forgiven": false, - "lines": { - "object": "list", - "data": [ - { - "id": "sub_8E6nlabIu0FNDK", - "object": "line_item", - "amount": 3000, - "currency": "usd", - "description": null, - "discountable": true, - "livemode": false, - "metadata": {}, - "period": { - "start": 1460041067, - "end": 1462633067 - }, - "plan": { - "id": "mensuel-standard-month-20160404171519", - "object": "plan", - "amount": 3000, - "created": 1459782921, - "currency": "usd", - "interval": "month", - "interval_count": 1, - "livemode": false, - "metadata": {}, - "name": "Mensuel - standard, association - month", - "statement_descriptor": null, - "trial_period_days": null - }, - "proration": false, - "quantity": 1, - "subscription": null, - "type": "subscription" - } - ], - "has_more": false, - "total_count": 1, - "url": "/v1/invoices/in_17xeZr2sOmf47Nz9JTOtgIXv/lines" - }, - "livemode": false, - "metadata": {}, - "next_payment_attempt": null, - "paid": true, - "period_end": 1460041067, - "period_start": 1460038527, - "receipt_number": null, - "starting_balance": 0, - "statement_descriptor": null, - "subscription": "sub_8E6nlabIu0FNDK", - "subtotal": 3000, - "tax": null, - "tax_percent": null, - "total": 3000, - "webhooks_delivered_at": 1460041067 - } - ], - "has_more": true, - "url": "/v1/invoices" - } - http_version: - recorded_at: Thu, 07 Apr 2016 14:57:48 GMT + recorded_at: Mon, 11 Apr 2016 15:43:53 GMT - request: method: get uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX @@ -518,8 +201,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -528,11 +211,11 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 14:57:49 GMT + - Mon, 11 Apr 2016 15:43:54 GMT Content-Type: - application/json Content-Length: - - '4474' + - '4479' Connection: - keep-alive Access-Control-Allow-Credentials: @@ -546,7 +229,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E6nTDGRZ4k0vh + - req_8FcRHlSiyZJDhh Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -608,8 +291,8 @@ http_interactions: "id": "sub_8E6nlabIu0FNDK", "object": "subscription", "application_fee_percent": null, - "cancel_at_period_end": false, - "canceled_at": null, + "cancel_at_period_end": true, + "canceled_at": 1460041071, "current_period_end": 1462633067, "current_period_start": 1460041067, "customer": "cus_8E2ys9zDZgetWX", @@ -710,13 +393,13 @@ http_interactions: } } http_version: - recorded_at: Thu, 07 Apr 2016 14:57:49 GMT + recorded_at: Mon, 11 Apr 2016 15:43:54 GMT - request: - method: get - uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions/sub_8E6nlabIu0FNDK + method: post + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions body: - encoding: US-ASCII - string: '' + encoding: UTF-8 + string: plan=mensuel-standard-month-20160404171519&card=tok_17z7Ce2sOmf47Nz9tArxQ9hI headers: Accept: - "*/*; q=0.5, application/xml" @@ -730,8 +413,10 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' + Content-Length: + - '76' response: status: code: 200 @@ -740,7 +425,7 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 14:57:50 GMT + - Mon, 11 Apr 2016 15:43:55 GMT Content-Type: - application/json Content-Length: @@ -758,7 +443,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E6nOZSSSXyv3E + - req_8FcR3oaI9ppgXN Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -767,13 +452,13 @@ http_interactions: encoding: UTF-8 string: | { - "id": "sub_8E6nlabIu0FNDK", + "id": "sub_8FcRgFLyTO4ZeY", "object": "subscription", "application_fee_percent": null, "cancel_at_period_end": false, "canceled_at": null, - "current_period_end": 1462633067, - "current_period_start": 1460041067, + "current_period_end": 1462981435, + "current_period_start": 1460389435, "customer": "cus_8E2ys9zDZgetWX", "discount": null, "ended_at": null, @@ -793,17 +478,17 @@ http_interactions: "trial_period_days": null }, "quantity": 1, - "start": 1460041067, + "start": 1460389435, "status": "active", "tax_percent": null, "trial_end": null, "trial_start": null } http_version: - recorded_at: Thu, 07 Apr 2016 14:57:50 GMT + recorded_at: Mon, 11 Apr 2016 15:43:55 GMT - request: - method: delete - uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions/sub_8E6nlabIu0FNDK?at_period_end=true + method: get + uri: https://api.stripe.com/v1/invoices?customer=cus_8E2ys9zDZgetWX&limit=1 body: encoding: US-ASCII string: '' @@ -820,8 +505,8 @@ http_interactions: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux - version 3.13.0-83-generic (buildd@lgw01-55) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) - ) #127-Ubuntu SMP Fri Mar 11 00:25:37 UTC 2016","hostname":"sylvain-sleede-pc"}' + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' response: status: code: 200 @@ -830,7 +515,478 @@ http_interactions: Server: - nginx Date: - - Thu, 07 Apr 2016 14:57:51 GMT + - Mon, 11 Apr 2016 15:44:00 GMT + Content-Type: + - application/json + Content-Length: + - '2207' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8FcRYAHuZb5cyO + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "object": "list", + "data": [ + { + "id": "in_17z7Ch2sOmf47Nz9q4hc7msO", + "object": "invoice", + "amount_due": 3000, + "application_fee": null, + "attempt_count": 1, + "attempted": true, + "charge": "ch_17z7Ch2sOmf47Nz9HcBWY6sb", + "closed": true, + "currency": "usd", + "customer": "cus_8E2ys9zDZgetWX", + "date": 1460389435, + "description": null, + "discount": null, + "ending_balance": 0, + "forgiven": false, + "lines": { + "object": "list", + "data": [ + { + "id": "sub_8FcRgFLyTO4ZeY", + "object": "line_item", + "amount": 3000, + "currency": "usd", + "description": null, + "discountable": true, + "livemode": false, + "metadata": {}, + "period": { + "start": 1460389435, + "end": 1462981435 + }, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "proration": false, + "quantity": 1, + "subscription": null, + "type": "subscription" + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/invoices/in_17z7Ch2sOmf47Nz9q4hc7msO/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "paid": true, + "period_end": 1460389435, + "period_start": 1460038527, + "receipt_number": null, + "starting_balance": 0, + "statement_descriptor": null, + "subscription": "sub_8FcRgFLyTO4ZeY", + "subtotal": 3000, + "tax": null, + "tax_percent": null, + "total": 3000, + "webhooks_delivered_at": 1460389435 + } + ], + "has_more": true, + "url": "/v1/invoices" + } + http_version: + recorded_at: Mon, 11 Apr 2016 15:44:00 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 11 Apr 2016 15:44:00 GMT + Content-Type: + - application/json + Content-Length: + - '5499' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8FcRYEKmK6OB6n + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "cus_8E2ys9zDZgetWX", + "object": "customer", + "account_balance": 0, + "created": 1460026822, + "currency": "usd", + "default_source": "card_17z7Ce2sOmf47Nz91IP2CV16", + "delinquent": false, + "description": "Lucile Seguin", + "discount": null, + "email": "lucile.seguin@live.fr", + "livemode": false, + "metadata": {}, + "shipping": null, + "sources": { + "object": "list", + "data": [ + { + "id": "card_17z7Ce2sOmf47Nz91IP2CV16", + "object": "card", + "address_city": null, + "address_country": null, + "address_line1": null, + "address_line1_check": null, + "address_line2": null, + "address_state": null, + "address_zip": null, + "address_zip_check": null, + "brand": "Visa", + "country": "US", + "customer": "cus_8E2ys9zDZgetWX", + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 4, + "exp_year": 2017, + "fingerprint": "o52jybR7bnmNn6AT", + "funding": "credit", + "last4": "4242", + "metadata": {}, + "name": null, + "tokenization_method": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/sources" + }, + "subscriptions": { + "object": "list", + "data": [ + { + "id": "sub_8FcRgFLyTO4ZeY", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462981435, + "current_period_start": 1460389435, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460389435, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E6nlabIu0FNDK", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": true, + "canceled_at": 1460041071, + "current_period_end": 1462633067, + "current_period_start": 1460041067, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460041067, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E694MZ1FBtXBg", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630683, + "current_period_start": 1460038683, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038683, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + }, + { + "id": "sub_8E67Z0lSjjVxBn", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462630527, + "current_period_start": 1460038527, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460038527, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + ], + "has_more": false, + "total_count": 4, + "url": "/v1/customers/cus_8E2ys9zDZgetWX/subscriptions" + } + } + http_version: + recorded_at: Mon, 11 Apr 2016 15:44:01 GMT +- request: + method: get + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions/sub_8FcRgFLyTO4ZeY + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 11 Apr 2016 15:44:01 GMT + Content-Type: + - application/json + Content-Length: + - '821' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET, POST, HEAD, OPTIONS, DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Request-Id: + - req_8FcRuKDuUfa7Gd + Stripe-Version: + - '2015-10-16' + Strict-Transport-Security: + - max-age=31556926; includeSubDomains + body: + encoding: UTF-8 + string: | + { + "id": "sub_8FcRgFLyTO4ZeY", + "object": "subscription", + "application_fee_percent": null, + "cancel_at_period_end": false, + "canceled_at": null, + "current_period_end": 1462981435, + "current_period_start": 1460389435, + "customer": "cus_8E2ys9zDZgetWX", + "discount": null, + "ended_at": null, + "metadata": {}, + "plan": { + "id": "mensuel-standard-month-20160404171519", + "object": "plan", + "amount": 3000, + "created": 1459782921, + "currency": "usd", + "interval": "month", + "interval_count": 1, + "livemode": false, + "metadata": {}, + "name": "Mensuel - standard, association - month", + "statement_descriptor": null, + "trial_period_days": null + }, + "quantity": 1, + "start": 1460389435, + "status": "active", + "tax_percent": null, + "trial_end": null, + "trial_start": null + } + http_version: + recorded_at: Mon, 11 Apr 2016 15:44:01 GMT +- request: + method: delete + uri: https://api.stripe.com/v1/customers/cus_8E2ys9zDZgetWX/subscriptions/sub_8FcRgFLyTO4ZeY?at_period_end=true + body: + encoding: US-ASCII + string: '' + headers: + Accept: + - "*/*; q=0.5, application/xml" + Accept-Encoding: + - gzip, deflate + User-Agent: + - Stripe/v1 RubyBindings/1.30.2 + Authorization: + - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-User-Agent: + - '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 4.4.5-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP + PREEMPT Thu Mar 10 07:38:19 CET 2016","hostname":"Sylvain-desktop"}' + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 11 Apr 2016 15:44:02 GMT Content-Type: - application/json Content-Length: @@ -848,7 +1004,7 @@ http_interactions: Cache-Control: - no-cache, no-store Request-Id: - - req_8E6nip0fkOtET5 + - req_8FcRLf7OAD4RGL Stripe-Version: - '2015-10-16' Strict-Transport-Security: @@ -857,13 +1013,13 @@ http_interactions: encoding: UTF-8 string: | { - "id": "sub_8E6nlabIu0FNDK", + "id": "sub_8FcRgFLyTO4ZeY", "object": "subscription", "application_fee_percent": null, "cancel_at_period_end": true, - "canceled_at": 1460041071, - "current_period_end": 1462633067, - "current_period_start": 1460041067, + "canceled_at": 1460389442, + "current_period_end": 1462981435, + "current_period_start": 1460389435, "customer": "cus_8E2ys9zDZgetWX", "discount": null, "ended_at": null, @@ -883,12 +1039,12 @@ http_interactions: "trial_period_days": null }, "quantity": 1, - "start": 1460041067, + "start": 1460389435, "status": "active", "tax_percent": null, "trial_end": null, "trial_start": null } http_version: - recorded_at: Thu, 07 Apr 2016 14:57:51 GMT + recorded_at: Mon, 11 Apr 2016 15:44:02 GMT recorded_with: VCR 3.0.1 From 59153f42984ac9fb404f5cb8c9fb8e77c0d88ff9 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 12 Apr 2016 15:09:47 +0200 Subject: [PATCH 53/64] test admin renew subscription --- .../subscriptions/renew_as_admin_test.rb | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 test/integration/subscriptions/renew_as_admin_test.rb diff --git a/test/integration/subscriptions/renew_as_admin_test.rb b/test/integration/subscriptions/renew_as_admin_test.rb new file mode 100644 index 000000000..1253aca40 --- /dev/null +++ b/test/integration/subscriptions/renew_as_admin_test.rb @@ -0,0 +1,56 @@ +class Subscriptions::RenewAsAdminTest < ActionDispatch::IntegrationTest + + setup do + @admin = User.find_by_username('admin') + login_as(@admin, scope: :user) + end + + test 'admin successfully renew a subscription before it has ended' do + + user = User.find_by_username('kdumas') + plan = Plan.find_by(base_name: 'Mensuel tarif réduit') + + VCR.use_cassette("subscriptions_admin_renew_success") do + post '/api/subscriptions', + { + subscription: { + plan_id: plan.id, + user_id: user.id + } + }.to_json, default_headers + end + + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the correct plan was subscribed + subscription = json_response(response.body) + assert_equal plan.id, subscription[:plan_id], 'subscribed plan does not match' + + # Check that the user has the correct subscription + assert_not_nil user.subscription, "user's subscription was not found" + assert_not_nil user.subscription.plan, "user's subscribed plan was not found" + assert_equal plan.id, user.subscription.plan_id, "user's plan does not match" + + # Check that the training credits were set correctly + assert_empty user.training_credits, 'training credits were not reset' + assert_equal user.subscription.plan.training_credit_nb, plan.training_credit_nb, 'trainings credits were not allocated' + + # Check that the user benefit from prices of his plan + printer = Machine.find_by_slug('imprimante-3d') + assert_equal 10, (printer.prices.find_by(group_id: user.group_id, plan_id: user.subscription.plan_id).amount / 100), 'machine hourly price does not match' + + # Check notification was sent to the user + notification = Notification.find_by(notification_type_id: NotificationType.find_by_name('notify_member_subscribed_plan'), attached_object_type: 'Subscription', attached_object_id: subscription[:id]) + assert_not_nil notification, 'user notification was not created' + assert_equal user.id, notification.receiver_id, 'wrong user notified' + + # Check generated invoice + invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id]) + assert_invoice_pdf invoice + assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription' + + end + +end \ No newline at end of file From 745a89f18fe11f79bec5bfc742bfa0c8c1db3e80 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 12 Apr 2016 15:41:22 +0200 Subject: [PATCH 54/64] [fixtures] make subscriptions dates dynamic --- test/fixtures/subscriptions.yml | 31 ----------------------------- test/fixtures/subscriptions.yml.erb | 31 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 31 deletions(-) delete mode 100644 test/fixtures/subscriptions.yml create mode 100644 test/fixtures/subscriptions.yml.erb diff --git a/test/fixtures/subscriptions.yml b/test/fixtures/subscriptions.yml deleted file mode 100644 index 0eca46fdd..000000000 --- a/test/fixtures/subscriptions.yml +++ /dev/null @@ -1,31 +0,0 @@ - -subscription_1: - id: 1 - plan_id: 2 - user_id: 3 - stp_subscription_id: sub_8DGB4ErIc2asOv - created_at: 2016-04-05 08:35:51.784514000 Z - updated_at: 2016-04-05 08:35:51.784514000 Z - expired_at: 2016-06-05 08:35:51.000000000 Z - canceled_at: 2016-04-05 08:35:55.615387000 Z - -subscription_2: - id: 2 - plan_id: 3 - user_id: 4 - stp_subscription_id: - created_at: 2016-04-05 08:36:46.829879000 Z - updated_at: 2016-04-05 08:36:46.829879000 Z - expired_at: 2016-05-05 08:36:46.828332000 Z - canceled_at: - -# subscription has expired (do not change dates) -subscription_3: - id: 3 - plan_id: 1 - user_id: 7 - stp_subscription_id: - created_at: 2012-03-12 11:03:31.651441000 Z - updated_at: 2012-03-12 11:03:31.651441000 Z - expired_at: 2012-04-12 11:03:31.648274000 Z - canceled_at: diff --git a/test/fixtures/subscriptions.yml.erb b/test/fixtures/subscriptions.yml.erb new file mode 100644 index 000000000..c7a5ea120 --- /dev/null +++ b/test/fixtures/subscriptions.yml.erb @@ -0,0 +1,31 @@ + +subscription_1: + id: 1 + plan_id: 2 + user_id: 3 + stp_subscription_id: sub_8DGB4ErIc2asOv + created_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + updated_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + expired_at: <%= (1.month.from_now - 10.days).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + canceled_at: <%= (10.days.ago + 1.minute).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + +subscription_2: + id: 2 + plan_id: 3 + user_id: 4 + stp_subscription_id: + created_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + updated_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + expired_at: <%= (1.month.from_now - 10.days).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + canceled_at: + +# subscription has expired (do not change dates) +subscription_3: + id: 3 + plan_id: 1 + user_id: 7 + stp_subscription_id: + created_at: 2012-03-12 11:03:31.651441000 Z + updated_at: 2012-03-12 11:03:31.651441000 Z + expired_at: 2012-04-12 11:03:31.648274000 Z + canceled_at: From 7817e285f0191db74af7db19d804a781545fe48e Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 12 Apr 2016 16:43:10 +0200 Subject: [PATCH 55/64] rake task to remove stripe secrets from VCR cassettes --- lib/tasks/fablab.rake | 13 ++++++++++++- ...ate_for_machine_with_subscription_success.yml | 16 ++++++++-------- ...te_for_machine_without_subscription_error.yml | 10 +++++----- ..._for_machine_without_subscription_success.yml | 16 ++++++++-------- ...te_for_training_with_subscription_success.yml | 10 +++++----- ...for_training_without_subscription_success.yml | 16 ++++++++-------- .../subscriptions_admin_create_success.yml | 12 ++++++------ .../subscriptions_user_create_failed.yml | 4 ++-- .../subscriptions_user_create_success.yml | 16 ++++++++-------- .../subscriptions_user_renew_failed.yml | 6 +++--- .../subscriptions_user_renew_success.yml | 16 ++++++++-------- 11 files changed, 73 insertions(+), 62 deletions(-) diff --git a/lib/tasks/fablab.rake b/lib/tasks/fablab.rake index 32c3b4010..1786f819a 100644 --- a/lib/tasks/fablab.rake +++ b/lib/tasks/fablab.rake @@ -31,7 +31,7 @@ namespace :fablab do puts "-> Done" end - desc "Cancel strip subscriptions" + desc "Cancel stripe subscriptions" task cancel_subscriptions: :environment do Subscription.where("expired_at >= ?", Time.now.at_beginning_of_day).each do |s| puts "-> Start cancel subscription of #{s.user.email}" @@ -179,4 +179,15 @@ namespace :fablab do ar_base.dump_fixtures end end + + desc 'clean stripe secrets from VCR cassettes' + task clean_cassettes_secrets: :environment do + Dir['test/vcr_cassettes/*.yml'].each do |cassette_file| + cassette = File.read(cassette_file) + cassette.gsub!(Rails.application.secrets.stripe_api_key, 'sk_test_testfaketestfaketestfake') + cassette.gsub!(Rails.application.secrets.stripe_publishable_key, 'pk_test_faketestfaketestfaketest') + puts cassette + File.write(cassette_file, cassette) + end + end end diff --git a/test/vcr_cassettes/reservations_create_for_machine_with_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_machine_with_subscription_success.yml index f1273017f..b41abceb0 100644 --- a/test/vcr_cassettes/reservations_create_for_machine_with_subscription_success.yml +++ b/test/vcr_cassettes/reservations_create_for_machine_with_subscription_success.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -186,7 +186,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -266,7 +266,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -352,7 +352,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -436,7 +436,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -573,7 +573,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -710,7 +710,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml index 18ff86370..51b5dc8b1 100644 --- a/test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml +++ b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_error.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -186,7 +186,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -365,7 +365,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -430,7 +430,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml index 9249aa5fc..47be47a36 100644 --- a/test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml +++ b/test/vcr_cassettes/reservations_create_for_machine_without_subscription_success.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -186,7 +186,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -365,7 +365,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -449,7 +449,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -655,7 +655,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -773,7 +773,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -891,7 +891,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml index 7cb903c66..0e3f2a47a 100644 --- a/test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml +++ b/test/vcr_cassettes/reservations_create_for_training_with_subscription_success.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -186,7 +186,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -272,7 +272,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -390,7 +390,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml b/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml index f33512801..a90e48296 100644 --- a/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml +++ b/test/vcr_cassettes/reservations_create_for_training_without_subscription_success.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -186,7 +186,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -367,7 +367,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -451,7 +451,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -650,7 +650,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -768,7 +768,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -886,7 +886,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/subscriptions_admin_create_success.yml b/test/vcr_cassettes/subscriptions_admin_create_success.yml index 11fca6153..2a7c2bf10 100644 --- a/test/vcr_cassettes/subscriptions_admin_create_success.yml +++ b/test/vcr_cassettes/subscriptions_admin_create_success.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -193,7 +193,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -285,7 +285,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -421,7 +421,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -633,7 +633,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -723,7 +723,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/subscriptions_user_create_failed.yml b/test/vcr_cassettes/subscriptions_user_create_failed.yml index bce52ebeb..b32669f29 100644 --- a/test/vcr_cassettes/subscriptions_user_create_failed.yml +++ b/test/vcr_cassettes/subscriptions_user_create_failed.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/subscriptions_user_create_success.yml b/test/vcr_cassettes/subscriptions_user_create_success.yml index 6f650ef27..4f945c009 100644 --- a/test/vcr_cassettes/subscriptions_user_create_success.yml +++ b/test/vcr_cassettes/subscriptions_user_create_success.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -196,7 +196,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -377,7 +377,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -469,7 +469,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -605,7 +605,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -809,7 +809,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -899,7 +899,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/subscriptions_user_renew_failed.yml b/test/vcr_cassettes/subscriptions_user_renew_failed.yml index 4597cfc7b..29e03a51c 100644 --- a/test/vcr_cassettes/subscriptions_user_renew_failed.yml +++ b/test/vcr_cassettes/subscriptions_user_renew_failed.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -76,7 +76,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -321,7 +321,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: diff --git a/test/vcr_cassettes/subscriptions_user_renew_success.yml b/test/vcr_cassettes/subscriptions_user_renew_success.yml index f406f04f1..4eade7125 100644 --- a/test/vcr_cassettes/subscriptions_user_renew_success.yml +++ b/test/vcr_cassettes/subscriptions_user_renew_success.yml @@ -14,7 +14,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -106,7 +106,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -196,7 +196,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -408,7 +408,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -500,7 +500,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -636,7 +636,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -881,7 +881,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: @@ -971,7 +971,7 @@ http_interactions: User-Agent: - Stripe/v1 RubyBindings/1.30.2 Authorization: - - Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE + - Bearer sk_test_testfaketestfaketestfake Content-Type: - application/x-www-form-urlencoded X-Stripe-Client-User-Agent: From cc8991f6bcfbb7dafff18fe61c991f07c1ea0048 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 12 Apr 2016 16:51:36 +0200 Subject: [PATCH 56/64] fix test fixtures --- test/fixtures/subscriptions.yml.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/subscriptions.yml.erb b/test/fixtures/subscriptions.yml.erb index c7a5ea120..46b992d3b 100644 --- a/test/fixtures/subscriptions.yml.erb +++ b/test/fixtures/subscriptions.yml.erb @@ -6,7 +6,7 @@ subscription_1: stp_subscription_id: sub_8DGB4ErIc2asOv created_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> updated_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> - expired_at: <%= (1.month.from_now - 10.days).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + expired_at: <%= (1.month.from_now - 11.days).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> canceled_at: <%= (10.days.ago + 1.minute).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> subscription_2: @@ -16,7 +16,7 @@ subscription_2: stp_subscription_id: created_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> updated_at: <%= 10.days.ago.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> - expired_at: <%= (1.month.from_now - 10.days).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + expired_at: <%= (1.month.from_now - 11.days).utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> canceled_at: # subscription has expired (do not change dates) From 02c72e55d962cecd97c2004c4c8af7024dab6bab Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 13 Apr 2016 10:43:25 +0200 Subject: [PATCH 57/64] test admins --- db/test_seeds.rb | 64 --------------------------------- test/integration/abuses_test.rb | 2 +- test/integration/admins_test.rb | 50 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 65 deletions(-) delete mode 100644 db/test_seeds.rb create mode 100644 test/integration/admins_test.rb diff --git a/db/test_seeds.rb b/db/test_seeds.rb deleted file mode 100644 index 1b28fc80c..000000000 --- a/db/test_seeds.rb +++ /dev/null @@ -1,64 +0,0 @@ -Group.create!([ - {name: "standard, association", slug: "standard"}, - {name: "étudiant, - de 25 ans, enseignant, demandeur d'emploi", slug: "student"}, - {name: "artisan, commerçant, chercheur, auto-entrepreneur", slug: "merchant"}, - {name: "PME, PMI, SARL, SA", slug: "business"} -]) - -if Category.count == 0 - Category.create!([ - {name: "Stage"}, - {name: "Atelier"} - ]) -end - -if StatisticIndex.count == 0 - StatisticIndex.create!([ - {id:1, es_type_key:'subscription', label:'Abonnements'}, - {id:2, es_type_key:'machine', label:'Heures machines'}, - {id:3, es_type_key:'training', label:'Formations'}, - {id:4, es_type_key:'event', label:'Ateliers/Stages'}, - {id:5, es_type_key:'account', label:'Inscriptions', ca: false}, - {id:6, es_type_key:'project', label:'Projets', ca: false}, - {id:7, es_type_key:'user', label:'Utilisateurs', table: false, ca: false} - ]) - connection = ActiveRecord::Base.connection - if connection.instance_values["config"][:adapter] == 'postgresql' - connection.execute("SELECT setval('statistic_indices_id_seq', 7);") - end -end - -if StatisticField.count == 0 - StatisticField.create!([ - # available data_types : index, number, date, text, list - {key:'trainingId', label:'ID Formation', statistic_index_id: 3, data_type: 'index'}, - {key:'trainingDate', label:'Date Formation', statistic_index_id: 3, data_type: 'date'}, - {key:'eventId', label:'ID Évènement', statistic_index_id: 4, data_type: 'index'}, - {key:'eventDate', label:'Date Évènement', statistic_index_id: 4, data_type: 'date'}, - {key:'themes', label:'Thèmes', statistic_index_id: 6, data_type: 'list'}, - {key:'components', label:'Composants', statistic_index_id: 6, data_type: 'list'}, - {key:'machines', label:'Machines', statistic_index_id: 6, data_type: 'list'}, - {key:'name', label:'Nom Évènement', statistic_index_id: 4, data_type: 'text'}, - {key:'userId', label:'ID Utilisateur', statistic_index_id: 7, data_type: 'index'} - ]) -end - -if StatisticType.count == 0 - StatisticType.create!([ - {id:1, statistic_index_id: 1, key: 'month', label:'Abonnements mensuels', graph: true, simple: true}, - {id:2, statistic_index_id: 1, key: 'year', label:'Abonnements annuels', graph: true, simple: true}, - {id:3, statistic_index_id: 2, key: 'booking', label:'Réservations', graph: true, simple: true}, - {id:4, statistic_index_id: 2, key: 'hour', label:"Nombre d'heures", graph: true, simple: false}, - {id:5, statistic_index_id: 3, key: 'booking', label:'Réservations', graph: false, simple: true}, - {id:6, statistic_index_id: 3, key: 'hour', label:"Nombre d'heures", graph: false, simple: false}, - {id:7, statistic_index_id: 4, key: 'booking', label:'Nombre de places', graph: false, simple: false}, - {id:8, statistic_index_id: 4, key: 'hour', label:"Nombre d'heures", graph: false, simple: false}, - {id:9, statistic_index_id: 5, key: 'member', label:'Utilisateurs', graph: true, simple: true}, - {id:10, statistic_index_id: 6, key: 'project', label:'Projets', graph: false, simple: true}, - {id:11, statistic_index_id: 7, key: 'revenue', label:"Chiffre d'affaires", graph: false, simple: false} - ]) - connection = ActiveRecord::Base.connection - if connection.instance_values["config"][:adapter] == 'postgresql' - connection.execute("SELECT setval('statistic_types_id_seq', 11);") - end -end diff --git a/test/integration/abuses_test.rb b/test/integration/abuses_test.rb index fd3b4a27d..2a0b5bbfe 100644 --- a/test/integration/abuses_test.rb +++ b/test/integration/abuses_test.rb @@ -15,7 +15,7 @@ class AbusesTest < ActionDispatch::IntegrationTest # Abuse report test 'visitor report an abuse' do - project = Project.first + project = Project.take post '/api/abuses', { diff --git a/test/integration/admins_test.rb b/test/integration/admins_test.rb new file mode 100644 index 000000000..8969b7697 --- /dev/null +++ b/test/integration/admins_test.rb @@ -0,0 +1,50 @@ +class AdminsTest < ActionDispatch::IntegrationTest + + # Called before every test method runs. Can be used + # to set up fixture information. + def setup + @admin = User.find_by_username('admin') + login_as(@admin, scope: :user) + end + + # Called after every test method runs. Can be used to tear + # down fixture information. + + def teardown + # Do nothing + end + + test 'create an admin' do + + post '/api/admins', + { + admin: { + username: 'glepower', + email: 'gerard.lepower@admins.net', + profile_attributes: { + first_name: 'Gérard', + last_name: 'Lepower', + gender: true, + birthday: '1999-09-19', + phone: '0547124852', + address_attributes: { + address: '6 Avenue Henri de Bournazel, 19000 Tulle' + } + } + } + }.to_json, + default_headers + + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the correct admin was created + admin = json_response(response.body) + user = User.where(id: admin[:admin][:id]).first + assert_not_nil user, 'admin was not created in database' + + # Check he's got the admin role + assert user.has_role?(:admin), 'admin does not have the admin role' + end +end \ No newline at end of file From c0f57cc213b6b54d32a15a31ef9bd35cb85dae5e Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 13 Apr 2016 11:53:21 +0200 Subject: [PATCH 58/64] [ongoing] availability tests --- test/integration/availabilities_test.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/integration/availabilities_test.rb b/test/integration/availabilities_test.rb index 94db8f5da..8b399ea60 100644 --- a/test/integration/availabilities_test.rb +++ b/test/integration/availabilities_test.rb @@ -4,10 +4,23 @@ class AvailabilitiesTest < ActionDispatch::IntegrationTest login_as(admin, scope: :user) end - test "return availability by id" do + test 'return availability by id' do a = Availability.take get "/api/availabilities/#{a.id}" + + # Check response format & status assert_equal 200, response.status + assert_equal Mime::JSON, response.content_type + + # Check the correct availability was returned + availability = json_response(response.body) + assert_equal a.id, availability[:id], 'availability id does not match' + end + + test 'get machine availabilities' do + m = Machine.find_by_slug('decoupeuse-vinyle') + + get "/api/availabilities/machines/#{m.id}" end end From 423431dc726bf87a649ff8e6d43ed75f741a39a6 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 13 Apr 2016 15:08:49 +0200 Subject: [PATCH 59/64] make availability fixtures dynamic --- ...ilabilities.yml => availabilities.yml.erb} | 32 +++++++++---------- test/fixtures/slots.yml | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) rename test/fixtures/{availabilities.yml => availabilities.yml.erb} (59%) diff --git a/test/fixtures/availabilities.yml b/test/fixtures/availabilities.yml.erb similarity index 59% rename from test/fixtures/availabilities.yml rename to test/fixtures/availabilities.yml.erb index 7e3e00131..0a66d412a 100644 --- a/test/fixtures/availabilities.yml +++ b/test/fixtures/availabilities.yml.erb @@ -1,8 +1,8 @@ availability_1: id: 1 - start_at: 2016-04-11 06:00:00.000000000 Z - end_at: 2016-04-11 10:00:00.000000000 Z + start_at: <%= DateTime.now.monday.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= DateTime.now.monday.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: training created_at: 2016-04-04 15:24:01.517486000 Z updated_at: 2016-04-04 15:24:01.517486000 Z @@ -11,8 +11,8 @@ availability_1: availability_2: id: 2 - start_at: 2016-04-12 06:00:00.000000000 Z - end_at: 2016-04-12 10:00:00.000000000 Z + start_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: training created_at: 2016-04-04 15:24:09.169364000 Z updated_at: 2016-04-04 15:24:09.169364000 Z @@ -21,8 +21,8 @@ availability_2: availability_3: id: 3 - start_at: 2016-04-11 12:00:00.000000000 Z - end_at: 2016-04-11 18:00:00.000000000 Z + start_at: <%= DateTime.now.monday.utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= DateTime.now.monday.utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: machines created_at: 2016-04-04 15:24:27.587583000 Z updated_at: 2016-04-04 15:24:27.587583000 Z @@ -31,8 +31,8 @@ availability_3: availability_4: id: 4 - start_at: 2016-04-12 12:00:00.000000000 Z - end_at: 2016-04-12 18:00:00.000000000 Z + start_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: machines created_at: 2016-04-04 15:24:44.044908000 Z updated_at: 2016-04-04 15:24:44.044908000 Z @@ -41,8 +41,8 @@ availability_4: availability_5: id: 5 - start_at: 2016-04-13 12:00:00.000000000 Z - end_at: 2016-04-13 18:00:00.000000000 Z + start_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: machines created_at: 2016-04-04 15:25:48.584444000 Z updated_at: 2016-04-04 15:25:48.584444000 Z @@ -51,8 +51,8 @@ availability_5: availability_6: id: 6 - start_at: 2016-04-14 12:00:00.000000000 Z - end_at: 2016-04-14 18:00:00.000000000 Z + start_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: machines created_at: 2016-04-04 15:26:17.953216000 Z updated_at: 2016-04-04 15:26:17.953216000 Z @@ -61,8 +61,8 @@ availability_6: availability_7: id: 7 - start_at: 2016-04-14 12:00:00.000000000 Z - end_at: 2016-04-14 18:00:00.000000000 Z + start_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: machines created_at: 2016-04-04 15:26:39.278627000 Z updated_at: 2016-04-04 15:26:39.278627000 Z @@ -71,8 +71,8 @@ availability_7: availability_8: id: 8 - start_at: 2016-04-13 06:00:00.000000000 Z - end_at: 2016-04-13 10:00:00.000000000 Z + start_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> available_type: training created_at: 2016-04-04 15:26:49.572724000 Z updated_at: 2016-04-04 15:26:49.572724000 Z diff --git a/test/fixtures/slots.yml b/test/fixtures/slots.yml index ace3405fb..10141ae73 100644 --- a/test/fixtures/slots.yml +++ b/test/fixtures/slots.yml @@ -3,10 +3,10 @@ slot_1: id: 1 start_at: 2012-04-11 06:00:00.000000000 Z end_at: 2012-04-11 10:00:00.000000000 Z - reservation_id: 12 + reservation_id: 1 created_at: 2012-03-12 13:40:22.342717000 Z updated_at: 2012-03-12 13:40:22.342717000 Z - availability_id: 1 + availability_id: 12 ex_start_at: canceled_at: ex_end_at: From 6f4e795d9feb93f47254fda625ffa895ea4dabc9 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 13 Apr 2016 15:19:57 +0200 Subject: [PATCH 60/64] machine availabilities test --- test/integration/availabilities_test.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/integration/availabilities_test.rb b/test/integration/availabilities_test.rb index 8b399ea60..37bc355d8 100644 --- a/test/integration/availabilities_test.rb +++ b/test/integration/availabilities_test.rb @@ -22,5 +22,16 @@ class AvailabilitiesTest < ActionDispatch::IntegrationTest m = Machine.find_by_slug('decoupeuse-vinyle') get "/api/availabilities/machines/#{m.id}" + + # Check response format & status + assert_equal 200, response.status + assert_equal Mime::JSON, response.content_type + + # Check the correct availabilities was returned + availabilities = json_response(response.body) + assert_not_empty availabilities, 'no availabilities were found' + assert_not_nil availabilities[0], 'first availability was unexpectedly nil' + assert_not_nil availabilities[0][:machine], "first availability's machine was unexpectedly nil" + assert_equal m.id, availabilities[0][:machine][:id], "first availability's machine does not match the required machine" end end From 3016ac1e82662344b36062c6b73080387d6d1e5b Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 13 Apr 2016 17:26:17 +0200 Subject: [PATCH 61/64] tests for availabilities --- test/fixtures/availabilities.yml.erb | 41 +++++++++++++++++ test/fixtures/machines_availabilities.yml | 20 +++++++++ .../availabilities/as_admin_test.rb | 45 +++++++++++++++++++ .../as_user_test.rb} | 33 +++++++------- 4 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 test/integration/availabilities/as_admin_test.rb rename test/integration/{availabilities_test.rb => availabilities/as_user_test.rb} (55%) diff --git a/test/fixtures/availabilities.yml.erb b/test/fixtures/availabilities.yml.erb index 0a66d412a..3fefe7c87 100644 --- a/test/fixtures/availabilities.yml.erb +++ b/test/fixtures/availabilities.yml.erb @@ -117,4 +117,45 @@ availability_12: created_at: 2012-04-04 15:24:01.517486000 Z updated_at: 2012-04-04 15:24:01.517486000 Z nb_total_places: + destroying: false + + availability_13: + id: 13 + start_at: 2015-06-15 12:00:28.000000000 Z + end_at: 2015-06-15 18:00:28.000000000 Z + available_type: machines + created_at: 2015-05-30 18:40:39.141601000 Z + updated_at: 2015-05-30 18:40:39.141601000 Z + nb_total_places: + destroying: false + + +availability_14: + id: 14 + start_at: <%= 20.days.from_now.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= 20.days.from_now.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + available_type: machines + created_at: 2016-04-04 15:44:04.023557000 Z + updated_at: 2016-04-04 15:44:04.023557000 Z + nb_total_places: + destroying: false + +availability_15: + id: 15 + start_at: <%= 40.days.from_now.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= 40.days.from_now.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + available_type: machines + created_at: 2016-04-04 15:44:04.023557000 Z + updated_at: 2016-04-04 15:44:04.023557000 Z + nb_total_places: + destroying: false + +availability_16: + id: 16 + start_at: <%= 80.days.from_now.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + end_at: <%= 80.days.from_now.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + available_type: machines + created_at: 2016-04-04 15:44:04.023557000 Z + updated_at: 2016-04-04 15:44:04.023557000 Z + nb_total_places: destroying: false \ No newline at end of file diff --git a/test/fixtures/machines_availabilities.yml b/test/fixtures/machines_availabilities.yml index c045b25ac..919de5bdf 100644 --- a/test/fixtures/machines_availabilities.yml +++ b/test/fixtures/machines_availabilities.yml @@ -83,3 +83,23 @@ machines_availability_17: id: 17 machine_id: 6 availability_id: 7 + +machines_availability_18: + id: 18 + machine_id: 2 + availability_id: 13 + +machines_availability_19: + id: 19 + machine_id: 2 + availability_id: 14 + +machines_availability_20: + id: 20 + machine_id: 2 + availability_id: 15 + +machines_availability_21: + id: 21 + machine_id: 2 + availability_id: 16 diff --git a/test/integration/availabilities/as_admin_test.rb b/test/integration/availabilities/as_admin_test.rb new file mode 100644 index 000000000..59b17106f --- /dev/null +++ b/test/integration/availabilities/as_admin_test.rb @@ -0,0 +1,45 @@ +module Availabilities + class AsAdminTest < ActionDispatch::IntegrationTest + setup do + admin = User.with_role(:admin).first + login_as(admin, scope: :user) + end + + test 'return availability by id' do + a = Availability.take + + get "/api/availabilities/#{a.id}" + + # Check response format & status + assert_equal 200, response.status + assert_equal Mime::JSON, response.content_type + + # Check the correct availability was returned + availability = json_response(response.body) + assert_equal a.id, availability[:id], 'availability id does not match' + end + + test 'get machine availabilities as admin' do + m = Machine.find_by_slug('decoupeuse-vinyle') + + get "/api/availabilities/machines/#{m.id}" + + # Check response format & status + assert_equal 200, response.status + assert_equal Mime::JSON, response.content_type + + # Check the correct availabilities was returned + availabilities = json_response(response.body) + assert_not_empty availabilities, 'no availabilities were found' + assert_not_nil availabilities[0], 'first availability was unexpectedly nil' + assert_not_nil availabilities[0][:machine], "first availability's machine was unexpectedly nil" + assert_equal m.id, availabilities[0][:machine][:id], "first availability's machine does not match the required machine" + + # Check that we din't get availabilities from the past + availabilities.each do |a| + assert_not a[:start] < DateTime.now, 'retrieved a slot in the past' + end + end +end +end + diff --git a/test/integration/availabilities_test.rb b/test/integration/availabilities/as_user_test.rb similarity index 55% rename from test/integration/availabilities_test.rb rename to test/integration/availabilities/as_user_test.rb index 37bc355d8..d61654525 100644 --- a/test/integration/availabilities_test.rb +++ b/test/integration/availabilities/as_user_test.rb @@ -1,24 +1,10 @@ -class AvailabilitiesTest < ActionDispatch::IntegrationTest +class Availabilities::AsUserTest < ActionDispatch::IntegrationTest setup do - admin = User.with_role(:admin).first - login_as(admin, scope: :user) + user = User.find_by_username('kdumas') + login_as(user, scope: :user) end - test 'return availability by id' do - a = Availability.take - - get "/api/availabilities/#{a.id}" - - # Check response format & status - assert_equal 200, response.status - assert_equal Mime::JSON, response.content_type - - # Check the correct availability was returned - availability = json_response(response.body) - assert_equal a.id, availability[:id], 'availability id does not match' - end - - test 'get machine availabilities' do + test 'get machine availabilities as user' do m = Machine.find_by_slug('decoupeuse-vinyle') get "/api/availabilities/machines/#{m.id}" @@ -33,5 +19,16 @@ class AvailabilitiesTest < ActionDispatch::IntegrationTest assert_not_nil availabilities[0], 'first availability was unexpectedly nil' assert_not_nil availabilities[0][:machine], "first availability's machine was unexpectedly nil" assert_equal m.id, availabilities[0][:machine][:id], "first availability's machine does not match the required machine" + + # Check that we din't get availabilities from the past + availabilities.each do |a| + assert_not a[:start] < DateTime.now, 'retrieved a slot in the past' + end + + # Check that we don't get availabilities in more than a month + availabilities.each do |a| + assert_not a[:start] > 1.month.from_now , 'retrieved a slot in more than 1 month for user who has no yearly subscription' + end end end + From d880a8f0f4177d5c7eb26590901e6779975fb120 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 13 Apr 2016 18:21:01 +0200 Subject: [PATCH 62/64] fix unable to reserve Event --- app/models/reservation.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 2c4359064..fa0f5f0cf 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -219,8 +219,8 @@ class Reservation < ActiveRecord::Base end end - UsersCredits::Manager.new(reservation: self).update_credits - return true + UsersCredits::Manager.new(reservation: self).update_credits unless reservable_type == 'Event' + true end end @@ -252,7 +252,7 @@ class Reservation < ActiveRecord::Base if user.invoicing_disabled? if valid? save! - UsersCredits::Manager.new(reservation: self).update_credits + UsersCredits::Manager.new(reservation: self).update_credits unless reservable_type == 'Event' return true end else @@ -279,7 +279,7 @@ class Reservation < ActiveRecord::Base save! end - UsersCredits::Manager.new(reservation: self).update_credits + UsersCredits::Manager.new(reservation: self).update_credits unless reservable_type == 'Event' return true end end From 34648c7e9ebeb85db5ce738f8e5cd2e932efc898 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 13 Apr 2016 18:33:43 +0200 Subject: [PATCH 63/64] event test --- test/integration/events_test.rb | 117 ++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 test/integration/events_test.rb diff --git a/test/integration/events_test.rb b/test/integration/events_test.rb new file mode 100644 index 000000000..ca821ad45 --- /dev/null +++ b/test/integration/events_test.rb @@ -0,0 +1,117 @@ +class EventsTest < ActionDispatch::IntegrationTest + + setup do + admin = User.with_role(:admin).first + login_as(admin, scope: :user) + end + + test 'creation modification reservation and re-modification scenario' do + + # First, we create a new event + post '/api/events', + { + event: { + title: 'OpenLab discovery day', + description: 'A day to discover the Fablab and try its machines and possibilities.', + start_date: 1.week.from_now.utc, + start_time: 1.week.from_now.utc.change({hour: 16}), + end_date: 1.week.from_now.utc, + end_time: 1.week.from_now.utc.change({hour: 20}), + category_ids: [Category.first.id], + amount: 0 + } + }.to_json, + default_headers + + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the event was created correctly + event = json_response(response.body) + e = Event.where(id: event[:id]).first + assert_not_nil e, 'Event was not created in database' + + # Check the remaining free places are not defined + assert_nil e.nb_free_places, "Free places shouldn't be defined" + + # Then, modify the event to set a nb of places + put "/api/events/#{e.id}", + { + event: { + title: 'OpenLab discovery day', + description: 'A day to discover the Fablab and try its machines and possibilities.', + start_date: 1.week.from_now.utc, + start_time: 1.week.from_now.utc.change({hour: 16}), + end_date: 1.week.from_now.utc, + end_time: 1.week.from_now.utc.change({hour: 20}), + category_ids: [Category.first.id], + amount: 0, + nb_total_places: 10 + } + } + + # Check response format & status + assert_equal 200, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the places numbers were updated successfully + e = Event.where(id: event[:id]).first + assert_equal 10, e.nb_total_places, 'Total number of places was not updated' + assert_equal 10, e.nb_free_places, 'Number of free places was not updated' + + # Now, let's make a reservation on this event + post '/api/reservations', + { + reservation: { + user_id: User.find_by_username('pdurand').id, + reservable_id: e.id, + reservable_type: 'Event', + nb_reserve_places: 2, + nb_reserve_reduced_places: 0, + slot_attributes: [ + { + start_at: e.availability.start_at, + end_at: e.availability.end_at, + availability_id: e.availability.id, + offered: false + } + ] + } + }.to_json, + default_headers + + # Check response format & status + assert_equal 201, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the remaining places were updated successfully + e = Event.where(id: event[:id]).first + assert_equal 8, e.nb_free_places, 'Number of free places was not updated' + + # Finally, modify the event to add some places + put "/api/events/#{e.id}", + { + event: { + title: 'OpenLab discovery day', + description: 'A day to discover the Fablab and try its machines and possibilities.', + start_date: 1.week.from_now.utc, + start_time: 1.week.from_now.utc.change({hour: 16}), + end_date: 1.week.from_now.utc, + end_time: 1.week.from_now.utc.change({hour: 20}), + category_ids: [Category.first.id], + amount: 0, + nb_total_places: 20 + } + } + + # Check response format & status + assert_equal 200, response.status, response.body + assert_equal Mime::JSON, response.content_type + + # Check the places numbers were updated successfully + e = Event.where(id: event[:id]).first + assert_equal 20, e.nb_total_places, 'Total number of places was not updated' + assert_equal 18, e.nb_free_places, 'Number of free places was not updated' + end +end \ No newline at end of file From ed478f95c7cb691a29d7abaceae7d4f9285e54f9 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Wed, 20 Apr 2016 11:24:28 +0200 Subject: [PATCH 64/64] UsersCredits::Manager accept an event Reservation but do not do nothing, acting as a blackbox --- app/models/reservation.rb | 6 +++--- app/services/users_credits/manager.rb | 13 ++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/models/reservation.rb b/app/models/reservation.rb index fa0f5f0cf..ab9f353d4 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -219,7 +219,7 @@ class Reservation < ActiveRecord::Base end end - UsersCredits::Manager.new(reservation: self).update_credits unless reservable_type == 'Event' + UsersCredits::Manager.new(reservation: self).update_credits true end end @@ -252,7 +252,7 @@ class Reservation < ActiveRecord::Base if user.invoicing_disabled? if valid? save! - UsersCredits::Manager.new(reservation: self).update_credits unless reservable_type == 'Event' + UsersCredits::Manager.new(reservation: self).update_credits return true end else @@ -279,7 +279,7 @@ class Reservation < ActiveRecord::Base save! end - UsersCredits::Manager.new(reservation: self).update_credits unless reservable_type == 'Event' + UsersCredits::Manager.new(reservation: self).update_credits return true end end diff --git a/app/services/users_credits/manager.rb b/app/services/users_credits/manager.rb index 6fa9b7398..ce0016575 100644 --- a/app/services/users_credits/manager.rb +++ b/app/services/users_credits/manager.rb @@ -15,8 +15,10 @@ module UsersCredits @manager = Managers::Training.new(reservation, plan) elsif reservation.reservable_type == "Machine" @manager = Managers::Machine.new(reservation, plan) + elsif reservation.reservable_type == "Event" + @manager = Managers::Event.new(reservation, plan) else - raise ArgumentError, "reservation.reservable_type must be Training or Machine" + raise ArgumentError, "reservation.reservable_type must be Training, Machine or Event" end else raise ArgumentError, "you have to pass either a reservation or a user to initialize a UsersCredits::Manager" @@ -141,5 +143,14 @@ module UsersCredits return false, nil end end + + class Event < Reservation + def will_use_credits? + false + end + + def update_credits + end + end end end