@@ -13,154 +13,200 @@ def process
# This error happened with invalid email addresses from PureChat
return if @email.from[:email].match(/\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/).blank?

# scan users DB for sender email
@user = User.where("lower(email) = ?", @email.from[:email].downcase).first
if @user.nil?
create_user
end

# Set attributes from email
sitename = AppSettings["settings.site_name"]
message = @email.body.nil? ? "" : @email.body
raw = @email.raw_body.nil? ? "" : @email.raw_body
email_address = @email.from[:email].downcase
email_name = @email.from[:name].blank? ? @email.from[:token].gsub(/[^a-zA-Z]/, '') : @email.from[:name]
message = @email.body.nil? ? "" : encode_entity(@email.body)
raw = @email.raw_body.nil? ? "" : encode_entity(@email.raw_body)
to = @email.to.first[:email]
cc = @email.cc ? @email.cc.map { |e| e[:full] }.join(", ") : nil

subject = @email.subject
token = @email.to.first[:token]
subject = check_subject(@email.subject)
attachments = @email.attachments
number_of_attachments = attachments.present? ? attachments.size : 0

if subject.include?("[#{sitename}]") # this is a reply to an existing topic
EmailProcessor.create_reply_from_email(@email, email_address, email_name, subject, raw, message, token, to, sitename, cc, number_of_attachments)
elsif subject.include?("Fwd: ") # this is a forwarded message TODO: Expand this to handle foreign email formatting
EmailProcessor.create_forwarded_message_from_email(@email, subject, raw, message, token, to, cc, number_of_attachments)
else # this is a new direct message
EmailProcessor.create_new_ticket_from_email(@email, email_address, email_name, subject, raw, message, token, to, cc, number_of_attachments)
end

complete_subject = subject.split("[#{sitename}]")[1].strip
ticket_number = complete_subject.split("-")[0].split("#")[1].strip
topic = Topic.find(ticket_number)
# rescue
# render status: 200
end

#insert post to new topic
message = "Attachments:" if @email.attachments.present? && @email.body.blank?
post = topic.posts.create(
:body => encode_entity(message),
:raw_email => encode_entity(raw),
:user_id => @user.id,
:cc => cc,
:kind => "reply"
)
# Insert a default subject if subject is missing
def check_subject(subject)
subject.blank? ? "(No Subject)" : subject
end

# Push array of attachments and send to Cloudinary
handle_attachments(@email, post)
def encode_entity(entity)
!entity.nil? ? entity.encode('utf-8', invalid: :replace, replace: '?') : entity
end

if @tracker
@tracker.event(category: "Email", action: "Inbound", label: "Reply", non_interactive: true)
@tracker.event(category: "Agent: #{topic.assigned_user.name}", action: "User Replied by Email", label: topic.to_param) unless topic.assigned_user.nil?
def self.handle_attachments(email, post)
return unless email.attachments.present?
if AppSettings['cloudinary.cloud_name'].present? && AppSettings['cloudinary.api_key'].present? && AppSettings['cloudinary.api_secret'].present?
array_of_files = []
email.attachments.each do |attachment|
array_of_files << File.open(attachment.tempfile.path, 'r')
end
elsif subject.include?("Fwd: ") # this is a forwarded message DOES NOT WORK CURRENTLY

#clean message
# message = MailExtract.new(message).body

#parse_forwarded_message(message)
topic = Forum.first.topics.create!(
:name => subject,
:user_id => @user.id,
:private => true
post.screenshots = array_of_files
else
post.update(
attachments: email.attachments
)
if post.valid?
post.save
end
end
end

#insert post to new topic
message = "Attachments:" if @email.attachments.present? && @email.body.blank?
post = topic.posts.create!(
:body => encode_entity(message),
:raw_email => encode_entity(raw),
:user_id => @user.id,
:cc => cc,
kind: 'first'
)
def cloudinary_enabled?
AppSettings['cloudinary.cloud_name'].present? && AppSettings['cloudinary.api_key'].present? && AppSettings['cloudinary.api_secret'].present?
end

# Push array of attachments and send to Cloudinary
handle_attachments(@email, post)
def google_analytics_enabled?
AppSettings['settings.google_analytics_enabled'] == '1'
end

# Call to GA
if @tracker
@tracker.event(category: "Email", action: "Inbound", label: "Forwarded New Topic", non_interactive: true)
@tracker.event(category: "Agent: Unassigned", action: "Forwarded New", label: topic.to_param)
end
else # this is a new direct message
# Creates a new ticket from an email
def self.create_new_ticket_from_email(email, email_address, email_name, subject, raw, message, token, to, cc, number_of_attachments)
@user = User.where("lower(email) = ?", email_address).first
if @user.nil?
@user = EmailProcessor.create_user_for_email(email_address, token, email_name)
end

topic = Forum.first.topics.create(:name => subject, :user_id => @user.id, :private => true)
# if @email.header['X-Helpy-Teams'].present?
# topic.team_list = @email.header['X-Helpy-Teams']
topic = Forum.first.topics.new(
name: subject,
user_id: @user.id,
private: true
)

if @email.to[0][:token].include?("+")
topic.team_list.add(@email.to[0][:token].split('+')[1])
if topic.save
if token.include?("+")
topic.team_list.add(token.split('+')[1])
topic.save
elsif @email.to[0][:token] != 'support'
topic.team_list.add(@email.to[0][:token])
topic.team_list.add(token)
topic.save
end

#insert post to new topic
message = "Attachments:" if @email.attachments.present? && @email.body.blank?
message = "-" if message.blank? && number_of_attachments > 0
post = topic.posts.create(
:body => encode_entity(message),
:raw_email => encode_entity(raw),
:user_id => @user.id,
:cc => cc,
:kind => "first"
body: message,
raw_email: raw,
user_id: @user.id,
kind: "first",
cc: cc
)

# Push array of attachments and send to Cloudinary
handle_attachments(@email, post)
EmailProcessor.handle_attachments(email, post)

# Call to GA
if @tracker
@tracker.event(category: "Email", action: "Inbound", label: "New Topic", non_interactive: true)
@tracker.event(category: "Agent: Unassigned", action: "New", label: topic.to_param)
end
end

# rescue
# render status: 200
end

def encode_entity(entity)
!entity.nil? ? entity.encode('utf-8', invalid: :replace, replace: '?') : entity
end
# Creates a ticket from a forwarded email
def self.create_forwarded_message_from_email(email, subject, raw, message, token, to, cc, number_of_attachments)

def handle_attachments(email, post)
if email.attachments.present? && cloudinary_enabled?
array_of_files = []
email.attachments.each do |attachment|
array_of_files << File.open(attachment.tempfile.path, 'r')
end
post.screenshots = array_of_files
elsif email.attachments.present?
post.update(
attachments: email.attachments
# Parse from out of the forwarded raw body
from = raw[/From: .*<(.*?)>/, 1]
from_token = from.split("@")[0]

# scan users DB for sender email
@user = User.where("lower(email) = ?", from).first
if @user.nil?
@user = EmailProcessor.create_user_for_email(from, from_token, "")
end

#clean message
message = MailExtract.new(raw).body

topic = Forum.first.topics.new(
name: subject,
user_id: @user.id,
private: true
)

if topic.save
#insert post to new topic
message = "-" if message.blank? && number_of_attachments > 0
post = topic.posts.create!(
body: raw,
raw_email: raw,
user_id: @user.id,
kind: 'first',
cc: cc
)
if post.valid?
post.save

# Push array of attachments and send to Cloudinary
EmailProcessor.handle_attachments(email, post)

# Call to GA
if @tracker
@tracker.event(category: "Email", action: "Inbound", label: "Forwarded New Topic", non_interactive: true)
@tracker.event(category: "Agent: Unassigned", action: "Forwarded New", label: topic.to_param)
end
end
end

def cloudinary_enabled?
AppSettings['cloudinary.cloud_name'].present? && AppSettings['cloudinary.api_key'].present? && AppSettings['cloudinary.api_secret'].present?
end
# Adds a reply to an existing ticket thread from an email response.
def self.create_reply_from_email(email, email_address, email_name, subject, raw, message, token, to, sitename, cc, number_of_attachments)
@user = User.where("lower(email) = ?", email_address).first
if @user.nil?
@user = EmailProcessor.create_user_for_email(email_address, token, email_name)
end

def google_analytics_enabled?
AppSettings['settings.google_analytics_enabled'] == '1'
complete_subject = subject.split("[#{sitename}]")[1].strip
ticket_number = complete_subject.split("-")[0].split("#")[1].strip
topic = Topic.find(ticket_number)

if topic.present?
# insert post to new topic
message = "-" if message.blank? && number_of_attachments > 0
post = topic.posts.create(
body: message,
raw_email: raw,
user_id: @user.id,
kind: "reply",
cc: cc
)

# Push array of attachments and send to Cloudinary
EmailProcessor.handle_attachments(email, post)

if @tracker
@tracker.event(category: "Email", action: "Inbound", label: "Reply", non_interactive: true)
@tracker.event(category: "Agent: #{topic.assigned_user.name}", action: "User Replied by Email", label: topic.to_param) unless topic.assigned_user.nil?
end
end
end

def create_user
def self.create_user_for_email(email_address, token, name)
# create user
@user = User.new

@token, enc = Devise.token_generator.generate(User, :reset_password_token)
@user.reset_password_token = enc
@user.reset_password_sent_at = Time.now.utc

@user.email = @email.from[:email]
@user.name = @email.from[:name].blank? ? @email.from[:token].gsub(/[^a-zA-Z]/, '') : @email.from[:name]
@user.email = email_address
@user.name = name.blank? ? token.gsub(/[^a-zA-Z]/, '') : name
@user.password = User.create_password

if @user.save
UserMailer.new_user(@user.id, @token).deliver_later
UserMailer.new_user(@user.id, @token).deliver_later if @user.save
else
@user = User.find(2) # just in case new user not saved, default to system user
end

return @user
end

end
@@ -114,7 +114,7 @@ namespace :db do
doc = category.docs.create!(
title_tag: title,
title: title,
body: Faker::Lorem.paragraphs(rand(1..5)).join('<br/><br/>'),
body: paragraphs(rand(2..4)),
meta_description: Faker::Lorem.sentences(1),
user_id: User.team.sample.id
)
@@ -138,7 +138,7 @@ namespace :db do
doc_id: doc.id
)
post = topic.posts.create!(
body: Faker::Lorem.paragraphs(rand(1..2)).join('<br/><br/>'),
body: paragraphs(rand(2..4)),
user_id: topic.user_id,
kind: 'first'
)
@@ -149,7 +149,7 @@ namespace :db do
# create posts about this doc
rand(0..5).times do
post = topic.posts.create!(
body: Faker::Lorem.paragraphs(rand(1..2)).join('<br/><br/>'),
body: paragraphs(rand(2..4)),
user_id: User.customers.sample.id,
kind: 'reply'
)
@@ -186,7 +186,7 @@ namespace :db do

# create first post in thread
post = topic.posts.create!(
body: Faker::Lorem.paragraphs(rand(4..8)).join('<br/><br/>'),
body: paragraphs(rand(2..4)),
user_id: topic.user_id,
kind: 'first'
)
@@ -196,7 +196,7 @@ namespace :db do

rand(2..5).times do
post = topic.posts.create!(
body: Faker::Lorem.paragraphs(rand(1..3)).join('<br/><br/>'),
body: paragraphs(rand(2..4)),
user_id: User.customers.sample.id,
kind: 'reply'
)
@@ -222,21 +222,22 @@ namespace :db do
user_id: User.customers.sample.id,
private: true,
assigned_user_id: User.agents.sample.id,
team_list: ticket_issue.split("|")[1]
team_list: ticket_issue.split("|")[1],
kind: 'internal'
)

# create first post in thread
post = topic.posts.create!(
body: Faker::Lorem.paragraphs(rand(2..5)).join('<br/><br/>'),
body: paragraphs(3),
user_id: topic.user_id,
kind: 'first'
kind: ['first','first','note'].sample
)
puts "Post added to topic"

Timecop.scale(120000)
rand(0..5).times do |i|
post = topic.posts.new
post.body = Faker::Lorem.paragraphs(rand(2..5)).join('<br/><br/>')
post.body = paragraphs(rand(2..4))
post.kind = 'reply'
if i.even?
post.user_id = topic.assigned_user_id
@@ -264,6 +265,23 @@ namespace :db do
puts 'All done'
end

def paragraphs(number)
t = ""
number.times do
t += (paragraph + " <br/><br/>")
end
return t

end

def paragraph
p = ""
rand(3..5).times do
p += Faker::Lorem.sentence(rand(3..9)) + ". "
end
return p
end

def build_question(q="something")
[
"How do I use #{q}?",
@@ -137,6 +137,19 @@ class Admin::TopicsControllerTest < ActionController::TestCase
assert_response :success
end

test "an #{admin} should be able to unassign an agent" do
sign_in users(admin.to_sym)
topic = Topic.find(1)
topic.assigned_user_id = 1
topic.save!
assert_difference "Post.count", 1 do
xhr :get, :unassign_agent, { assigned_user_id: nil, topic_ids: [1] }
end
assert_response :success
topic.reload
assert_nil topic.assigned_user_id, "assigned user should be nil"
end

### tests of changing status

test "an #{admin} posting an internal note should not change status on its own" do
@@ -320,6 +333,13 @@ class Admin::TopicsControllerTest < ActionController::TestCase
end
end

test "an #{admin} should be able to create an internal ticket and create a new user" do
sign_in users(admin.to_sym)
assert_difference "User.count", 1 do
xhr :post, :create, topic: { user: { name: "Joe Smith", email: "joe.smith34@test.com" }, name: "some new private topic", post: { body: "this is the body", kind: 'first' }, forum_id: 1, current_status: 'new', kind: 'internal' }
end
end

### test assign_team and unassign_team

test "an #{admin} should be able to assign_team of a topic" do
@@ -251,7 +251,7 @@ def app
assert_equal 2, object['tag_list'].count
end

test "a non-registered API user should not be registered and should not create a ticket by email if provided name is invalid" do
test "creating a user by api with number in name should success and strip numbers" do
params = {
name: "Got a problem",
body: "This is some really profound question",
@@ -264,11 +264,11 @@ def app

post '/api/v1/tickets.json', @default_params.merge(params)

assert_nil User.find_by(email: params[:user_email])
assert_not_nil User.find_by(email: params[:user_email])

object = JSON.parse(last_response.body)
assert_equal 403, last_response.status
assert object['error'].include?('Ticket not created. User could not be registered')
assert_equal 'User Nt Rgistrd', object['user_name']
assert_equal 201, last_response.status
end

test "an API user should be able to assign a ticket" do
@@ -63,16 +63,16 @@ class CategoriesControllerTest < ActionController::TestCase

test "a browsing user should not be able to load the index if KB features are not enabled" do
AppSettings['settings.knowledgebase'] = "0"
assert_raises(ActionController::RoutingError) do
get :index, locale: :en
end
assert_response :redirect
assert_equal(response.redirect_url, root_url)
end

test "a browsing user should not be able to see a category page if KB features are not enabled" do
AppSettings['settings.knowledgebase'] = "0"
assert_raises(ActionController::RoutingError) do
get :show, id: 1, locale: :en
end
assert_response :redirect
assert_equal(response.redirect_url, root_url)
end

test "a browsing user should NOT be able to see the common replies category page" do
@@ -60,9 +60,8 @@ class DocsControllerTest < ActionController::TestCase

test "a browsing user should not be able to see a doc page if KB features are not enabled" do
AppSettings['settings.knowledgebase'] = "0"
assert_raises(ActionController::RoutingError) do
get :show, id: 1, locale: :en
end
get(:show, id: 1, locale: :en)
assert_response :redirect
assert_equal(response.redirect_url, root_url)
end

end
@@ -32,9 +32,8 @@ class ForumsControllerTest < ActionController::TestCase

test "a browsing user should not be able to see index of forums if forums are not enabled" do
AppSettings['settings.forums'] = "0"
assert_raises(ActionController::RoutingError) do
get :index, locale: :en
end
assert_response :redirect
assert_equal(response.redirect_url, root_url)
end

end
@@ -52,9 +52,9 @@ class PostsControllerTest < ActionController::TestCase

test "a browsing user should not get index of posts for a given topic, if forums are disabled" do
AppSettings['settings.forums'] = "0"
assert_raises(ActionController::RoutingError) do
get :index, topic_id: topics(:public).id, locale: :en
end
assert_response :redirect
assert_equal(response.redirect_url, root_url)
end

# logged in user
@@ -43,9 +43,9 @@ class TopicsControllerTest < ActionController::TestCase

test "a browsing user should not index of topics if forums are not enabled" do
AppSettings['settings.forums'] = "0"
assert_raises(ActionController::RoutingError) do
get :index, forum_id: 3, locale: :en
end
assert_response :redirect
assert_equal(response.redirect_url, root_url)
end

test 'a browsing user should not get index of topics in a private forum' do
@@ -373,9 +373,9 @@ class TopicsControllerTest < ActionController::TestCase
AppSettings['settings.forums'] = "0"

sign_in users(:user)
assert_raises(ActionController::RoutingError) do
get :new, locale: :en
end
assert_response :redirect
assert_equal(response.redirect_url, root_url)
end

end
@@ -1,4 +1,4 @@
FactoryGirl.define do
FactoryBot.define do
factory :api_key do
name { "MyApiKey" }

@@ -1,4 +1,4 @@
FactoryGirl.define do
FactoryBot.define do
factory :category do
name { "something in lowercase" }
end
@@ -1,4 +1,4 @@
FactoryGirl.define do
FactoryBot.define do
factory :doc do
title { "something in lowercase" }
body { 'test test test' }
@@ -1,58 +1,75 @@
FactoryGirl.define do
FactoryBot.define do

factory :email_from_unknown, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' })
subject 'email subject'
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' }) }
subject { 'email subject' }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :email_from_includes_numbers, class: OpenStruct do
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user1990', host: 'email.com', email: 'from_email1990@email.com', full: 'From1990 <from_user1990@email.com>', name: '' }) }
subject { 'email subject' }
header {}
body { 'Hello!' }
end

factory :email_forwarded, class: OpenStruct do
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: '' }) }
subject { 'Fwd: email subject' }
header {}
raw_body { '---------- Forwarded message ---------\nFrom: Happy Forwarder <happyfwd@test.com> \nDate: Wed, Nov 7, 2018 at 5:05 AM\nSubject: Re: Test forward\nTo: to_user\n\nThis is the body here!' }
body { '---------- Forwarded message ---------\nFrom: Happy Forwarder <happyfwd@test.com> \nDate: Wed, Nov 7, 2018 at 5:05 AM\nSubject: Re: Test forward\nTo: to_user\n\nThis is the body here!' }
end

factory :email_from_unknown_invalid_utf8, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' })
subject 'email subject'
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' }) }
subject { 'email subject' }
header {}
body "hi \xAD"
body { "hi \xAD" }
end

factory :email_from_unknown_name_missing, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'from_user@email.com', name: '' })
subject 'email subject'
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'from_user@email.com', name: '' }) }
subject { 'email subject' }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :email_from_known_token_numbers, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'from_user.me7731', host: 'email.com', email: 'from_user.me7731@email.com', full: 'from_user.me7731@email.com', name: '' })
subject 'email subject'
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user.me7731', host: 'email.com', email: 'from_user.me7731@email.com', full: 'from_user.me7731@email.com', name: '' }) }
subject { 'email subject' }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :email_to_multiple, class: OpenStruct do
to [{ full: 'to_user@email.com <to_user@email.com>, second_user <second_user@email.com>', email: 'to_user@email.com, second_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' })
subject 'email subject'
to { [{ full: 'to_user@email.com <to_user@email.com>, second_user <second_user@email.com>', email: 'to_user@email.com, second_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' }) }
subject { 'email subject' }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :email_to_quoted, class: OpenStruct do
to [{ full: '"to_user@email.com" <to_user@email.com>', email: '"to_user@email.com"', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: '"From User" <from_user@email.com>', name: 'From User' })
subject 'email subject'
to { [{ full: '"to_user@email.com" <to_user@email.com>', email: '"to_user@email.com"', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: '"From User" <from_user@email.com>', name: 'From User' }) }
subject { 'email subject' }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :email_from_unknown_with_attachments, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' })
subject 'email subject'
body 'Hello!'
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' }) }
subject { 'email subject' }
body { 'Hello!' }
attachments {[]}

