Added business hours tests.

This commit is contained in:
Martin Edenhofer 2015-09-21 00:19:45 +02:00
parent dcc542ab1b
commit 50546fa2d4
7 changed files with 377 additions and 103 deletions

View file

@ -500,7 +500,7 @@ class App.ControllerForm extends App.Controller
time = new Date( Date.parse( param[key] ) ) time = new Date( Date.parse( param[key] ) )
if time is 'Invalid Datetime' if time is 'Invalid Datetime'
throw "Invalid Datetime #{param[key]}" throw "Invalid Datetime #{param[key]}"
param[newKey] = time.toISOString().replace(/:\d\d\.\d\d\dZ$/, ':00Z') param[newKey] = time.toISOString().replace(/:\d\d\.\d\d\dZ$/, ':00.000Z')
catch err catch err
param[newKey] = "invalid #{param[key]}" param[newKey] = "invalid #{param[key]}"
console.log('ERR', err) console.log('ERR', err)
@ -527,6 +527,32 @@ class App.ControllerForm extends App.Controller
for key of inputSelectObject for key of inputSelectObject
param[ key ] = inputSelectObject[ key ] param[ key ] = inputSelectObject[ key ]
# data type conversion
for key of param
# get {business_hours}
if key.substr(0,16) is '{business_hours}'
newKey = key.substr(16, key.length)
if lookupForm.find("[data-name=\"#{newKey}\"]").hasClass('is-hidden')
param[newKey] = null
else if param[key]
newParams = {}
for day, value of param[key]
newParams[day] = {}
newParams[day].active = false
if value.active is 'true'
newParams[day].active = true
newParams[day].timeframes = []
if _.isArray(value.start)
for pos of value.start
newParams[day].timeframes.push [ value.start[pos], value.end[pos] ]
else
newParams[day].timeframes.push [ value.start, value.end ]
param[newKey] = newParams
else
param[newKey] = undefined
delete param[key]
#App.Log.notice 'ControllerForm', 'formParam', form, param #App.Log.notice 'ControllerForm', 'formParam', form, param
param param

View file

@ -1,10 +1,15 @@
class App.UiElement.business_hours class App.UiElement.business_hours
@render: (attribute, params) -> @render: (attributeOrig) ->
attribute = _.clone(attributeOrig)
attribute.nameRaw = attribute.name
attribute.name = "{business_hours}#{attribute.name}"
# Martin: our frontend doesn't create 24:00. # Martin: our frontend doesn't create 24:00.
# you have to check second values ('till') for 00:00 # you have to check second values ('till') for 00:00
# and convert them to 24:00 # and convert them to 24:00
hours = if !attribute.value
attribute.value =
mon: mon:
active: true active: true
timeframes: [ timeframes: [
@ -13,7 +18,7 @@ class App.UiElement.business_hours
tue: tue:
active: true active: true
timeframes: [ timeframes: [
['00:00','24:00'] ['00:00','22:00']
] ]
wed: wed:
active: true active: true
@ -23,7 +28,7 @@ class App.UiElement.business_hours
thu: thu:
active: true active: true
timeframes: [ timeframes: [
['09:00','12:00'] ['09:00','12:00'],
['13:00','17:00'] ['13:00','17:00']
] ]
fri: fri:
@ -43,7 +48,8 @@ class App.UiElement.business_hours
] ]
businessHours = new App.BusinessHours businessHours = new App.BusinessHours
hours: hours attribute: attribute
hours: attribute.value
businessHours.render() businessHours.render()
businessHours.el businessHours.el

View file

@ -79,8 +79,8 @@ class App.UiElement.ticket_selector
elementRow = $(e.target).closest('.js-filterElement') elementRow = $(e.target).closest('.js-filterElement')
@rebuildAttributeSelectors(item, elementRow, groupAndAttribute) @rebuildAttributeSelectors(item, elementRow, groupAndAttribute)
@rebuildOperater(item, elementRow, groupAndAttribute, elements) @rebuildOperater(item, elementRow, groupAndAttribute, elements, undefined, attribute)
@buildValue(item, elementRow, groupAndAttribute, elements) @buildValue(item, elementRow, groupAndAttribute, elements, undefined, undefined, attribute)
) )
# change operator # change operator
@ -88,7 +88,7 @@ class App.UiElement.ticket_selector
groupAndAttribute = $(e.target).find('.js-attributeSelector option:selected').attr('value') groupAndAttribute = $(e.target).find('.js-attributeSelector option:selected').attr('value')
operator = $(e.target).find('option:selected').attr('value') operator = $(e.target).find('option:selected').attr('value')
elementRow = $(e.target).closest('.js-filterElement') elementRow = $(e.target).closest('.js-filterElement')
@buildValue(item, elementRow, groupAndAttribute, elements, undefined, operator) @buildValue(item, elementRow, groupAndAttribute, elements, undefined, operator, attribute)
) )
# build inital params # build inital params
@ -108,8 +108,8 @@ class App.UiElement.ticket_selector
# clone, rebuild and append # clone, rebuild and append
elementClone = elementFirst.clone(true) elementClone = elementFirst.clone(true)
@rebuildAttributeSelectors(item, elementClone, groupAndAttribute) @rebuildAttributeSelectors(item, elementClone, groupAndAttribute)
@rebuildOperater(item, elementClone, groupAndAttribute, elements, operator) @rebuildOperater(item, elementClone, groupAndAttribute, elements, operator, attribute)
@buildValue(item, elementClone, groupAndAttribute, elements, value, operator) @buildValue(item, elementClone, groupAndAttribute, elements, value, operator, attribute)
elementLast.after(elementClone) elementLast.after(elementClone)
# remove first dummy row # remove first dummy row
@ -169,10 +169,10 @@ class App.UiElement.ticket_selector
ticket_ids: ticket_ids ticket_ids: ticket_ids
) )
@buildValue: (elementFull, elementRow, groupAndAttribute, elements, value, operator) -> @buildValue: (elementFull, elementRow, groupAndAttribute, elements, value, operator, attribute) ->
# do nothing if item already exists # do nothing if item already exists
name = "condition::#{groupAndAttribute}::value" name = "#{attribute.name}::#{groupAndAttribute}::value"
return if elementRow.find("[name=\"#{name}\"]").get(0) return if elementRow.find("[name=\"#{name}\"]").get(0)
return if elementRow.find("[data-name=\"#{name}\"]").get(0) return if elementRow.find("[data-name=\"#{name}\"]").get(0)
@ -237,8 +237,8 @@ class App.UiElement.ticket_selector
if groupAndAttribute if groupAndAttribute
elementRow.find('.js-attributeSelector select').val(groupAndAttribute) elementRow.find('.js-attributeSelector select').val(groupAndAttribute)
@buildOperator: (elementFull, elementRow, groupAndAttribute, elements, current_operator) -> @buildOperator: (elementFull, elementRow, groupAndAttribute, elements, current_operator, attribute) ->
selection = $("<select class=\"form-control\" name=\"condition::#{groupAndAttribute}::operator\"></select>") selection = $("<select class=\"form-control\" name=\"#{attribute.name}::#{groupAndAttribute}::operator\"></select>")
attributeConfig = elements[groupAndAttribute] attributeConfig = elements[groupAndAttribute]
if attributeConfig.operator if attributeConfig.operator
@ -250,15 +250,15 @@ class App.UiElement.ticket_selector
selection.append("<option value=\"#{operator}\" #{selected}>#{operatorName}</option>") selection.append("<option value=\"#{operator}\" #{selected}>#{operatorName}</option>")
selection selection
@rebuildOperater: (elementFull, elementRow, groupAndAttribute, elements, current_operator) -> @rebuildOperater: (elementFull, elementRow, groupAndAttribute, elements, current_operator, attribute) ->
return if !groupAndAttribute return if !groupAndAttribute
# do nothing if item already exists # do nothing if item already exists
name = "condition::#{groupAndAttribute}::operator" name = "#{attribute.name}::#{groupAndAttribute}::operator"
return if elementRow.find("[name=\"#{name}\"]").get(0) return if elementRow.find("[name=\"#{name}\"]").get(0)
# render new operator # render new operator
operator = @buildOperator(elementFull, elementRow, groupAndAttribute, elements, current_operator) operator = @buildOperator(elementFull, elementRow, groupAndAttribute, elements, current_operator, attribute)
elementRow.find('.js-operator select').replaceWith(operator) elementRow.find('.js-operator select').replaceWith(operator)
@humanText: (condition) -> @humanText: (condition) ->

View file

