feat: Add CSAT response APIs (#2503)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
parent
2e71006f9d
commit
dd9d5e410c
28 changed files with 358 additions and 23 deletions
28
app/builders/csat_surveys/response_builder.rb
Normal file
28
app/builders/csat_surveys/response_builder.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
class CsatSurveys::ResponseBuilder
|
||||
pattr_initialize [:message]
|
||||
|
||||
def perform
|
||||
raise 'Invalid Message' unless message.input_csat?
|
||||
|
||||
conversation = message.conversation
|
||||
rating = message.content_attributes.dig('submitted_values', 'csat_survey_response', 'rating')
|
||||
feedback_message = message.content_attributes.dig('submitted_values', 'csat_survey_response', 'feedback_message')
|
||||
|
||||
return if rating.blank?
|
||||
|
||||
process_csat_response(conversation, rating, feedback_message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def process_csat_response(conversation, rating, feedback_message)
|
||||
csat_survey_response = message.csat_survey_response || CsatSurveyResponse.new(
|
||||
message_id: message.id, account_id: message.account_id, conversation_id: message.conversation_id,
|
||||
contact_id: conversation.contact_id, assigned_agent: conversation.assignee
|
||||
)
|
||||
csat_survey_response.rating = rating
|
||||
csat_survey_response.feedback_message = feedback_message
|
||||
csat_survey_response.save!
|
||||
csat_survey_response
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
class V2::ReportBuilder
|
||||
include DateRangeHelper
|
||||
attr_reader :account, :params
|
||||
|
||||
def initialize(account, params)
|
||||
|
@ -83,10 +84,6 @@ class V2::ReportBuilder
|
|||
.average(:value)
|
||||
end
|
||||
|
||||
def range
|
||||
parse_date_time(params[:since])..parse_date_time(params[:until])
|
||||
end
|
||||
|
||||
# Taking average of average is not too accurate
|
||||
# https://en.wikipedia.org/wiki/Simpson's_paradox
|
||||
# TODO: Will optimize this later
|
||||
|
@ -101,11 +98,4 @@ class V2::ReportBuilder
|
|||
|
||||
(avg_first_response_time.values.sum / avg_first_response_time.values.length)
|
||||
end
|
||||
|
||||
def parse_date_time(datetime)
|
||||
return datetime if datetime.is_a?(DateTime)
|
||||
return datetime.to_datetime if datetime.is_a?(Time) || datetime.is_a?(Date)
|
||||
|
||||
DateTime.strptime(datetime, '%s')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
class Api::V1::Accounts::CsatSurveyResponsesController < Api::V1::Accounts::BaseController
|
||||
include DateRangeHelper
|
||||
|
||||
RESULTS_PER_PAGE = 25
|
||||
|
||||
before_action :check_authorization
|
||||
before_action :csat_survey_responses, only: [:index]
|
||||
|
||||
def index; end
|
||||
|
||||
private
|
||||
|
||||
def csat_survey_responses
|
||||
@csat_survey_responses = Current.account.csat_survey_responses
|
||||
@csat_survey_responses = @csat_survey_responses.where(created_at: range) if range.present?
|
||||
@csat_survey_responses.page(@current_page).per(RESULTS_PER_PAGE)
|
||||
end
|
||||
|
||||
def set_current_page
|
||||
@current_page = params[:page] || 1
|
||||
end
|
||||
end
|
|
@ -54,7 +54,7 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController
|
|||
end
|
||||
|
||||
def message_update_params
|
||||
params.permit(message: [{ submitted_values: [:name, :title, :value, { csat_survey_response: [:feedback, :rating] }] }])
|
||||
params.permit(message: [{ submitted_values: [:name, :title, :value, { csat_survey_response: [:feedback_message, :rating] }] }])
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
|
|
|
@ -10,10 +10,12 @@ class AsyncDispatcher < BaseDispatcher
|
|||
|
||||
def listeners
|
||||
[
|
||||
CampaignListener.instance,
|
||||
CsatSurveyListener.instance,
|
||||
EventListener.instance,
|
||||
WebhookListener.instance,
|
||||
InstallationWebhookListener.instance, HookListener.instance,
|
||||
CampaignListener.instance
|
||||
HookListener.instance,
|
||||
InstallationWebhookListener.instance,
|
||||
WebhookListener.instance
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
19
app/helpers/date_range_helper.rb
Normal file
19
app/helpers/date_range_helper.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
##############################################
|
||||
# Helpers to implement date range filtering to APIs
|
||||
# Include in your controller or service class where params is available
|
||||
##############################################
|
||||
|
||||
module DateRangeHelper
|
||||
def range
|
||||
return if params[:since].blank? || params[:until].blank?
|
||||
|
||||
parse_date_time(params[:since])..parse_date_time(params[:until])
|
||||
end
|
||||
|
||||
def parse_date_time(datetime)
|
||||
return datetime if datetime.is_a?(DateTime)
|
||||
return datetime.to_datetime if datetime.is_a?(Time) || datetime.is_a?(Date)
|
||||
|
||||
DateTime.strptime(datetime, '%s')
|
||||
end
|
||||
end
|
|
@ -43,7 +43,7 @@ const generateCSATContent = (
|
|||
const {
|
||||
submitted_values: { csat_survey_response: surveyResponse = {} } = {},
|
||||
} = contentAttributes;
|
||||
const { rating, feedback } = surveyResponse || {};
|
||||
const { rating, feedback_message } = surveyResponse || {};
|
||||
|
||||
let messageContent = '';
|
||||
if (rating) {
|
||||
|
@ -53,9 +53,9 @@ const generateCSATContent = (
|
|||
messageContent += `<div><strong>${ratingTitle}</strong></div>`;
|
||||
messageContent += `<p>${ratingObject.emoji}</p>`;
|
||||
}
|
||||
if (feedback) {
|
||||
if (feedback_message) {
|
||||
messageContent += `<div><strong>${feedbackTitle}</strong></div>`;
|
||||
messageContent += `<p>${feedback}</p>`;
|
||||
messageContent += `<p>${feedback_message}</p>`;
|
||||
}
|
||||
return messageContent;
|
||||
};
|
||||
|
|
|
@ -21,7 +21,10 @@ describe('#generateBotMessageContent', () => {
|
|||
expect(
|
||||
generateBotMessageContent('input_csat', {
|
||||
submitted_values: {
|
||||
csat_survey_response: { rating: 5, feedback: 'Great Service' },
|
||||
csat_survey_response: {
|
||||
rating: 5,
|
||||
feedback_message: 'Great Service',
|
||||
},
|
||||
},
|
||||
})
|
||||
).toEqual(
|
||||
|
@ -33,7 +36,7 @@ describe('#generateBotMessageContent', () => {
|
|||
'input_csat',
|
||||
{
|
||||
submitted_values: {
|
||||
csat_survey_response: { rating: 1, feedback: '' },
|
||||
csat_survey_response: { rating: 1, feedback_message: '' },
|
||||
},
|
||||
},
|
||||
{ csat: { ratingTitle: 'റേറ്റിംഗ്', feedbackTitle: 'പ്രതികരണം' } }
|
||||
|
|
|
@ -130,7 +130,7 @@ export default {
|
|||
submittedValues: {
|
||||
csat_survey_response: {
|
||||
rating,
|
||||
feedback,
|
||||
feedback_message: feedback,
|
||||
},
|
||||
},
|
||||
messageId: this.messageId,
|
||||
|
|
8
app/listeners/csat_survey_listener.rb
Normal file
8
app/listeners/csat_survey_listener.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
class CsatSurveyListener < BaseListener
|
||||
def message_updated(event)
|
||||
message = extract_message_and_account(event)[0]
|
||||
return unless message.input_csat?
|
||||
|
||||
CsatSurveys::ResponseBuilder.new(message: message).perform
|
||||
end
|
||||
end
|
|
@ -34,6 +34,7 @@ class Account < ApplicationRecord
|
|||
has_many :account_users, dependent: :destroy
|
||||
has_many :agent_bot_inboxes, dependent: :destroy
|
||||
has_many :agent_bots, dependent: :destroy
|
||||
has_many :csat_survey_responses, dependent: :destroy
|
||||
has_many :data_imports, dependent: :destroy
|
||||
has_many :users, through: :account_users
|
||||
has_many :inboxes, dependent: :destroy
|
||||
|
|
|
@ -39,6 +39,7 @@ class Contact < ApplicationRecord
|
|||
belongs_to :account
|
||||
has_many :conversations, dependent: :destroy
|
||||
has_many :contact_inboxes, dependent: :destroy
|
||||
has_many :csat_survey_responses, dependent: :destroy
|
||||
has_many :inboxes, through: :contact_inboxes
|
||||
has_many :messages, as: :sender, dependent: :destroy
|
||||
has_many :notes, dependent: :destroy
|
||||
|
|
|
@ -60,6 +60,7 @@ class Conversation < ApplicationRecord
|
|||
belongs_to :campaign, optional: true
|
||||
|
||||
has_many :messages, dependent: :destroy, autosave: true
|
||||
has_one :csat_survey_response, dependent: :destroy
|
||||
|
||||
before_create :set_bot_conversation
|
||||
|
||||
|
|
43
app/models/csat_survey_response.rb
Normal file
43
app/models/csat_survey_response.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: csat_survey_responses
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# feedback_message :text
|
||||
# rating :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# assigned_agent_id :bigint
|
||||
# contact_id :bigint not null
|
||||
# conversation_id :bigint not null
|
||||
# message_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_csat_survey_responses_on_account_id (account_id)
|
||||
# index_csat_survey_responses_on_assigned_agent_id (assigned_agent_id)
|
||||
# index_csat_survey_responses_on_contact_id (contact_id)
|
||||
# index_csat_survey_responses_on_conversation_id (conversation_id)
|
||||
# index_csat_survey_responses_on_message_id (message_id) UNIQUE
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id)
|
||||
# fk_rails_... (assigned_agent_id => users.id)
|
||||
# fk_rails_... (contact_id => contacts.id)
|
||||
# fk_rails_... (conversation_id => conversations.id)
|
||||
# fk_rails_... (message_id => messages.id)
|
||||
#
|
||||
class CsatSurveyResponse < ApplicationRecord
|
||||
belongs_to :account
|
||||
belongs_to :conversation
|
||||
belongs_to :contact
|
||||
belongs_to :message
|
||||
belongs_to :assigned_agent, class_name: 'User', optional: true
|
||||
|
||||
validates :rating, presence: true, inclusion: { in: [1, 2, 3, 4, 5] }
|
||||
validates :account_id, presence: true
|
||||
validates :contact_id, presence: true
|
||||
validates :conversation_id, presence: true
|
||||
end
|
|
@ -79,6 +79,7 @@ class Message < ApplicationRecord
|
|||
belongs_to :sender, polymorphic: true, required: false
|
||||
|
||||
has_many :attachments, dependent: :destroy, autosave: true, before_add: :validate_attachments_limit
|
||||
has_one :csat_survey_response, dependent: :destroy
|
||||
|
||||
after_create :reopen_conversation,
|
||||
:notify_via_mail
|
||||
|
|
|
@ -71,6 +71,7 @@ class User < ApplicationRecord
|
|||
|
||||
has_many :assigned_conversations, foreign_key: 'assignee_id', class_name: 'Conversation', dependent: :nullify
|
||||
alias_attribute :conversations, :assigned_conversations
|
||||
has_many :csat_survey_responses, foreign_key: 'assigned_agent_id', dependent: :nullify
|
||||
|
||||
has_many :inbox_members, dependent: :destroy
|
||||
has_many :inboxes, through: :inbox_members, source: :inbox
|
||||
|
|
5
app/policies/csat_survey_response_policy.rb
Normal file
5
app/policies/csat_survey_response_policy.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class CsatSurveyResponsePolicy < ApplicationPolicy
|
||||
def index?
|
||||
@account_user.administrator?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
json.array! @csat_survey_responses do |csat_survey_response|
|
||||
json.partial! 'api/v1/models/csat_survey_response.json.jbuilder', resource: csat_survey_response
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
json.id resource.id
|
||||
json.rating resource.rating
|
||||
json.feedback_message resource.feedback_message
|
||||
json.account_id resource.account_id
|
||||
json.message_id resource.message_id
|
||||
json.contact resource.contact
|
||||
json.conversation_id resource.conversation.display_id
|
||||
json.assigned_agent resource.assigned_agent
|
||||
json.created_at resource.created_at
|
|
@ -87,6 +87,7 @@ Rails.application.routes.draw do
|
|||
resources :labels, only: [:create, :index]
|
||||
end
|
||||
end
|
||||
resources :csat_survey_responses, only: [:index]
|
||||
resources :custom_filters, only: [:index, :show, :create, :update, :destroy]
|
||||
resources :inboxes, only: [:index, :create, :update, :destroy] do
|
||||
get :assignable_agents, on: :member
|
||||
|
|
15
db/migrate/20210623155413_create_csat_survey_responses.rb
Normal file
15
db/migrate/20210623155413_create_csat_survey_responses.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
class CreateCsatSurveyResponses < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
create_table :csat_survey_responses do |t|
|
||||
t.references :account, null: false, foreign_key: true
|
||||
t.references :conversation, null: false, foreign_key: true
|
||||
t.references :message, null: false, foreign_key: true, index: { unique: true }
|
||||
t.integer :rating, null: false
|
||||
t.text :feedback_message
|
||||
t.references :contact, null: false, foreign_key: true
|
||||
t.references :assigned_agent, foreign_key: { to_table: :users }
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
24
db/schema.rb
24
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_06_23_150613) do
|
||||
ActiveRecord::Schema.define(version: 2021_06_23_155413) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_stat_statements"
|
||||
|
@ -267,6 +267,23 @@ ActiveRecord::Schema.define(version: 2021_06_23_150613) do
|
|||
t.index ["team_id"], name: "index_conversations_on_team_id"
|
||||
end
|
||||
|
||||
create_table "csat_survey_responses", force: :cascade do |t|
|
||||
t.bigint "account_id", null: false
|
||||
t.bigint "conversation_id", null: false
|
||||
t.bigint "message_id", null: false
|
||||
t.integer "rating", null: false
|
||||
t.text "feedback_message"
|
||||
t.bigint "contact_id", null: false
|
||||
t.bigint "assigned_agent_id"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["account_id"], name: "index_csat_survey_responses_on_account_id"
|
||||
t.index ["assigned_agent_id"], name: "index_csat_survey_responses_on_assigned_agent_id"
|
||||
t.index ["contact_id"], name: "index_csat_survey_responses_on_contact_id"
|
||||
t.index ["conversation_id"], name: "index_csat_survey_responses_on_conversation_id"
|
||||
t.index ["message_id"], name: "index_csat_survey_responses_on_message_id", unique: true
|
||||
end
|
||||
|
||||
create_table "custom_filters", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.integer "filter_type", default: 0, null: false
|
||||
|
@ -652,6 +669,11 @@ ActiveRecord::Schema.define(version: 2021_06_23_150613) do
|
|||
add_foreign_key "conversations", "campaigns"
|
||||
add_foreign_key "conversations", "contact_inboxes"
|
||||
add_foreign_key "conversations", "teams"
|
||||
add_foreign_key "csat_survey_responses", "accounts"
|
||||
add_foreign_key "csat_survey_responses", "contacts"
|
||||
add_foreign_key "csat_survey_responses", "conversations"
|
||||
add_foreign_key "csat_survey_responses", "messages"
|
||||
add_foreign_key "csat_survey_responses", "users", column: "assigned_agent_id"
|
||||
add_foreign_key "data_imports", "accounts"
|
||||
add_foreign_key "notes", "accounts"
|
||||
add_foreign_key "notes", "contacts"
|
||||
|
|
30
spec/builders/csat_surveys/response_builder_spec.rb
Normal file
30
spec/builders/csat_surveys/response_builder_spec.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe ::CsatSurveys::ResponseBuilder do
|
||||
let(:message) do
|
||||
create(
|
||||
:message, content_type: :input_csat,
|
||||
content_attributes: { 'submitted_values': { 'csat_survey_response': { 'rating': 5, 'feedback_message': 'hello' } } }
|
||||
)
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
it 'creates a new csat survey response' do
|
||||
csat_survey_response = described_class.new(
|
||||
message: message
|
||||
).perform
|
||||
|
||||
expect(csat_survey_response.valid?).to eq(true)
|
||||
end
|
||||
|
||||
it 'updates the value of csat survey response if response already exists' do
|
||||
existing_survey_response = create(:csat_survey_response, message: message)
|
||||
csat_survey_response = described_class.new(
|
||||
message: message
|
||||
).perform
|
||||
|
||||
expect(csat_survey_response.id).to eq(existing_survey_response.id)
|
||||
expect(csat_survey_response.rating).to eq(5)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -18,7 +18,9 @@ RSpec.describe 'Campaigns API', type: :request do
|
|||
let!(:campaign) { create(:campaign, account: account) }
|
||||
|
||||
it 'returns unauthorized for agents' do
|
||||
get "/api/v1/accounts/#{account.id}/campaigns"
|
||||
get "/api/v1/accounts/#{account.id}/campaigns",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'CSAT Survey Responses API', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let!(:csat_survey_response) { create(:csat_survey_response, account: account) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/csat_survey_responses' do
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
get "/api/v1/accounts/#{account.id}/csat_survey_responses"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
it 'returns unauthorized for agents' do
|
||||
get "/api/v1/accounts/#{account.id}/csat_survey_responses",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
it 'returns all the csat survey responses for administrators' do
|
||||
get "/api/v1/accounts/#{account.id}/csat_survey_responses",
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(JSON.parse(response.body).first['feedback_message']).to eq(csat_survey_response.feedback_message)
|
||||
end
|
||||
|
||||
it 'filters csat responsed based on a date range' do
|
||||
csat_10_days_ago = create(:csat_survey_response, account: account, created_at: 10.days.ago)
|
||||
csat_3_days_ago = create(:csat_survey_response, account: account, created_at: 3.days.ago)
|
||||
|
||||
get "/api/v1/accounts/#{account.id}/csat_survey_responses",
|
||||
params: { since: 5.days.ago.to_time.to_i.to_s, until: Time.zone.today.to_time.to_i.to_s },
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
response_data = JSON.parse(response.body)
|
||||
expect(response_data.pluck('id')).to include(csat_3_days_ago.id)
|
||||
expect(response_data.pluck('id')).not_to include(csat_10_days_ago.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
12
spec/factories/csat_survey_responses.rb
Normal file
12
spec/factories/csat_survey_responses.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :csat_survey_response do
|
||||
rating { 1 }
|
||||
feedback_message { Faker::Movie.quote }
|
||||
account
|
||||
conversation
|
||||
message
|
||||
contact
|
||||
end
|
||||
end
|
36
spec/listeners/csat_survey_listener_spec.rb
Normal file
36
spec/listeners/csat_survey_listener_spec.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
require 'rails_helper'
|
||||
describe CsatSurveyListener do
|
||||
let(:listener) { described_class.instance }
|
||||
let!(:account) { create(:account) }
|
||||
let!(:user) { create(:user, account: account) }
|
||||
let!(:inbox) { create(:inbox, account: account) }
|
||||
let!(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: user) }
|
||||
let!(:message) do
|
||||
create(
|
||||
:message, message_type: 'outgoing', account: account, inbox: inbox, conversation: conversation,
|
||||
content_type: :input_csat,
|
||||
content_attributes: { 'submitted_values': { 'csat_survey_response': { 'rating': 5, 'feedback_message': 'hello' } } }
|
||||
)
|
||||
end
|
||||
let!(:event) { Events::Base.new(event_name, Time.zone.now, message: message) }
|
||||
|
||||
describe '#message_updated' do
|
||||
let(:event_name) { 'message.updated' }
|
||||
let(:response_builder) { double }
|
||||
|
||||
context 'when CsatSurveys::ResponseBuilder' do
|
||||
it 'triggers if message is input csat' do
|
||||
expect(response_builder).to receive(:perform)
|
||||
expect(CsatSurveys::ResponseBuilder).to receive(:new).with(message: message).and_return(response_builder).once
|
||||
listener.message_updated(event)
|
||||
end
|
||||
|
||||
it 'will not trigger if message is not input csat' do
|
||||
message = create(:message)
|
||||
event = Events::Base.new(event_name, Time.zone.now, message: message)
|
||||
expect(CsatSurveys::ResponseBuilder).not_to receive(:new).with(message: message)
|
||||
listener.message_updated(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
28
spec/models/csat_survey_response_spec.rb
Normal file
28
spec/models/csat_survey_response_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe CsatSurveyResponse, type: :model do
|
||||
describe 'validations' do
|
||||
it { is_expected.to validate_presence_of(:rating) }
|
||||
it { is_expected.to validate_presence_of(:account_id) }
|
||||
it { is_expected.to validate_presence_of(:conversation_id) }
|
||||
it { is_expected.to validate_presence_of(:contact_id) }
|
||||
|
||||
it 'validates that the rating can only be in range 1-5' do
|
||||
csat_survey_response = build(:csat_survey_response, rating: 6)
|
||||
expect(csat_survey_response.valid?).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:account) }
|
||||
it { is_expected.to belong_to(:conversation) }
|
||||
it { is_expected.to belong_to(:contact) }
|
||||
end
|
||||
|
||||
describe 'validates_factory' do
|
||||
it 'creates valid csat_survey_response object' do
|
||||
csat_survey_response = create(:csat_survey_response)
|
||||
expect(csat_survey_response.valid?).to eq true
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue