feat: Add APIs for Campaigns (#2175)
This commit is contained in:
parent
3afc9b5f5b
commit
b89cc9cf57
23 changed files with 452 additions and 1 deletions
28
app/controllers/api/v1/accounts/campaigns_controller.rb
Normal file
28
app/controllers/api/v1/accounts/campaigns_controller.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
class Api::V1::Accounts::CampaignsController < Api::V1::Accounts::BaseController
|
||||
before_action :campaign, except: [:index, :create]
|
||||
before_action :check_authorization
|
||||
|
||||
def index
|
||||
@campaigns = Current.account.campaigns
|
||||
end
|
||||
|
||||
def create
|
||||
@campaign = Current.account.campaigns.create!(campaign_params)
|
||||
end
|
||||
|
||||
def show; end
|
||||
|
||||
def update
|
||||
@campaign.update(campaign_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def campaign
|
||||
@campaign ||= Current.account.campaigns.find_by(display_id: params[:id])
|
||||
end
|
||||
|
||||
def campaign_params
|
||||
params.require(:campaign).permit(:title, :description, :content, :enabled, :inbox_id, :sender_id, trigger_rules: {})
|
||||
end
|
||||
end
|
|
@ -11,6 +11,10 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
|
|||
@assignable_agents = (Current.account.users.where(id: @inbox.members.select(:user_id)) + Current.account.administrators).uniq
|
||||
end
|
||||
|
||||
def campaigns
|
||||
@campaigns = @inbox.campaigns
|
||||
end
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
channel = create_channel
|
||||
|
|
|
@ -36,6 +36,7 @@ class Account < ApplicationRecord
|
|||
has_many :data_imports, dependent: :destroy
|
||||
has_many :users, through: :account_users
|
||||
has_many :inboxes, dependent: :destroy
|
||||
has_many :campaigns, dependent: :destroy
|
||||
has_many :conversations, dependent: :destroy
|
||||
has_many :messages, dependent: :destroy
|
||||
has_many :contacts, dependent: :destroy
|
||||
|
@ -104,4 +105,8 @@ class Account < ApplicationRecord
|
|||
trigger.after(:insert).for_each(:row) do
|
||||
"execute format('create sequence IF NOT EXISTS conv_dpid_seq_%s', NEW.id);"
|
||||
end
|
||||
|
||||
trigger.name('camp_dpid_before_insert').after(:insert).for_each(:row) do
|
||||
"execute format('create sequence IF NOT EXISTS camp_dpid_seq_%s', NEW.id);"
|
||||
end
|
||||
end
|
||||
|
|
49
app/models/campaign.rb
Normal file
49
app/models/campaign.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: campaigns
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# content :text not null
|
||||
# description :text
|
||||
# enabled :boolean default(TRUE)
|
||||
# title :string not null
|
||||
# trigger_rules :jsonb
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# display_id :integer not null
|
||||
# inbox_id :bigint not null
|
||||
# sender_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_campaigns_on_account_id (account_id)
|
||||
# index_campaigns_on_inbox_id (inbox_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id)
|
||||
# fk_rails_... (inbox_id => inboxes.id)
|
||||
#
|
||||
class Campaign < ApplicationRecord
|
||||
validates :account_id, presence: true
|
||||
validates :inbox_id, presence: true
|
||||
belongs_to :account
|
||||
belongs_to :inbox
|
||||
belongs_to :sender, class_name: 'User', optional: true
|
||||
|
||||
has_many :conversations, dependent: :nullify, autosave: true
|
||||
|
||||
after_commit :set_display_id, unless: :display_id?
|
||||
|
||||
private
|
||||
|
||||
def set_display_id
|
||||
reload
|
||||
end
|
||||
|
||||
# creating db triggers
|
||||
trigger.before(:insert).for_each(:row) do
|
||||
"NEW.display_id := nextval('camp_dpid_seq_' || NEW.account_id);"
|
||||
end
|
||||
end
|
|
@ -14,6 +14,7 @@
|
|||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# assignee_id :integer
|
||||
# campaign_id :bigint
|
||||
# contact_id :bigint
|
||||
# contact_inbox_id :bigint
|
||||
# display_id :integer not null
|
||||
|
@ -24,11 +25,13 @@
|
|||
#
|
||||
# index_conversations_on_account_id (account_id)
|
||||
# index_conversations_on_account_id_and_display_id (account_id,display_id) UNIQUE
|
||||
# index_conversations_on_campaign_id (campaign_id)
|
||||
# index_conversations_on_contact_inbox_id (contact_inbox_id)
|
||||
# index_conversations_on_team_id (team_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (campaign_id => campaigns.id)
|
||||
# fk_rails_... (contact_inbox_id => contact_inboxes.id)
|
||||
# fk_rails_... (team_id => teams.id)
|
||||
#
|
||||
|
@ -54,6 +57,7 @@ class Conversation < ApplicationRecord
|
|||
belongs_to :contact
|
||||
belongs_to :contact_inbox
|
||||
belongs_to :team, optional: true
|
||||
belongs_to :campaign, optional: true
|
||||
|
||||
has_many :messages, dependent: :destroy, autosave: true
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class Inbox < ApplicationRecord
|
|||
|
||||
belongs_to :channel, polymorphic: true, dependent: :destroy
|
||||
|
||||
has_many :campaigns, dependent: :destroy
|
||||
has_many :contact_inboxes, dependent: :destroy
|
||||
has_many :contacts, through: :contact_inboxes
|
||||
|
||||
|
|
21
app/policies/campaign_policy.rb
Normal file
21
app/policies/campaign_policy.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
class CampaignPolicy < ApplicationPolicy
|
||||
def index?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
||||
def update?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
||||
def show?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
||||
def create?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
||||
def destroy?
|
||||
@account_user.administrator?
|
||||
end
|
||||
end
|
|
@ -27,6 +27,10 @@ class InboxPolicy < ApplicationPolicy
|
|||
true
|
||||
end
|
||||
|
||||
def campaigns?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
||||
def create?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
|
1
app/views/api/v1/accounts/campaigns/create.json.jbuilder
Normal file
1
app/views/api/v1/accounts/campaigns/create.json.jbuilder
Normal file
|
@ -0,0 +1 @@
|
|||
json.partial! 'api/v1/models/campaign.json.jbuilder', resource: @campaign
|
3
app/views/api/v1/accounts/campaigns/index.json.jbuilder
Normal file
3
app/views/api/v1/accounts/campaigns/index.json.jbuilder
Normal file
|
@ -0,0 +1,3 @@
|
|||
json.array! @campaigns do |campaign|
|
||||
json.partial! 'api/v1/models/campaign.json.jbuilder', resource: campaign
|
||||
end
|
1
app/views/api/v1/accounts/campaigns/show.json.jbuilder
Normal file
1
app/views/api/v1/accounts/campaigns/show.json.jbuilder
Normal file
|
@ -0,0 +1 @@
|
|||
json.partial! 'api/v1/models/campaign.json.jbuilder', resource: @campaign
|
1
app/views/api/v1/accounts/campaigns/update.json.jbuilder
Normal file
1
app/views/api/v1/accounts/campaigns/update.json.jbuilder
Normal file
|
@ -0,0 +1 @@
|
|||
json.partial! 'api/v1/models/campaign.json.jbuilder', resource: @campaign
|
|
@ -0,0 +1,3 @@
|
|||
json.array! @campaigns do |campaign|
|
||||
json.partial! 'api/v1/models/campaign.json.jbuilder', resource: campaign
|
||||
end
|
15
app/views/api/v1/models/_campaign.json.jbuilder
Normal file
15
app/views/api/v1/models/_campaign.json.jbuilder
Normal file
|
@ -0,0 +1,15 @@
|
|||
json.id resource.display_id
|
||||
json.content resource.content
|
||||
json.description resource.description
|
||||
json.enabled resource.enabled
|
||||
json.title resource.title
|
||||
json.trigger_rules resource.trigger_rules
|
||||
json.account_id resource.account_id
|
||||
json.inbox do
|
||||
json.partial! 'api/v1/models/inbox.json.jbuilder', resource: resource.inbox
|
||||
end
|
||||
json.sender do
|
||||
json.partial! 'api/v1/models/agent.json.jbuilder', resource: resource.sender if resource.sender.present?
|
||||
end
|
||||
json.created_at resource.created_at
|
||||
json.updated_at resource.updated_at
|
|
@ -42,6 +42,8 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
resources :canned_responses, except: [:show, :edit, :new]
|
||||
resources :campaigns, only: [:index, :create, :show, :update]
|
||||
|
||||
namespace :channels do
|
||||
resource :twilio_channel, only: [:create]
|
||||
end
|
||||
|
@ -89,6 +91,7 @@ Rails.application.routes.draw do
|
|||
|
||||
resources :inboxes, only: [:index, :create, :update, :destroy] do
|
||||
get :assignable_agents, on: :member
|
||||
get :campaigns, on: :member
|
||||
post :set_agent_bot, on: :member
|
||||
end
|
||||
resources :inbox_members, only: [:create, :show], param: :inbox_id
|
||||
|
|
18
db/migrate/20210428135041_campaigns.rb
Normal file
18
db/migrate/20210428135041_campaigns.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
class Campaigns < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
create_table :campaigns do |t|
|
||||
t.integer :display_id, null: false
|
||||
t.string :title, null: false
|
||||
t.text :description
|
||||
t.text :content, null: false
|
||||
t.integer :sender_id
|
||||
t.boolean :enabled, default: true
|
||||
t.references :account, null: false, foreign_key: true
|
||||
t.references :inbox, null: false, foreign_key: true
|
||||
t.column :trigger_rules, :jsonb, default: {}
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_reference :conversations, :campaign, foreign_key: true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
# This migration was auto-generated via `rake db:generate_trigger_migration'.
|
||||
# While you can edit this file, any changes you make to the definitions here
|
||||
# will be undone by the next auto-generated trigger migration.
|
||||
|
||||
class CreateTriggersAccountsInsertOrCampaignsInsert < ActiveRecord::Migration[6.0]
|
||||
def up
|
||||
create_trigger('camp_dpid_before_insert', generated: true, compatibility: 1)
|
||||
.on('accounts')
|
||||
.name('camp_dpid_before_insert')
|
||||
.after(:insert)
|
||||
.for_each(:row) do
|
||||
"execute format('create sequence IF NOT EXISTS camp_dpid_seq_%s', NEW.id);"
|
||||
end
|
||||
|
||||
create_trigger('campaigns_before_insert_row_tr', generated: true, compatibility: 1)
|
||||
.on('campaigns')
|
||||
.before(:insert)
|
||||
.for_each(:row) do
|
||||
"NEW.display_id := nextval('camp_dpid_seq_' || NEW.account_id);"
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
drop_trigger('camp_dpid_before_insert', 'accounts', generated: true)
|
||||
|
||||
drop_trigger('campaigns_before_insert_row_tr', 'campaigns', generated: true)
|
||||
end
|
||||
end
|
38
db/schema.rb
38
db/schema.rb
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2021_04_26_191914) do
|
||||
ActiveRecord::Schema.define(version: 2021_04_28_151147) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_stat_statements"
|
||||
|
@ -113,6 +113,22 @@ ActiveRecord::Schema.define(version: 2021_04_26_191914) do
|
|||
t.string "extension"
|
||||
end
|
||||
|
||||
create_table "campaigns", force: :cascade do |t|
|
||||
t.integer "display_id", null: false
|
||||
t.string "title", null: false
|
||||
t.text "description"
|
||||
t.text "content", null: false
|
||||
t.integer "sender_id"
|
||||
t.boolean "enabled", default: true
|
||||
t.bigint "account_id", null: false
|
||||
t.bigint "inbox_id", null: false
|
||||
t.jsonb "trigger_rules", default: {}
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["account_id"], name: "index_campaigns_on_account_id"
|
||||
t.index ["inbox_id"], name: "index_campaigns_on_inbox_id"
|
||||
end
|
||||
|
||||
create_table "canned_responses", id: :serial, force: :cascade do |t|
|
||||
t.integer "account_id", null: false
|
||||
t.string "short_code"
|
||||
|
@ -235,8 +251,10 @@ ActiveRecord::Schema.define(version: 2021_04_26_191914) do
|
|||
t.string "identifier"
|
||||
t.datetime "last_activity_at", default: -> { "CURRENT_TIMESTAMP" }, null: false
|
||||
t.bigint "team_id"
|
||||
t.bigint "campaign_id"
|
||||
t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true
|
||||
t.index ["account_id"], name: "index_conversations_on_account_id"
|
||||
t.index ["campaign_id"], name: "index_conversations_on_campaign_id"
|
||||
t.index ["contact_inbox_id"], name: "index_conversations_on_contact_inbox_id"
|
||||
t.index ["team_id"], name: "index_conversations_on_team_id"
|
||||
end
|
||||
|
@ -592,8 +610,11 @@ ActiveRecord::Schema.define(version: 2021_04_26_191914) do
|
|||
add_foreign_key "account_users", "accounts"
|
||||
add_foreign_key "account_users", "users"
|
||||
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "campaigns", "accounts"
|
||||
add_foreign_key "campaigns", "inboxes"
|
||||
add_foreign_key "contact_inboxes", "contacts"
|
||||
add_foreign_key "contact_inboxes", "inboxes"
|
||||
add_foreign_key "conversations", "campaigns"
|
||||
add_foreign_key "conversations", "contact_inboxes"
|
||||
add_foreign_key "conversations", "teams"
|
||||
add_foreign_key "data_imports", "accounts"
|
||||
|
@ -614,4 +635,19 @@ ActiveRecord::Schema.define(version: 2021_04_26_191914) do
|
|||
"NEW.display_id := nextval('conv_dpid_seq_' || NEW.account_id);"
|
||||
end
|
||||
|
||||
create_trigger("camp_dpid_before_insert", :generated => true, :compatibility => 1).
|
||||
on("accounts").
|
||||
name("camp_dpid_before_insert").
|
||||
after(:insert).
|
||||
for_each(:row) do
|
||||
"execute format('create sequence IF NOT EXISTS camp_dpid_seq_%s', NEW.id);"
|
||||
end
|
||||
|
||||
create_trigger("campaigns_before_insert_row_tr", :generated => true, :compatibility => 1).
|
||||
on("campaigns").
|
||||
before(:insert).
|
||||
for_each(:row) do
|
||||
"NEW.display_id := nextval('camp_dpid_seq_' || NEW.account_id);"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
148
spec/controllers/api/v1/accounts/campaigns_controller_spec.rb
Normal file
148
spec/controllers/api/v1/accounts/campaigns_controller_spec.rb
Normal file
|
@ -0,0 +1,148 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Campaigns API', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/campaigns' do
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
get "/api/v1/accounts/#{account.id}/campaigns"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
let!(:campaign) { create(:campaign, account: account) }
|
||||
|
||||
it 'returns unauthorized for agents' do
|
||||
get "/api/v1/accounts/#{account.id}/campaigns"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
it 'returns all campaigns to administrators' do
|
||||
get "/api/v1/accounts/#{account.id}/campaigns",
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
body = JSON.parse(response.body, symbolize_names: true)
|
||||
expect(body.first[:id]).to eq(campaign.display_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/campaigns/:id' do
|
||||
let(:campaign) { create(:campaign, account: account) }
|
||||
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
get "/api/v1/accounts/#{account.id}/campaigns/#{campaign.display_id}"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
|
||||
it 'returns unauthorized for agents' do
|
||||
get "/api/v1/accounts/#{account.id}/campaigns/#{campaign.display_id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
it 'shows the campaign for administrators' do
|
||||
get "/api/v1/accounts/#{account.id}/campaigns/#{campaign.display_id}",
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(JSON.parse(response.body, symbolize_names: true)[:id]).to eq(campaign.display_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/{account.id}/campaigns' do
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
post "/api/v1/accounts/#{account.id}/campaigns",
|
||||
params: { inbox_id: inbox.id, title: 'test', content: 'test message' },
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
|
||||
it 'returns unauthorized for agents' do
|
||||
post "/api/v1/accounts/#{account.id}/campaigns",
|
||||
params: { inbox_id: inbox.id, title: 'test', content: 'test message' },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
it 'creates a new campaign' do
|
||||
post "/api/v1/accounts/#{account.id}/campaigns",
|
||||
params: { inbox_id: inbox.id, title: 'test', content: 'test message' },
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(JSON.parse(response.body, symbolize_names: true)[:title]).to eq('test')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH /api/v1/accounts/{account.id}/campaigns/:id' do
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
let!(:campaign) { create(:campaign, account: account) }
|
||||
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
patch "/api/v1/accounts/#{account.id}/campaigns/#{campaign.display_id}",
|
||||
params: { inbox_id: inbox.id, title: 'test', content: 'test message' },
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
|
||||
it 'returns unauthorized for agents' do
|
||||
patch "/api/v1/accounts/#{account.id}/campaigns/#{campaign.display_id}",
|
||||
params: { inbox_id: inbox.id, title: 'test', content: 'test message' },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
it 'updates the campaign' do
|
||||
patch "/api/v1/accounts/#{account.id}/campaigns/#{campaign.display_id}",
|
||||
params: { inbox_id: inbox.id, title: 'test', content: 'test message' },
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(JSON.parse(response.body, symbolize_names: true)[:title]).to eq('test')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -74,6 +74,44 @@ RSpec.describe 'Inboxes API', type: :request do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/campaigns' do
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
|
||||
let!(:campaign) { create(:campaign, account: account, inbox: inbox) }
|
||||
|
||||
it 'returns unauthorized for agents' do
|
||||
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
it 'returns all campaigns belonging to the inbox to administrators' do
|
||||
# create a random campaign
|
||||
create(:campaign, account: account)
|
||||
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns",
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
body = JSON.parse(response.body, symbolize_names: true)
|
||||
expect(body.first[:id]).to eq(campaign.display_id)
|
||||
expect(body.length).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/{account.id}/inboxes/:id' do
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
|
||||
|
|
16
spec/factories/campaigns.rb
Normal file
16
spec/factories/campaigns.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :campaign do
|
||||
sequence(:title) { |n| "Campaign #{n}" }
|
||||
sequence(:content) { |n| "Campaign content #{n}" }
|
||||
after(:build) do |campaign|
|
||||
campaign.account ||= create(:account)
|
||||
campaign.inbox ||= create(
|
||||
:inbox,
|
||||
account: campaign.account,
|
||||
channel: create(:channel_widget, account: campaign.account)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
23
spec/models/campaign_spec.rb
Normal file
23
spec/models/campaign_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Campaign, type: :model do
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:account) }
|
||||
it { is_expected.to belong_to(:inbox) }
|
||||
end
|
||||
|
||||
describe '.before_create' do
|
||||
let(:campaign) { build(:campaign, display_id: nil) }
|
||||
|
||||
before do
|
||||
campaign.save
|
||||
campaign.reload
|
||||
end
|
||||
|
||||
it 'runs before_create callbacks' do
|
||||
expect(campaign.display_id).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,6 +7,7 @@ require Rails.root.join 'spec/models/concerns/round_robin_handler_spec.rb'
|
|||
RSpec.describe Conversation, type: :model do
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:account) }
|
||||
it { is_expected.to belong_to(:inbox) }
|
||||
end
|
||||
|
||||
describe 'concerns' do
|
||||
|
|
Loading…
Reference in a new issue