@ -24,6 +24,7 @@ class App.BusinessHours extends Spine.Controller
@updateMaxTimeframes() @updateMaxTimeframes()
html = App.view('generic/business_hours') html = App.view('generic/business_hours')
attribute: @attribute
days: @days days: @days
hours: @options.hours hours: @options.hours
maxTimeframes: @maxTimeframes maxTimeframes: @maxTimeframes
@ -71,7 +72,8 @@ class App.BusinessHours extends Spine.Controller
validate: => validate: =>
for day, hours of @options.hours for day, hours of @options.hours
break if not hours.active break if !hours.active
break if !hours.timeframes
# edge case: full day # edge case: full day
if hours.timeframes[0][0] is '00:00' and hours.timeframes[hours.timeframes.length - 1][1] is '00:00' if hours.timeframes[0][0] is '00:00' and hours.timeframes[hours.timeframes.length - 1][1] is '00:00'

View file

@ -4,7 +4,7 @@
<th style="text-align: center"> <th style="text-align: center">
<label class="day-name"> <label class="day-name">
<span class="checkbox-replacement checkbox-replacement--inline"> <span class="checkbox-replacement checkbox-replacement--inline">
<input class="js-toggle-day" data-target="<%- id %>" type="checkbox"<%- ' checked' if @hours[id].active %>> <input class="js-toggle-day" name="<%= @attribute.name %>::<%- id %>::active" value="true" data-target="<%- id %>" type="checkbox"<%- ' checked' if @hours[id].active %>>
<%- @Icon('checkbox', 'icon-unchecked') %> <%- @Icon('checkbox', 'icon-unchecked') %>
<%- @Icon('checkbox-checked', 'icon-checked') %> <%- @Icon('checkbox-checked', 'icon-checked') %>
</span> </span>
@ -19,9 +19,9 @@
<% if @hours[id].timeframes[slot]: %> <% if @hours[id].timeframes[slot]: %>
<td data-day="<%- id %>" data-slot="<%- slot %>" class="form-group day-time<%- ' is-active' if @hours[id].active %>"> <td data-day="<%- id %>" data-slot="<%- slot %>" class="form-group day-time<%- ' is-active' if @hours[id].active %>">
<label for="<%- id %>_start_time">from</label> <label for="<%- id %>_start_time">from</label>
<input type="text" id="<%- id %>_start_time" value="<%- @hours[id].timeframes[slot][0] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="0" class="form-control form-control--small time js-time"> <input type="text" id="<%- id %>_start_time" name="<%= @attribute.name %>::<%- id %>::start" value="<%- @hours[id].timeframes[slot][0] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="0" class="form-control form-control--small time js-time">
<label for="monday_end_time">till</label> <label for="monday_end_time">till</label>
<input type="text" id="monday_end_time" value="<%- @hours[id].timeframes[slot][1] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="1" class="form-control form-control--small time js-time"> <input type="text" id="monday_end_time" name="<%= @attribute.name %>::<%- id %>::end" value="<%- @hours[id].timeframes[slot][1] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="1" class="form-control form-control--small time js-time">
<% else: %> <% else: %>
<td class="empty-cell"> <td class="empty-cell">
<% end %> <% end %>

View file

@ -1,6 +1,6 @@
// form // form
test( "form simple checks", function() { test( 'form checks', function() {
App.TicketPriority.refresh( [ App.TicketPriority.refresh( [
{ {
@ -33,55 +33,254 @@ test( "form simple checks", function() {
}, },
] ) ] )
// timeplan
$('#forms').append('<hr><h1>form time check</h1><form id="form1"></form>') $('#forms').append('<hr><h1>form time check</h1><form id="form1"></form>')
var el = $('#form1') var el = $('#form1')
var defaults = { var defaults = {
times: { working_hours: {
days: ['mon', 'wed'], mon: {
hours: [2], active: true,
timeframes: [
['09:00','17:00']
]
}, },
tue: {
active: true,
timeframes: [
['00:00','22:00']
]
},
wed: {
active: true,
timeframes: [
['09:00','17:00']
]
},
thu: {
active: true,
timeframes: [
['09:00','12:00'],
['13:00','17:00']
]
},
fri: {
active: true,
timeframes: [
['09:00','17:00']
]
},
sat: {
active: false,
timeframes: [
['10:00','14:00']
]
},
sun: {
active: false,
timeframes: [
['10:00','14:00']
]
},
},
first_response_time: 150,
solution_time: '',
update_time: 45,
conditions: { conditions: {
'tickets.title': 'some title', 'ticket.title': {
'tickets.priority_id': [1,2,3], operator: 'contains',
value: 'some title',
},
'ticket.priority_id': {
operator: 'is',
value: [1,2,3],
},
'ticket.created_at': {
operator: 'before (absolute)',
value: '2015-09-20T03:41:00.000Z',
},
}, },
executions: { executions: {
'tickets.title': 'some title new', 'ticket.title': {
'tickets.priority_id': 3, value: 'some title new',
},
'ticket.priority_id': {
value: 3,
},
}, },
} }
new App.ControllerForm({ new App.ControllerForm({
el: el, el: el,
model: { model: {
configure_attributes: [ configure_attributes: [
{ name: 'times', display: 'Times', tag: 'timeplan', null: true, default: defaults['times'] }, { name: 'escalation_times', display: 'Times', tag: 'sla_times', null: true },
{ name: 'conditions', display: 'Conditions', tag: 'ticket_attribute_selection', null: true, default: defaults['conditions'] }, { name: 'working_hours', display: 'Hours', tag: 'business_hours', null: true },
{ name: 'executions', display: 'Executions', tag: 'ticket_attribute_set', null: true, default: defaults['executions'] }, { name: 'conditions', display: 'Conditions', tag: 'ticket_selector', null: true },
{ name: 'executions', display: 'Executions', tag: 'ticket_perform_action', null: true },
] ]
}, },
params: defaults,
autofocus: true autofocus: true
}); });
deepEqual( el.find('[name="times::days"]').val(), ['mon', 'wed'], 'check times::days value')
equal( el.find('[name="times::hours"]').val(), 2, 'check times::hours value')
equal( el.find('[name="times::minutes"]').val(), null, 'check times::minutes value')
var params = App.ControllerForm.params( el ) var params = App.ControllerForm.params( el )
var test_params = { var test_params = {
times: { first_response_time: '150',
days: ['mon', 'wed'], first_response_time_in_text: '02:30',
hours: '2', solution_time: '',
}, solution_time_in_text: '',
update_time: '45',
update_time_in_text: '00:45',
conditions: { conditions: {
'tickets.title': 'some title', 'ticket.title': {
'tickets.priority_id': ['1','3'], operator: 'contains',
value: 'some title',
},
'ticket.priority_id': {
operator: 'is',
value: ['1', '3'],
},
'ticket.created_at': {
operator: 'before (absolute)',
value: '2015-09-20T03:41:00.000Z',
},
}, },
executions: { executions: {
'tickets.title': 'some title new', 'ticket.title': {
'tickets.priority_id': '3', value: 'some title new',
},
'ticket.priority_id': {
value: '3',
},
},
working_hours: {
mon: {
active: true,
timeframes: [
['09:00','17:00']
]
},
tue: {
active: true,
timeframes: [
['00:00','22:00']
]
},
wed: {
active: true,
timeframes: [
['09:00','17:00']
]
},
thu: {
active: true,
timeframes: [
['09:00','12:00'],
['13:00','17:00']
]
},
fri: {
active: true,
timeframes: [
['09:00','17:00']
]
},
sat: {
active: false,
timeframes: [
['10:00','14:00']
]
},
sun: {
active: false,
timeframes: [
['10:00','14:00']
]
},
}, },
} }
deepEqual( params, test_params, 'form param check' ); deepEqual( params, test_params, 'form param check' );
// change sla times
el.find('[name="first_response_time_in_text"]').val('0:30').trigger('blur')
el.find('#update_time').click()
// change selector
el.find('[name="conditions::ticket.priority_id::value"]').closest('.js-filterElement').find('.js-remove').click()
el.find('[name="executions::ticket.title::value"]').closest('.js-filterElement').find('.js-remove').click()
var params = App.ControllerForm.params( el )
var test_params = {
working_hours: {
mon: {
active: true,
timeframes: [
['09:00','17:00']
]
},
tue: {
active: true,
timeframes: [
['00:00','22:00']
]
},
wed: {
active: true,
timeframes: [
['09:00','17:00']
]
},
thu: {
active: true,
timeframes: [
['09:00','12:00'],
['13:00','17:00']
]
},
fri: {
active: true,
timeframes: [
['09:00','17:00']
]
},
sat: {
active: false,
timeframes: [
['10:00','14:00']
]
},
sun: {
active: false,
timeframes: [
['10:00','14:00']
]
},
},
first_response_time: '30',
first_response_time_in_text: '00:30',
solution_time: '',
solution_time_in_text: '',
update_time: '',
update_time_in_text: '',
conditions: {
'ticket.title': {
operator: 'contains',
value: 'some title',
},
'ticket.created_at': {
operator: 'before (absolute)',
value: '2015-09-20T03:41:00.000Z',
},
},
executions: {
'ticket.priority_id': {
value: '3',
},
},
}
deepEqual( params, test_params, 'form param check' );
//deepEqual( el.find('[name="times::days"]').val(), ['mon', 'wed'], 'check times::days value')
//equal( el.find('[name="times::hours"]').val(), 2, 'check times::hours value')
//equal( el.find('[name="times::minutes"]').val(), null, 'check times::minutes value')
}); });

View file

@ -685,14 +685,29 @@ test( "form postmaster filter", function() {
var defaults = { var defaults = {
input2: 'some name', input2: 'some name',
match: { match: {
from: 'some@address', from: {
subject: 'some subject', operator: 'contains',
value: 'some@address',
},
subject: {
operator: 'contains',
value: 'some subject',
},
}, },
set: { set: {
'x-zammad-ticket-owner': 'owner', 'x-zammad-ticket-customer': {
'x-zammad-ticket-customer': 'customer', value: 'customer'
'x-zammad-ticket-priority_id': 2, },
'x-zammad-ticket-group_id': 1, 'x-zammad-ticket-group_id': {
value: '1'
},
'x-zammad-ticket-owner': {
value: 'owner',
value_completion: ''
},
'x-zammad-ticket-priority_id': {
value: '1'
}
}, },
} }
new App.ControllerForm({ new App.ControllerForm({
@ -709,35 +724,61 @@ test( "form postmaster filter", function() {
}); });
params = App.ControllerForm.params( el ) params = App.ControllerForm.params( el )
test_params = { test_params = {
input1: "some not used default", input1: 'some not used default',
input2: "some name", input2: 'some name',
match: { match: {
from: 'some@address', from: {
subject: 'some subject', operator: 'contains',
value: 'some@address'
},
subject: {
operator: 'contains',
value: 'some subject'
}
}, },
set: { set: {
'x-zammad-ticket-owner': 'owner', 'x-zammad-ticket-customer': {
'x-zammad-ticket-customer': 'customer', value: 'customer'
'x-zammad-ticket-priority_id': '2', },
'x-zammad-ticket-group_id': '1', 'x-zammad-ticket-group_id': {
value: '1'
},
'x-zammad-ticket-owner': {
value: 'owner',
value_completion: ''
},
'x-zammad-ticket-priority_id': {
value: '1'
}
}, },
}; };
deepEqual( params, test_params, 'form param check' ); deepEqual( params, test_params, 'form param check' );
el.find('[name="set::x-zammad-ticket-priority_id"]').closest('.form-group').find('.remove').click() el.find('[name="set::x-zammad-ticket-priority_id::value"]').closest('.js-filterElement').find('.js-remove').click()
el.find('[name="set::x-zammad-ticket-customer"]').closest('.form-group').find('.remove').click() el.find('[name="set::x-zammad-ticket-customer::value"]').closest('.js-filterElement').find('.js-remove').click()
App.Delay.set( function() { App.Delay.set( function() {
test( "form param check after remove click", function() { test( "form param check after remove click", function() {
params = App.ControllerForm.params( el ) params = App.ControllerForm.params( el )
test_params = { test_params = {
input1: "some not used default", input1: 'some not used default',
input2: "some name", input2: 'some name',
match: { match: {
from: 'some@address', from: {
subject: 'some subject', operator: 'contains',
value: 'some@address'
},
subject: {
operator: 'contains',
value: 'some subject'
}
}, },
set: { set: {
'x-zammad-ticket-owner': 'owner', 'x-zammad-ticket-owner': {
'x-zammad-ticket-group_id': '1', value: 'owner',
value_completion: ''
},
'x-zammad-ticket-group_id': {
value: '1'
},
}, },
}; };
deepEqual( params, test_params, 'form param check' ); deepEqual( params, test_params, 'form param check' );
@ -765,8 +806,8 @@ test( "form selector", function() {
params: defaults, params: defaults,
}); });
test_params = { test_params = {
input1: "some not used default33", input1: 'some not used default33',
input2: "some name66", input2: 'some name66',
}; };
params = App.ControllerForm.params( el ) params = App.ControllerForm.params( el )
deepEqual( params, test_params, 'form param check via $("#form")' ); deepEqual( params, test_params, 'form param check via $("#form")' );