=begin require 'spec_helper' describe "TestDrive Lesson Flow" do let(:user) { FactoryGirl.create(:user, remaining_test_drives: 0) } let(:teacher_user) { FactoryGirl.create(:teacher_user) } let(:teacher_user2) { FactoryGirl.create(:teacher_user) } let(:teacher) { teacher_user.teacher } let(:lesson_booking_slot_single1) { FactoryGirl.build(:lesson_booking_slot_single) } let(:lesson_booking_slot_single2) { FactoryGirl.build(:lesson_booking_slot_single) } let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring) } let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) } let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] } let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] } let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) } let(:affiliate_partner2) { FactoryGirl.create(:affiliate_partner, lesson_rate: 0.30) } let(:school) { FactoryGirl.create(:school) } let(:card_lessons) {FactoryGirl.create(:posa_card_lesson_4)} let(:retailer) {FactoryGirl.create(:retailer)} before { teacher.stripe_account_id = stripe_account1_id teacher.save! } after { Timecop.return } it "works" do user.desired_package = LessonPackageType.test_drive_2 user.save! # user has no test drives, no credit card on file, but attempts to book a lesson booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") booking.errors.any?.should be_false booking.card_presumed_ok.should be_false booking.user.should eql user booking.card_presumed_ok.should be_false booking.should eql user.unprocessed_test_drive booking.sent_notices.should be_false teacher_user.has_booked_test_drive_with_student?(user).should be_true user.reload user.remaining_test_drives.should eql 0 ########## Need validate their credit card token = create_stripe_token result = user.payment_update({token: token, zip: '78759', test_drive: true, booking_id: booking.id}) booking = result[:lesson] booking.errors.any?.should be_false lesson = booking.lesson_sessions[0] lesson.errors.any?.should be_false test_drive = result[:test_drive] test_drive.errors.any?.should be_false user.reload user.remaining_test_drives.should eql 1 booking.card_presumed_ok.should be_true booking.sent_notices.should be_true lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0) lesson.reload test_drive.stripe_charge_id.should_not be_nil test_drive.recurly_tax_in_cents.should be 247 test_drive.recurly_total_in_cents.should eql 2999 + 247 test_drive.recurly_subtotal_in_cents.should eql 2999 test_drive.recurly_currency.should eql 'USD' line_item = test_drive.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON line_item.product_id.should eq LessonPackageType.test_drive_2.id user.reload user.stripe_customer_id.should_not be nil user.lesson_purchases.length.should eql 1 user.remaining_test_drives.should eql 1 lesson_purchase = user.lesson_purchases[0] lesson_purchase.price.should eql 29.99 lesson_purchase.lesson_package_type.is_test_drive?.should eql true customer = Stripe::Customer.retrieve(user.stripe_customer_id) customer.email.should eql user.email booking.lesson_sessions.length.should eql 1 lesson_session = booking.lesson_sessions[0] lesson_session.status.should eql LessonBooking::STATUS_REQUESTED booking.status.should eql LessonBooking::STATUS_REQUESTED ######### Teacher counters with new slot teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 14) UserMailer.deliveries.clear lesson_session.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'}) booking.reload booking.errors.any?.should be false lesson_session.lesson_booking.errors.any?.should be false lesson_session.lesson_booking_slots.length.should eql 1 lesson_session.lesson_booking_slots[0].proposer.should eql teacher_user teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last teacher_counter.should eql teacher_countered_slot teacher_counter.proposer.should eql teacher_user # booking.lesson_booking_slots.length.should eql 3 UserMailer.deliveries.length.should eql 1 chat = ChatMessage.unscoped.order(:created_at).last chat.channel.should eql ChatMessage::CHANNEL_LESSON chat.message.should eql 'Does this work?' chat.user.should eql teacher_user chat.target_user.should eql user notification = Notification.unscoped.order(:created_at).last notification.session_id.should eql lesson_session.music_session.id notification.student_directed.should eql true notification.purpose.should eql 'counter' notification.description.should eql NotificationTypes::LESSON_MESSAGE ######### Student counters with new slot student_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 16) UserMailer.deliveries.clear lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'}) lesson_session.errors.any?.should be false lesson_session.lesson_booking.errors.any?.should be false lesson_session.lesson_booking_slots.length.should eql 2 student_counter = booking.lesson_booking_slots.order(:created_at).last student_counter.proposer.should eql user booking.reload # booking.lesson_booking_slots.length.should eql 4 UserMailer.deliveries.length.should eql 1 chat = ChatMessage.unscoped.order(:created_at).last chat.message.should eql 'Does this work better?' chat.channel.should eql ChatMessage::CHANNEL_LESSON chat.user.should eql user chat.target_user.should eql teacher_user notification = Notification.unscoped.order(:created_at).last notification.session_id.should eql lesson_session.music_session.id notification.student_directed.should eql false notification.purpose.should eql 'counter' notification.description.should eql NotificationTypes::LESSON_MESSAGE ######## Teacher accepts slot UserMailer.deliveries.clear lesson_session.accept({message: 'Yeah I got this', slot: student_counter.id, update_all: false, accepter: teacher_user}) lesson_session.errors.any?.should be_false lesson_session.reload lesson_session.slot.should eql student_counter lesson_session.status.should eql LessonSession::STATUS_APPROVED booking.reload booking.default_slot.should eql student_counter lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0) booking.status.should eql LessonBooking::STATUS_APPROVED UserMailer.deliveries.length.should eql 2 chat = ChatMessage.unscoped.order(:created_at).last chat.message.should eql 'Yeah I got this' chat.channel.should eql ChatMessage::CHANNEL_LESSON chat.user.should eql teacher_user chat.target_user.should eql user notification = Notification.unscoped.order(:created_at).last notification.session_id.should eql lesson_session.music_session.id notification.student_directed.should eql true notification.purpose.should eql 'accept' notification.description.should eql NotificationTypes::LESSON_MESSAGE notification.message.should be_nil # teacher & student get into session start = lesson_session.scheduled_start end_time = lesson_session.scheduled_start + (60 * lesson_session.duration) uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time) # artificially end the session, which is covered by other background jobs lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! Timecop.travel(end_time + 1) UserMailer.deliveries.clear # background code comes around and analyses the session lesson.analyse lesson.session_completed lesson_session.reload lesson_session.analysed.should be_true analysis = lesson_session.analysis analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT analysis["student"].should eql LessonSessionAnalyser::NO_SHOW lesson_session.billed.should be false if lesson_session.billing_error_detail puts "testdrive flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests end lesson_session.billing_error_reason.should be_nil lesson_session.sent_notices.should be true purchase = lesson_session.lesson_package_purchase purchase.should_not be_nil purchase.price_in_cents.should eql 2999 purchase.lesson_package_type.is_test_drive?.should be true user.reload user.remaining_test_drives.should eql 1 UserMailer.deliveries.length.should eql 2 # one for student, one for teacher found_student_email = false UserMailer.deliveries.each do |d| if d.subject == "You have used 1 of 2 TestDrive lesson credits" found_student_email = true end end found_student_email.should be_true teacher_distribution = lesson_session.teacher_distribution teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.ready.should be_true teacher_distribution.distributed.should be_false LessonBooking.hourly_check LessonSession.hourly_check teacher_distribution.reload teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.ready.should be_true teacher_distribution.distributed.should be_false TeacherPayment.count.should eql 0 TeacherPayment.hourly_check TeacherPayment.count.should eql 1 lesson_session.reload purchase.reload purchase.teacher_distribution.should be_nil teacher_payment = TeacherPayment.first teacher_payment.amount_in_cents.should eql 1000 teacher_payment.fee_in_cents.should eql 0 teacher_payment.teacher.should eql teacher_user teacher_distribution.reload teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.ready.should be_true teacher_distribution.distributed.should be_true teacher_payment.teacher_payment_charge.amount_in_cents.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round teacher_payment.teacher_payment_charge.fee_in_cents.should eql 0 user.sales.count.should eql 1 sale = user.sales[0] sale.sale_line_items.count.should eql 1 sale.sale_line_items[0].affiliate_distributions.count.should eql 0 lesson_session.lesson_booking.status.should eql LessonBooking::STATUS_COMPLETED lesson_session.lesson_booking.success.should be_true LessonBooking.bookings(user, teacher_user, nil).count.should eql 1 LessonBooking.engaged_bookings(user, teacher_user, nil).count.should eql 1 teacher_user.has_booked_test_drive_with_student?(user).should be_true booking.reload booking.lesson_sessions.length.should eql 1 end it "works using posa card" do PosaCard.activate(card_lessons, retailer) card_lessons.reload card_lessons.claim(user) card_lessons.errors.any?.should be false user.reload user.jamclass_credits.should eql 4 # user has no test drives, no credit card on file, but attempts to book a lesson booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") booking.errors.any?.should be_false booking.card_presumed_ok.should be_false booking.user.should eql user booking.sent_notices.should be_true booking.posa_card.should eql card_lessons booking.posa_card_purchased.should be_true user.unprocessed_test_drive.should be_nil teacher_user.has_booked_test_drive_with_student?(user).should be_true user.reload user.jamclass_credits.should eql 3 lesson_session = booking.lesson_sessions[0] lesson_session.posa_card.should eql card_lessons lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0) lesson_session.reload #booking.lesson_package_purchases.should eql [card_lessons.lesson_package_purchase] user.stripe_customer_id.should be nil user.lesson_purchases.length.should eql 1 lesson_purchase = user.lesson_purchases[0] lesson_purchase.price.should eql 49.99 lesson_purchase.lesson_package_type.is_test_drive?.should eql true lesson_purchase.posa_card.should eql card_lessons lesson_session.status.should eql LessonBooking::STATUS_REQUESTED booking.status.should eql LessonBooking::STATUS_REQUESTED ######### Teacher counters with new slot teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 14) UserMailer.deliveries.clear lesson_session.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'}) booking.reload booking.errors.any?.should be false lesson_session.lesson_booking.errors.any?.should be false lesson_session.lesson_booking_slots.length.should eql 1 lesson_session.lesson_booking_slots[0].proposer.should eql teacher_user teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last teacher_counter.should eql teacher_countered_slot teacher_counter.proposer.should eql teacher_user # booking.lesson_booking_slots.length.should eql 3 UserMailer.deliveries.length.should eql 1 chat = ChatMessage.unscoped.order(:created_at).last chat.channel.should eql ChatMessage::CHANNEL_LESSON chat.message.should eql 'Does this work?' chat.user.should eql teacher_user chat.target_user.should eql user notification = Notification.unscoped.order(:created_at).last notification.session_id.should eql lesson_session.music_session.id notification.student_directed.should eql true notification.purpose.should eql 'counter' notification.description.should eql NotificationTypes::LESSON_MESSAGE ######### Student counters with new slot student_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 16) UserMailer.deliveries.clear lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'}) lesson_session.errors.any?.should be false lesson_session.lesson_booking.errors.any?.should be false lesson_session.lesson_booking_slots.length.should eql 2 student_counter = booking.lesson_booking_slots.order(:created_at).last student_counter.proposer.should eql user booking.reload # booking.lesson_booking_slots.length.should eql 4 UserMailer.deliveries.length.should eql 1 chat = ChatMessage.unscoped.order(:created_at).last chat.message.should eql 'Does this work better?' chat.channel.should eql ChatMessage::CHANNEL_LESSON chat.user.should eql user chat.target_user.should eql teacher_user notification = Notification.unscoped.order(:created_at).last notification.session_id.should eql lesson_session.music_session.id notification.student_directed.should eql false notification.purpose.should eql 'counter' notification.description.should eql NotificationTypes::LESSON_MESSAGE ######## Teacher accepts slot UserMailer.deliveries.clear lesson_session.accept({message: 'Yeah I got this', slot: student_counter.id, update_all: false, accepter: teacher_user}) lesson_session.errors.any?.should be_false lesson_session.reload lesson_session.slot.should eql student_counter lesson_session.status.should eql LessonSession::STATUS_APPROVED booking.reload booking.default_slot.should eql student_counter lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0) booking.status.should eql LessonBooking::STATUS_APPROVED UserMailer.deliveries.length.should eql 2 chat = ChatMessage.unscoped.order(:created_at).last chat.message.should eql 'Yeah I got this' chat.channel.should eql ChatMessage::CHANNEL_LESSON chat.user.should eql teacher_user chat.target_user.should eql user notification = Notification.unscoped.order(:created_at).last notification.session_id.should eql lesson_session.music_session.id notification.student_directed.should eql true notification.purpose.should eql 'accept' notification.description.should eql NotificationTypes::LESSON_MESSAGE notification.message.should be_nil # teacher & student get into session start = lesson_session.scheduled_start end_time = lesson_session.scheduled_start + (60 * lesson_session.duration) uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time) # artificially end the session, which is covered by other background jobs lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! Timecop.travel(end_time + 1) UserMailer.deliveries.clear # background code comes around and analyses the session lesson_session.analyse lesson_session.session_completed lesson_session.reload lesson_session.analysed.should be_true analysis = lesson_session.analysis analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT analysis["student"].should eql LessonSessionAnalyser::NO_SHOW lesson_session.billed.should be false if lesson_session.billing_error_detail puts "testdrive flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests end lesson_session.billing_error_reason.should be_nil lesson_session.sent_notices.should be true purchase = lesson_session.lesson_package_purchase purchase.should_not be_nil purchase.price_in_cents.should eql 4999 purchase.lesson_package_type.is_test_drive?.should be true user.reload user.remaining_test_drives.should eql 0 UserMailer.deliveries.length.should eql 2 # one for student, one for teacher found_student_email = false UserMailer.deliveries.each do |d| if d.subject == "You have used 1 of 4 TestDrive lesson credits" found_student_email = true end end found_student_email.should be_true teacher_distribution = lesson_session.teacher_distribution teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.ready.should be_true teacher_distribution.distributed.should be_false LessonBooking.hourly_check LessonSession.hourly_check teacher_distribution.reload teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.ready.should be_true teacher_distribution.distributed.should be_false TeacherPayment.count.should eql 0 TeacherPayment.hourly_check TeacherPayment.count.should eql 1 lesson_session.reload purchase.reload purchase.teacher_distribution.should be_nil teacher_payment = TeacherPayment.first teacher_payment.amount_in_cents.should eql 1000 teacher_payment.fee_in_cents.should eql 0 teacher_payment.teacher.should eql teacher_user teacher_distribution.reload teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.ready.should be_true teacher_distribution.distributed.should be_true teacher_payment.teacher_payment_charge.amount_in_cents.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round teacher_payment.teacher_payment_charge.fee_in_cents.should eql 0 user.sales.count.should eql 1 sale = user.sales[0] sale.sale_line_items.count.should eql 1 sale.sale_line_items[0].affiliate_distributions.count.should eql 0 lesson_session.lesson_booking.status.should eql LessonBooking::STATUS_COMPLETED lesson_session.lesson_booking.success.should be_true LessonBooking.bookings(user, teacher_user, nil).count.should eql 1 LessonBooking.engaged_bookings(user, teacher_user, nil).count.should eql 1 teacher_user.has_booked_test_drive_with_student?(user).should be_true end # VRFS-4069 it "cancels with no credit card" do slots = [] slots << FactoryGirl.build(:lesson_booking_slot_single) slots << FactoryGirl.build(:lesson_booking_slot_single) booking = LessonBooking.book_test_drive(user, teacher_user, slots, "Hey I've heard of you before.") booking.errors.any?.should be_false lesson = booking.lesson_sessions[0] booking.card_presumed_ok.should be_false user.reload user.remaining_test_drives.should eql 0 lesson.cancel({canceler: user, message: "sorry about that"}) user.reload user.remaining_test_drives.should eql 0 booking.reload booking.status.should eql LessonBooking::STATUS_CANCELED teacher_user.has_booked_test_drive_with_student?(user).should be_false end it "cancels with credit card" do lesson = testdrive_lesson(user, teacher_user) user.reload user.remaining_test_drives.should eql 3 lesson.cancel({canceler: user, message: "sorry about that"}) user.reload user.remaining_test_drives.should eql 4 end it "post-lesson emails" do UserMailer.deliveries.clear lesson = testdrive_lesson(user, teacher_user, {accept:true, success: true}) user.reload user.remaining_test_drives.should eql 3 found_student_email = false UserMailer.deliveries.each do |d| if d.subject == "You have used 1 of 4 TestDrive lesson credits" found_student_email = true end end found_student_email.should be_true end # tests that the correct emails are sent out after test drives are done it "both no show, then student no shows" do UserMailer.deliveries.clear lesson = testdrive_lesson(user, teacher_user, {accept: true, miss: true, package_count: 2}) found_no_credit_email = false found_no_success_email = false UserMailer.deliveries.each do |d| if d.subject == "Your TestDrive with #{teacher_user.name} will not use a credit" found_no_credit_email = true end if d.subject == "Your TestDrive with #{user.name} was not successful" found_no_success_email = true end end found_no_credit_email.should be_true found_no_success_email.should be_true UserMailer.deliveries.clear user.reload user.remaining_test_drives.should eql 2 lesson = testdrive_lesson(user, teacher_user, {accept: true, finish: true}) user.reload user.remaining_test_drives.should eql 1 completed_test_drive = false done_not_completed = false paid_but_no_show = false UserMailer.deliveries.each do |d| if d.subject == "You have used #{user.remaining_test_drives} of #{user.total_test_drives} TestDrive lesson credits" done_not_completed = true end if d.subject == "You have used all TestDrive lesson credits" completed_test_drive = true end if d.subject == "You successfully completed a lesson with #{user.name}" paid_but_no_show = true end end done_not_completed.should be_true paid_but_no_show.should be_true completed_test_drive.should be_false UserMailer.deliveries.clear # now use last credit lesson = testdrive_lesson(user, teacher_user2, {accept: true, finish: true, student_show: true}) user.reload user.remaining_test_drives.should eql 0 completed_test_drive = true paid = false UserMailer.deliveries.each do |d| if d.subject == "You have used all TestDrive lesson credits" completed_test_drive = true end if d.subject == "You successfully completed a lesson with #{user.name}" paid = true end end # You successfully completed a lesson with #{@student.name}" completed_test_drive.should be_true paid.should be_true end end =end