Fixes #1589 - No localised time displayed in trigger (autoreply/slack/...) notifications.
This commit is contained in:
parent
487f36a5a5
commit
63214c9327
22 changed files with 696 additions and 217 deletions
|
@ -0,0 +1,35 @@
|
|||
class App.SettingsAreaItemDefaultTimezone extends App.SettingsAreaItem
|
||||
result: {}
|
||||
|
||||
render: =>
|
||||
@fetchTimezones()
|
||||
|
||||
localRender: (data) =>
|
||||
options = {}
|
||||
for timezone, offset of data.timezones
|
||||
if !offset.toString().match(/(\+|\-)/)
|
||||
offset = "+#{offset}"
|
||||
options[timezone] = "#{timezone} (GMT#{offset})"
|
||||
configure_attributes = [
|
||||
{ name: 'timezone_default', display: '', tag: 'searchable_select', null: false, class: 'input', options: options, default: @setting.state_current.value },
|
||||
]
|
||||
|
||||
@html App.view(@template)(
|
||||
setting: @setting
|
||||
)
|
||||
|
||||
new App.ControllerForm(
|
||||
el: @el.find('.form-item')
|
||||
model: { configure_attributes: configure_attributes, className: '' }
|
||||
autofocus: false
|
||||
)
|
||||
|
||||
fetchTimezones: =>
|
||||
@ajax(
|
||||
id: 'calendar_timezones'
|
||||
type: 'GET'
|
||||
url: "#{@apiPath}/calendars/timezones"
|
||||
success: (data) =>
|
||||
@result = data
|
||||
@localRender(data)
|
||||
)
|
|
@ -340,6 +340,7 @@ class Base extends App.WizardFullScreen
|
|||
@params = @formParam(e.target)
|
||||
@params.logo = @logoPreview.attr('src')
|
||||
@params.locale_default = App.i18n.detectBrowserLocale()
|
||||
@params.timezone_default = App.i18n.detectBrowserTimezone()
|
||||
|
||||
store = (logoResizeDataUrl) =>
|
||||
@params.logo_resize = logoResizeDataUrl
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
class DefaultTimezone extends App.Controller
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
check = =>
|
||||
timezone = App.i18n.detectBrowserTimezone()
|
||||
return if !timezone
|
||||
|
||||
# check system timezone_default
|
||||
if _.isEmpty(@Config('timezone_default')) && @permissionCheck('admin.system')
|
||||
App.Setting.fetchFull(
|
||||
=> @updateSetting(timezone)
|
||||
force: false
|
||||
)
|
||||
|
||||
# prepare user based timezone
|
||||
# check current user timezone
|
||||
#preferences = App.Session.get('preferences')
|
||||
#return if !preferences
|
||||
#return if !_.isEmpty(preferences.timezone)
|
||||
#@ajax(
|
||||
# id: "i18n-set-user-timezone"
|
||||
# type: 'PUT'
|
||||
# url: "#{App.Config.get('api_path')}/users/preferences"
|
||||
# data: JSON.stringify(timezone: timezone)
|
||||
# processData: true
|
||||
#)
|
||||
|
||||
App.Event.bind('auth:login', (session) =>
|
||||
@delay(check, 8500, 'default_timezone')
|
||||
)
|
||||
|
||||
updateSetting: (timezone) ->
|
||||
App.Setting.set('timezone_default', timezone)
|
||||
|
||||
App.Config.set('default_timezone', DefaultTimezone, 'Widgets')
|
|
@ -103,6 +103,17 @@ class App.i18n
|
|||
|
||||
window.navigator.userLanguage || window.navigator.language || 'en-us'
|
||||
|
||||
@detectBrowserTimezone: ->
|
||||
return if !window.Intl
|
||||
return if !window.Intl.DateTimeFormat
|
||||
DateTimeFormat = Intl.DateTimeFormat()
|
||||
return if !DateTimeFormat
|
||||
return if !DateTimeFormat.resolvedOptions
|
||||
resolvedOptions = DateTimeFormat.resolvedOptions()
|
||||
return if !resolvedOptions
|
||||
return if !resolvedOptions.timeZone
|
||||
resolvedOptions.timeZone
|
||||
|
||||
class _i18nSingleton extends Spine.Module
|
||||
@include App.LogInclude
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class CalendarsController < ApplicationController
|
||||
prepend_before_action { authentication_check(permission: 'admin.calendar') }
|
||||
prepend_before_action -> { authentication_check(permission: 'admin.calendar') }, only: %i[init index show create update destroy]
|
||||
prepend_before_action -> { authentication_check(permission: 'admin') }, only: %i[timezones]
|
||||
|
||||
def init
|
||||
assets = {}
|
||||
|
@ -41,4 +42,10 @@ class CalendarsController < ApplicationController
|
|||
model_destroy_render(Calendar, params)
|
||||
end
|
||||
|
||||
def timezones
|
||||
render json: {
|
||||
timezones: Calendar.timezones
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -148,6 +148,11 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
|||
settings[:locale_default] = params[:locale_default]
|
||||
end
|
||||
|
||||
# add timezone_default
|
||||
if params[:timezone_default].present?
|
||||
settings[:timezone_default] = params[:timezone_default]
|
||||
end
|
||||
|
||||
if messages.present?
|
||||
render json: {
|
||||
result: 'invalid',
|
||||
|
|
|
@ -1543,10 +1543,13 @@ result
|
|||
end
|
||||
|
||||
objects = build_notification_template_objects(article)
|
||||
body = NotificationFactory::Renderer.new(objects, 'en-en', value['body'], false)
|
||||
.render
|
||||
.html2text
|
||||
.tr(' ', ' ') # convert non-breaking space to simple space
|
||||
body = NotificationFactory::Renderer.new(
|
||||
objects: objects,
|
||||
locale: 'en-en',
|
||||
timezone: Setting.get('timezone_default'),
|
||||
template: value['body'],
|
||||
escape: false
|
||||
).render.html2text.tr(' ', ' ') # convert non-breaking space to simple space
|
||||
|
||||
# attributes content_type is not needed for SMS
|
||||
article = Ticket::Article.create(
|
||||
|
|
|
@ -242,7 +242,7 @@ class Transaction::Notification
|
|||
|
||||
# only show allowed attributes
|
||||
attribute_list = ObjectManager::Attribute.by_object_as_hash('Ticket', user)
|
||||
#puts "AL #{attribute_list.inspect}"
|
||||
|
||||
user_related_changes = {}
|
||||
@item[:changes].each do |key, value|
|
||||
|
||||
|
|
|
@ -84,7 +84,8 @@ class Transaction::Slack
|
|||
|
||||
result = NotificationFactory::Slack.template(
|
||||
template: template,
|
||||
locale: user[:preferences][:locale],
|
||||
locale: user[:preferences][:locale] || Setting.get('locale_default'),
|
||||
timezone: user[:preferences][:timezone] || Setting.get('timezone_default'),
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
article: article,
|
||||
|
|
|
@ -215,6 +215,90 @@ translate strings in ruby context, e. g. for notifications
|
|||
|
||||
=begin
|
||||
|
||||
translate timestampes in ruby context, e. g. for notifications
|
||||
|
||||
translated = Translation.timestamp('de-de', 'Europe/Berlin', '2018-10-10T10:00:00Z0')
|
||||
|
||||
or
|
||||
|
||||
translated = Translation.timestamp('de-de', 'Europe/Berlin', Time.zone.parse('2018-10-10T10:00:00Z0'))
|
||||
|
||||
=end
|
||||
|
||||
def self.timestamp(locale, timezone, timestamp)
|
||||
|
||||
if timestamp.class == String
|
||||
begin
|
||||
timestamp_parsed = Time.zone.parse(timestamp)
|
||||
return timestamp.to_s if !timestamp_parsed
|
||||
|
||||
timestamp = timestamp_parsed
|
||||
rescue
|
||||
return timestamp.to_s
|
||||
end
|
||||
end
|
||||
|
||||
record = Translation.where(locale: locale, source: 'timestamp', format: 'time').pluck(:target).first
|
||||
return timestamp.to_s if !record
|
||||
|
||||
begin
|
||||
timestamp = timestamp.in_time_zone(timezone)
|
||||
rescue
|
||||
return timestamp.to_s
|
||||
end
|
||||
record.sub!('dd', format('%02d', timestamp.day))
|
||||
record.sub!('d', timestamp.day.to_s)
|
||||
record.sub!('mm', format('%02d', timestamp.month))
|
||||
record.sub!('m', timestamp.month.to_s)
|
||||
record.sub!('yyyy', timestamp.year.to_s)
|
||||
record.sub!('yy', timestamp.year.to_s.last(2))
|
||||
record.sub!('SS', format('%02d', timestamp.sec.to_s))
|
||||
record.sub!('MM', format('%02d', timestamp.min.to_s))
|
||||
record.sub!('HH', format('%02d', timestamp.hour.to_s))
|
||||
"#{record} (#{timezone})"
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
translate date in ruby context, e. g. for notifications
|
||||
|
||||
translated = Translation.date('de-de', '2018-10-10')
|
||||
|
||||
or
|
||||
|
||||
translated = Translation.date('de-de', Date.parse('2018-10-10'))
|
||||
|
||||
=end
|
||||
|
||||
def self.date(locale, date)
|
||||
|
||||
if date.class == String
|
||||
begin
|
||||
date_parsed = Date.parse(date)
|
||||
return date.to_s if !date_parsed
|
||||
|
||||
date = date_parsed
|
||||
rescue
|
||||
return date.to_s
|
||||
end
|
||||
end
|
||||
|
||||
return date.to_s if date.class != Date
|
||||
|
||||
record = Translation.where(locale: locale, source: 'date', format: 'time').pluck(:target).first
|
||||
return date.to_s if !record
|
||||
|
||||
record.sub!('dd', format('%02d', date.day))
|
||||
record.sub!('d', date.day.to_s)
|
||||
record.sub!('mm', format('%02d', date.month))
|
||||
record.sub!('m', date.month.to_s)
|
||||
record.sub!('yyyy', date.year.to_s)
|
||||
record.sub!('yy', date.year.to_s.last(2))
|
||||
record
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
load translations from local
|
||||
|
||||
all:
|
||||
|
|
|
@ -2,11 +2,12 @@ Zammad::Application.routes.draw do
|
|||
api_path = Rails.configuration.api_path
|
||||
|
||||
# calendars
|
||||
match api_path + '/calendars_init', to: 'calendars#init', via: :get
|
||||
match api_path + '/calendars', to: 'calendars#index', via: :get
|
||||
match api_path + '/calendars/:id', to: 'calendars#show', via: :get
|
||||
match api_path + '/calendars', to: 'calendars#create', via: :post
|
||||
match api_path + '/calendars/:id', to: 'calendars#update', via: :put
|
||||
match api_path + '/calendars/:id', to: 'calendars#destroy', via: :delete
|
||||
match api_path + '/calendars_init', to: 'calendars#init', via: :get
|
||||
match api_path + '/calendars/timezones', to: 'calendars#timezones', via: :get
|
||||
match api_path + '/calendars', to: 'calendars#index', via: :get
|
||||
match api_path + '/calendars/:id', to: 'calendars#show', via: :get
|
||||
match api_path + '/calendars', to: 'calendars#create', via: :post
|
||||
match api_path + '/calendars/:id', to: 'calendars#update', via: :put
|
||||
match api_path + '/calendars/:id', to: 'calendars#destroy', via: :delete
|
||||
|
||||
end
|
||||
|
|
27
db/migrate/20190208000001_setting_timezone_default.rb
Normal file
27
db/migrate/20190208000001_setting_timezone_default.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
class SettingTimezoneDefault < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
# return if it's a new setup
|
||||
return if !Setting.find_by(name: 'system_init_done')
|
||||
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Timezone',
|
||||
name: 'timezone_default',
|
||||
area: 'System::Branding',
|
||||
description: 'Defines the system default timezone.',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
name: 'timezone_default',
|
||||
}
|
||||
],
|
||||
},
|
||||
state: '',
|
||||
preferences: {
|
||||
prio: 9,
|
||||
controller: 'SettingsAreaItemDefaultTimezone',
|
||||
permission: ['admin.system'],
|
||||
},
|
||||
frontend: true
|
||||
)
|
||||
end
|
||||
end
|
|
@ -176,6 +176,26 @@ Setting.create_if_not_exists(
|
|||
},
|
||||
frontend: true
|
||||
)
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Timezone',
|
||||
name: 'timezone_default',
|
||||
area: 'System::Branding',
|
||||
description: 'Defines the system default timezone.',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
name: 'timezone_default',
|
||||
}
|
||||
],
|
||||
},
|
||||
state: '',
|
||||
preferences: {
|
||||
prio: 9,
|
||||
controller: 'SettingsAreaItemDefaultTimezone',
|
||||
permission: ['admin.system'],
|
||||
},
|
||||
frontend: true
|
||||
)
|
||||
Setting.create_or_update(
|
||||
title: 'Pretty Date',
|
||||
name: 'pretty_date_format',
|
||||
|
|
|
@ -228,6 +228,7 @@ retunes
|
|||
result = NotificationFactory::Mailer.template(
|
||||
template: 'password_reset',
|
||||
locale: 'en-us',
|
||||
timezone: 'America/Santiago',
|
||||
objects: {
|
||||
recipient: User.find(2),
|
||||
},
|
||||
|
@ -236,6 +237,7 @@ retunes
|
|||
result = NotificationFactory::Mailer.template(
|
||||
templateInline: "Invitation to \#{config.product_name} at \#{config.fqdn}",
|
||||
locale: 'en-us',
|
||||
timezone: 'America/Santiago',
|
||||
objects: {
|
||||
recipient: User.find(2),
|
||||
},
|
||||
|
@ -247,6 +249,7 @@ only raw subject/body
|
|||
result = NotificationFactory::Mailer.template(
|
||||
template: 'password_reset',
|
||||
locale: 'en-us',
|
||||
timezone: 'America/Santiago',
|
||||
objects: {
|
||||
recipient: User.find(2),
|
||||
},
|
||||
|
@ -266,7 +269,13 @@ returns
|
|||
def self.template(data)
|
||||
|
||||
if data[:templateInline]
|
||||
return NotificationFactory::Renderer.new(data[:objects], data[:locale], data[:templateInline], data[:quote]).render
|
||||
return NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: data[:templateInline],
|
||||
escape: data[:quote]
|
||||
).render
|
||||
end
|
||||
|
||||
template = NotificationFactory.template_read(
|
||||
|
@ -276,8 +285,19 @@ returns
|
|||
type: 'mailer',
|
||||
)
|
||||
|
||||
message_subject = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:subject], false).render
|
||||
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:body]).render
|
||||
message_subject = NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: template[:subject],
|
||||
escape: false
|
||||
).render
|
||||
message_body = NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: template[:body]
|
||||
).render
|
||||
|
||||
if !data[:raw]
|
||||
application_template = NotificationFactory.application_template_read(
|
||||
|
@ -286,7 +306,12 @@ returns
|
|||
)
|
||||
data[:objects][:message] = message_body
|
||||
data[:objects][:standalone] = data[:standalone]
|
||||
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], application_template).render
|
||||
message_body = NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: application_template
|
||||
).render
|
||||
end
|
||||
{
|
||||
subject: message_subject,
|
||||
|
|
|
@ -5,27 +5,30 @@ class NotificationFactory::Renderer
|
|||
examples how to use
|
||||
|
||||
message_subject = NotificationFactory::Renderer.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: Ticket.first,
|
||||
},
|
||||
'de-de',
|
||||
'some template <b>#{ticket.title}</b> {config.fqdn}',
|
||||
false
|
||||
locale: 'de-de',
|
||||
timezone: 'America/Port-au-Prince',
|
||||
template: 'some template <b>#{ticket.title}</b> {config.fqdn}',
|
||||
escape: false
|
||||
).render
|
||||
|
||||
message_body = NotificationFactory::Renderer.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: Ticket.first,
|
||||
},
|
||||
'de-de',
|
||||
'some template <b>#{ticket.title}</b> #{config.fqdn}',
|
||||
locale: 'de-de',
|
||||
timezone: 'America/Port-au-Prince',
|
||||
template: 'some template <b>#{ticket.title}</b> #{config.fqdn}',
|
||||
).render
|
||||
|
||||
=end
|
||||
|
||||
def initialize(objects, locale, template, escape = true)
|
||||
def initialize(objects:, locale: nil, timezone: nil, template:, escape: true)
|
||||
@objects = objects
|
||||
@locale = locale || Setting.get('locale_default') || 'en-us'
|
||||
@timezone = timezone || Setting.get('timezone_default')
|
||||
@template = NotificationFactory::Template.new(template, escape)
|
||||
@escape = escape
|
||||
end
|
||||
|
@ -141,7 +144,8 @@ examples how to use
|
|||
else
|
||||
value
|
||||
end
|
||||
escaping(placeholder, escape)
|
||||
|
||||
escaping(convert_to_timezone(placeholder), escape)
|
||||
end
|
||||
|
||||
# c - config
|
||||
|
@ -159,15 +163,22 @@ examples how to use
|
|||
end
|
||||
|
||||
# h - htmlEscape
|
||||
# h('fqdn', htmlEscape)
|
||||
def h(key)
|
||||
return key if !key
|
||||
# h(htmlEscape)
|
||||
def h(value)
|
||||
return value if !value
|
||||
|
||||
CGI.escapeHTML(key.to_s)
|
||||
CGI.escapeHTML(convert_to_timezone(value).to_s)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def convert_to_timezone(value)
|
||||
return Translation.timestamp(@locale, @timezone, value) if value.class == ActiveSupport::TimeWithZone
|
||||
return Translation.date(@locale, value) if value.class == Date
|
||||
|
||||
value
|
||||
end
|
||||
|
||||
def escaping(key, escape)
|
||||
return key if escape == false
|
||||
return key if escape.nil? && !@escape
|
||||
|
|
|
@ -5,6 +5,7 @@ class NotificationFactory::Slack
|
|||
result = NotificationFactory::Slack.template(
|
||||
template: 'ticket_update',
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
objects: {
|
||||
recipient: User.find(2),
|
||||
ticket: Ticket.find(1)
|
||||
|
@ -23,7 +24,12 @@ returns
|
|||
def self.template(data)
|
||||
|
||||
if data[:templateInline]
|
||||
return NotificationFactory::Renderer.new(data[:objects], data[:locale], data[:templateInline]).render
|
||||
return NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: data[:templateInline]
|
||||
).render
|
||||
end
|
||||
|
||||
template = NotificationFactory.template_read(
|
||||
|
@ -33,8 +39,20 @@ returns
|
|||
type: 'slack',
|
||||
)
|
||||
|
||||
message_subject = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:subject], false).render
|
||||
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:body], false).render
|
||||
message_subject = NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: template[:subject],
|
||||
escape: false
|
||||
).render
|
||||
message_body = NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: template[:body],
|
||||
escape: false
|
||||
).render
|
||||
|
||||
if !data[:raw]
|
||||
application_template = NotificationFactory.application_template_read(
|
||||
|
@ -43,7 +61,13 @@ returns
|
|||
)
|
||||
data[:objects][:message] = message_body
|
||||
data[:objects][:standalone] = data[:standalone]
|
||||
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], application_template, false).render
|
||||
message_body = NotificationFactory::Renderer.new(
|
||||
objects: data[:objects],
|
||||
locale: data[:locale],
|
||||
timezone: data[:timezone],
|
||||
template: application_template,
|
||||
escape: false
|
||||
).render
|
||||
end
|
||||
{
|
||||
subject: message_subject.strip!,
|
||||
|
|
|
@ -5,6 +5,6 @@ FactoryBot.define do
|
|||
template ''
|
||||
escape true
|
||||
|
||||
initialize_with { new(objects, locale, template, escape) }
|
||||
initialize_with { new(objects: objects, locale: locale, template: template, escape: escape) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe Translation do
|
|||
Translation.sync('de-de')
|
||||
end
|
||||
|
||||
context 'default translations' do
|
||||
context 'default string translations' do
|
||||
|
||||
it 'en with existing word' do
|
||||
expect(Translation.translate('en', 'New')).to eq('New')
|
||||
|
@ -31,6 +31,82 @@ RSpec.describe Translation do
|
|||
|
||||
end
|
||||
|
||||
context 'default timestamp translations' do
|
||||
|
||||
it 'de-de with array' do
|
||||
expect(Translation.timestamp('de-de', 'Europe/Berlin', ['some value'])).to eq('["some value"]')
|
||||
end
|
||||
|
||||
it 'not_existing with timestamp as string' do
|
||||
expect(Translation.timestamp('not_existing', 'Europe/Berlin', '2018-10-10T10:00:00Z0')).to eq('2018-10-10 10:00:00 UTC')
|
||||
end
|
||||
|
||||
it 'not_existing with time object' do
|
||||
expect(Translation.timestamp('not_existing', 'Europe/Berlin', Time.zone.parse('2018-10-10T10:00:00Z0'))).to eq('2018-10-10 10:00:00 UTC')
|
||||
end
|
||||
|
||||
it 'not_existing with invalid timestamp string' do
|
||||
expect(Translation.timestamp('not_existing', 'Europe/Berlin', 'something')).to eq('something')
|
||||
end
|
||||
|
||||
it 'en-us with invalid time zone' do
|
||||
expect(Translation.timestamp('en-us', 'Europe/Berlin', '2018-10-10T10:00:00Z0')).to eq('10/10/2018 12:00 (Europe/Berlin)')
|
||||
end
|
||||
|
||||
it 'en-us with timestamp as string' do
|
||||
expect(Translation.timestamp('en-us', 'Europe/Berlin', '2018-10-10T10:00:00Z0')).to eq('10/10/2018 12:00 (Europe/Berlin)')
|
||||
end
|
||||
|
||||
it 'en-us with time object' do
|
||||
expect(Translation.timestamp('en-us', 'Europe/Berlin', Time.zone.parse('2018-10-10T10:00:00Z0'))).to eq('10/10/2018 12:00 (Europe/Berlin)')
|
||||
end
|
||||
|
||||
it 'de-de with timestamp as string' do
|
||||
expect(Translation.timestamp('de-de', 'Europe/Berlin', '2018-10-10T10:00:00Z0')).to eq('10.10.2018 12:00 (Europe/Berlin)')
|
||||
end
|
||||
|
||||
it 'de-de with time object' do
|
||||
expect(Translation.timestamp('de-de', 'Europe/Berlin', Time.zone.parse('2018-10-10T10:00:00Z0'))).to eq('10.10.2018 12:00 (Europe/Berlin)')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'default date translations' do
|
||||
|
||||
it 'de-de with array' do
|
||||
expect(Translation.date('de-de', ['some value'])).to eq('["some value"]')
|
||||
end
|
||||
|
||||
it 'not_existing with date as string' do
|
||||
expect(Translation.date('not_existing', '2018-10-10')).to eq('2018-10-10')
|
||||
end
|
||||
|
||||
it 'not_existing with date object' do
|
||||
expect(Translation.date('not_existing', Date.parse('2018-10-10'))).to eq('2018-10-10')
|
||||
end
|
||||
|
||||
it 'not_existing with invalid data as string' do
|
||||
expect(Translation.date('not_existing', 'something')).to eq('something')
|
||||
end
|
||||
|
||||
it 'en-us with date as string' do
|
||||
expect(Translation.date('en-us', '2018-10-10')).to eq('10/10/2018')
|
||||
end
|
||||
|
||||
it 'en-us with date object' do
|
||||
expect(Translation.date('en-us', Date.parse('2018-10-10'))).to eq('10/10/2018')
|
||||
end
|
||||
|
||||
it 'de-de with date as string' do
|
||||
expect(Translation.date('de-de', '2018-10-10')).to eq('10.10.2018')
|
||||
end
|
||||
|
||||
it 'de-de with date object' do
|
||||
expect(Translation.date('de-de', Date.parse('2018-10-10'))).to eq('10.10.2018')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'remote_translation_need_update? tests' do
|
||||
|
||||
it 'translation is still the same' do
|
||||
|
|
|
@ -20,6 +20,12 @@ RSpec.describe 'Calendars', type: :request do
|
|||
|
||||
expect(json_response).to be_a_kind_of(Hash)
|
||||
expect(json_response['error']).to eq('authentication failed')
|
||||
|
||||
get '/api/v1/calendars/timezones', as: :json
|
||||
expect(response).to have_http_status(401)
|
||||
|
||||
expect(json_response).to be_a_kind_of(Hash)
|
||||
expect(json_response['error']).to eq('authentication failed')
|
||||
end
|
||||
|
||||
it 'does calendar index with admin' do
|
||||
|
@ -58,6 +64,13 @@ RSpec.describe 'Calendars', type: :request do
|
|||
expect(json_response['timezones']['America/Sitka']).to be_between(-9, -8)
|
||||
expect(json_response['timezones']['Europe/Berlin']).to be_between(1, 2)
|
||||
expect(json_response['assets']).to be_truthy
|
||||
|
||||
# timezones
|
||||
get '/api/v1/calendars/timezones', as: :json
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response).to be_a_kind_of(Hash)
|
||||
expect(json_response['timezones']).to be_a_kind_of(Hash)
|
||||
expect(json_response['timezones']['America/New_York']).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -39,149 +39,164 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
|
||||
template = "\#{ticket.title}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML(ticket.title), result)
|
||||
|
||||
template = "\#{ticket.created_at}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(ticket.created_at.to_s, result)
|
||||
assert_equal('11/12/2016 13:00 (Europe/Berlin)', result)
|
||||
|
||||
template = "\#{ticket.created_by.firstname}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('CurrentUser<b>xxx</b>', result)
|
||||
|
||||
template = "\#{ticket.updated_at}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(ticket.updated_at.to_s, result)
|
||||
assert_equal('11/12/2016 15:00 (Europe/Berlin)', result)
|
||||
|
||||
template = "\#{ticket.updated_by.firstname}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('CurrentUser<b>xxx</b>', result)
|
||||
|
||||
template = "\#{ticket.owner.firstname}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('Owner<b>xxx</b>', result)
|
||||
|
||||
template = "\#{ticket. title}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML(ticket.title), result)
|
||||
|
||||
template = "\#{ticket.\n title}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML(ticket.title), result)
|
||||
|
||||
template = "\#{ticket.\t title}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML(ticket.title), result)
|
||||
|
||||
template = "\#{ticket.\t\n title\t}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML(ticket.title), result)
|
||||
|
||||
template = "\#{ticket.\" title\t}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML(ticket.title), result)
|
||||
|
||||
template = "\#{<a href=\"/test123\">ticket.\" title</a>}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML(ticket.title), result)
|
||||
|
||||
template = "some test<br>\#{article.body}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
article: article_html1,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('some test<br>> test hello<br>> some new line<br>', result)
|
||||
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
article: article_plain1,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('some test<br>> test <b>hello</b><br>> some new line<br>', result)
|
||||
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
article: article_plain2,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('some test<br>> test <b>hello</b><br>> some new line<br>', result)
|
||||
|
||||
|
@ -192,11 +207,12 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
setting = 'fqdn'
|
||||
template = "\#{config.#{setting}}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(Setting.get(setting), result)
|
||||
|
||||
|
@ -204,11 +220,12 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
setting2 = 'product_name'
|
||||
template = "some \#{config.#{setting1}} and \#{config.#{setting2}}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal("some #{Setting.get(setting1)} and #{Setting.get(setting2)}", result)
|
||||
|
||||
|
@ -216,11 +233,12 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
setting2 = 'product_name'
|
||||
template = "some \#{ config.#{setting1}} and \#{\tconfig.#{setting2}}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal("some #{Setting.get(setting1)} and #{Setting.get(setting2)}", result)
|
||||
end
|
||||
|
@ -230,41 +248,45 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
#template = "<%= t 'new' %>"
|
||||
template = "\#{t('new')}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'de-de',
|
||||
template,
|
||||
locale: 'de-de',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('neu', result)
|
||||
|
||||
template = "some text \#{t('new')} and \#{t('open')}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'de-de',
|
||||
template,
|
||||
locale: 'de-de',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('some text neu and offen', result)
|
||||
|
||||
template = "some text \#{t('new') } and \#{ t('open')}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'de-de',
|
||||
template,
|
||||
locale: 'de-de',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('some text neu and offen', result)
|
||||
|
||||
template = "some text \#{\nt('new') } and \#{ t('open')\t}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'de-de',
|
||||
template,
|
||||
locale: 'de-de',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal('some text neu and offen', result)
|
||||
|
||||
|
@ -275,11 +297,12 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
template = "\#{t(ticket.state.name)}"
|
||||
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'de-de',
|
||||
template,
|
||||
locale: 'de-de',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
|
||||
assert_equal('neu', result)
|
||||
|
@ -289,111 +312,122 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
|
||||
template = "\#{}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{no such object}'), result)
|
||||
|
||||
template = "\#{notexsiting.notexsiting}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
|
||||
|
||||
template = "\#{ticket.notexsiting}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.notexsiting / no such method}'), result)
|
||||
|
||||
template = "\#{ticket.}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket. / no such method}'), result)
|
||||
|
||||
template = "\#{ticket.title.notexsiting}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.title.notexsiting / no such method}'), result)
|
||||
|
||||
template = "\#{ticket.notexsiting.notexsiting}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.notexsiting / no such method}'), result)
|
||||
|
||||
template = "\#{notexsiting}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
|
||||
|
||||
template = "\#{notexsiting.}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
|
||||
|
||||
template = "\#{string}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
string: 'some string',
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('some string'), result)
|
||||
|
||||
template = "\#{fixum}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
fixum: 123,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('123'), result)
|
||||
|
||||
template = "\#{float}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
float: 123.99,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('123.99'), result)
|
||||
|
||||
|
@ -403,181 +437,199 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
|
||||
template = "\#{ticket.title `echo 1`}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.title`echo1` / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.destroy}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.destroy / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.save}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.save / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.update}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.update / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.create}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.create / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.delete}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.delete / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.remove}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.remove / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.drop}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.drop / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.create}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.create / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.new}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.new / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.update_att}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.update_att / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.all}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.all / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.find}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.find / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.where}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.where / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket. destroy}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('#{ticket.destroy / not allowed}'), result)
|
||||
|
||||
template = "\#{ticket.\n destroy}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
|
||||
|
||||
template = "\#{ticket.\t destroy}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
|
||||
|
||||
template = "\#{ticket.\r destroy}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
|
||||
|
||||
|
@ -587,51 +639,56 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
|
|||
|
||||
template = "\#{ticket.title.first(3)}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('<b>'), result)
|
||||
|
||||
template = "\#{ticket.title.last(4)}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML('</b>'), result)
|
||||
|
||||
template = "\#{ticket.title.slice(3, 4)}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal(CGI.escapeHTML("\#{ticket.title.slice(3,4) / invalid parameter: 3,4}"), result)
|
||||
|
||||
template = "\#{ticket.title.first('some invalid parameter')}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal("\#{ticket.title.first(someinvalidparameter) / invalid parameter: someinvalidparameter}", result)
|
||||
|
||||
template = "\#{ticket.title.chomp(`cat /etc/passwd`)}"
|
||||
result = described_class.new(
|
||||
{
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
},
|
||||
'en-us',
|
||||
template,
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
template: template,
|
||||
).render
|
||||
assert_equal("\#{ticket.title.chomp(`cat/etc/passwd`) / not allowed}", result)
|
||||
end
|
||||
|
|
|
@ -66,7 +66,8 @@ class NotificationFactorySlackTemplateTest < ActiveSupport::TestCase
|
|||
changes = {}
|
||||
result = NotificationFactory::Slack.template(
|
||||
template: 'ticket_create',
|
||||
locale: 'es-us',
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
article: article,
|
||||
|
@ -97,12 +98,14 @@ class NotificationFactorySlackTemplateTest < ActiveSupport::TestCase
|
|||
created_by_id: 1,
|
||||
)
|
||||
changes = {
|
||||
state: %w[aaa bbb],
|
||||
group: %w[xxx yyy],
|
||||
state: %w[aaa bbb],
|
||||
group: %w[xxx yyy],
|
||||
pending_time: [Time.zone.parse('2019-04-01T10:00:00Z0'), Time.zone.parse('2019-04-01T23:00:00Z0')],
|
||||
}
|
||||
result = NotificationFactory::Slack.template(
|
||||
template: 'ticket_update',
|
||||
locale: 'es-us',
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
article: article,
|
||||
|
@ -111,14 +114,31 @@ class NotificationFactorySlackTemplateTest < ActiveSupport::TestCase
|
|||
changes: changes,
|
||||
},
|
||||
)
|
||||
|
||||
assert_match('# Welcome to Zammad!', result[:subject])
|
||||
assert_match('User<b>xxx</b>', result[:body])
|
||||
assert_match('state: aaa -> bbb', result[:body])
|
||||
assert_match('group: xxx -> yyy', result[:body])
|
||||
assert_match('pending_time: 04/01/2019 12:00 (Europe/Berlin) -> 04/02/2019 01:00 (Europe/Berlin)', result[:body])
|
||||
assert_no_match('Dein', result[:body])
|
||||
assert_no_match('longname', result[:body])
|
||||
assert_match('Current User', result[:body])
|
||||
|
||||
# en notification
|
||||
ticket.escalation_at = Time.zone.parse('2019-04-01T10:00:00Z')
|
||||
result = NotificationFactory::Slack.template(
|
||||
template: 'ticket_escalation',
|
||||
locale: 'en-us',
|
||||
timezone: 'Europe/Berlin',
|
||||
objects: {
|
||||
ticket: ticket,
|
||||
article: article,
|
||||
recipient: agent1,
|
||||
}
|
||||
)
|
||||
|
||||
assert_match('# Welcome to Zammad!', result[:subject])
|
||||
assert_match('is escalated since "04/01/2019 12:00 (Europe/Berlin)"!', result[:body])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -2,6 +2,7 @@ require 'test_helper'
|
|||
|
||||
class TicketNotificationTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
Setting.set('timezone_default', 'Europe/Berlin')
|
||||
Trigger.create_or_update(
|
||||
name: 'auto reply - new ticket',
|
||||
condition: {
|
||||
|
@ -78,7 +79,8 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
roles: roles,
|
||||
groups: groups,
|
||||
preferences: {
|
||||
locale: 'en-ca',
|
||||
locale: 'en-us',
|
||||
timezone: 'America/St_Lucia',
|
||||
},
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
|
@ -1152,6 +1154,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
# en notification
|
||||
result = NotificationFactory::Mailer.template(
|
||||
locale: @agent2.preferences[:locale],
|
||||
timezone: @agent2.preferences[:timezone],
|
||||
template: 'ticket_update',
|
||||
objects: {
|
||||
ticket: ticket1,
|
||||
|
@ -1165,7 +1168,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
assert_match(/1 low/, result[:body])
|
||||
assert_match(/2 normal/, result[:body])
|
||||
assert_match(/Pending till/, result[:body])
|
||||
assert_match(/2015-01-11 23:33:47 UTC/, result[:body])
|
||||
assert_match('01/11/2015 19:33 (America/St_Lucia)', result[:body])
|
||||
assert_match(/update/, result[:body])
|
||||
assert_no_match(/pending_till/, result[:body])
|
||||
assert_no_match(/i18n/, result[:body])
|
||||
|
@ -1181,9 +1184,10 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
assert_not(human_changes['pending_time'])
|
||||
assert_not(human_changes['pending_till'])
|
||||
|
||||
# de notification
|
||||
# de & Europe/Berlin notification
|
||||
result = NotificationFactory::Mailer.template(
|
||||
locale: @agent1.preferences[:locale],
|
||||
timezone: @agent1.preferences[:timezone],
|
||||
template: 'ticket_update',
|
||||
objects: {
|
||||
ticket: ticket1,
|
||||
|
@ -1198,7 +1202,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
assert_match(/1 niedrig/, result[:body])
|
||||
assert_match(/2 normal/, result[:body])
|
||||
assert_match(/Warten/, result[:body])
|
||||
assert_match(/2015-01-11 23:33:47 UTC/, result[:body])
|
||||
assert_match('12.01.2015 00:33 (Europe/Berlin)', result[:body])
|
||||
assert_match(/aktualis/, result[:body])
|
||||
assert_no_match(/pending_till/, result[:body])
|
||||
assert_no_match(/i18n/, result[:body])
|
||||
|
@ -1229,6 +1233,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
# de notification
|
||||
result = NotificationFactory::Mailer.template(
|
||||
locale: @agent1.preferences[:locale],
|
||||
timezone: @agent1.preferences[:timezone],
|
||||
template: 'ticket_update',
|
||||
objects: {
|
||||
ticket: ticket1,
|
||||
|
@ -1254,6 +1259,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
# en notification
|
||||
result = NotificationFactory::Mailer.template(
|
||||
locale: @agent2.preferences[:locale],
|
||||
timezone: @agent2.preferences[:timezone],
|
||||
template: 'ticket_update',
|
||||
objects: {
|
||||
ticket: ticket1,
|
||||
|
@ -1276,6 +1282,22 @@ class TicketNotificationTest < ActiveSupport::TestCase
|
|||
assert_no_match(/pending_till/, result[:body])
|
||||
assert_no_match(/i18n/, result[:body])
|
||||
|
||||
# en notification
|
||||
ticket1.escalation_at = Time.zone.parse('2019-04-01T10:00:00Z')
|
||||
result = NotificationFactory::Mailer.template(
|
||||
locale: @agent2.preferences[:locale],
|
||||
timezone: @agent2.preferences[:timezone],
|
||||
template: 'ticket_escalation',
|
||||
objects: {
|
||||
ticket: ticket1,
|
||||
article: article,
|
||||
recipient: @agent2,
|
||||
}
|
||||
)
|
||||
|
||||
assert_match('Ticket is escalated (some notification template test 1 Bobs\'s resumé', result[:subject])
|
||||
assert_match('is escalated since "04/01/2019 06:00 (America/St_Lucia)"!', result[:body])
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue