improves twitter outgoing direct message, fixes #1931
This commit is contained in:
parent
711a704602
commit
28b789c47b
7 changed files with 279 additions and 80 deletions
|
@ -235,7 +235,15 @@ class EmailReply extends App.Controller
|
|||
|
||||
articleTypes
|
||||
|
||||
@setArticleType: (type, ticket, ui, signaturePosition) ->
|
||||
@setArticleTypePre: (type, ticket, ui, signaturePosition) ->
|
||||
|
||||
# remove old signature
|
||||
if type isnt 'email'
|
||||
ui.$('[data-name=body] [data-signature=true]').remove()
|
||||
return
|
||||
|
||||
@setArticleTypePost: (type, ticket, ui, signaturePosition) ->
|
||||
return if type isnt 'email'
|
||||
|
||||
# detect current signature (use current group_id, if not set, use ticket.group_id)
|
||||
ticketCurrent = App.Ticket.fullLocal(ticket.id)
|
||||
|
@ -249,7 +257,7 @@ class EmailReply extends App.Controller
|
|||
signature = App.Signature.find(group.signature_id)
|
||||
|
||||
# add/replace signature
|
||||
if signature && signature.body && type is 'email'
|
||||
if signature && signature.body
|
||||
|
||||
# if signature has changed, remove it
|
||||
signature_id = ui.$('[data-signature=true]').data('signature-id')
|
||||
|
@ -271,15 +279,6 @@ class EmailReply extends App.Controller
|
|||
body.append(signature)
|
||||
ui.$('[data-name=body]').replaceWith(body)
|
||||
|
||||
# remove old signature
|
||||
else
|
||||
ui.$('[data-name=body] [data-signature=true]').remove()
|
||||
|
||||
if type isnt 'email'
|
||||
ui.$('[name=to]').val('')
|
||||
ui.$('[name=cc]').val('')
|
||||
ui.$('[name=subject]').val('')
|
||||
|
||||
@validation: (type, params, ui) ->
|
||||
return true if type isnt 'email'
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ class TelegramReply
|
|||
}
|
||||
articleTypes
|
||||
|
||||
@setArticleType: (type, ticket, ui) ->
|
||||
@setArticleTypePost: (type, ticket, ui) ->
|
||||
return if type isnt 'telegram personal-message'
|
||||
rawHTML = ui.$('[data-name=body]').html()
|
||||
cleanHTML = App.Utils.htmlRemoveRichtext(rawHTML)
|
||||
|
|
|
@ -116,7 +116,7 @@ class TwitterReply
|
|||
else
|
||||
articleNew.to = article.from
|
||||
|
||||
if !articleNew.to
|
||||
if !articleNew.to && customer && customer.accounts
|
||||
articleNew.to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
|
||||
|
||||
App.Event.trigger('ui::ticket::setArticleType', {
|
||||
|
@ -169,9 +169,23 @@ class TwitterReply
|
|||
textLength = ui.maxTextLength - App.Utils.textLengthWithUrl(params.body)
|
||||
return false if textLength < 0
|
||||
|
||||
# check if recipient exists
|
||||
if _.isEmpty(params.to)
|
||||
new App.ControllerModal(
|
||||
head: 'Text missing'
|
||||
buttonCancel: 'Cancel'
|
||||
buttonCancelClass: 'btn--danger'
|
||||
buttonSubmit: false
|
||||
message: 'Need recipient in "To".'
|
||||
shown: true
|
||||
small: true
|
||||
container: ui.el.closest('.content')
|
||||
)
|
||||
return false
|
||||
|
||||
true
|
||||
|
||||
@setArticleType: (type, ticket, ui) ->
|
||||
@setArticleTypePost: (type, ticket, ui) ->
|
||||
return if type isnt 'twitter status' && type isnt 'twitter direct-message'
|
||||
rawHTML = ui.$('[data-name=body]').html()
|
||||
cleanHTML = App.Utils.htmlRemoveRichtext(rawHTML)
|
||||
|
|
|
@ -51,6 +51,8 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
@bind('ui::ticket::setArticleType', (data) =>
|
||||
return if data.ticket.id.toString() isnt @ticket_id.toString()
|
||||
|
||||
@setArticleTypePre(data.type.name, data.signaturePosition)
|
||||
|
||||
@openTextarea(null, true)
|
||||
for key, value of data.article
|
||||
if key is 'body'
|
||||
|
@ -58,8 +60,7 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
else
|
||||
@$("[name=\"#{key}\"]").val(value).trigger('change')
|
||||
|
||||
# preselect article type
|
||||
@setArticleType(data.type.name, data.signaturePosition)
|
||||
@setArticleTypePost(data.type.name, data.signaturePosition)
|
||||
|
||||
# set focus into field
|
||||
if data.focus
|
||||
|
@ -120,11 +121,8 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
App.Delay.set(a, 500, undefined, 'tags')
|
||||
|
||||
setPossibleArticleTypes: =>
|
||||
actionConfig = App.Config.get('TicketZoomArticleAction')
|
||||
keys = _.keys(actionConfig).sort()
|
||||
@articleTypes = []
|
||||
for key in keys
|
||||
config = actionConfig[key]
|
||||
for config in @actions()
|
||||
if config && config.articleTypes
|
||||
@articleTypes = config.articleTypes(@articleTypes, @ticket, @)
|
||||
|
||||
|
@ -166,7 +164,8 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
isCustomer: @permissionCheck('ticket.customer')
|
||||
internalSelector: @internalSelector
|
||||
)
|
||||
@setArticleType(@type)
|
||||
@setArticleTypePre(@type)
|
||||
@setArticleTypePost(@type)
|
||||
|
||||
new App.WidgetAvatar(
|
||||
el: @$('.js-avatar')
|
||||
|
@ -278,10 +277,7 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
params.internal = false
|
||||
|
||||
# backend based validation
|
||||
actionConfig = App.Config.get('TicketZoomArticleAction')
|
||||
keys = _.keys(actionConfig).sort()
|
||||
for key in keys
|
||||
config = actionConfig[key]
|
||||
for config in @actions()
|
||||
if config && config.params
|
||||
params = config.params(params.type, params, @)
|
||||
|
||||
|
@ -323,10 +319,7 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
return false
|
||||
|
||||
# backend based validation
|
||||
actionConfig = App.Config.get('TicketZoomArticleAction')
|
||||
keys = _.keys(actionConfig).sort()
|
||||
for key in keys
|
||||
config = actionConfig[key]
|
||||
for config in @actions()
|
||||
if config && config.validation
|
||||
return false if !config.validation(params.type, params, @)
|
||||
|
||||
|
@ -350,10 +343,11 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
selectArticleType: (event) =>
|
||||
event.stopPropagation()
|
||||
articleTypeToSet = $(event.target).closest('.pop-selectable').data('value')
|
||||
@setArticleType(articleTypeToSet)
|
||||
@setArticleTypePre(articleTypeToSet)
|
||||
@hideSelectableArticleType()
|
||||
@setArticleTypePost(articleTypeToSet)
|
||||
|
||||
$(window).off 'click.ticket-zoom-select-type'
|
||||
$(window).off('click.ticket-zoom-select-type')
|
||||
@tokanice()
|
||||
|
||||
hideSelectableArticleType: =>
|
||||
|
@ -374,8 +368,14 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
|
||||
@$('[name=internal]').val('')
|
||||
|
||||
setArticleType: (type, signaturePosition = 'bottom') =>
|
||||
setArticleTypePre: (type, signaturePosition = 'bottom') =>
|
||||
wasScrolledToBottom = @isScrolledToBottom()
|
||||
|
||||
# reset old params
|
||||
if type isnt @type
|
||||
for key in ['to', 'cc', 'bcc', 'subject', 'in_reply_to']
|
||||
@$("[name=#{key}]").val('').trigger('change')
|
||||
|
||||
@type = type
|
||||
@$('[name=type]').val(type).trigger('change')
|
||||
@articleNewEdit.attr('data-type', type)
|
||||
|
@ -395,13 +395,6 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
else
|
||||
@setArticleInternal(false)
|
||||
|
||||
actionConfig = App.Config.get('TicketZoomArticleAction')
|
||||
keys = _.keys(actionConfig).sort()
|
||||
for key in keys
|
||||
localConfig = actionConfig[key]
|
||||
if localConfig && localConfig.setArticleType
|
||||
localConfig.setArticleType(@type, @ticket, @, signaturePosition)
|
||||
|
||||
# show/hide attributes/features
|
||||
@maxTextLength = undefined
|
||||
@warningTextLength = undefined
|
||||
|
@ -438,6 +431,11 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
|
||||
@scrollToBottom() if wasScrolledToBottom
|
||||
|
||||
setArticleTypePost: (type, signaturePosition = 'bottom') =>
|
||||
for localConfig in @actions()
|
||||
if localConfig && localConfig.setArticleTypePost
|
||||
localConfig.setArticleTypePost(@type, @ticket, @, signaturePosition)
|
||||
|
||||
isScrolledToBottom: ->
|
||||
return @el.scrollParent().scrollTop() + @el.scrollParent().height() is @el.scrollParent().prop('scrollHeight')
|
||||
|
||||
|
@ -615,3 +613,13 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
if element.find('.attachment').length == 0
|
||||
element.empty()
|
||||
)
|
||||
|
||||
actions: ->
|
||||
actionConfig = App.Config.get('TicketZoomArticleAction')
|
||||
keys = _.keys(actionConfig).sort()
|
||||
actions = []
|
||||
for key in keys
|
||||
localConfig = actionConfig[key]
|
||||
if localConfig
|
||||
actions.push localConfig
|
||||
actions
|
||||
|
|
|
@ -23,6 +23,7 @@ class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer
|
|||
type = Ticket::Article::Type.lookup(id: record.type_id)
|
||||
return if type['name'] !~ /\Atwitter/i
|
||||
|
||||
raise Exceptions::UnprocessableEntity, 'twitter to: parameter is missing' if record.to.blank? && type['name'] == 'twitter direct-message'
|
||||
Delayed::Job.enqueue(Observer::Ticket::Article::CommunicateTwitter::BackgroundJob.new(record.id))
|
||||
end
|
||||
|
||||
|
|
|
@ -3,36 +3,7 @@ require 'browser_test_helper'
|
|||
|
||||
class TwitterBrowserTest < TestCase
|
||||
def test_add_config
|
||||
|
||||
# app config
|
||||
if !ENV['TWITTER_BT_CONSUMER_KEY']
|
||||
raise "ERROR: Need TWITTER_BT_CONSUMER_KEY - hint TWITTER_BT_CONSUMER_KEY='1234'"
|
||||
end
|
||||
consumer_key = ENV['TWITTER_BT_CONSUMER_KEY']
|
||||
if !ENV['TWITTER_BT_CONSUMER_SECRET']
|
||||
raise "ERROR: Need TWITTER_BT_CONSUMER_SECRET - hint TWITTER_BT_CONSUMER_SECRET='1234'"
|
||||
end
|
||||
consumer_secret = ENV['TWITTER_BT_CONSUMER_SECRET']
|
||||
|
||||
if !ENV['TWITTER_BT_USER_LOGIN']
|
||||
raise "ERROR: Need TWITTER_BT_USER_LOGIN - hint TWITTER_BT_USER_LOGIN='1234'"
|
||||
end
|
||||
twitter_user_login = ENV['TWITTER_BT_USER_LOGIN']
|
||||
|
||||
if !ENV['TWITTER_BT_USER_PW']
|
||||
raise "ERROR: Need TWITTER_BT_USER_PW - hint TWITTER_BT_USER_PW='1234'"
|
||||
end
|
||||
twitter_user_pw = ENV['TWITTER_BT_USER_PW']
|
||||
|
||||
if !ENV['TWITTER_BT_CUSTOMER_TOKEN']
|
||||
raise "ERROR: Need TWITTER_BT_CUSTOMER_TOKEN - hint TWITTER_BT_CUSTOMER_TOKEN='1234'"
|
||||
end
|
||||
twitter_customer_token = ENV['TWITTER_BT_CUSTOMER_TOKEN']
|
||||
|
||||
if !ENV['TWITTER_BT_CUSTOMER_TOKEN_SECRET']
|
||||
raise "ERROR: Need TWITTER_BT_CUSTOMER_TOKEN_SECRET - hint TWITTER_BT_CUSTOMER_TOKEN_SECRET='1234'"
|
||||
end
|
||||
twitter_customer_token_secret = ENV['TWITTER_BT_CUSTOMER_TOKEN_SECRET']
|
||||
twitter_config
|
||||
|
||||
hash = "#sweet#{hash_gen}"
|
||||
|
||||
|
@ -51,7 +22,7 @@ class TwitterBrowserTest < TestCase
|
|||
sleep 2
|
||||
set(
|
||||
css: '.content.active .modal [name=consumer_key]',
|
||||
value: consumer_key,
|
||||
value: twitter_config[:consumer_key],
|
||||
)
|
||||
set(
|
||||
css: '.content.active .modal [name=consumer_secret]',
|
||||
|
@ -66,7 +37,7 @@ class TwitterBrowserTest < TestCase
|
|||
|
||||
set(
|
||||
css: '.content.active .modal [name=consumer_secret]',
|
||||
value: consumer_secret,
|
||||
value: twitter_config[:consumer_secret],
|
||||
)
|
||||
click(css: '.content.active .modal .js-submit')
|
||||
|
||||
|
@ -95,7 +66,7 @@ class TwitterBrowserTest < TestCase
|
|||
|
||||
set(
|
||||
css: '.content.active .modal [name=consumer_secret]',
|
||||
value: consumer_secret,
|
||||
value: twitter_config[:consumer_secret],
|
||||
)
|
||||
click(css: '.content.active .modal .js-submit')
|
||||
|
||||
|
@ -115,12 +86,12 @@ class TwitterBrowserTest < TestCase
|
|||
|
||||
set(
|
||||
css: '#username_or_email',
|
||||
value: twitter_user_login,
|
||||
value: twitter_config[:twitter_user_login],
|
||||
no_click: true, # <label> other element would receive the click
|
||||
)
|
||||
set(
|
||||
css: '#password',
|
||||
value: twitter_user_pw,
|
||||
value: twitter_config[:twitter_user_pw],
|
||||
no_click: true, # <label> other element would receive the click
|
||||
)
|
||||
click(css: '#allow')
|
||||
|
@ -139,6 +110,7 @@ class TwitterBrowserTest < TestCase
|
|||
click(css: '.content.active .modal .js-searchTermAdd')
|
||||
set(css: '.content.active .modal [name="search::term"]', value: hash)
|
||||
select(css: '.content.active .modal [name="search::group_id"]', value: 'Users')
|
||||
select(css: '.content.active .modal [name="direct_messages::group_id"]', value: 'Users')
|
||||
click(css: '.content.active .modal .js-submit')
|
||||
modal_disappear
|
||||
|
||||
|
@ -148,7 +120,7 @@ class TwitterBrowserTest < TestCase
|
|||
)
|
||||
watch_for(
|
||||
css: '.content.active',
|
||||
value: "@#{twitter_user_login}",
|
||||
value: "@#{twitter_config[:twitter_user_login]}",
|
||||
)
|
||||
exists(
|
||||
css: '.content.active .main .action:nth-child(1)'
|
||||
|
@ -177,7 +149,7 @@ class TwitterBrowserTest < TestCase
|
|||
)
|
||||
watch_for(
|
||||
css: '.content.active',
|
||||
value: "@#{twitter_user_login}",
|
||||
value: "@#{twitter_config[:twitter_user_login]}",
|
||||
)
|
||||
exists(
|
||||
css: '.content.active .main .action:nth-child(1)'
|
||||
|
@ -191,10 +163,10 @@ class TwitterBrowserTest < TestCase
|
|||
|
||||
# start tweet from customer
|
||||
client = Twitter::REST::Client.new do |config|
|
||||
config.consumer_key = consumer_key
|
||||
config.consumer_secret = consumer_secret
|
||||
config.access_token = twitter_customer_token
|
||||
config.access_token_secret = twitter_customer_token_secret
|
||||
config.consumer_key = twitter_config[:consumer_key]
|
||||
config.consumer_secret = twitter_config[:consumer_secret]
|
||||
config.access_token = twitter_config[:twitter_customer_token]
|
||||
config.access_token_secret = twitter_config[:twitter_customer_token_secret]
|
||||
end
|
||||
|
||||
text = "Today #{rand_word}... #{hash} #{hash_gen}"
|
||||
|
@ -272,6 +244,100 @@ class TwitterBrowserTest < TestCase
|
|||
|
||||
end
|
||||
|
||||
def reply_direct_message
|
||||
twitter_config
|
||||
|
||||
@browser = browser_instance
|
||||
login(
|
||||
username: 'master@example.com',
|
||||
password: 'test',
|
||||
url: browser_url,
|
||||
auto_wizard: true,
|
||||
)
|
||||
tasks_close_all()
|
||||
|
||||
client = Twitter::REST::Client.new do |config|
|
||||
config.consumer_key = twitter_config[:consumer_key]
|
||||
config.consumer_secret = twitter_config[:consumer_secret]
|
||||
config.access_token = twitter_config[:twitter_customer_token]
|
||||
config.access_token_secret = twitter_config[:twitter_customer_token_secret]
|
||||
end
|
||||
|
||||
text = "Today #{rand_word}... #{hash} #{hash_gen}"
|
||||
tweet = client.create_direct_message(
|
||||
"@#{twitter_config[:twitter_user_login]}",
|
||||
text,
|
||||
)
|
||||
|
||||
# watch till tweet is in app
|
||||
click(text: 'Overviews')
|
||||
|
||||
# enable full overviews
|
||||
execute(
|
||||
js: '$(".content.active .sidebar").css("display", "block")',
|
||||
)
|
||||
|
||||
click(text: 'Unassigned & Open')
|
||||
|
||||
watch_for(
|
||||
css: '.content.active',
|
||||
value: hash,
|
||||
timeout: 36,
|
||||
)
|
||||
|
||||
ticket_open_by_title(
|
||||
title: hash,
|
||||
)
|
||||
|
||||
# reply via app
|
||||
click(css: '.content.active [data-type="twitterStatusReply"]')
|
||||
|
||||
ticket_update(
|
||||
data: {
|
||||
body: '@dzucker6 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890',
|
||||
},
|
||||
do_not_submit: true,
|
||||
)
|
||||
click(
|
||||
css: '.content.active .js-submit',
|
||||
)
|
||||
sleep 10
|
||||
click(
|
||||
css: '.content.active .js-reset',
|
||||
)
|
||||
sleep 2
|
||||
|
||||
match_not(
|
||||
css: '.content.active',
|
||||
value: '1234567890',
|
||||
)
|
||||
|
||||
click(css: '.content.active [data-type="twitterStatusReply"]')
|
||||
sleep 2
|
||||
|
||||
re_hash = "#{hash}re#{rand(99_999)}"
|
||||
|
||||
ticket_update(
|
||||
data: {
|
||||
body: "@dzucker6 #{rand_word} reply #{re_hash} #{rand(999_999)}",
|
||||
},
|
||||
)
|
||||
sleep 20
|
||||
|
||||
match(
|
||||
css: '.content.active .ticket-article',
|
||||
value: re_hash,
|
||||
)
|
||||
|
||||
# watch till tweet reached customer
|
||||
sleep 10
|
||||
text = nil
|
||||
client.search(re_hash, result_type: 'mixed').collect do |local_tweet|
|
||||
text = local_tweet.text
|
||||
end
|
||||
assert(text)
|
||||
end
|
||||
|
||||
def hash_gen
|
||||
(0...10).map { ('a'..'z').to_a[rand(26)] }.join + rand(999).to_s
|
||||
end
|
||||
|
@ -298,4 +364,44 @@ class TwitterBrowserTest < TestCase
|
|||
words[rand(words.length)]
|
||||
end
|
||||
|
||||
def twitter_config
|
||||
# app config
|
||||
if !ENV['TWITTER_BT_CONSUMER_KEY']
|
||||
raise "ERROR: Need TWITTER_BT_CONSUMER_KEY - hint TWITTER_BT_CONSUMER_KEY='1234'"
|
||||
end
|
||||
consumer_key = ENV['TWITTER_BT_CONSUMER_KEY']
|
||||
if !ENV['TWITTER_BT_CONSUMER_SECRET']
|
||||
raise "ERROR: Need TWITTER_BT_CONSUMER_SECRET - hint TWITTER_BT_CONSUMER_SECRET='1234'"
|
||||
end
|
||||
consumer_secret = ENV['TWITTER_BT_CONSUMER_SECRET']
|
||||
|
||||
if !ENV['TWITTER_BT_USER_LOGIN']
|
||||
raise "ERROR: Need TWITTER_BT_USER_LOGIN - hint TWITTER_BT_USER_LOGIN='1234'"
|
||||
end
|
||||
twitter_user_login = ENV['TWITTER_BT_USER_LOGIN']
|
||||
|
||||
if !ENV['TWITTER_BT_USER_PW']
|
||||
raise "ERROR: Need TWITTER_BT_USER_PW - hint TWITTER_BT_USER_PW='1234'"
|
||||
end
|
||||
twitter_user_pw = ENV['TWITTER_BT_USER_PW']
|
||||
|
||||
if !ENV['TWITTER_BT_CUSTOMER_TOKEN']
|
||||
raise "ERROR: Need TWITTER_BT_CUSTOMER_TOKEN - hint TWITTER_BT_CUSTOMER_TOKEN='1234'"
|
||||
end
|
||||
twitter_customer_token = ENV['TWITTER_BT_CUSTOMER_TOKEN']
|
||||
|
||||
if !ENV['TWITTER_BT_CUSTOMER_TOKEN_SECRET']
|
||||
raise "ERROR: Need TWITTER_BT_CUSTOMER_TOKEN_SECRET - hint TWITTER_BT_CUSTOMER_TOKEN_SECRET='1234'"
|
||||
end
|
||||
twitter_customer_token_secret = ENV['TWITTER_BT_CUSTOMER_TOKEN_SECRET']
|
||||
|
||||
hash = {
|
||||
consumer_key: consumer_key,
|
||||
consumer_secret: consumer_secret,
|
||||
twitter_user_login: twitter_user_login,
|
||||
twitter_user_pw: twitter_user_pw,
|
||||
twitter_customer_token: twitter_customer_token,
|
||||
twitter_customer_token_secret: twitter_customer_token_secret
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -427,6 +427,75 @@ class TwitterTest < ActiveSupport::TestCase
|
|||
assert_equal('ok', channel.status_in)
|
||||
end
|
||||
|
||||
test 'c new by direct message outbound without required parameters' do
|
||||
|
||||
# cleanup direct messages of system
|
||||
client = Twitter::REST::Client.new do |config|
|
||||
config.consumer_key = consumer_key
|
||||
config.consumer_secret = consumer_secret
|
||||
config.access_token = system_token
|
||||
config.access_token_secret = system_token_secret
|
||||
end
|
||||
dms = client.direct_messages(count: 100)
|
||||
dms.each do |dm|
|
||||
client.destroy_direct_message(dm.id)
|
||||
end
|
||||
client = Twitter::REST::Client.new(
|
||||
consumer_key: consumer_key,
|
||||
consumer_secret: consumer_secret,
|
||||
access_token: customer_token,
|
||||
access_token_secret: customer_token_secret
|
||||
)
|
||||
dms = client.direct_messages(count: 100)
|
||||
dms.each do |dm|
|
||||
client.destroy_direct_message(dm.id)
|
||||
end
|
||||
hash = "#citheo44 #{hash_gen}"
|
||||
text = "How about #{rand_word} the details? #{hash} - #{'Long' * 50}"
|
||||
dm = client.create_direct_message(
|
||||
system_login_without_at,
|
||||
text,
|
||||
)
|
||||
assert(dm, "dm with ##{hash} created")
|
||||
|
||||
# fetch check system account
|
||||
sleep 15
|
||||
article = nil
|
||||
1.times do
|
||||
Channel.fetch
|
||||
|
||||
# check if ticket and article has been created
|
||||
article = Ticket::Article.find_by(message_id: dm.id)
|
||||
break if article
|
||||
sleep 10
|
||||
end
|
||||
|
||||
assert(article, "inbound article '#{text}' created")
|
||||
assert_equal(customer_login, article.from, 'ticket article from')
|
||||
assert_equal(text, article.body, 'ticket article body')
|
||||
ticket = article.ticket
|
||||
assert(ticket, 'ticket of inbound article exists')
|
||||
assert(ticket.articles, 'ticket.articles exists')
|
||||
assert_equal(1, ticket.articles.count, 'ticket article inbound count')
|
||||
assert_equal(ticket.state.name, 'closed')
|
||||
|
||||
# reply via ticket
|
||||
reply = assert_raises(Exceptions::UnprocessableEntity) do
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket.id,
|
||||
in_reply_to: '123456789',
|
||||
body: "Will call you later #{rand_word}!",
|
||||
type: Ticket::Article::Type.find_by(name: 'twitter direct-message'),
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
|
||||
internal: false,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
end
|
||||
|
||||
assert_equal('twitter to: parameter is missing', reply.message)
|
||||
end
|
||||
|
||||
test 'd track_retweets enabled' do
|
||||
|
||||
# enable track_retweets
|
||||
|
@ -538,6 +607,7 @@ class TwitterTest < ActiveSupport::TestCase
|
|||
ActiveRecord::Base.connection.query_cache.clear
|
||||
sleep 10
|
||||
end
|
||||
|
||||
assert(article, "article from customer with text '#{text}' message_id '#{tweet.id}' created")
|
||||
assert_equal(customer_login, article.from, 'ticket article from')
|
||||
assert_nil(article.to, 'ticket article to')
|
||||
|
@ -768,6 +838,7 @@ class TwitterTest < ActiveSupport::TestCase
|
|||
)
|
||||
article = nil
|
||||
5.times do
|
||||
Channel.fetch
|
||||
Scheduler.worker(true)
|
||||
article = Ticket::Article.find_by(message_id: tweet.id)
|
||||
break if article
|
||||
|
|
Loading…
Reference in a new issue