refactor(contact): form is persisted in db before pushed to HS
This commit is contained in:
parent
4bc0a04106
commit
5af32b46f4
10 changed files with 236 additions and 290 deletions
|
@ -2,25 +2,31 @@ class SupportController < ApplicationController
|
|||
invisible_captcha only: [:create], on_spam: :redirect_to_root
|
||||
|
||||
def index
|
||||
@form = Helpscout::Form.new(tags: tags_from_query_params, dossier_id: dossier&.id, current_user:)
|
||||
@form = ContactForm.new(tags: support_form_params.fetch(:tags, []), dossier_id: dossier&.id)
|
||||
@form.user = current_user
|
||||
end
|
||||
|
||||
def admin
|
||||
@form = Helpscout::Form.new(tags: tags_from_query_params, current_user:, for_admin: true)
|
||||
@form = ContactForm.new(tags: support_form_params.fetch(:tags, []), for_admin: true)
|
||||
@form.user = current_user
|
||||
end
|
||||
|
||||
def create
|
||||
if direct_message? && create_commentaire
|
||||
if direct_message?
|
||||
create_commentaire!
|
||||
flash.notice = "Votre message a été envoyé sur la messagerie de votre dossier."
|
||||
|
||||
redirect_to messagerie_dossier_path(dossier)
|
||||
return
|
||||
end
|
||||
|
||||
@form = Helpscout::Form.new(support_form_params.except(:piece_jointe).merge(current_user:))
|
||||
form_params = support_form_params
|
||||
@form = ContactForm.new(form_params.except(:piece_jointe))
|
||||
@form.piece_jointe.attach(form_params[:piece_jointe]) if form_params[:piece_jointe].present?
|
||||
@form.user = current_user
|
||||
|
||||
if @form.valid?
|
||||
create_conversation_later(@form)
|
||||
if @form.save
|
||||
@form.create_conversation_later
|
||||
flash.notice = "Votre message a été envoyé."
|
||||
|
||||
redirect_to root_path
|
||||
|
@ -32,29 +38,7 @@ class SupportController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def create_conversation_later(form)
|
||||
if support_form_params[:piece_jointe].present?
|
||||
blob = ActiveStorage::Blob.create_and_upload!(
|
||||
io: support_form_params[:piece_jointe].tempfile,
|
||||
filename: support_form_params[:piece_jointe].original_filename,
|
||||
content_type: support_form_params[:piece_jointe].content_type,
|
||||
identify: false
|
||||
).tap(&:scan_for_virus_later)
|
||||
end
|
||||
|
||||
HelpscoutCreateConversationJob.perform_later(
|
||||
blob_id: blob&.id,
|
||||
subject: form.subject,
|
||||
email: current_user&.email || form.email,
|
||||
phone: form.phone,
|
||||
text: form.text,
|
||||
dossier_id: form.dossier_id,
|
||||
browser: browser_name,
|
||||
tags: form.tags_array
|
||||
)
|
||||
end
|
||||
|
||||
def create_commentaire
|
||||
def create_commentaire!
|
||||
attributes = {
|
||||
piece_jointe: support_form_params[:piece_jointe],
|
||||
body: "[#{support_form_params[:subject]}]<br><br>#{support_form_params[:text]}"
|
||||
|
@ -68,12 +52,11 @@ class SupportController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def tags_from_query_params
|
||||
support_form_params[:tags]&.join(",") || ""
|
||||
end
|
||||
|
||||
def direct_message?
|
||||
user_signed_in? && support_form_params[:type] == Helpscout::Form::TYPE_INSTRUCTION && dossier.present? && dossier.messagerie_available?
|
||||
return false unless user_signed_in?
|
||||
return false unless support_form_params[:question_type] == ContactForm::TYPE_INSTRUCTION
|
||||
|
||||
dossier&.messagerie_available?
|
||||
end
|
||||
|
||||
def dossier
|
||||
|
@ -85,9 +68,9 @@ class SupportController < ApplicationController
|
|||
end
|
||||
|
||||
def support_form_params
|
||||
keys = [:email, :subject, :text, :type, :dossier_id, :piece_jointe, :phone, :tags, :for_admin]
|
||||
if params.key?(:helpscout_form) # submitting form
|
||||
params.require(:helpscout_form).permit(*keys)
|
||||
keys = [:email, :subject, :text, :question_type, :dossier_id, :piece_jointe, :phone, :for_admin, tags: []]
|
||||
if params.key?(:contact_form) # submitting form
|
||||
params.require(:contact_form).permit(*keys)
|
||||
else
|
||||
params.permit(:dossier_id, tags: []) # prefilling form
|
||||
end
|
||||
|
|
|
@ -8,41 +8,49 @@ class HelpscoutCreateConversationJob < ApplicationJob
|
|||
|
||||
retry_on FileNotScannedYetError, wait: :exponentially_longer, attempts: 10
|
||||
|
||||
attr_reader :contact_form
|
||||
attr_reader :api
|
||||
|
||||
def perform(blob_id: nil, **params)
|
||||
if blob_id.present?
|
||||
blob = ActiveStorage::Blob.find(blob_id)
|
||||
raise FileNotScannedYetError if blob.virus_scanner.pending?
|
||||
def perform(contact_form)
|
||||
@contact_form = contact_form
|
||||
|
||||
blob = nil unless blob.virus_scanner.safe?
|
||||
if contact_form.piece_jointe.attached?
|
||||
raise FileNotScannedYetError if contact_form.piece_jointe.virus_scanner.pending?
|
||||
end
|
||||
|
||||
@api = Helpscout::API.new
|
||||
|
||||
create_conversation(params, blob)
|
||||
create_conversation
|
||||
|
||||
contact_form.destroy
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_conversation(params, blob)
|
||||
def create_conversation
|
||||
response = api.create_conversation(
|
||||
params[:email],
|
||||
params[:subject],
|
||||
params[:text],
|
||||
blob
|
||||
contact_form.email,
|
||||
contact_form.subject,
|
||||
contact_form.text,
|
||||
safe_blob
|
||||
)
|
||||
|
||||
if response.success?
|
||||
conversation_id = response.headers['Resource-ID']
|
||||
|
||||
if params[:phone].present?
|
||||
api.add_phone_number(params[:email], params[:phone])
|
||||
if contact_form.phone.present?
|
||||
api.add_phone_number(contact_form.email, contact_form.phone)
|
||||
end
|
||||
|
||||
api.add_tags(conversation_id, params[:tags])
|
||||
api.add_tags(conversation_id, contact_form.tags)
|
||||
else
|
||||
fail "Error while creating conversation: #{response.response_code} '#{response.body}'"
|
||||
end
|
||||
end
|
||||
|
||||
def safe_blob
|
||||
return if !contact_form.piece_jointe.virus_scanner&.safe?
|
||||
|
||||
contact_form.piece_jointe
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
class Helpscout::Form
|
||||
include ActiveModel::Model
|
||||
include ActiveModel::Attributes
|
||||
|
||||
attribute :email, :string
|
||||
attribute :subject, :string
|
||||
attribute :text, :string
|
||||
attribute :type, :string
|
||||
attribute :dossier_id, :integer
|
||||
attribute :tags, :string
|
||||
attribute :phone, :string
|
||||
attribute :tags, :string
|
||||
attribute :for_admin, :boolean, default: false
|
||||
|
||||
validates :email, presence: true, strict_email: true, if: :require_email? # i18n-tasks-use t('activemodel.errors.models.helpscout/form.invalid_email_format')
|
||||
validates :subject, presence: true
|
||||
validates :text, presence: true
|
||||
validates :type, presence: true
|
||||
|
||||
attr_reader :current_user
|
||||
attr_reader :options
|
||||
|
||||
TYPE_INFO = 'procedure_info'
|
||||
TYPE_PERDU = 'lost_user'
|
||||
TYPE_INSTRUCTION = 'instruction_info'
|
||||
TYPE_AMELIORATION = 'product'
|
||||
TYPE_AUTRE = 'other'
|
||||
|
||||
ADMIN_TYPE_RDV = 'admin_demande_rdv'
|
||||
ADMIN_TYPE_QUESTION = 'admin_question'
|
||||
ADMIN_TYPE_SOUCIS = 'admin_soucis'
|
||||
ADMIN_TYPE_PRODUIT = 'admin_suggestion_produit'
|
||||
ADMIN_TYPE_DEMANDE_COMPTE = 'admin_demande_compte'
|
||||
ADMIN_TYPE_AUTRE = 'admin_autre'
|
||||
|
||||
def self.default_options
|
||||
[
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_INFO]), TYPE_INFO, I18n.t("links.common.faq.contacter_service_en_charge_url")],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_PERDU]), TYPE_PERDU, LISTE_DES_DEMARCHES_URL],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_INSTRUCTION]), TYPE_INSTRUCTION, I18n.t("links.common.faq.ou_en_est_mon_dossier_url")],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_AMELIORATION]), TYPE_AMELIORATION, FEATURE_UPVOTE_URL],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_AUTRE]), TYPE_AUTRE]
|
||||
]
|
||||
end
|
||||
|
||||
def self.admin_options
|
||||
[
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_QUESTION], app_name: Current.application_name), ADMIN_TYPE_QUESTION],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_RDV], app_name: Current.application_name), ADMIN_TYPE_RDV],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_SOUCIS], app_name: Current.application_name), ADMIN_TYPE_SOUCIS],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_PRODUIT]), ADMIN_TYPE_PRODUIT],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_DEMANDE_COMPTE]), ADMIN_TYPE_DEMANDE_COMPTE],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_AUTRE]), ADMIN_TYPE_AUTRE]
|
||||
]
|
||||
end
|
||||
|
||||
def initialize(params)
|
||||
@current_user = params.delete(:current_user)
|
||||
params[:email] = EmailSanitizableConcern::EmailSanitizer.sanitize(params[:email]) if params[:email].present?
|
||||
super(params)
|
||||
|
||||
@options = if for_admin?
|
||||
self.class.admin_options
|
||||
else
|
||||
self.class.default_options
|
||||
end
|
||||
end
|
||||
|
||||
alias for_admin? for_admin
|
||||
|
||||
def tags_array
|
||||
(tags&.split(",") || []) + ['contact form', type]
|
||||
end
|
||||
|
||||
def require_email? = current_user.blank?
|
||||
|
||||
def persisted? = false
|
||||
end
|
|
@ -1,2 +1,81 @@
|
|||
class ContactForm < ApplicationRecord
|
||||
attr_reader :options
|
||||
|
||||
belongs_to :user, optional: true, dependent: :destroy
|
||||
|
||||
after_initialize :set_options
|
||||
before_validation :normalize_strings
|
||||
before_validation :sanitize_email
|
||||
before_save :add_default_tags
|
||||
|
||||
validates :email, presence: true, strict_email: true, if: :require_email?
|
||||
validates :subject, presence: true
|
||||
validates :text, presence: true
|
||||
validates :question_type, presence: true
|
||||
|
||||
has_one_attached :piece_jointe
|
||||
|
||||
TYPE_INFO = 'procedure_info'
|
||||
TYPE_PERDU = 'lost_user'
|
||||
TYPE_INSTRUCTION = 'instruction_info'
|
||||
TYPE_AMELIORATION = 'product'
|
||||
TYPE_AUTRE = 'other'
|
||||
|
||||
ADMIN_TYPE_RDV = 'admin_demande_rdv'
|
||||
ADMIN_TYPE_QUESTION = 'admin_question'
|
||||
ADMIN_TYPE_SOUCIS = 'admin_soucis'
|
||||
ADMIN_TYPE_PRODUIT = 'admin_suggestion_produit'
|
||||
ADMIN_TYPE_DEMANDE_COMPTE = 'admin_demande_compte'
|
||||
ADMIN_TYPE_AUTRE = 'admin_autre'
|
||||
|
||||
def self.default_options
|
||||
[
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_INFO]), TYPE_INFO, I18n.t("links.common.faq.contacter_service_en_charge_url")],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_PERDU]), TYPE_PERDU, LISTE_DES_DEMARCHES_URL],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_INSTRUCTION]), TYPE_INSTRUCTION, I18n.t("links.common.faq.ou_en_est_mon_dossier_url")],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_AMELIORATION]), TYPE_AMELIORATION, FEATURE_UPVOTE_URL],
|
||||
[I18n.t(:question, scope: [:support, :index, TYPE_AUTRE]), TYPE_AUTRE]
|
||||
]
|
||||
end
|
||||
|
||||
def self.admin_options
|
||||
[
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_QUESTION], app_name: Current.application_name), ADMIN_TYPE_QUESTION],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_RDV], app_name: Current.application_name), ADMIN_TYPE_RDV],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_SOUCIS], app_name: Current.application_name), ADMIN_TYPE_SOUCIS],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_PRODUIT]), ADMIN_TYPE_PRODUIT],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_DEMANDE_COMPTE]), ADMIN_TYPE_DEMANDE_COMPTE],
|
||||
[I18n.t(:question, scope: [:support, :admin, ADMIN_TYPE_AUTRE]), ADMIN_TYPE_AUTRE]
|
||||
]
|
||||
end
|
||||
|
||||
def for_admin=(value)
|
||||
super(value)
|
||||
set_options
|
||||
end
|
||||
|
||||
def create_conversation_later
|
||||
HelpscoutCreateConversationJob.perform_later(self)
|
||||
end
|
||||
|
||||
def require_email? = user.blank?
|
||||
|
||||
private
|
||||
|
||||
def normalize_strings
|
||||
self.subject = subject&.strip
|
||||
self.text = text&.strip
|
||||
end
|
||||
|
||||
def sanitize_email
|
||||
self.email = EmailSanitizableConcern::EmailSanitizer.sanitize(email) if email.present?
|
||||
end
|
||||
|
||||
def add_default_tags
|
||||
self.tags = tags.push('contact form', question_type).uniq
|
||||
end
|
||||
|
||||
def set_options
|
||||
@options = for_admin? ? self.class.admin_options : self.class.default_options
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,23 +3,23 @@
|
|||
|
||||
- if form.require_email?
|
||||
= render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { autocomplete: 'email' }) do |c|
|
||||
- c.with_label { Helpscout::Form.human_attribute_name(form.for_admin? ? :email_pro : :email) }
|
||||
- c.with_label { ContactForm.human_attribute_name(form.for_admin? ? :email_pro : :email) }
|
||||
|
||||
%fieldset.fr-fieldset{ name: "type" }
|
||||
%fieldset.fr-fieldset{ name: "question_type" }
|
||||
%legend.fr-fieldset__legend.fr-fieldset__legend--regular
|
||||
= t('.your_question')
|
||||
= render EditableChamp::AsteriskMandatoryComponent.new
|
||||
.fr-fieldset__content
|
||||
- form.options.each do |(question, question_type, link)|
|
||||
.fr-radio-group
|
||||
= f.radio_button :type, question_type, required: true, data: {"support-target": "inputRadio" }, checked: question_type == form.type
|
||||
= f.label "type_#{question_type}", { 'aria-controls': link ? "card-#{question_type}" : nil, class: 'fr-label' } do
|
||||
= f.radio_button :question_type, question_type, required: true, data: {"support-target": "inputRadio" }, checked: question_type == form.question_type
|
||||
= f.label "question_type_#{question_type}", { 'aria-controls': link ? "card-#{question_type}" : nil, class: 'fr-label' } do
|
||||
= question
|
||||
|
||||
- if link.present?
|
||||
.fr-ml-3w{ id: "card-#{question_type}",
|
||||
class: class_names('hidden' => question_type != form.type),
|
||||
"aria-hidden": question_type != form.type,
|
||||
class: class_names('hidden' => question_type != form.question_type),
|
||||
"aria-hidden": question_type != form.question_type,
|
||||
data: { "support-target": "content" } }
|
||||
= render Dsfr::CalloutComponent.new(title: t('.our_answer')) do |c|
|
||||
- c.with_html_body do
|
||||
|
@ -43,13 +43,15 @@
|
|||
%span.fr-hint-text
|
||||
= t('.notice_upload_group')
|
||||
|
||||
%p.notice.hidden{ data: { 'contact-type-only': Helpscout::Form::TYPE_AMELIORATION } }
|
||||
%p.notice.hidden{ data: { 'contact-type-only': ContactForm::TYPE_AMELIORATION } }
|
||||
= t('.notice_pj_product')
|
||||
%p.notice.hidden{ data: { 'contact-type-only': Helpscout::Form::TYPE_AUTRE } }
|
||||
%p.notice.hidden{ data: { 'contact-type-only': ContactForm::TYPE_AUTRE } }
|
||||
= t('.notice_pj_other')
|
||||
= f.file_field :piece_jointe, class: 'fr-upload', accept: '.jpg, .jpeg, .png, .pdf'
|
||||
|
||||
= f.hidden_field :tags
|
||||
- f.object.tags.each_with_index do |tag, index|
|
||||
= f.hidden_field :tags, name: f.field_name(:tags, multiple: true), id: f.field_id(:tag, index), value: tag
|
||||
|
||||
= f.hidden_field :for_admin
|
||||
|
||||
= invisible_captcha
|
||||
|
|
|
@ -9,69 +9,4 @@
|
|||
|
||||
.fr-highlight= t('.intro_html')
|
||||
|
||||
.description
|
||||
.recommandations
|
||||
= t('.intro_html')
|
||||
%p.mandatory-explanation= t('asterisk_html', scope: [:utils])
|
||||
|
||||
- if !user_signed_in?
|
||||
.fr-input-group
|
||||
= label_tag :email, class: 'fr-label' do
|
||||
Email
|
||||
= render EditableChamp::AsteriskMandatoryComponent.new
|
||||
%span.fr-hint-text
|
||||
= t('.notice_email')
|
||||
= email_field_tag :email, params[:email], required: true, autocomplete: 'email', class: 'fr-input'
|
||||
|
||||
%fieldset.fr-fieldset{ name: "type" }
|
||||
%legend.fr-fieldset__legend
|
||||
= t('.your_question')
|
||||
= render EditableChamp::AsteriskMandatoryComponent.new
|
||||
.fr-fieldset__content
|
||||
- @options.each do |(question, question_type, link)|
|
||||
.fr-radio-group
|
||||
= radio_button_tag :type, question_type, false, required: true, data: {"support-target": "inputRadio" }
|
||||
= label_tag "type_#{question_type}", { 'aria-controls': link ? "card-#{question_type}" : nil, class: 'fr-label' } do
|
||||
= question
|
||||
|
||||
- if link.present?
|
||||
.fr-ml-3w.hidden{ id: "card-#{question_type}", "aria-hidden": true , data: { "support-target": "content" } }
|
||||
= render Dsfr::CalloutComponent.new(title: t('.our_answer')) do |c|
|
||||
- c.with_html_body do
|
||||
-# i18n-tasks-use t("support.index.#{question_type}.answer_html")
|
||||
= t('answer_html', scope: [:support, :index, question_type], base_url: Current.application_base_url, "link_#{question_type}": link)
|
||||
|
||||
.fr-input-group
|
||||
= label_tag :dossier_id, t('file_number', scope: [:utils]), class: 'fr-label'
|
||||
= text_field_tag :dossier_id, @dossier_id, class: 'fr-input'
|
||||
|
||||
.fr-input-group
|
||||
= label_tag :subject, class: 'fr-label' do
|
||||
= t('subject', scope: [:utils])
|
||||
= render EditableChamp::AsteriskMandatoryComponent.new
|
||||
= text_field_tag :subject, params[:subject], required: true, class: 'fr-input'
|
||||
|
||||
.fr-input-group
|
||||
= label_tag :text, class: 'fr-label' do
|
||||
= t('message', scope: [:utils])
|
||||
= render EditableChamp::AsteriskMandatoryComponent.new
|
||||
= text_area_tag :text, params[:text], rows: 6, required: true, class: 'fr-input'
|
||||
|
||||
.fr-upload-group
|
||||
= label_tag :piece_jointe, class: 'fr-label' do
|
||||
= t('pj', scope: [:utils])
|
||||
%span.fr-hint-text
|
||||
= t('.notice_upload_group')
|
||||
|
||||
%p.notice.hidden{ data: { 'contact-type-only': Helpscout::FormAdapter::TYPE_AMELIORATION } }
|
||||
= t('.notice_pj_product')
|
||||
%p.notice.hidden{ data: { 'contact-type-only': Helpscout::FormAdapter::TYPE_AUTRE } }
|
||||
= t('.notice_pj_other')
|
||||
= file_field_tag :piece_jointe, class: 'fr-upload', accept: '.jpg, .jpeg, .png, .pdf'
|
||||
|
||||
= hidden_field_tag :tags, @tags&.join(',')
|
||||
|
||||
= invisible_captcha
|
||||
|
||||
.send-wrapper.fr-my-3w
|
||||
= button_tag t('send_mail', scope: [:utils]), type: :submit, class: 'fr-btn send'
|
||||
= render partial: "form", object: @form
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
en:
|
||||
activemodel:
|
||||
activerecord:
|
||||
attributes:
|
||||
helpscout/form:
|
||||
contact_form:
|
||||
email: 'Your email address'
|
||||
email_pro: Professional email address
|
||||
phone: Professional phone number (direct line)
|
||||
|
@ -12,15 +12,10 @@ en:
|
|||
email: 'Example: address@mail.com'
|
||||
errors:
|
||||
models:
|
||||
helpscout/form:
|
||||
contact_form:
|
||||
invalid_email_format: 'is not valid'
|
||||
support:
|
||||
index:
|
||||
contact: Contact
|
||||
intro_html:
|
||||
'<p>Contact us via this form and we will answer you as quickly as possible.</p>
|
||||
<p>Make sure you provide all the required information so we can help you in the best way.</p>'
|
||||
notice_email: 'Expected format: address@mail.com'
|
||||
form:
|
||||
your_question: Your question
|
||||
our_answer: Our answer
|
||||
notice_pj_product: A screenshot can help us identify the element to improve.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
fr:
|
||||
activemodel:
|
||||
activerecord:
|
||||
attributes:
|
||||
helpscout/form:
|
||||
contact_form:
|
||||
email: 'Votre adresse email'
|
||||
email_pro: Votre adresse email professionnelle
|
||||
phone: Numéro de téléphone professionnel (ligne directe)
|
||||
|
@ -12,15 +12,10 @@ fr:
|
|||
email: 'Exemple: adresse@mail.com'
|
||||
errors:
|
||||
models:
|
||||
helpscout/form:
|
||||
contact_form:
|
||||
invalid_email_format: 'est invalide'
|
||||
support:
|
||||
index:
|
||||
contact: Contact
|
||||
intro_html:
|
||||
'<p>Contactez-nous via ce formulaire et nous vous répondrons dans les plus brefs délais.</p>
|
||||
<p>Pensez bien à nous donner le plus d’informations possible pour que nous puissions vous aider au mieux.</p>'
|
||||
notice_email: 'Format attendu : adresse@mail.com'
|
||||
form:
|
||||
your_question: Votre question
|
||||
our_answer: Notre réponse
|
||||
notice_pj_product: Une capture d’écran peut nous aider à identifier plus facilement l’endroit à améliorer.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
describe SupportController, type: :controller do
|
||||
describe SupportController, question_type: :controller do
|
||||
render_views
|
||||
|
||||
context 'signed in' do
|
||||
|
@ -45,22 +45,30 @@ describe SupportController, type: :controller do
|
|||
get :index, params: { tags: tags }
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.body).to include(tags.join(','))
|
||||
expect(response.body).to include("value=\"yolo\"")
|
||||
expect(response.body).to include("value=\"toto\"")
|
||||
end
|
||||
end
|
||||
|
||||
describe "send form" do
|
||||
subject do
|
||||
post :create, params: { helpscout_form: params }
|
||||
post :create, params: { contact_form: params }
|
||||
end
|
||||
|
||||
context "when invisible captcha is ignored" do
|
||||
let(:params) { { subject: 'bonjour', text: 'un message', type: 'procedure_info' } }
|
||||
let(:params) { { subject: 'bonjour', text: 'un message', question_type: 'procedure_info' } }
|
||||
|
||||
it 'creates a conversation on HelpScout' do
|
||||
expect { subject }.to \
|
||||
change(Commentaire, :count).by(0).and \
|
||||
have_enqueued_job(HelpscoutCreateConversationJob).with(hash_including(params.except(:type)))
|
||||
change(ContactForm, :count).by(1)
|
||||
|
||||
contact_form = ContactForm.last
|
||||
expect(HelpscoutCreateConversationJob).to have_been_enqueued.with(contact_form)
|
||||
|
||||
expect(contact_form.subject).to eq("bonjour")
|
||||
expect(contact_form.text).to eq("un message")
|
||||
expect(contact_form.tags).to include("procedure_info")
|
||||
|
||||
expect(flash[:notice]).to match('Votre message a été envoyé.')
|
||||
expect(response).to redirect_to root_path
|
||||
|
@ -73,7 +81,7 @@ describe SupportController, type: :controller do
|
|||
let(:params) do
|
||||
{
|
||||
dossier_id: dossier.id,
|
||||
type: Helpscout::Form::TYPE_INSTRUCTION,
|
||||
question_type: ContactForm::TYPE_INSTRUCTION,
|
||||
subject: 'bonjour',
|
||||
text: 'un message'
|
||||
}
|
||||
|
@ -82,7 +90,11 @@ describe SupportController, type: :controller do
|
|||
it 'creates a conversation on HelpScout' do
|
||||
expect { subject }.to \
|
||||
change(Commentaire, :count).by(0).and \
|
||||
have_enqueued_job(HelpscoutCreateConversationJob).with(hash_including(subject: 'bonjour', dossier_id: dossier.id))
|
||||
change(ContactForm, :count).by(1)
|
||||
|
||||
contact_form = ContactForm.last
|
||||
expect(HelpscoutCreateConversationJob).to have_been_enqueued.with(contact_form)
|
||||
expect(contact_form.dossier_id).to eq(dossier.id)
|
||||
|
||||
expect(flash[:notice]).to match('Votre message a été envoyé.')
|
||||
expect(response).to redirect_to root_path
|
||||
|
@ -96,7 +108,7 @@ describe SupportController, type: :controller do
|
|||
let(:params) do
|
||||
{
|
||||
dossier_id: dossier.id,
|
||||
type: Helpscout::Form::TYPE_INSTRUCTION,
|
||||
question_type: ContactForm::TYPE_INSTRUCTION,
|
||||
subject: 'bonjour',
|
||||
text: 'un message'
|
||||
}
|
||||
|
@ -120,7 +132,7 @@ describe SupportController, type: :controller do
|
|||
context "when invisible captcha is filled" do
|
||||
subject do
|
||||
post :create, params: {
|
||||
helpscout_form: { subject: 'bonjour', text: 'un message', type: 'procedure_info' },
|
||||
contact_form: { subject: 'bonjour', text: 'un message', question_type: 'procedure_info' },
|
||||
InvisibleCaptcha.honeypots.sample => 'boom'
|
||||
}
|
||||
end
|
||||
|
@ -156,15 +168,19 @@ describe SupportController, type: :controller do
|
|||
|
||||
describe 'send form' do
|
||||
subject do
|
||||
post :create, params: { helpscout_form: params }
|
||||
post :create, params: { contact_form: params }
|
||||
end
|
||||
|
||||
let(:params) { { subject: 'bonjour', email: "me@rspec.net", text: 'un message', type: 'procedure_info' } }
|
||||
let(:params) { { subject: 'bonjour', email: "me@rspec.net", text: 'un message', question_type: 'procedure_info' } }
|
||||
|
||||
it 'creates a conversation on HelpScout' do
|
||||
expect { subject }.to \
|
||||
change(Commentaire, :count).by(0).and \
|
||||
have_enqueued_job(HelpscoutCreateConversationJob).with(hash_including(params.except(:type)))
|
||||
change(ContactForm, :count).by(1)
|
||||
|
||||
contact_form = ContactForm.last
|
||||
expect(HelpscoutCreateConversationJob).to have_been_enqueued.with(contact_form)
|
||||
expect(contact_form.email).to eq("me@rspec.net")
|
||||
|
||||
expect(flash[:notice]).to match('Votre message a été envoyé.')
|
||||
expect(response).to redirect_to root_path
|
||||
|
@ -184,15 +200,32 @@ describe SupportController, type: :controller do
|
|||
end
|
||||
|
||||
context 'contact admin' do
|
||||
subject do
|
||||
post :create, params: { helpscout_form: params }
|
||||
context 'index' do
|
||||
it 'should have professionnal email field' do
|
||||
get :admin
|
||||
expect(response.body).to have_text('Votre adresse email professionnelle')
|
||||
expect(response.body).to have_text('téléphone')
|
||||
expect(response.body).to include('for_admin')
|
||||
end
|
||||
end
|
||||
|
||||
let(:params) { { for_admin: "true", email: "email@pro.fr", subject: 'bonjour', text: 'un message', type: 'admin question', phone: '06' } }
|
||||
context 'create' do
|
||||
subject do
|
||||
post :create, params: { contact_form: params }
|
||||
end
|
||||
|
||||
let(:params) { { for_admin: "true", email: "email@pro.fr", subject: 'bonjour', text: 'un message', question_type: 'admin question', phone: '06' } }
|
||||
|
||||
describe "when form is filled" do
|
||||
it "creates a conversation on HelpScout" do
|
||||
expect { subject }.to have_enqueued_job(HelpscoutCreateConversationJob).with(hash_including(params.except(:for_admin, :type)))
|
||||
expect { subject }.to change(ContactForm, :count).by(1)
|
||||
|
||||
contact_form = ContactForm.last
|
||||
expect(HelpscoutCreateConversationJob).to have_been_enqueued.with(contact_form)
|
||||
expect(contact_form.email).to eq(params[:email])
|
||||
expect(contact_form.phone).to eq("06")
|
||||
expect(contact_form.tags).to match_array(["admin question", "contact form"])
|
||||
|
||||
expect(flash[:notice]).to match('Votre message a été envoyé.')
|
||||
end
|
||||
|
||||
|
@ -201,17 +234,17 @@ describe SupportController, type: :controller do
|
|||
let(:params) { super().merge(piece_jointe: logo) }
|
||||
|
||||
it "create blob and pass it to conversation job" do
|
||||
expect { subject }.to \
|
||||
change(ActiveStorage::Blob, :count).by(1).and \
|
||||
have_enqueued_job(HelpscoutCreateConversationJob).with(hash_including(blob_id: Integer)).and \
|
||||
have_enqueued_job(VirusScannerJob)
|
||||
expect { subject }.to change(ContactForm, :count).by(1)
|
||||
|
||||
contact_form = ContactForm.last
|
||||
expect(contact_form.piece_jointe).to be_attached
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "when invisible captcha is filled" do
|
||||
subject do
|
||||
post :create, params: { helpscout_form: params, InvisibleCaptcha.honeypots.sample => 'boom' }
|
||||
post :create, params: { contact_form: params, InvisibleCaptcha.honeypots.sample => 'boom' }
|
||||
end
|
||||
|
||||
it 'does not create a conversation on HelpScout' do
|
||||
|
@ -221,3 +254,4 @@ describe SupportController, type: :controller do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,16 +6,9 @@ RSpec.describe HelpscoutCreateConversationJob, type: :job do
|
|||
let(:subject_text) { 'Bonjour' }
|
||||
let(:text) { "J'ai un pb" }
|
||||
let(:tags) { ["first tag"] }
|
||||
let(:question_type) { "lost" }
|
||||
let(:phone) { nil }
|
||||
let(:params) {
|
||||
{
|
||||
email:,
|
||||
subject: subject_text,
|
||||
text:,
|
||||
tags:,
|
||||
phone:
|
||||
}
|
||||
}
|
||||
let(:contact_form) { create(:contact_form, email:, subject: subject_text, text:, tags:, phone:, question_type:) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
|
@ -26,56 +19,55 @@ RSpec.describe HelpscoutCreateConversationJob, type: :job do
|
|||
headers: { 'Resource-ID' => 'new-conversation-id' }
|
||||
))
|
||||
allow(api).to receive(:add_tags)
|
||||
allow(api).to receive(:add_phone_number) if params[:phone].present?
|
||||
allow(api).to receive(:add_phone_number) if phone.present?
|
||||
end
|
||||
|
||||
subject {
|
||||
described_class.perform_now(**params)
|
||||
described_class.perform_now(contact_form)
|
||||
}
|
||||
|
||||
context 'when blob_id is not present' do
|
||||
context 'when no file is attached' do
|
||||
it 'sends the form without a file' do
|
||||
subject
|
||||
expect(api).to have_received(:create_conversation).with(email, subject_text, text, nil)
|
||||
expect(api).to have_received(:add_tags).with("new-conversation-id", tags)
|
||||
expect(api).to have_received(:add_tags).with("new-conversation-id", match_array(tags.concat(["contact form", question_type])))
|
||||
expect(contact_form).to be_destroyed
|
||||
end
|
||||
end
|
||||
|
||||
context 'when blob_id is present' do
|
||||
let(:blob) {
|
||||
ActiveStorage::Blob.create_and_upload!(io: StringIO.new("toto"), filename: "toto.png")
|
||||
}
|
||||
let(:params) { super().merge(blob_id: blob.id) }
|
||||
|
||||
context 'when a file is attached' do
|
||||
before do
|
||||
allow(blob).to receive(:virus_scanner).and_return(double('VirusScanner', pending?: pending, safe?: safe))
|
||||
allow(ActiveStorage::Blob).to receive(:find).with(blob.id).and_return(blob)
|
||||
file = fixture_file_upload('spec/fixtures/files/white.png', 'image/png')
|
||||
contact_form.piece_jointe.attach(file)
|
||||
end
|
||||
|
||||
context 'when the file has not been scanned yet' do
|
||||
let(:pending) { true }
|
||||
let(:safe) { false }
|
||||
before do
|
||||
allow_any_instance_of(ActiveStorage::Blob).to receive(:virus_scanner).and_return(double('VirusScanner', pending?: true, safe?: false))
|
||||
end
|
||||
|
||||
it 'reenqueue job' do
|
||||
expect { subject }.to have_enqueued_job(described_class).with(params)
|
||||
it 'reenqueues job' do
|
||||
expect { subject }.to have_enqueued_job(described_class).with(contact_form)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the file is safe' do
|
||||
let(:pending) { false }
|
||||
let(:safe) { true }
|
||||
before do
|
||||
allow_any_instance_of(ActiveStorage::Blob).to receive(:virus_scanner).and_return(double('VirusScanner', pending?: false, safe?: true))
|
||||
end
|
||||
|
||||
it 'downloads the file and sends the form' do
|
||||
it 'sends the form with the file' do
|
||||
subject
|
||||
expect(api).to have_received(:create_conversation).with(email, subject_text, text, blob)
|
||||
expect(api).to have_received(:create_conversation).with(email, subject_text, text, contact_form.piece_jointe)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the file is not safe' do
|
||||
let(:pending) { false }
|
||||
let(:safe) { false }
|
||||
before do
|
||||
allow_any_instance_of(ActiveStorage::Blob).to receive(:virus_scanner).and_return(double('VirusScanner', pending?: false, safe?: false))
|
||||
end
|
||||
|
||||
it 'ignore the file' do
|
||||
it 'ignores the file' do
|
||||
subject
|
||||
expect(api).to have_received(:create_conversation).with(email, subject_text, text, nil)
|
||||
end
|
||||
|
@ -84,6 +76,7 @@ RSpec.describe HelpscoutCreateConversationJob, type: :job do
|
|||
|
||||
context 'with a phone' do
|
||||
let(:phone) { "06" }
|
||||
|
||||
it 'associates the phone number' do
|
||||
subject
|
||||
expect(api).to have_received(:add_phone_number).with(email, phone)
|
||||
|
|
Loading…
Reference in a new issue