trait :with_attachment do
@@ -91,52 +108,61 @@
end

factory :email_from_known, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' })
subject 'email subject'
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' }) }
subject { 'email subject' }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :reply, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' })
subject "Re: [Helpy Support] #1-Pending private topic"
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' }) }
subject { "Re: [Helpy Support] #1-Pending private topic" }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :email_with_cc, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' })
cc([{ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' }])
subject 'email subject'
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' }) }
cc { ([{ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' }]) }
subject { 'email subject' }
header {}
body { 'Hello!' }
end

factory :email_with_no_subject, class: OpenStruct do
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from { ({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' }) }
cc { ([{ token: 'from_user', host: 'email.com', email: 'from_email@email.com', full: 'From User <from_user@email.com>', name: 'From User' }]) }
subject {''}
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :reply_to_closed_ticket, class: OpenStruct do
to [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }]
from({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' })
subject "Re: [Helpy Support] #3-Closed private topic"
to { [{ full: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com', name: nil }] }
from{ ({ token: 'scott.miller', host: 'test.com', email: 'scott.miller@test.com', full: 'Scott Miller <scott.miller@test.com>', name: 'Scott Miller' }) }
subject { "Re: [Helpy Support] #3-Closed private topic" }
header {}
body 'Hello!'
body { 'Hello!' }
end

factory :acts_as_taggable_on_tag, class: ActsAsTaggableOn::Tag do
name "test_tag"
show_on_admin false
show_on_helpcenter false
show_on_dashboard false
name { "test_tag" }
show_on_admin { false }
show_on_helpcenter { false }
show_on_dashboard { false }
end

factory :admin, class: User do
name "admin"
admin true
role 'admin'
email 'admin@admin.com'
password 'password'
account_number '123456'
name { "admin" }
admin { true }
role { 'admin' }
email { 'admin@admin.com' }
password { 'password' }
account_number { '123456' }
end

end
@@ -1,4 +1,4 @@
FactoryGirl.define do
FactoryBot.define do
factory :forum do
name { "something in lowercase" }
description { 'test test test' }
@@ -1,4 +1,4 @@
FactoryGirl.define do
FactoryBot.define do
factory :post do
body { "this is a reply" }
kind { "first" }
@@ -1,4 +1,4 @@
FactoryGirl.define do
FactoryBot.define do
factory :topic do
sequence(:name) { |n| "something in lowercase #{n}" }
forum
@@ -1,4 +1,4 @@
FactoryGirl.define do
FactoryBot.define do
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
sequence(:password) { |n| "person@{n}" }
@@ -0,0 +1,25 @@
require 'integration_test_helper'

include Warden::Test::Helpers

class ClientSideValidationForGroupNewFormTest < ActionDispatch::IntegrationTest
def setup
Capybara.current_driver = :chrome
Warden.test_mode!
set_default_settings
sign_in('admin@test.com')
end

def teardown
Capybara.reset_sessions!
Warden.test_reset!
Capybara.use_default_driver
end

test 'browsing will throw a error if user input with nil value on new form group' do
visit '/admin/settings/groups/new'
fill_in('acts_as_taggable_on_tag[name]', with: '')
click_on 'Save Settings'
assert page.has_content?("can't be blank")
end
end
@@ -0,0 +1,35 @@
require 'integration_test_helper'

include Warden::Test::Helpers

class FeatureDisableTest < ActionDispatch::IntegrationTest
def setup
Warden.test_mode!
set_default_settings
sign_in('system@test.com')
end

def teardown
Capybara.reset_sessions!
Warden.test_reset!
end

test 'the page will redirect to root_path when the forums are disabled' do
AppSettings['settings.forums'] = "0"
visit '/en/community/'
assert_equal root_path, current_path
end

test 'the page will redirect to root_path when the knowledgebase is disabled' do
AppSettings['settings.knowledgebase'] = "0"
visit '/en/knowledgebase/'
assert_equal root_path, current_path
end

test 'the page will redirect to root_path when the tickets or forums are disabled' do
AppSettings['settings.tickets'] = "0"
AppSettings['settings.forums'] = '0'
visit '/en/topics/new'
assert_equal root_path, current_path
end
end
@@ -4,7 +4,7 @@ class ImportJobTest < ActiveSupport::TestCase

#user import
test "it should import all new records from valid csv" do
admin = FactoryGirl.create(:admin)
admin = FactoryBot.create(:admin)
files_detail = {}
file = File.join(Rails.root, 'test', 'fixtures', 'files', 'user_import.csv')
files_detail[:user] = {path: file, name: 'user_import.csv'}
@@ -14,7 +14,7 @@ class ImportJobTest < ActiveSupport::TestCase
end

test "it should save error_log for all unsaved records" do
admin = FactoryGirl.create(:admin)
admin = FactoryBot.create(:admin)
files_detail = {}
file = File.join(Rails.root, 'test', 'fixtures', 'files', 'user_import.csv')
files_detail[:user] = {path: file, name: 'user_import.csv'}
@@ -27,7 +27,7 @@ class ImportJobTest < ActiveSupport::TestCase
end

test "it should update record if record is already present." do
admin = FactoryGirl.create(:admin)
admin = FactoryBot.create(:admin)
user = User.find(8)

files_detail = {}
@@ -43,7 +43,7 @@ class ImportJobTest < ActiveSupport::TestCase

#Topic import
test "it should import topic record from csv" do
admin = FactoryGirl.create(:admin)
admin = FactoryBot.create(:admin)

files_detail = {}
file = File.join(Rails.root, 'test', 'fixtures', 'files', 'topics_import.csv')
@@ -58,7 +58,7 @@ class ImportJobTest < ActiveSupport::TestCase

#post import
test "it should import post record from csv" do
admin = FactoryGirl.create(:admin)
admin = FactoryBot.create(:admin)

files_detail = {}
file = File.join(Rails.root, 'test', 'fixtures', 'files', 'post_import.csv')
@@ -130,6 +130,33 @@ class EmailProcessorTest < ActiveSupport::TestCase
end
end

test 'an email with a blank subject should create topic and post' do
assert_difference('Topic.where(current_status: "new").count', 1) do
assert_difference('Post.count', 1) do
EmailProcessor.new(build(:email_with_no_subject)).process
end
end
assert_equal "(No Subject)", Topic.last.name
end

test 'an email with a from with numbers should create' do
assert_difference('Topic.where(current_status: "new").count', 1) do
assert_difference('Post.count', 1) do
EmailProcessor.new(build(:email_from_includes_numbers)).process
end
end
end

test 'a forwarded email should create' do
assert_difference('Topic.where(current_status: "new").count', 1) do
assert_difference('Post.count', 1) do
EmailProcessor.new(build(:email_forwarded)).process
end
end
assert_equal 'happyfwd@test.com', User.last.email
assert_equal 'happyfwd', User.last.name
end

test 'an email with cc should create post containing same cc' do
email = build(:email_with_cc)
EmailProcessor.new(email).process
@@ -117,15 +117,16 @@ class UserTest < ActiveSupport::TestCase

end

test "should not accept names with numbers" do
test "should remove numbers in the name" do
names = [
"Vasiya2",
"123123"
"123123Tim"
]

names.each do |name|
user = build :user, name: name
assert_equal user.valid?, false
assert_equal user.valid?, true
assert_not_equal names, user.name
end
end

@@ -330,7 +331,7 @@ class UserTest < ActiveSupport::TestCase
assert_nil u.thumbnail
assert_nil u.medium_image
assert_nil u.large_image
assert_equal FALSE, u.active
assert_equal false, u.active
assert_equal "change", u.email.split('@')[0]
assert_nil u.current_sign_in_ip
assert_nil u.last_sign_in_ip
@@ -340,4 +341,22 @@ class UserTest < ActiveSupport::TestCase

end

test "can be edited should be true if the current user is an admin and the user is admin" do
current_user = User.find(1)
user = User.find(5)
assert_equal true, user.can_be_edited?(current_user)
end

test "can be edited should be false if the current user is an agent and the user is admin" do
current_user = User.find(6)
user = User.find(1)
assert_equal false, user.can_be_edited?(current_user)
end

test "can be edited should be true if the current user is an agent and the user is user" do
current_user = User.find(6)
user = User.find(2)
assert_equal true, user.can_be_edited?(current_user)
end

end
@@ -14,14 +14,19 @@
require 'pry'

class ActiveSupport::TestCase
include FactoryGirl::Syntax::Methods
include FactoryBot::Syntax::Methods
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all

# Add more helper methods to be used by all tests here...
# Settings.send_email = false
end

Capybara.register_driver :chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new(args: %w[no-sandbox headless disable-gpu --disable-dev-shm-usage])
Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

class ActionController::TestCase
include Devise::TestHelpers
end