diff --git a/Gemfile b/Gemfile index d095397..0939189 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'faraday', '>= 0.8', '~> 0.14.0' +gem 'faraday', '~> 1.0' gem 'json' group :test do diff --git a/README.md b/README.md index 3376f6d..db262fb 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,170 @@ clevertap.upload(event) clevertap.upload(events) # Works as well with [CleverTap::Event] ``` +### Create a campaign +CleverTap documentation: https://developer.clevertap.com/docs/create-campaign-api + +```ruby +client = CleverTap::Client.new(AUTH_ACCOUNT_ID, AUTH_PASSCODE) + +## SMS +campaign = CleverTap::Campaign::Sms.new( + to: { 'Email' => ['john@doe.com'] }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } +) + +client.create_campaign(campaign) +``` + + +
+ Web push example + + ```ruby + ## Web push + campaign = CleverTap::Campaign::WebPush.new( + to: { + 'FBID' => %w[102029292929388 114342342453463], + 'Email' => ['john@doe.com', 'jane@doe.com'], + 'Identity' => ['JohnDoe'], + 'objectId' => [ + '_asdnkansdjknaskdjnasjkndja', + '-adffajjdfoaiaefiohnefwprjf' + ] + }, + tag_group: 'my tag group', + campaign_id: 1_000_000_043, + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'How are you doing today?', + 'platform_specific' => { # Optional + 'safari' => { + 'deep_link' => 'https://apple.com', + 'ttl' => 10 + }, + 'chrome' => { + 'image' => 'https://www.exampleImage.com', + 'icon' => 'https://www.exampleIcon.com', + 'deep_link' => ' https://google.co', + 'ttl' => 10, + 'require_interaction' => true, + 'cta_title1' => 'title', + 'cta_link1' => 'http://www.example2.com', + 'cta_iconlink1' => 'https://www.exampleIcon2.com' + }, + 'firefox' => { + 'icon' => 'https://www.exampleIcon.com', + 'deep_link' => 'https://mozilla.org', + 'ttl' => 10 + } + } + } + ) + + client.create_campaign(campaign) + ``` +
+ + +
+ Push example + + ```ruby + ## Push + campaign = CleverTap::Campaign::Push.new( + to: { + 'FBID' => %w[ + 102029292929388 + 114342342453463 + ], + 'GPID' => [ + '1928288389299292' + ], + 'Email' => [ + 'john@doe.com', + 'jane@doe.com' + ], + 'Identity' => [ + 'JohnDoe' + ], + 'objectId' => [ + '_asdnkansdjknaskdjnasjkndja', + '-adffajjdfoaiaefiohnefwprjf' + ] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Welcome', + 'body' => 'Smsbody', + 'platform_specific' => { # Optional + 'ios' => { + 'deep_link' => 'example.com', + 'sound_file' => 'example.caf', + 'category' => 'notification category', + 'badge_count' => 1, + 'key' => 'value_ios' + }, + 'android' => { + 'background_image' => 'http://example.jpg', + 'default_sound' => true, + 'deep_link' => 'example.com', + 'large_icon' => 'http://example.png', + 'key' => 'value_android', + 'wzrk_cid' => 'engagement' + } + } + } + ) + + client.create_campaign(campaign) + ``` +
+ + +
+ Email example + + ```ruby + ## Email + campaign = CleverTap::Campaign::Email.new( + to: { + 'FBID' => %w[ + 102029292929388 + 114342342453463 + ], + 'GPID' => [ + '1928288389299292' + ], + 'Email' => [ + 'john@doe.com', + 'jane@doe.com' + ], + 'Identity' => [ + 'JohnDoe' + ], + 'objectId' => [ + '_asdnkansdjknaskdjnasjkndja', + '-adffajjdfoaiaefiohnefwprjf' + ] + }, + tag_group: 'my tag group', + respect_frequency_caps: false, + content: { + 'subject' => 'Welcome', + 'body' => '
Your HTML content for the email
', + 'sender_name' => 'CleverTap' + } + ) + + client.create_campaign(campaign) + ``` +
+ + ### Send requests as *Dry Run* Passing parameter `dry_run: true` to upload methods you can test the data submitted for a validation errors. diff --git a/clever_tap.gemspec b/clever_tap.gemspec index a6e8bbf..7d6387b 100644 --- a/clever_tap.gemspec +++ b/clever_tap.gemspec @@ -25,7 +25,7 @@ Gem::Specification.new do |spec| 'public gem pushes.' end - spec.add_dependency 'faraday', '>= 0.8', '<= 0.14.0' + spec.add_dependency 'faraday', '~> 1.0' spec.add_dependency 'json' spec.add_development_dependency 'bundler', '~> 1.14' diff --git a/lib/clever_tap.rb b/lib/clever_tap.rb index 9481f4e..e3c77b9 100644 --- a/lib/clever_tap.rb +++ b/lib/clever_tap.rb @@ -2,10 +2,16 @@ require 'clever_tap/config' require 'clever_tap/client' +require 'clever_tap/campaign' +require 'clever_tap/campaign/sms' +require 'clever_tap/campaign/web_push' +require 'clever_tap/campaign/push' +require 'clever_tap/campaign/email' require 'clever_tap/entity' require 'clever_tap/event' require 'clever_tap/profile' require 'clever_tap/uploader' +require 'clever_tap/campaign_creator' require 'clever_tap/response' require 'clever_tap/successful_response' require 'clever_tap/failed_response' @@ -66,6 +72,11 @@ def upload_profile(profile, **options) upload_profiles([profile], options) end + def create_campaign(campaign) + response = CampaignCreator.new(campaign).call(client) + normalize_response(response, records: [campaign]) + end + private def normalize_response(response, records:) diff --git a/lib/clever_tap/campaign.rb b/lib/clever_tap/campaign.rb new file mode 100644 index 0000000..86ff1ff --- /dev/null +++ b/lib/clever_tap/campaign.rb @@ -0,0 +1,190 @@ +class CleverTap + class NoContentError < RuntimeError + def message + 'No `content` param provided for Campaign' + end + end + + class NoReceiversError < RuntimeError + def message + 'No `to` param provided for Campaign' + end + end + + class InvalidIdentityTypeError < RuntimeError + def message + 'The identities types are not valid for Campaigns' + end + end + + class ReceiversLimitExceededError < RuntimeError + def message + 'The max users per campaign limit was exceeded' + end + end + + class NoChannelIdError < RuntimeError + def message + 'Channel Id (wzrk_cid) must be sent' + end + end + + # @!attribute to + # @return [Hash{String=>Array}] list of receivers + class Campaign + ALLOWED_IDENTITIES = %w[FBID Email Identity objectId GPID ID].freeze + TO_STRING = 'to'.freeze + TAG_GROUP = 'tag_group'.freeze + CAMPAIGN_ID = 'campaign_id'.freeze + CONTENT = 'content'.freeze + PROVIDER_NICK_NAME = 'provider_nick_name'.freeze + NOTIFICATION_SENT = 'notification_sent'.freeze + RESPECT_FREQUENCY_CAPS = 'respect_frequency_caps'.freeze + WZRK_CID = 'wzrk_cid'.freeze + BADGE_ID = 'badge_id'.freeze + BADGE_ICON = 'badge_icon'.freeze + MUTABLE_CONTENT = 'mutable-content'.freeze + PLATFORM_SPECIFIC = 'platform_specific'.freeze + MAX_USERS_PER_CAMPAIGN = 1000 + + attr_accessor :to + + # @param to [Hash{String=>Array}] List of receivers' identities grouped by type + # @param content [Hash{String=>Array] Content hash + def initialize(to:, + content:, + tag_group: nil, + campaign_id: nil, + provider_nick_name: nil, + notification_sent: nil, + respect_frequency_caps: nil, + wzrk_cid: nil, + badge_id: nil, + badge_icon: nil, + mutable_content: nil, + platform_specific: nil) + @to = to + @tag_group = tag_group + @campaign_id = campaign_id + @content = content + @provider_nick_name = provider_nick_name + @notification_sent = notification_sent + @respect_frequency_caps = respect_frequency_caps + @wzrk_cid = wzrk_cid + @badge_id = badge_id + @badge_icon = badge_icon + @mutable_content = mutable_content + @platform_specific = platform_specific || content_platform_specific + end + + # @return [Hash] + def to_h + receivers_hash + .merge(tag_group_hash) + .merge(provider_nick_name_hash) + .merge(notification_sent_hash) + .merge(respect_frequency_caps_hash) + .merge(badge_id_hash) + .merge(badge_icon_hash) + .merge(mutable_content_hash) + end + + # @return [Hash] + def receivers_hash + raise NoReceiversError if empty_receivers? + raise InvalidIdentityTypeError unless allowed?(@to.keys) + raise ReceiversLimitExceededError if receivers_limit_exceeded? + + { TO_STRING => @to } + end + + # @return [Hash] + def tag_group_hash + return {} unless @tag_group + + { TAG_GROUP => @tag_group } + end + + # @return [Hash] + def campaign_id_hash + return {} unless @campaign_id + + { CAMPAIGN_ID => @campaign_id } + end + + # @return [Hash] + def content_hash + raise NotImplementedError + end + + # @return [Hash] + def provider_nick_name_hash + return {} unless @provider_nick_name + + { PROVIDER_NICK_NAME => @provider_nick_name } + end + + # @return [Hash] + def notification_sent_hash + return {} unless @notification_sent + + { NOTIFICATION_SENT => @notification_sent } + end + + # @return [Hash] + def respect_frequency_caps_hash + return {} if @respect_frequency_caps.nil? + + { RESPECT_FREQUENCY_CAPS => @respect_frequency_caps } + end + + # @return [Hash] + def wzrk_cid_hash + return {} unless @wzrk_cid + + { WZRK_CID => @wzrk_cid } + end + + # @return [Hash] + def badge_id_hash + return {} unless @badge_id + + { BADGE_ID => @badge_id } + end + + # @return [Hash] + def badge_icon_hash + return {} unless @badge_icon + + { BADGE_ICON => @badge_icon } + end + + # @return [Hash] + def mutable_content_hash + return {} if @mutable_content.nil? + + { MUTABLE_CONTENT => @mutable_content } + end + + # @return [Hash] + def content_platform_specific + @platform_specific ||= @content[:platform_specific] + @platform_specific ||= @content['platform_specific'] + end + + # @return [Boolean] + def empty_receivers? + @to.to_h.empty? || @to.values.all?(&:empty?) + end + + # @return [Boolean] + def receivers_limit_exceeded? + @to.values.map(&:size).reduce(&:+) > MAX_USERS_PER_CAMPAIGN + end + + # @return [Boolean] + def allowed?(indentities) + (indentities - ALLOWED_IDENTITIES).empty? + end + end +end diff --git a/lib/clever_tap/campaign/email.rb b/lib/clever_tap/campaign/email.rb new file mode 100644 index 0000000..1086d51 --- /dev/null +++ b/lib/clever_tap/campaign/email.rb @@ -0,0 +1,29 @@ +class CleverTap + class Campaign::Email < Campaign + + # @return [Hash] + def to_h + super.merge(content_hash) + end + + # @return [Hash] + # @raise [NoContentError] if no content provided or content is invalid + def content_hash + raise NoContentError if @content.to_h.empty? + raise NoContentError unless content_valid? + + { CONTENT => @content } + end + + private + + # @return [Boolean] + def content_valid? + body = @content.to_h['body'] || @content.to_h[:body] + sender_name = @content.to_h['sender_name'] || @content.to_h[:sender_name] + subject = @content.to_h['subject'] || @content.to_h[:subject] + + !(body.nil? || sender_name.nil? || subject.nil?) + end + end +end diff --git a/lib/clever_tap/campaign/push.rb b/lib/clever_tap/campaign/push.rb new file mode 100644 index 0000000..284ae6c --- /dev/null +++ b/lib/clever_tap/campaign/push.rb @@ -0,0 +1,48 @@ +class CleverTap + class Campaign::Push < Campaign + + # @return [Hash] + def to_h + super.merge(content_hash) + end + + # @return [Hash] + # @raise [NoContentError] if no content provided or content is invalid + def content_hash + raise NoContentError if @content.to_h.empty? + raise NoContentError unless content_valid? + + platform_specific = platform_specific_hash + @content.merge!(platform_specific) unless platform_specific.empty? + + { CONTENT => @content } + end + + # @return [Hash] + # @raise [NoChannelIdError] if android campaign doesn't have a channel id + def platform_specific_hash + return {} unless @platform_specific + + android = @platform_specific[:android] || @platform_specific['android'] + + if android + channel = @wzrk_cid || android[:wzrk_cid] || android['wzrk_cid'] + raise NoChannelIdError unless channel + + @platform_specific['android']['wzrk_cid'] = channel + end + + { PLATFORM_SPECIFIC => @platform_specific } + end + + private + + # @return [Boolean] + def content_valid? + body = @content.to_h['body'] || @content.to_h[:body] + title = @content.to_h['title'] || @content.to_h[:title] + + !(body.nil? || title.nil?) + end + end +end diff --git a/lib/clever_tap/campaign/sms.rb b/lib/clever_tap/campaign/sms.rb new file mode 100644 index 0000000..1cdbc2a --- /dev/null +++ b/lib/clever_tap/campaign/sms.rb @@ -0,0 +1,26 @@ +class CleverTap + class Campaign::Sms < Campaign + + # @return [Hash] + def to_h + super.merge(content_hash) + end + + # @return [Hash] + # @raise [NoContentError] if no content provided or content is invalid + def content_hash + raise NoContentError if @content.to_h.empty? + raise NoContentError unless content_valid? + + { CONTENT => @content } + end + + private + + # @return [Boolean] + def content_valid? + body = @content.to_h['body'] || @content.to_h[:body] + !body.nil? + end + end +end diff --git a/lib/clever_tap/campaign/web_push.rb b/lib/clever_tap/campaign/web_push.rb new file mode 100644 index 0000000..e5f4f13 --- /dev/null +++ b/lib/clever_tap/campaign/web_push.rb @@ -0,0 +1,38 @@ +class CleverTap + class Campaign::WebPush < Campaign + + # @return [Hash] + def to_h + super.merge(content_hash) + end + + # @return [Hash] + # @raise [NoContentError] if no content provided or content is invalid + def content_hash + raise NoContentError if @content.to_h.empty? + raise NoContentError unless content_valid? + + platform_specific = platform_specific_hash + @content.merge!(platform_specific) unless platform_specific.empty? + + { CONTENT => @content } + end + + # @return [Hash] + def platform_specific_hash + return {} unless @platform_specific + + { PLATFORM_SPECIFIC => @platform_specific } + end + + private + + # @return [Boolean] + def content_valid? + body = @content.to_h['body'] || @content.to_h[:body] + title = @content.to_h['title'] || @content.to_h[:title] + + !(body.nil? || title.nil?) + end + end +end diff --git a/lib/clever_tap/campaign_creator.rb b/lib/clever_tap/campaign_creator.rb new file mode 100644 index 0000000..d3aa6ee --- /dev/null +++ b/lib/clever_tap/campaign_creator.rb @@ -0,0 +1,67 @@ +class CleverTap + + class CampaignTypeError < RuntimeError + def message + 'Unknown campaign type' + end + end + + # @!attribute [r] campaign + # @return [CleverTap::Campaign] Campaign to create + # @!attribute [r] type + # @return [Symbol] Campaign type + class CampaignCreator + HTTP_PATH = 'send/'.freeze + + TYPE_SMS = :sms + TYPE_PUSH = :push + TYPE_WEBPUSH = :web_push + TYPE_EMAIL = :email + + CAMPAIGNS_NOTIFICATIONS_ENDPOINTS = { + TYPE_SMS => 'sms.json', + TYPE_PUSH => 'push.json', + TYPE_WEBPUSH => 'webpush.json', + TYPE_EMAIL => 'email.json' + }.freeze + + attr_reader :campaign, :type + + # @param campaign [CleverTap::Campaign] + # @return HTTP response + def initialize(campaign) + @campaign = campaign + @type = type_of(campaign) + end + + # @param client [CleverTap::Client] + def call(client) + uri = HTTP_PATH + CAMPAIGNS_NOTIFICATIONS_ENDPOINTS[type] + response = client.post(uri, campaign.to_h.to_json) + parse_response(response) + end + + private + + # @param campaign [CleverTap::Campaign] + # @raise [CampaignTypeError] + def type_of(campaign) + case campaign + when CleverTap::Campaign::Sms + TYPE_SMS + when CleverTap::Campaign::WebPush + TYPE_WEBPUSH + when CleverTap::Campaign::Push + TYPE_PUSH + when CleverTap::Campaign::Email + TYPE_EMAIL + else + raise CampaignTypeError + end + end + + def parse_response(http_response) + http_response + end + end +end diff --git a/lib/clever_tap/client.rb b/lib/clever_tap/client.rb index a64949a..f488f90 100644 --- a/lib/clever_tap/client.rb +++ b/lib/clever_tap/client.rb @@ -19,6 +19,9 @@ class Client attr_accessor :account_id, :passcode, :configure, :on_success, :on_failure + # @param account_id [String] + # @param passcode [String] + # @param configure [Proc] def initialize(account_id = nil, passcode = nil, &configure) @account_id = assign_account_id(account_id) @passcode = assign_passcode(passcode) @@ -33,7 +36,7 @@ def connection configure.call(config) # NOTE: set adapter only if there isn't one set - config.adapter :net_http if config.builder.handlers.empty? + config.adapter :net_http if config.builder.adapter.nil? config.headers['Content-Type'] = 'application/json' config.headers[ACCOUNT_HEADER] = account_id @@ -68,8 +71,39 @@ def upload(records, dry_run: 0) all_responses end + # Creates a campaign in CleverTap + # + # @param campaign [CleverTap::Campaign] Campaign to create + # @return [Array] Array of parsed HTTP responses + def create_campaign(campaign) + responses = [] + + receivers_chunks(campaign) do |receivers| + campaign.to = receivers + responses << CampaignCreator.new(campaign).call(self) + end + + responses + end + private + # This method splits receivers' identity list in chunks by Campaign::MAX_USERS_PER_CAMPAIGN + # and yields a block on every chunk. + # + # @yieldparam chunked_to [Hash] Hash with receivers' identities chunked to Campaign::MAX_USERS_PER_CAMPAIGN size + def receivers_chunks(campaign) + identity_pairs = campaign.to.flat_map { |type, list| list.map { |id| [type, id] } } + + identity_pairs.each_slice(Campaign::MAX_USERS_PER_CAMPAIGN) do |slice| + chunked_to = slice.group_by(&:first) + .map { |k, v| [k, v.map(&:last)] } + .to_h + + yield chunked_to if block_given? + end + end + def batched_upload(entity, payload, dry_run) payload.each_slice(entity.upload_limit) do |group| response = post(HTTP_PATH, request_body(group)) do |request| diff --git a/lib/clever_tap/entity.rb b/lib/clever_tap/entity.rb index eede7fd..f60ca2c 100644 --- a/lib/clever_tap/entity.rb +++ b/lib/clever_tap/entity.rb @@ -7,7 +7,7 @@ def message class MissingIdentityError < RuntimeError def message - "Couldn'n find `identity` in CleverTap.config or `data`" + "Couldn't find `identity` in CleverTap.config or `data`" end end @@ -24,6 +24,7 @@ def upload_limit self::UPLOAD_LIMIT end + # @return [Boolean] def all_same_type?(items) items.all? { |i| i.class == self } end @@ -35,51 +36,63 @@ def initialize(**args) @timestamp = choose_timestamp(args) end + # @return [Hash] def to_h - put_identity_pair - .merge(put_timestamp_pair) - .merge(put_type_pair) - .merge(put_data) + identity_hash + .merge(timestamp_hash) + .merge(type_hash) + .merge(data_hash) end private - def put_identity_pair + # @return [Hash] + def identity_hash raise NoDataError if @data.to_h.empty? raise MissingIdentityError if @identity == '' || @data[@identity].nil? return { @identity => @data[@identity].to_s } if allowed?(@identity) + { IDENTITY_STRING => @data[@identity].to_s } end - def put_timestamp_pair + # @return [Hash] + def timestamp_hash return {} unless @timestamp + { TIMESTAMP_STRING => @timestamp } end - def put_type_pair + # @return [Hash] + def type_hash { TYPE_KEY_STRING => self.class::TYPE_VALUE_STRING } end - def put_data + # @return [Hash] + def data_hash raise NoDataError if @data.to_h.empty? + @data.delete(@identity) if allowed?(@identity) { self.class::DATA_STRING => @data } end + # @return [String] def choose_identity(args) identity = args[:identity].to_s - return identity if allowed?(identity) && @data.to_h.key?(identity) + CleverTap.identity_field.to_s end + # @return [Integer, nil] def choose_timestamp(args) return args[:custom_timestamp].to_i if args[:custom_timestamp] - return @data.delete(args[:timestamp_field].to_s).to_i if args[:timestamp_field] + + @data.delete(args[:timestamp_field].to_s).to_i if args[:timestamp_field] end + # @return [Boolean] def allowed?(identity) ALLOWED_IDENTITIES.include?(identity) end diff --git a/lib/clever_tap/event.rb b/lib/clever_tap/event.rb index fc59c5d..0da06ac 100644 --- a/lib/clever_tap/event.rb +++ b/lib/clever_tap/event.rb @@ -16,14 +16,17 @@ def initialize(**args) @name = args[:name] end + # @return [Hash] def to_h - super.merge(put_event_name_pair) + super.merge(event_name_hash) end private - def put_event_name_pair + # @return [Hash] + def event_name_hash raise MissingEventNameError if @name.nil? + { EVENT_NAME_STRING => @name } end end diff --git a/lib/clever_tap/version.rb b/lib/clever_tap/version.rb index 34bb817..ea202ab 100644 --- a/lib/clever_tap/version.rb +++ b/lib/clever_tap/version.rb @@ -1,3 +1,3 @@ class CleverTap - VERSION = '0.3.0'.freeze + VERSION = '0.4.1'.freeze end diff --git a/spec/integrations/clever_tap_spec.rb b/spec/integrations/clever_tap_spec.rb index c2f5bf5..d40d9e2 100644 --- a/spec/integrations/clever_tap_spec.rb +++ b/spec/integrations/clever_tap_spec.rb @@ -78,4 +78,21 @@ end end end + + describe 'creating a campaign' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { 'Email' => ['john@doe.com'] }, + content: { 'body' => 'Smsbody' } + ) + end + + it 'succeed' do + response = clever_tap.create_campaign(campaign) + + aggregate_failures 'success response' do + expect(response.code).to eq(200) + end + end + end end diff --git a/spec/shared/clever_tap_client.rb b/spec/shared/clever_tap_client.rb index 2be070c..18d200c 100644 --- a/spec/shared/clever_tap_client.rb +++ b/spec/shared/clever_tap_client.rb @@ -4,10 +4,3 @@ expect(subject.passcode).to eq account_passcode end end - -shared_examples 'configured `Client`' do - it 'preserves credentials in `Client`' do - expect(subject.account_id).to eq account_id - expect(subject.passcode).to eq account_passcode - end -end diff --git a/spec/units/campaign/email_spec.rb b/spec/units/campaign/email_spec.rb new file mode 100644 index 0000000..2bcb387 --- /dev/null +++ b/spec/units/campaign/email_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' + +RSpec.describe CleverTap::Campaign::Email do + describe '#to_h' do + subject { described_class.new(**params).to_h } + + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'my tag group', + respect_frequency_caps: false, + content: { + 'subject' => 'Welcome', + 'body' => '
Your HTML content for the email
', + 'sender_name' => 'CleverTap' + } + } + end + + let(:parsed_params) { Hash[params.map { |k, v| [k.to_s, v] }] } + + context 'When content is not sent' do + before do + params.delete :content + end + + it 'should raise a ArgumentError error' do + expect { subject }.to raise_error(ArgumentError) + end + end + + context 'When content does not have body' do + before do + params[:content] = {} + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'When content does not have body' do + before do + params[:content].delete 'body' + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'When content does not have sender_name' do + before do + params[:content].delete 'sender_name' + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'When content does not have subject' do + before do + params[:content].delete 'subject' + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'success' do + it { is_expected.to eq parsed_params } + end + end +end diff --git a/spec/units/campaign/push_spec.rb b/spec/units/campaign/push_spec.rb new file mode 100644 index 0000000..ee0c7cd --- /dev/null +++ b/spec/units/campaign/push_spec.rb @@ -0,0 +1,205 @@ +require 'spec_helper' + +RSpec.describe CleverTap::Campaign::Push do + describe '#to_h' do + subject { described_class.new(**params).to_h } + + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Welcome', + 'body' => 'Smsbody', + 'platform_specific' => { # Optional + 'ios' => { + 'deep_link' => 'example.com', + 'sound_file' => 'example.caf', + 'category' => 'notification category', + 'badge_count' => 1, + 'key' => 'value_ios' + }, + 'android' => { + 'background_image' => 'http://example.jpg', + 'default_sound' => true, + 'deep_link' => 'example.com', + 'large_icon' => 'http://example.png', + 'key' => 'value_android', + 'wzrk_cid' => 'engagement' + } + } + } + } + end + + let(:parsed_params) { Hash[params.map { |k, v| [k.to_s, v] }] } + + context 'When content is not sent' do + before do + params.delete :content + end + + it 'should raise a ArgumentError error' do + expect { subject }.to raise_error(ArgumentError) + end + end + + context 'When content does not have content' do + before do + params[:content] = {} + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'When content does not have body' do + before do + params[:content].delete 'body' + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'When content does not have title' do + before do + params[:content].delete 'title' + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'success' do + it { is_expected.to eq parsed_params } + end + + context 'When platform_specific is sended into content (Symbol)' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'Smsbody', + platform_specific: { # Optional + 'ios' => { + 'deep_link' => 'example.com', + 'sound_file' => 'example.caf', + 'category' => 'notification category', + 'badge_count' => 1, + 'key' => 'value_ios' + } + } + } + } + end + + it 'has content and includes platform_specific' do + expect(subject['content']).to include('platform_specific') + end + end + + context 'When platform_specific is sended into content' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'Smsbody', + 'platform_specific' => { # Optional + 'ios' => { + 'deep_link' => 'example.com', + 'sound_file' => 'example.caf', + 'category' => 'notification category', + 'badge_count' => 1, + 'key' => 'value_ios' + } + } + } + } + end + + it 'has content and includes platform_specific' do + expect(subject['content']).to include('platform_specific') + end + end + + context 'When platform_specific is sended as param' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'Smsbody' + }, + platform_specific: { # Optional + 'ios' => { + 'deep_link' => 'example.com', + 'sound_file' => 'example.caf', + 'category' => 'notification category', + 'badge_count' => 1, + 'key' => 'value_ios' + } + } + } + end + + it 'has content and includes platform_specific' do + expect(subject['content']).to include('platform_specific') + end + end + + context 'When platform_specific has android section, without channel' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'Smsbody', + 'platform_specific' => { # Optional + 'android' => { + 'background_image' => 'http://example.jpg', + 'default_sound' => true, + 'deep_link' => 'example.com', + 'large_icon' => 'http://example.png', + 'key' => 'value_android' + } + } + } + } + end + + it 'should raise a NoChannelIdError error' do + expect { subject }.to raise_error(CleverTap::NoChannelIdError) + end + end + end +end diff --git a/spec/units/campaign/sms_spec.rb b/spec/units/campaign/sms_spec.rb new file mode 100644 index 0000000..7ee854a --- /dev/null +++ b/spec/units/campaign/sms_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +RSpec.describe CleverTap::Campaign::Sms do + describe '#to_h' do + subject { described_class.new(**params).to_h } + + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + } + end + + let(:parsed_params) { Hash[params.map { |k, v| [k.to_s, v] }] } + + context 'When content is not sent' do + before do + params.delete :content + end + + it 'should raise a ArgumentError error' do + expect { subject }.to raise_error(ArgumentError) + end + end + + context 'When content does not have body' do + before do + params[:content] = {} + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'success' do + it { is_expected.to eq parsed_params } + end + end +end diff --git a/spec/units/campaign/web_push_spec.rb b/spec/units/campaign/web_push_spec.rb new file mode 100644 index 0000000..a5d927e --- /dev/null +++ b/spec/units/campaign/web_push_spec.rb @@ -0,0 +1,170 @@ +require 'spec_helper' + +RSpec.describe CleverTap::Campaign::WebPush do + describe '#to_h' do + subject { described_class.new(**params).to_h } + + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'How are you doing today?', + 'platform_specific' => { # Optional + 'safari' => { + 'deep_link' => 'https://apple.com', + 'ttl' => 10 + }, + 'chrome' => { + 'image' => 'https://www.exampleImage.com', + 'icon' => 'https://www.exampleIcon.com', + 'deep_link' => ' https://google.co', + 'ttl' => 10, + 'require_interaction' => true, + 'cta_title1' => 'title', + 'cta_link1' => 'http://www.example2.com', + 'cta_iconlink1' => 'https://www.exampleIcon2.com' + }, + 'firefox' => { + 'icon' => 'https://www.exampleIcon.com', + 'deep_link' => 'https://mozilla.org', + 'ttl' => 10 + } + } + } + } + end + + let(:parsed_params) { Hash[params.map { |k, v| [k.to_s, v] }] } + + context 'When content is not sent' do + before do + params.delete :content + end + + it 'should raise a ArgumentError error' do + expect { subject }.to raise_error(ArgumentError) + end + end + + context 'When content does not have content' do + before do + params[:content] = {} + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'When content does not have body' do + before do + params[:content].delete 'body' + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'When content does not have title' do + before do + params[:content].delete 'title' + end + + it 'should raise a NoContentError error' do + expect { subject }.to raise_error(CleverTap::NoContentError) + end + end + + context 'success' do + it { is_expected.to eq parsed_params } + end + + context 'When platform_specific is sended into content (Symbol)' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'Smsbody', + platform_specific: { # Optional + 'safari' => { + 'deep_link' => 'https://apple.com', + 'ttl' => 10 + } + } + } + } + end + + it 'has content and includes platform_specific' do + expect(subject['content']).to include('platform_specific') + end + end + + context 'When platform_specific is sended into content' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'Smsbody', + 'platform_specific' => { # Optional + 'safari' => { + 'deep_link' => 'https://apple.com', + 'ttl' => 10 + } + } + } + } + end + + it 'has content and includes platform_specific' do + expect(subject['content']).to include('platform_specific') + end + end + + context 'When platform_specific is sended as param' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'Smsbody' + }, + platform_specific: { # Optional + 'safari' => { + 'deep_link' => 'https://apple.com', + 'ttl' => 10 + } + } + } + end + + it 'has content and includes platform_specific' do + expect(subject['content']).to include('platform_specific') + end + end + end +end diff --git a/spec/units/campaign_creator_spec.rb b/spec/units/campaign_creator_spec.rb new file mode 100644 index 0000000..f7b02e0 --- /dev/null +++ b/spec/units/campaign_creator_spec.rb @@ -0,0 +1,253 @@ +require 'spec_helper' + +describe CleverTap::CampaignCreator, vcr: true do + describe '#call' do + let(:client) { CleverTap::Client.new(AUTH_ACCOUNT_ID, AUTH_PASSCODE) } + + context 'sms' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { 'Email' => ['john@doe.com'] }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + subject { described_class.new(campaign) } + + context 'with valid data' do + it 'creates a new campaign' do + result = subject.call(client) + body = JSON.parse(result.body) + + aggregate_failures 'success response' do + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + end + + context 'web_push' do + let(:campaign) do + CleverTap::Campaign::WebPush.new( + to: { + 'FBID' => %w[ + 102029292929388 + 114342342453463 + ], + 'Email' => [ + 'john@doe.com', + 'jane@doe.com' + ], + 'Identity' => [ + 'JohnDoe' + ], + 'objectId' => [ + '_asdnkansdjknaskdjnasjkndja', + '-adffajjdfoaiaefiohnefwprjf' + ] + }, + tag_group: 'my tag group', + campaign_id: 1_000_000_043, + respect_frequency_caps: false, + content: { + 'title' => 'Hi!', + 'body' => 'How are you doing today?', + 'platform_specific' => { # Optional + 'safari' => { + 'deep_link' => 'https://apple.com', + 'ttl' => 10 + }, + 'chrome' => { + 'image' => 'https://www.exampleImage.com', + 'icon' => 'https://www.exampleIcon.com', + 'deep_link' => ' https://google.co', + 'ttl' => 10, + 'require_interaction' => true, + 'cta_title1' => 'title', + 'cta_link1' => 'http://www.example2.com', + 'cta_iconlink1' => 'https://www.exampleIcon2.com' + }, + 'firefox' => { + 'icon' => 'https://www.exampleIcon.com', + 'deep_link' => 'https://mozilla.org', + 'ttl' => 10 + } + } + } + ) + end + + subject { described_class.new(campaign) } + + context 'with valid data' do + it 'creates a new campaign' do + result = subject.call(client) + body = JSON.parse(result.body) + + aggregate_failures 'success response' do + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + end + + context 'push' do + let(:campaign) do + CleverTap::Campaign::Push.new( + to: { + 'FBID' => %w[ + 102029292929388 + 114342342453463 + ], + 'GPID' => [ + '1928288389299292' + ], + 'Email' => [ + 'john@doe.com', + 'jane@doe.com' + ], + 'Identity' => [ + 'JohnDoe' + ], + 'objectId' => [ + '_asdnkansdjknaskdjnasjkndja', + '-adffajjdfoaiaefiohnefwprjf' + ] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Welcome', + 'body' => 'Smsbody', + 'platform_specific' => { # Optional + 'ios' => { + 'deep_link' => 'example.com', + 'sound_file' => 'example.caf', + 'category' => 'notification category', + 'badge_count' => 1, + 'key' => 'value_ios' + }, + 'android' => { + 'background_image' => 'http://example.jpg', + 'default_sound' => true, + 'deep_link' => 'example.com', + 'large_icon' => 'http://example.png', + 'key' => 'value_android', + 'wzrk_cid' => 'engagement' + } + } + } + ) + end + + subject { described_class.new(campaign) } + + context 'with valid data push' do + it 'creates a new campaign' do + result = subject.call(client) + body = JSON.parse(result.body) + + aggregate_failures 'success response' do + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + + context 'when platform_specific is invalid' do + let(:campaign) do + CleverTap::Campaign::Push.new( + to: { + 'Email' => [ + 'john@doe.com', + 'jane@doe.com' + ] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { + 'title' => 'Welcome', + 'body' => 'Smsbody', + 'platform_specific' => { + 'ios' => { + 'deep_link' => 'example.com', + 'sound_file' => 'example.caf', + 'category' => 'notification category', + 'badge_count' => 1, + 'key' => 'value_ios' + }, + 'android' => { + 'background_image' => 'http://example.jpg', + 'default_sound' => true, + 'deep_link' => 'example.com', + 'large_icon' => 'http://example.png', + 'key' => 'value_android' + } + } + } + ) + end + + it 'should raise a NoChannelIdError error' do + expect { subject.call(client) }.to raise_error(CleverTap::NoChannelIdError) + end + end + end + + context 'email' do + let(:campaign) do + CleverTap::Campaign::Email.new( + to: { + 'FBID' => %w[ + 102029292929388 + 114342342453463 + ], + 'GPID' => [ + '1928288389299292' + ], + 'Email' => [ + 'john@doe.com', + 'jane@doe.com' + ], + 'Identity' => [ + 'JohnDoe' + ], + 'objectId' => [ + '_asdnkansdjknaskdjnasjkndja', + '-adffajjdfoaiaefiohnefwprjf' + ] + }, + tag_group: 'my tag group', + respect_frequency_caps: false, + content: { + 'subject' => 'Welcome', + 'body' => '
Your HTML content for the email
', + 'sender_name' => 'CleverTap' + } + ) + end + + subject { described_class.new(campaign) } + + context 'with valid data email' do + it 'creates a new campaign' do + result = subject.call(client) + body = JSON.parse(result.body) + + aggregate_failures 'success response' do + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + end + end +end diff --git a/spec/units/campaign_spec.rb b/spec/units/campaign_spec.rb new file mode 100644 index 0000000..a960ffb --- /dev/null +++ b/spec/units/campaign_spec.rb @@ -0,0 +1,115 @@ +require 'spec_helper' + +RSpec.describe CleverTap::Campaign do + describe '#to_h' do + subject { described_class.new(**params).to_h } + + let(:params) do + { + to: { + 'Email' => ['example@email.com'], + 'FBID' => ['fbidexample'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + } + end + + let(:parsed_params) { Hash[params.map { |k, v| [k.to_s, v] }] } + + context "When 'to' key is not defined" do + let(:params) do + { + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + } + end + + it 'should raise a ArgumentError error' do + expect { subject }.to raise_error(ArgumentError) + end + end + + context "When 'to' key is empty" do + let(:params) do + { + to: {}, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + } + end + + it 'should raise a NoReceiversError error' do + expect { subject }.to raise_error(CleverTap::NoReceiversError) + end + end + + context 'When identity key into to is invalid' do + let(:params) do + { + to: { + 'BadIdentity' => ['example'] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + } + end + + it 'should raise a InvalidIdentityTypeError error' do + expect { subject }.to raise_error(CleverTap::InvalidIdentityTypeError) + end + end + + context 'When indentity keys are empty' do + let(:params) do + { + to: { + 'FBID' => [], + 'Email' => [], + 'Identity' => [], + 'objectId' => [] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + } + end + + it 'should raise a NoReceiversError error' do + expect { subject }.to raise_error(CleverTap::NoReceiversError) + end + end + + context 'When content is not sent' do + before do + params.delete :content + end + + it 'should raise a ArgumentError error' do + expect { subject }.to raise_error(ArgumentError) + end + end + + context 'When users per campaign limit was exceeded' do + let(:params) do + { + to: { + 'Email' => ['example@email.com'] * 100, + 'FBID' => ['fbidexample'] * 901 + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + } + end + + it 'should raise a ReceiversLimitExceededError error' do + expect { subject }.to raise_error(CleverTap::ReceiversLimitExceededError) + end + end + end +end diff --git a/spec/units/clever_tap_client_spec.rb b/spec/units/clever_tap_client_spec.rb index 55fb3e2..d11f7ba 100644 --- a/spec/units/clever_tap_client_spec.rb +++ b/spec/units/clever_tap_client_spec.rb @@ -21,10 +21,9 @@ end it 'override the default adapter' do - handlers = subject.connection.builder.handlers + adapter = subject.connection.builder.adapter - expect(handlers.count).to eq(1) - expect(handlers.first).to eq(Faraday::Adapter::Test) + expect(adapter).to eq(Faraday::Adapter::Test) end end @@ -32,10 +31,9 @@ subject { described_class.new('123456', 'passcode') } it 'use Net::HTTP adapter' do - handlers = subject.connection.builder.handlers + adapter = subject.connection.builder.adapter - expect(handlers.count).to eq(1) - expect(handlers.first).to eq(Faraday::Adapter::NetHttp) + expect(adapter).to eq(Faraday::Adapter::NetHttp) end end end @@ -276,4 +274,222 @@ def config_client(account, pass) end end end + + describe '#receivers_chunks' do + before do + stub_const('CleverTap::Campaign::MAX_USERS_PER_CAMPAIGN', 4) + end + + subject { described_class.new(AUTH_ACCOUNT_ID, AUTH_PASSCODE) } + + context 'when the number of targets is greater than MAX_USERS_PER_CAMPAIGN' do + context 'the number of targets is not divisible by limit' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[a1 a2 a3 a4 a5], + 'Email' => %w[b1 b2 b3], + 'Identity' => %w[c1 c2 c3 c4 c5], + 'objectId' => %w[d1 d2 d3 d4 d5] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should yield 5 times' do + expect { |b| subject.send(:receivers_chunks, campaign, &b) }.to yield_control.exactly(5).times + end + end + + context 'just an identity and it does not exeed the limit' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[a1 a2 a3] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should yield 1 times' do + expect { |b| subject.send(:receivers_chunks, campaign, &b) }.to yield_control.exactly(1).times + end + end + + context 'the set of identities does not exeed the limit' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[a1], + 'Email' => %w[b1], + 'Identity' => %w[c1], + 'objectId' => %w[d1] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should yield 1 times' do + expect { |b| subject.send(:receivers_chunks, campaign, &b) }.to yield_control.exactly(1).times + end + end + + context 'empty targets' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[], + 'Email' => %w[], + 'Identity' => %w[], + 'objectId' => %w[] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should yield 0 times' do + expect { |b| subject.send(:receivers_chunks, campaign, &b) }.to yield_control.exactly(0).times + end + end + end + end + + describe '#create_campaign' do + before do + stub_const('CleverTap::Campaign::MAX_USERS_PER_CAMPAIGN', 4) + end + + subject { described_class.new(AUTH_ACCOUNT_ID, AUTH_PASSCODE).create_campaign(campaign) } + + context 'when the number of targets is greater than MAX_USERS_PER_CAMPAIGN' do + context 'the number of targets is not divisible by limit' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[a1 a2 a3 a4 a5], + 'Email' => %w[b1 b2 b3], + 'Identity' => %w[c1 c2 c3 c4 c5], + 'objectId' => %w[d1 d2 d3 d4 d5] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should return an array of 5 responses' do + expect(subject.size).to eq 5 + subject.each do |result| + body = JSON.parse(result.body) + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + + context 'just an identity and it does not exeed the limit' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[a1 a2 a3] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should return an array of 1 responses ' do + expect(subject.size).to eq 1 + subject.each do |result| + body = JSON.parse(result.body) + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + + context 'the set of identities does not exeed the limit' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[a1], + 'Email' => %w[b1], + 'Identity' => %w[c1], + 'objectId' => %w[d1] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should return an array of 1 responses' do + expect(subject.size).to eq 1 + subject.each do |result| + body = JSON.parse(result.body) + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + + context 'empty targets' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[], + 'Email' => %w[], + 'Identity' => %w[], + 'objectId' => %w[] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should return an empty array' do + expect(subject.size).to eq 0 + end + end + end + + context 'when the number of targest does not exeed the limit' do + let(:campaign) do + CleverTap::Campaign::Sms.new( + to: { + 'FBID' => %w[a1], + 'Email' => %w[b1], + 'Identity' => %w[c1], + 'objectId' => %w[d1] + }, + tag_group: 'mytaggroup', + respect_frequency_caps: false, + content: { 'body' => 'Smsbody' } + ) + end + + it 'should return a single response' do + expect(subject.size).to eq 1 + subject.each do |result| + body = JSON.parse(result.body) + expect(result.success?).to be_truthy + expect(result.status).to eq(200) + expect(body).to include('message' => 'Added to queue for processing', 'status' => 'success') + end + end + end + end end diff --git a/spec/vcr_cassettes/CleverTap/creating_a_campaign/succeed.yml b/spec/vcr_cassettes/CleverTap/creating_a_campaign/succeed.yml new file mode 100644 index 0000000..161bbd1 --- /dev/null +++ b/spec/vcr_cassettes/CleverTap/creating_a_campaign/succeed.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"Email":["john@doe.com"]},"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Mon, 12 Oct 2020 19:58:46 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Mon, 12 Oct 2020 19:58:46 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/email/with_valid_data_email/creates_a_new_campaign.yml b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/email/with_valid_data_email/creates_a_new_campaign.yml new file mode 100644 index 0000000..64c3c19 --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/email/with_valid_data_email/creates_a_new_campaign.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/email.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["102029292929388","114342342453463"],"GPID":["1928288389299292"],"Email":["john@doe.com","jane@doe.com"],"Identity":["JohnDoe"],"objectId":["_asdnkansdjknaskdjnasjkndja","-adffajjdfoaiaefiohnefwprjf"]},"tag_group":"my + tag group","content":{"subject":"Welcome","body":"
Your HTML content for + the email
","sender_name":"CleverTap"},"respect_frequency_caps":false}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 15 Oct 2020 22:29:59 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 15 Oct 2020 22:29:59 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/push/when_platform_specific_is_invalid/is_failure.yml b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/push/when_platform_specific_is_invalid/is_failure.yml new file mode 100644 index 0000000..8fc61dc --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/push/when_platform_specific_is_invalid/is_failure.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/push.json + body: + encoding: UTF-8 + string: '{"to":{"Email":["john@doe.com","jane@doe.com"]},"tag_group":"mytaggroup","content":{"title":"Welcome","body":"Smsbody","platform_specific":{"ios":{"deep_link":"example.com","sound_file":"example.caf","category":"notification + category","badge_count":1,"key":"value_ios"},"android":{"background_image":"http://example.jpg","default_sound":true,"deep_link":"example.com","large_icon":"http://example.png","key":"value_android"}}},"respect_frequency_caps":false}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 400 + message: Bad Request + headers: + date: + - Thu, 15 Oct 2020 22:29:58 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + body: + encoding: UTF-8 + string: '{ "status" : "fail" , "error" : "Notification channel is required for + devices having Android 8.0 or above" , "code" : 9}' + http_version: + recorded_at: Thu, 15 Oct 2020 22:29:58 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/push/with_valid_data_push/creates_a_new_campaign.yml b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/push/with_valid_data_push/creates_a_new_campaign.yml new file mode 100644 index 0000000..73aa2cb --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/push/with_valid_data_push/creates_a_new_campaign.yml @@ -0,0 +1,39 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/push.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["102029292929388","114342342453463"],"GPID":["1928288389299292"],"Email":["john@doe.com","jane@doe.com"],"Identity":["JohnDoe"],"objectId":["_asdnkansdjknaskdjnasjkndja","-adffajjdfoaiaefiohnefwprjf"]},"tag_group":"mytaggroup","content":{"title":"Welcome","body":"Smsbody","platform_specific":{"ios":{"deep_link":"example.com","sound_file":"example.caf","category":"notification + category","badge_count":1,"key":"value_ios"},"android":{"background_image":"http://example.jpg","default_sound":true,"deep_link":"example.com","large_icon":"http://example.png","key":"value_android","wzrk_cid":"engagement"}}},"respect_frequency_caps":false}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 15 Oct 2020 22:29:57 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 15 Oct 2020 22:29:58 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/sms/with_valid_data/creates_a_new_campaign.yml b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/sms/with_valid_data/creates_a_new_campaign.yml new file mode 100644 index 0000000..aa8fb9a --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/sms/with_valid_data/creates_a_new_campaign.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"Email":["john@doe.com"]},"tag_group":"mytaggroup","content":{"body":"Smsbody"},"respect_frequency_caps":false}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 15 Oct 2020 22:29:56 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 15 Oct 2020 22:29:56 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/web_push/with_valid_data/creates_a_new_campaign.yml b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/web_push/with_valid_data/creates_a_new_campaign.yml new file mode 100644 index 0000000..46fe279 --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_CampaignCreator/_call/web_push/with_valid_data/creates_a_new_campaign.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/webpush.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["102029292929388","114342342453463"],"Email":["john@doe.com","jane@doe.com"],"Identity":["JohnDoe"],"objectId":["_asdnkansdjknaskdjnasjkndja","-adffajjdfoaiaefiohnefwprjf"]},"tag_group":"my + tag group","content":{"title":"Hi!","body":"How are you doing today?","platform_specific":{"safari":{"deep_link":"https://apple.com","ttl":10},"chrome":{"image":"https://www.exampleImage.com","icon":"https://www.exampleIcon.com","deep_link":" + https://google.co","ttl":10,"require_interaction":true,"cta_title1":"title","cta_link1":"http://www.example2.com","cta_iconlink1":"https://www.exampleIcon2.com"},"firefox":{"icon":"https://www.exampleIcon.com","deep_link":"https://mozilla.org","ttl":10}}},"respect_frequency_caps":false}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 15 Oct 2020 22:29:57 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 15 Oct 2020 22:29:57 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targest_does_not_exeed_the_limit/should_return_a_single_response.yml b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targest_does_not_exeed_the_limit/should_return_a_single_response.yml new file mode 100644 index 0000000..20bfbd4 --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targest_does_not_exeed_the_limit/should_return_a_single_response.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["a1"],"Email":["b1"],"Identity":["c1"],"objectId":["d1"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:34 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:34 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/just_an_identity_and_it_does_not_exeed_the_limit/should_return_an_array_of_1_responses_.yml b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/just_an_identity_and_it_does_not_exeed_the_limit/should_return_an_array_of_1_responses_.yml new file mode 100644 index 0000000..b05105c --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/just_an_identity_and_it_does_not_exeed_the_limit/should_return_an_array_of_1_responses_.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["a1","a2","a3"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:32 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:32 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_number_of_targets_is_not_divisible_by_limit/should_return_an_array_of_5_responses.yml b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_number_of_targets_is_not_divisible_by_limit/should_return_an_array_of_5_responses.yml new file mode 100644 index 0000000..62e58c1 --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_number_of_targets_is_not_divisible_by_limit/should_return_an_array_of_5_responses.yml @@ -0,0 +1,178 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["a1","a2","a3","a4"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:28 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:28 GMT +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["a5"],"Email":["b1","b2","b3"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:29 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:29 GMT +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"Identity":["c1","c2","c3","c4"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:30 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:30 GMT +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"Identity":["c5"],"objectId":["d1","d2","d3"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:31 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:31 GMT +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"objectId":["d4","d5"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:31 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:31 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_set_of_identiteis_does_not_exeed_the_limit/should_return_an_array_of_1_responses_.yml b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_set_of_identiteis_does_not_exeed_the_limit/should_return_an_array_of_1_responses_.yml new file mode 100644 index 0000000..9cb0660 --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_set_of_identiteis_does_not_exeed_the_limit/should_return_an_array_of_1_responses_.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["a1"],"Email":["b1"],"Identity":["c1"],"objectId":["d1"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Thu, 22 Oct 2020 16:11:33 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Thu, 22 Oct 2020 16:11:33 GMT +recorded_with: VCR 5.1.0 diff --git a/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_set_of_identities_does_not_exeed_the_limit/should_return_an_array_of_1_responses.yml b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_set_of_identities_does_not_exeed_the_limit/should_return_an_array_of_1_responses.yml new file mode 100644 index 0000000..23a14e2 --- /dev/null +++ b/spec/vcr_cassettes/CleverTap_Client/_create_campaign/when_the_number_of_targets_is_greater_than_MAX_USERS_PER_CAMPAIGN/the_set_of_identities_does_not_exeed_the_limit/should_return_an_array_of_1_responses.yml @@ -0,0 +1,38 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.clevertap.com/1/send/sms.json + body: + encoding: UTF-8 + string: '{"to":{"FBID":["a1"],"Email":["b1"],"Identity":["c1"],"objectId":["d1"]},"tag_group":"mytaggroup","respect_frequency_caps":false,"content":{"body":"Smsbody"}}' + headers: + Content-Type: + - application/json + X-CleverTap-Account-Id: + - fake_account_id + X-CleverTap-Passcode: + - fake_passcode + User-Agent: + - Faraday v0.14.0 + response: + status: + code: 200 + message: OK + headers: + date: + - Fri, 23 Oct 2020 20:57:12 GMT + content-type: + - application/json;charset=utf-8 + transfer-encoding: + - chunked + connection: + - close + vary: + - Accept-Encoding, User-Agent + body: + encoding: ASCII-8BIT + string: '{ "message" : "Added to queue for processing" , "status" : "success"}' + http_version: + recorded_at: Fri, 23 Oct 2020 20:57:12 GMT +recorded_with: VCR 5.1.0