diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 7bc833f35..24a77506f 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -6,6 +6,8 @@ Hi there - thanks for filling an issue. Please ensure the following things befor
- Add the `log/production.log` file from your system. Attention: Make sure no confidential data is in it!
- Please write the issue in english
+Note: We always do our best. Unfortunately, sometimes the requests are too much and we can't handle everything at once. If you want to prioritize/escalate your issue, you can do so by means of a support contract (see https://zammad.com/pricing#selfhosted).
+
* The upper textblock will be removed automatically when you submit your issue *
-->
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8ce7141b6..e03893101 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -278,6 +278,18 @@ test:integration:telegram:
- ruby -I test test/integration/telegram_controller_test.rb
- rake db:drop
+test:integration:idoit:
+ stage: test
+ tags:
+ - core
+ script:
+ - export RAILS_ENV=test
+ - rake db:create
+ - rake db:migrate
+ - rake db:seed
+ - ruby -I test test/integration/idoit_controller_test.rb
+ - rake db:drop
+
test:integration:es_mysql:
stage: test
tags:
diff --git a/Gemfile b/Gemfile
index 356bc0c67..81955ce14 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
ruby '2.4.1'
-gem 'rails', '5.0.5'
+gem 'rails', '5.1.4'
gem 'rails-observers'
gem 'activerecord-session_store'
@@ -53,7 +53,8 @@ gem 'mime-types'
gem 'biz'
-gem 'composite_primary_keys'
+# temporary till pull request gets merged: https://github.com/composite-primary-keys/composite_primary_keys/pull/404
+gem 'composite_primary_keys', git: 'https://github.com/jkowens/composite_primary_keys.git', branch: 'rails-5_1'
gem 'delayed_job_active_record'
gem 'daemons'
diff --git a/Gemfile.lock b/Gemfile.lock
index 81c5c7655..2e8065d0f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,11 @@
+GIT
+ remote: https://github.com/jkowens/composite_primary_keys.git
+ revision: 7f4670b54b3c6e94992161b4efe2c8717d7c0e71
+ branch: rails-5_1
+ specs:
+ composite_primary_keys (9.0.7)
+ activerecord (~> 5.1.0)
+
GIT
remote: https://github.com/thorsteneckel/autodiscover.git
revision: 29d713ee0c8c25fcf74c4292ff13fe1fa4d0d827
@@ -17,38 +25,38 @@ GIT
GEM
remote: https://rubygems.org/
specs:
- actioncable (5.0.5)
- actionpack (= 5.0.5)
- nio4r (>= 1.2, < 3.0)
+ actioncable (5.1.4)
+ actionpack (= 5.1.4)
+ nio4r (~> 2.0)
websocket-driver (~> 0.6.1)
- actionmailer (5.0.5)
- actionpack (= 5.0.5)
- actionview (= 5.0.5)
- activejob (= 5.0.5)
+ actionmailer (5.1.4)
+ actionpack (= 5.1.4)
+ actionview (= 5.1.4)
+ activejob (= 5.1.4)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.0.5)
- actionview (= 5.0.5)
- activesupport (= 5.0.5)
+ actionpack (5.1.4)
+ actionview (= 5.1.4)
+ activesupport (= 5.1.4)
rack (~> 2.0)
- rack-test (~> 0.6.3)
+ rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.0.5)
- activesupport (= 5.0.5)
+ actionview (5.1.4)
+ activesupport (= 5.1.4)
builder (~> 3.1)
- erubis (~> 2.7.0)
+ erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (5.0.5)
- activesupport (= 5.0.5)
+ activejob (5.1.4)
+ activesupport (= 5.1.4)
globalid (>= 0.3.6)
- activemodel (5.0.5)
- activesupport (= 5.0.5)
- activerecord (5.0.5)
- activemodel (= 5.0.5)
- activesupport (= 5.0.5)
- arel (~> 7.0)
+ activemodel (5.1.4)
+ activesupport (= 5.1.4)
+ activerecord (5.1.4)
+ activemodel (= 5.1.4)
+ activesupport (= 5.1.4)
+ arel (~> 8.0)
activerecord-nulldb-adapter (0.3.7)
activerecord (>= 2.0.0)
activerecord-session_store (1.1.0)
@@ -57,14 +65,14 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 1.5.2, < 3)
railties (>= 4.0, < 5.2)
- activesupport (5.0.5)
+ activesupport (5.1.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
- arel (7.1.4)
+ arel (8.0.0)
argon2 (1.1.3)
ffi (~> 1.9)
ffi-compiler (~> 0.1)
@@ -94,8 +102,6 @@ GEM
coffee-script
execjs
json
- composite_primary_keys (9.0.7)
- activerecord (~> 5.0.0)
concurrent-ruby (1.0.5)
coveralls (0.8.21)
json (>= 1.8, < 3)
@@ -127,7 +133,7 @@ GEM
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
equalizer (0.0.11)
- erubis (2.7.0)
+ erubi (1.6.1)
eventmachine (1.2.5)
execjs (2.7.0)
factory_girl (4.8.0)
@@ -219,7 +225,7 @@ GEM
thread_safe (~> 0.3, >= 0.3.1)
method_source (0.8.2)
mime-types (2.99.3)
- mini_portile2 (2.2.0)
+ mini_portile2 (2.3.0)
minitest (5.10.3)
multi_json (1.12.1)
multi_xml (0.6.0)
@@ -231,8 +237,8 @@ GEM
net-ldap (0.16.0)
netrc (0.11.0)
nio4r (2.1.0)
- nokogiri (1.8.0)
- mini_portile2 (~> 2.2.0)
+ nokogiri (1.8.1)
+ mini_portile2 (~> 2.3.0)
nori (2.6.0)
notiffany (0.1.1)
nenv (~> 0.1)
@@ -279,7 +285,7 @@ GEM
rack
parser (2.4.0.0)
ast (~> 2.2)
- pg (0.20.0)
+ pg (0.21.0)
pluginator (1.5.0)
power_assert (1.1.0)
powerpack (0.1.1)
@@ -294,19 +300,19 @@ GEM
rack (2.0.3)
rack-livereload (0.3.16)
rack
- rack-test (0.6.3)
- rack (>= 1.0)
- rails (5.0.5)
- actioncable (= 5.0.5)
- actionmailer (= 5.0.5)
- actionpack (= 5.0.5)
- actionview (= 5.0.5)
- activejob (= 5.0.5)
- activemodel (= 5.0.5)
- activerecord (= 5.0.5)
- activesupport (= 5.0.5)
+ rack-test (0.7.0)
+ rack (>= 1.0, < 3)
+ rails (5.1.4)
+ actioncable (= 5.1.4)
+ actionmailer (= 5.1.4)
+ actionpack (= 5.1.4)
+ actionview (= 5.1.4)
+ activejob (= 5.1.4)
+ activemodel (= 5.1.4)
+ activerecord (= 5.1.4)
+ activesupport (= 5.1.4)
bundler (>= 1.3.0)
- railties (= 5.0.5)
+ railties (= 5.1.4)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
@@ -315,16 +321,16 @@ GEM
loofah (~> 2.0)
rails-observers (0.1.5)
activemodel (>= 4.0)
- railties (5.0.5)
- actionpack (= 5.0.5)
- activesupport (= 5.0.5)
+ railties (5.1.4)
+ actionpack (= 5.1.4)
+ activesupport (= 5.1.4)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
raindrops (0.19.0)
- rake (12.0.0)
+ rake (12.1.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
@@ -476,7 +482,7 @@ DEPENDENCIES
coffee-rails
coffee-script-source
coffeelint
- composite_primary_keys
+ composite_primary_keys!
coveralls
daemons
delayed_job_active_record
@@ -516,7 +522,7 @@ DEPENDENCIES
pre-commit
puma
rack-livereload
- rails (= 5.0.5)
+ rails (= 5.1.4)
rails-observers
rb-fsevent
rspec-rails
diff --git a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
index f764e5c57..71789f94c 100644
--- a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
+++ b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
@@ -1162,7 +1162,7 @@ class App.ObserverController extends App.Controller
@log 'debug', 'new', @object_id, @model
if App[@model].exists(@object_id)
- @maybeRender( App[@model].fullLocal(@object_id) )
+ @maybeRender(App[@model].fullLocal(@object_id))
else
App[@model].full(@object_id, @maybeRender)
@@ -1170,7 +1170,8 @@ class App.ObserverController extends App.Controller
if @globalRerender
@bind('ui:rerender', =>
@lastAttributres = undefined
- @maybeRender( App[@model].fullLocal(@object_id) )
+ console.log('aaaa', @model, @template)
+ @maybeRender(App[@model].fullLocal(@object_id))
)
subscribe: (object, typeOfChange) =>
diff --git a/app/assets/javascripts/app/controllers/_application_controller_table.coffee b/app/assets/javascripts/app/controllers/_application_controller_table.coffee
index 429624b1b..1779c7d43 100644
--- a/app/assets/javascripts/app/controllers/_application_controller_table.coffee
+++ b/app/assets/javascripts/app/controllers/_application_controller_table.coffee
@@ -1,3 +1,94 @@
+###
+
+ # table based on model
+
+ rowClick = (id, e) ->
+ e.preventDefault()
+ console.log('rowClick', id)
+ rowMouseover = (id, e) ->
+ e.preventDefault()
+ console.log('rowMouseover', id)
+ rowMouseout = (id, e) ->
+ e.preventDefault()
+ console.log('rowMouseout', id)
+ rowDblClick = (id, e) ->
+ e.preventDefault()
+ console.log('rowDblClick', id)
+
+ colClick = (id, e) ->
+ e.preventDefault()
+ console.log('colClick', e.target)
+
+ checkboxClick = (id, e) ->
+ e.preventDefault()
+ console.log('checkboxClick', e.target)
+
+ callbackHeader = (headers) ->
+ console.log('current header is', headers)
+ # add new header item
+ attribute =
+ name: 'some name'
+ display: 'Some Name'
+ headers.push attribute
+ console.log('new header is', headers)
+ headers
+
+ callbackAttributes = (value, object, attribute, header) ->
+ console.log('data of item col', value, object, attribute, header)
+ value = 'New Data To Show'
+ value
+
+ new App.ControllerTable(
+ tableId: 'some_id_to_idientify_user_based_table_preferences'
+ el: element
+ overview: ['host', 'user', 'adapter', 'active']
+ model: App.Channel
+ objects: data
+ groupBy: 'adapter'
+ checkbox: false
+ radio: false
+ class: 'some-css-class'
+ bindRow:
+ events:
+ 'click': rowClick
+ 'mouseover': rowMouseover
+ 'mouseout': rowMouseout
+ 'dblclick': rowDblClick
+ bindCol:
+ host:
+ events:
+ 'click': colClick
+ bindCheckbox:
+ events:
+ 'click': rowClick
+ 'mouseover': rowMouseover
+ 'mouseout': rowMouseout
+ 'dblclick': rowDblClick
+ callbackHeader: [callbackHeader]
+ callbackAttributes:
+ attributeName: [
+ callbackAttributes
+ ]
+ dndCallback: =>
+ items = @el.find('table > tbody > tr')
+ console.log('all effected items', items)
+ )
+
+ new App.ControllerTable(
+ el: element
+ overview: ['time', 'area', 'level', 'browser', 'location', 'data']
+ attribute_list: [
+ { name: 'time', display: 'Time', tag: 'datetime' },
+ { name: 'area', display: 'Area', type: 'text' },
+ { name: 'level', display: 'Level', type: 'text' },
+ { name: 'browser', display: 'Browser', type: 'text' },
+ { name: 'location', display: 'Location', type: 'text' },
+ { name: 'data', display: 'Data', type: 'text' },
+ ]
+ objects: data
+ )
+
+###
class App.ControllerTable extends App.Controller
minColWidth: 40
baseColWidth: 130
@@ -10,9 +101,53 @@ class App.ControllerTable extends App.Controller
elements:
'.js-tableHead': 'tableHead'
- constructor: (params) ->
+ events:
+ 'click .js-sort': 'sortByColumn'
+
+ overviewAttributes: undefined
+ #model: App.TicketPriority,
+ objects: []
+ checkbox: false
+ radio: false
+ renderState: undefined
+ groupBy: undefined
+
+ destroy: false
+
+ columnsLength: undefined
+ headers: undefined
+ headerWidth: {}
+
+ currentRows: []
+
+ orderDirection: 'ASC'
+ orderBy: undefined
+
+ lastOrderDirection: undefined
+ lastOrderBy: undefined
+ lastOverview: undefined
+
+ customOrderDirection: undefined
+ customOrderBy: undefined
+
+ bindCol: {}
+ bindRow: {}
+
+ constructor: ->
super
+ if !@model
+ @model = {}
+ @overviewAttributes ||= @overview || @model.configure_overview || []
+ @attributesListRaw ||= @attribute_list || @model.configure_attributes || {}
+ @attributesList = App.Model.attributesGet(false, @attributesListRaw)
+ console.log('Table', @overviewAttributes, @overview)
+ #@setHeaderWidths = App.Model.setHeaderWidthsGet(false, @attributesList)
+ @destroy = @model.configure_delete
+
+ throw 'overviewAttributes needed' if _.isEmpty(@overviewAttributes)
+ throw 'attributesList needed' if _.isEmpty(@attributesList)
+
# apply personal preferences
data = {}
if @tableId
@@ -21,20 +156,218 @@ class App.ControllerTable extends App.Controller
for key, value of data.order
@[key] = value
- @headerWidth = {}
if data.headerWidth
for key, value of data.headerWidth
@headerWidth[key] = value
@availableWidth = @el.width()
- @render()
- $(window).on 'resize.table', @onResize
+
+ @renderQueue()
release: =>
$(window).off 'resize.table', @onResize
+ update: (params) =>
+ console.log('params', params)
+ for key, value of params
+ @[key] = value
+
+ if params.sync is true
+ return @render()
+ @renderQueue()
+
+ renderQueue: =>
+ App.QueueManager.add('tableRender', @render)
+ App.QueueManager.run('tableRender')
+
render: =>
- @html @tableGen()
+ if @renderState is undefined
+
+ # check if table is empty
+ if _.isEmpty(@objects)
+ @renderState = 'emptyList'
+ @el.html(@renderEmptyList())
+ $(window).on 'resize.table', @onResize
+ return ['emptyList.new']
+ else
+ @renderState = 'List'
+ @renderTableFull()
+ $(window).on 'resize.table', @onResize
+ return ['fullRender.new']
+ else if @renderState is 'emptyList' && !_.isEmpty(@objects)
+ @renderState = 'List'
+ @renderTableFull()
+ return ['fullRender']
+ else if @renderState isnt 'emptyList' && _.isEmpty(@objects)
+ @renderState = 'emptyList'
+ @el.html(@renderEmptyList())
+ return ['emptyList']
+ else
+
+ # check if header has changed
+ if @tableHeadersHasChanged()
+ @renderTableFull()
+ return ['fullRender.overviewAttributesChanged']
+
+ # check for changes
+ newRows = @renderTableRows(true)
+ removedRows = _.difference(@currentRows, newRows)
+ addedRows = _.difference(newRows, @currentRows)
+
+ # if only rows are removed
+ if _.isEmpty(addedRows) && !_.isEmpty(removedRows) && removedRows.length < 15 && !_.isEmpty(newRows)
+ newCurrentRows = []
+ removePositions = []
+ for position in [0..@currentRows.length-1]
+ if _.contains(removedRows, @currentRows[position])
+ removePositions.push position
+ else
+ newCurrentRows.push @currentRows[position]
+
+ # check if order is still correct
+ if @_isSame(newRows, newCurrentRows) is true
+ for position in removePositions
+ @$("tbody > tr:nth-child(#{position+1})").remove()
+ @currentRows = newCurrentRows
+ console.log('fullRender.contentRemoved', removePositions)
+ return ['fullRender.contentRemoved', removePositions]
+
+ if newRows.length isnt @currentRows.length
+ result = ['fullRender.lenghtChanged', @currentRows.length, newRows.length]
+ @renderTableFull(newRows)
+ console.log('result', result)
+ return result
+
+ # compare rows
+ result = @_isSame(newRows, @currentRows)
+ if result isnt true
+ @renderTableFull(newRows)
+ console.log('result', "fullRender.contentChanged|row(#{result})")
+ return ['fullRender.contentChanged', result]
+
+ console.log('result', 'noChanges')
+ return ['noChanges']
+
+ renderEmptyList: =>
+ App.view('generic/admin/empty')(
+ explanation: @explanation
+ )
+
+ renderTableFull: (rows) =>
+ console.log('renderTableFull', @orderBy, @orderDirection)
+ @tableHeaders()
+ @sortList()
+ bulkIds = @getBulkSelected()
+ container = @renderTableContainer()
+ if !rows
+ rows = @renderTableRows()
+ @currentRows = clone(rows)
+ else
+ @currentRows = clone(rows)
+ container.find('.js-tableBody').html(rows)
+
+ cursorMap =
+ click: 'pointer'
+ dblclick: 'pointer'
+ #mouseover: 'alias'
+
+ # bind col.
+ if !_.isEmpty(@bindCol)
+ for name, item of @bindCol
+ if item.events
+ position = 0
+ if @dndCallback
+ position += 1
+ if @checkbox
+ position += 1
+ hit = false
+
+ for headerName in @headers
+ if !hit
+ position += 1
+ if headerName.name is name || headerName.name is "#{name}_id" || headerName.name is "#{name}_bulkIds"
+ hit = true
+
+ if hit
+ for event, callback of item.events
+ do (container, event, callback) ->
+ if cursorMap[event]
+ container.find("tbody > tr > td:nth-child(#{position})").css('cursor', cursorMap[event])
+ container.on( event, "tbody > tr > td:nth-child(#{position})",
+ (e) ->
+ e.stopPropagation()
+ id = $(e.target).parents('tr').data('id')
+ callback(id, e)
+ )
+
+ # bind row
+ if !_.isEmpty(@bindRow)
+ if @bindRow.events
+ for event, callback of @bindRow.events
+ do (container, event, callback) ->
+ if cursorMap[event]
+ container.find('tbody > tr').css( 'cursor', cursorMap[event] )
+ container.on( event, 'tbody > tr',
+ (e) ->
+ id = $(e.target).parents('tr').data('id')
+ callback(id, e)
+ )
+
+ # bind bindCheckbox
+ if @bindCheckbox
+ if @bindCheckbox.events
+ for event, callback of @bindCheckbox.events
+ do (container, event, callback) ->
+ container.delegate('input[name="bulk"]', event, (e) ->
+ e.stopPropagation()
+ id = $(e.currentTarget).parents('tr').data('id')
+ checked = $(e.currentTarget).prop('checked')
+ callback(id, checked, e)
+ )
+
+ # if we have a personalised table
+ if @tableId
+
+ # enable resize column
+ container.on 'mousedown', '.js-col-resize', @onColResizeMousedown
+ container.on 'click', '.js-col-resize', @stopPropagation
+
+ # enable checkbox bulk selection
+ if @checkbox
+
+ # click first tr>td, catch click
+ container.delegate('tr > td:nth-child(1)', 'click', (e) ->
+ e.stopPropagation()
+ )
+
+ # bind on full bulk click
+ container.delegate('input[name="bulk_all"]', 'change', (e) =>
+ e.stopPropagation()
+ clicks = []
+ if $(e.currentTarget).prop('checked')
+ $(e.currentTarget).parents('table').find('[name="bulk"]').each( ->
+ $element = $(@)
+ return if $element.prop('checked')
+ $element.prop('checked', true)
+ id = $element.parents('tr').data('id')
+ clicks.push [id, true]
+ )
+ else
+ $(e.currentTarget).parents('table').find('[name="bulk"]').each( ->
+ $element = $(@)
+ return if !$element.prop('checked')
+ $element.prop('checked', false)
+ id = $element.parents('tr').data('id')
+ clicks.push [id, false]
+ )
+ return if !@bindCheckbox
+ return if !@bindCheckbox.events
+ return if _.isEmpty(clicks)
+ for event, callback of @bindCheckbox.events
+ if event == 'click' || event == 'change'
+ for click in clicks
+ callback(click..., e)
+ )
if @dndCallback
dndOptions =
@@ -50,121 +383,79 @@ class App.ControllerTable extends App.Controller
# Set helper cell sizes to match the original sizes
$(@).width( originals.eq(index).outerWidth() )
return helper
- update: @dndCallback
- @el.find('table > tbody').sortable(dndOptions)
+ update: @dndCallback
+ container.find('tbody').sortable(dndOptions)
- ###
+ @el.html(container)
+ @setBulkSelected(bulkIds)
- # table based on model
+ renderTableContainer: =>
+ $(App.view('generic/table')(
+ tableId: @tableId
+ headers: @headers
+ checkbox: @checkbox
+ radio: @radio
+ class: @class
+ sortable: @dndCallback
+ ))
- rowClick = (id, e) ->
- e.preventDefault()
- console.log('rowClick', id)
- rowMouseover = (id, e) ->
- e.preventDefault()
- console.log('rowMouseover', id)
- rowMouseout = (id, e) ->
- e.preventDefault()
- console.log('rowMouseout', id)
- rowDblClick = (id, e) ->
- e.preventDefault()
- console.log('rowDblClick', id)
+ renderTableRows: (sort = false) =>
+ if sort is true
+ @sortList()
+ position = 0
+ columnsLength = @headers.length
+ if @checkbox || @radio
+ columnsLength++
+ groupLast = ''
+ tableBody = []
+ for object in @objects
+ position++
+ if @groupBy
+ groupByName = App.viewPrint(object, @groupBy, @attributesList)
+ if groupLast isnt groupByName
+ groupLast = groupByName
+ tableBody.push @renderTableGroupByRow(object, position, groupByName)
+ tableBody.push @renderTableRow(object, position)
+ tableBody
- colClick = (id, e) ->
- e.preventDefault()
- console.log('colClick', e.target)
-
- checkboxClick = (id, e) ->
- e.preventDefault()
- console.log('checkboxClick', e.target)
-
- callbackHeader = (headers) ->
- console.log('current header is', headers)
- # add new header item
- attribute =
- name: 'some name'
- display: 'Some Name'
- headers.push attribute
- console.log('new header is', headers)
- headers
-
- callbackAttributes = (value, object, attribute, header) ->
- console.log('data of item col', value, object, attribute, header)
- value = 'New Data To Show'
- value
-
- new App.ControllerTable(
- tableId: 'some_id_to_idientify_user_based_table_preferences'
- el: element
- overview: ['host', 'user', 'adapter', 'active']
- model: App.Channel
- objects: data
- groupBy: 'adapter'
- checkbox: false
- radio: false
- class: 'some-css-class'
- bindRow:
- events:
- 'click': rowClick
- 'mouseover': rowMouseover
- 'mouseout': rowMouseout
- 'dblclick': rowDblClick
- bindCol:
- host:
- events:
- 'click': colClick
- bindCheckbox:
- events:
- 'click': rowClick
- 'mouseover': rowMouseover
- 'mouseout': rowMouseout
- 'dblclick': rowDblClick
- callbackHeader: [callbackHeader]
- callbackAttributes:
- attributeName: [
- callbackAttributes
- ]
- dndCallback: =>
- items = @el.find('table > tbody > tr')
- console.log('all effected items', items)
+ renderTableGroupByRow: (object, position, groupByName) =>
+ App.view('generic/table_row_group_by')(
+ position: position
+ groupByName: groupByName
+ columnsLength: @columnsLength
)
- new App.ControllerTable(
- el: element
- overview: ['time', 'area', 'level', 'browser', 'location', 'data']
- attribute_list: [
- { name: 'time', display: 'Time', tag: 'datetime' },
- { name: 'area', display: 'Area', type: 'text' },
- { name: 'level', display: 'Level', type: 'text' },
- { name: 'browser', display: 'Browser', type: 'text' },
- { name: 'location', display: 'Location', type: 'text' },
- { name: 'data', display: 'Data', type: 'text' },
- ]
- objects: data
+ renderTableRow: (object, position) =>
+ App.view('generic/table_row')(
+ headers: @headers
+ attributes: @attributesList
+ checkbox: @checkbox
+ radio: @radio
+ callbacks: @callbackAttributes
+ sortable: @dndCallback
+ position: position
+ object: object
)
- ###
+ tableHeadersHasChanged: =>
+ return true if @overviewAttributes isnt @lastOverview
+ false
- tableGen: =>
- if !@model
- @model = {}
- overview = @overview || @model.configure_overview || []
- attributes = @attribute_list || @model.configure_attributes || {}
- attributes = App.Model.attributesGet(false, attributes)
- destroy = @model.configure_delete
+ tableHeaders: =>
+ orderBy = @customOrderBy || @orderBy
+ orderDirection = @customOrderDirection || @orderDirection
- # check if table is empty
- if _.isEmpty(@objects)
- table = App.view('generic/admin/empty')(
- explanation: @explanation
- )
- return $(table)
+ #console.log('LLL', @lastOrderBy, @orderBy, @lastOrderDirection, @orderDirection, @overviewAttributes, @lastOverview)
+ if @headers && @lastOrderBy is orderBy && @lastOrderDirection is orderDirection && !@tableHeadersHasChanged()
+ console.log('tableHeaders: same overviewAttributes just return headers', @headers)
+ return ['headers are the same', @headers]
+ @lastOverview = @overviewAttributes
# get header data
@headers = []
- for item in overview
+ for item in @overviewAttributes
headerFound = false
- for attributeName, attribute of attributes
+ for attributeName, attribute of @attributesList
# remove group by attribute from header
if !@groupBy || @groupBy isnt item
@@ -208,8 +499,19 @@ class App.ControllerTable extends App.Controller
attribute.displayWidth = value
@headers.push attribute
+
+ # execute header callback
+ if @callbackHeader
+ for callback in @callbackHeader
+ @headers = callback(@headers)
+
+ if @tableId
+ @calculateHeaderWidths()
+
+ throw 'no headers found' if _.isEmpty(@headers)
+
# add destroy header and col binding
- if destroy
+ if @destroy
@headers.push
name: 'destroy'
display: 'Delete'
@@ -219,14 +521,63 @@ class App.ControllerTable extends App.Controller
parentClass: 'js-delete'
icon: 'trash'
- if !@bindCol
- @bindCol = {}
@bindCol['destroy'] =
events:
click: @deleteRow
- if @orderDirection && @orderBy && !@groupBy
- @objects = @sortList(@objects)
+ @columnsLength = @headers.length
+ if @checkbox || @radio
+ @columnsLength++
+ console.log('tableHeaders: new headers', @headers)
+ ['new headers', @headers]
+
+ sortList: =>
+ return if _.isEmpty(@objects)
+
+
+ orderBy = @customOrderBy || @orderBy
+ orderDirection = @customOrderDirection || @orderDirection
+
+ console.log('order', @orderBy, @orderDirection)
+ console.log('customOrder', @customOrderBy, @customOrderDirection)
+
+ return if _.isEmpty(orderBy) && _.isEmpty(@groupBy)
+
+ return if @lastSortedobjects is @objects && @lastOrderDirection is orderDirection && @lastOrderBy is orderBy
+ @lastOrderDirection = orderDirection
+ @lastOrderBy = orderBy
+
+ if orderBy
+ for header in @headers
+ if header.name is orderBy || "#{header.name}_id" is orderBy# || header.name.substring(0, header.name.length - 3) is orderBy
+ localObjects = _.sortBy(
+ @objects
+ (item) ->
+ # if we need to sort translated col.
+ if header.translate
+ return App.i18n.translateInline(item[header.name])
+
+ # if we need to sort by relation name
+ if header.relation
+ if item[header.name]
+ localItem = App[header.relation].findNative(item[header.name])
+ if localItem
+ if localItem.displayName
+ localItem = localItem.displayName().toLowerCase()
+ if localItem.name
+ localItem = localItem.name.toLowerCase()
+ return localItem
+ return ''
+ item[header.name]
+ )
+ if orderDirection is 'DESC'
+ header.sortOrderIcon = ['arrow-down', 'table-sort-arrow']
+ localObjects = localObjects.reverse()
+ else
+ header.sortOrderIcon = ['arrow-up', 'table-sort-arrow']
+ else
+ header.sortOrderIcon = undefined
+ @objects = localObjects
# group by
if @groupBy
@@ -237,14 +588,19 @@ class App.ControllerTable extends App.Controller
group = object[@groupBy]
if !group
withId = "#{@groupBy}_id"
-
- if object[withId] && attributes[withId] && attributes[withId].relation
- if App[attributes[withId].relation].exists(object[withId])
- item = App[attributes[withId].relation].findNative(object[withId])
+ if object[withId] && @attributesList[withId] && @attributesList[withId].relation
+ if App[@attributesList[withId].relation].exists(object[withId])
+ item = App[@attributesList[withId].relation].findNative(object[withId])
if item && item.displayName
group = item.displayName().toLowerCase()
+ else if item.name
+ group = item.name.toLowerCase()
if _.isEmpty(group)
group = ''
+ if group.displayName
+ group = group.displayName().toLowerCase()
+ else if group.name
+ group = group.name.toLowerCase()
groupObjects[group] ||= []
groupObjects[group].push object
@@ -254,198 +610,15 @@ class App.ControllerTable extends App.Controller
groupsSorted = groupsSorted.sort()
# get new order
- @objects = []
+ localObjects = []
for group in groupsSorted
- localObjects = @sortList(groupObjects[group])
- @objects = @objects.concat localObjects
+ localObjects = localObjects.concat groupObjects[group]
groupObjects[group] = [] # release old array
- # execute header callback
- if @callbackHeader
- for callback in @callbackHeader
- @headers = callback(@headers)
+ @objects = localObjects
+ @lastSortedobjects = localObjects
- if @tableId
- @calculateHeaderWidths()
-
- # generate content
- position = 0
- columnsLength = @headers.length
- if @checkbox || @radio
- columnsLength++
- groupLast = ''
- tableBody = ''
- for object in @objects
- if @groupBy
- groupByName = App.viewPrint(object, @groupBy, attributes)
- if groupLast isnt groupByName
- groupLast = groupByName
- tableBody += App.view('generic/table_row_group_by')(
- position: position
- groupByName: groupByName
- columnsLength: columnsLength
- )
- position++
- tableBody += App.view('generic/table_row')(
- headers: @headers
- attributes: attributes
- checkbox: @checkbox
- radio: @radio
- callbacks: @callbackAttributes
- sortable: @dndCallback
- position: position
- object: object
- )
-
- # generate full table
- table = App.view('generic/table')(
- tableId: @tableId
- headers: @headers
- checkbox: @checkbox
- radio: @radio
- class: @class
- sortable: @dndCallback
- tableBody: tableBody
- )
-
- # convert to jquery object
- table = $(table)
-
- cursorMap =
- click: 'pointer'
- dblclick: 'pointer'
- #mouseover: 'alias'
-
- # bind col.
- if @bindCol
- for name, item of @bindCol
- if item.events
- position = 0
- if @dndCallback
- position += 1
- if @checkbox
- position += 1
- hit = false
-
- for headerName in @headers
- if !hit
- position += 1
- if headerName.name is name || headerName.name is "#{name}_id" || headerName.name is "#{name}_ids"
- hit = true
-
- if hit
- for event, callback of item.events
- do (table, event, callback) ->
- if cursorMap[event]
- table.find("tbody > tr > td:nth-child(#{position})").css('cursor', cursorMap[event])
- table.on( event, "tbody > tr > td:nth-child(#{position})",
- (e) ->
- e.stopPropagation()
- id = $(e.target).parents('tr').data('id')
- callback(id, e)
- )
-
- # bind row
- if @bindRow
- if @bindRow.events
- for event, callback of @bindRow.events
- do (table, event, callback) ->
- if cursorMap[event]
- table.find('tbody > tr').css( 'cursor', cursorMap[event] )
- table.on( event, 'tbody > tr',
- (e) ->
- id = $(e.target).parents('tr').data('id')
- callback(id, e)
- )
-
- # bind bindCheckbox
- if @bindCheckbox
- if @bindCheckbox.events
- for event, callback of @bindCheckbox.events
- do (table, event, callback) ->
- table.delegate('input[name="bulk"]', event, (e) ->
- e.stopPropagation()
- id = $(e.currentTarget).parents('tr').data('id')
- checked = $(e.currentTarget).prop('checked')
- callback(id, checked, e)
- )
-
- # if we have a personalised table
- if @tableId
- # enable resize column
- table.on 'mousedown', '.js-col-resize', @onColResizeMousedown
- table.on 'click', '.js-col-resize', @stopPropagation
-
- # enable sort column
- table.on 'click', '.js-sort', @sortByColumn
-
- # enable checkbox bulk selection
- if @checkbox
-
- # click first tr>td, catch click
- table.delegate('tr > td:nth-child(1)', 'click', (e) ->
- e.stopPropagation()
- )
-
- # bind on full bulk click
- table.delegate('input[name="bulk_all"]', 'change', (e) =>
- e.stopPropagation()
- clicks = []
- if $(e.currentTarget).prop('checked')
- $(e.currentTarget).parents('table').find('[name="bulk"]').each( ->
- $element = $(@)
- return if $element.prop('checked')
- $element.prop('checked', true)
- id = $element.parents('tr').data('id')
- clicks.push [id, true]
- )
- else
- $(e.currentTarget).parents('table').find('[name="bulk"]').each( ->
- $element = $(@)
- return if !$element.prop('checked')
- $element.prop('checked', false)
- id = $element.parents('tr').data('id')
- clicks.push [id, false]
- )
- return if !@bindCheckbox
- return if !@bindCheckbox.events
- return if _.isEmpty(clicks)
- for event, callback of @bindCheckbox.events
- if event == 'click' || event == 'change'
- for click in clicks
- callback(click..., e)
- )
- table
-
- sortList: (objects) =>
-
- for header in @headers
- if header.name is @orderBy
- objects = _.sortBy(
- objects
- (item) ->
- # if we need to sort translated col.
- if header.translate
- return App.i18n.translateInline(item[header.name])
-
- # if we need to sort by relation name
- if header.relation
- if item[header.name]
- localItem = App[header.relation].findNative(item[header.name])
- if localItem && localItem.displayName
- localItem = localItem.displayName().toLowerCase()
- return localItem
- return ''
- item[header.name]
- )
- if @orderDirection is 'DESC'
- header.sortOrderIcon = ['arrow-down', 'table-sort-arrow']
- objects = objects.reverse()
- else
- header.sortOrderIcon = ['arrow-up', 'table-sort-arrow']
- else
- header.sortOrderIcon = undefined
- objects
+ localObjects
# bind on delete dialog
deleteRow: (id, e) =>
@@ -559,30 +732,43 @@ class App.ControllerTable extends App.Controller
# update store and runtime @headerWidth
@preferencesStore('headerWidth', leftColumnKey, leftWidth)
+ @headerWidth[leftColumnKey] = leftWidth
_.find(@headers, (column) -> column.name is leftColumnKey).displayWidth = leftWidth
# update store and runtime @headerWidth
if rightColumnKey
@preferencesStore('headerWidth', rightColumnKey, rightWidth)
+ @headerWidth[rightColumnKey] = rightWidth
_.find(@headers, (column) -> column.name is rightColumnKey).displayWidth = rightWidth
sortByColumn: (event) =>
column = $(event.currentTarget).closest('[data-column-key]').attr('data-column-key')
+ orderBy = @customOrderBy || @orderBy
+ orderDirection = @customOrderDirection || @orderDirection
+
# sort, update runtime @orderBy and @orderDirection
- if @orderBy isnt column
- @orderBy = column
- @orderDirection = 'ASC'
+ if orderBy isnt column
+ orderBy = column
+ orderDirection = 'ASC'
else
- if @orderDirection is 'ASC'
- @orderDirection = 'DESC'
+ if orderDirection is 'ASC'
+ orderDirection = 'DESC'
else
- @orderDirection = 'ASC'
+ orderDirection = 'ASC'
+
+ @orderBy = orderBy
+ @orderDirection = orderDirection
+ @customOrderBy = orderBy
+ @customOrderDirection = orderDirection
# update store
- @preferencesStore('order', 'orderBy', @orderBy)
- @preferencesStore('order', 'orderDirection', @orderDirection)
- @render()
+ @preferencesStore('order', 'customOrderBy', @orderBy)
+ @preferencesStore('order', 'customOrderDirection', @orderDirection)
+ render = =>
+ @renderTableFull()
+ App.QueueManager.add('tableRender', render)
+ App.QueueManager.run('tableRender')
preferencesStore: (type, key, value) ->
data = @preferencesGet()
@@ -601,3 +787,25 @@ class App.ControllerTable extends App.Controller
preferencesStoreKey: =>
"tablePrefs:#{@tableId}"
+
+ getBulkSelected: =>
+ ids = []
+ @$('[name="bulk"]:checked').each( (index, element) ->
+ id = $(element).val()
+ ids.push id
+ )
+ ids
+
+ setBulkSelected: (ids) ->
+ @$('[name="bulk"]').each( (index, element) ->
+ id = $(element).val()
+ for idSelected in ids
+ if idSelected is id
+ $(element).prop('checked', true)
+ )
+
+ _isSame: (array1, array2) ->
+ for position in [0..array1.length-1]
+ if array1[position] isnt array2[position]
+ return position
+ true
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/ticket_overview.coffee b/app/assets/javascripts/app/controllers/ticket_overview.coffee
index 39f1c4e9a..da11a230f 100644
--- a/app/assets/javascripts/app/controllers/ticket_overview.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_overview.coffee
@@ -540,20 +540,23 @@ class App.TicketOverview extends App.Controller
render: ->
elLocal = $(App.view('ticket_overview/index')())
- @navBarControllerVertical = new Navbar
+ @navBarControllerVertical = new Navbar(
el: elLocal.find('.overview-header')
view: @view
vertical: true
+ )
- @navBarController = new Navbar
+ @navBarController = new Navbar(
el: elLocal.filter('.sidebar')
view: @view
+ )
- @contentController = new Table
+ @contentController = new Table(
el: elLocal.find('.overview-table')
view: @view
keyboardOn: @keyboardOn
keyboardOff: @keyboardOff
+ )
@renderBatchOverlay(elLocal.filter('.js-batch-overlay'))
@@ -662,10 +665,12 @@ class App.TicketOverview extends App.Controller
@viewLast = @view
# build content
- if @contentController
- @contentController.update(
- view: @view
- )
+ @contentController = new Table(
+ el: @$('.overview-table')
+ view: @view
+ keyboardOn: @keyboardOn
+ keyboardOff: @keyboardOff
+ )
hide: =>
@keyboardOff()
@@ -908,7 +913,7 @@ class Table extends App.Controller
super
if @view
- @bindId = App.OverviewListCollection.bind(@view, @render)
+ @bindId = App.OverviewListCollection.bind(@view, @updateTable)
# rerender view, e. g. on langauge change
@bind 'ui:rerender', =>
@@ -924,18 +929,17 @@ class Table extends App.Controller
for key, value of params
@[key] = value
- @view_mode = App.LocalStorage.get("mode:#{@view}", @Session.get('id')) || 's'
- @log 'notice', 'view:', @view, @view_mode
-
return if !@view
if @view
if @bindId
App.OverviewListCollection.unbind(@bindId)
- @bindId = App.OverviewListCollection.bind(@view, @render)
+ @bindId = App.OverviewListCollection.bind(@view, @updateTable)
- render: (data) =>
- return if !data
+ updateTable: (data) =>
+ if !@table
+ @render(data)
+ return
# use cache
overview = data.overview
@@ -943,6 +947,33 @@ class Table extends App.Controller
return if !overview && !tickets
+ # get ticket list
+ ticketListShow = []
+ for ticket in tickets
+ ticketListShow.push App.Ticket.find(ticket.id)
+ console.log('overview', overview)
+ @overview = App.Overview.find(overview.id)
+ console.log('TTT', @overview.view.s)
+ @table.update(
+ overviewAttributes: @overview.view.s
+ objects: ticketListShow
+ groupBy: @overview.group_by
+ orderBy: @overview.order.by
+ orderDirection: @overview.order.direction
+ )
+
+ render: (data) =>
+ return if !data
+
+ # use cache
+ overview = data.overview
+ tickets = data.tickets
+
+ return if !overview && !tickets
+
+ @view_mode = App.LocalStorage.get("mode:#{@view}", @Session.get('id')) || 's'
+ console.log 'notice', 'view:', @view, @view_mode
+
# get ticket list
ticketListShow = []
for ticket in tickets
@@ -953,8 +984,6 @@ class Table extends App.Controller
@html App.view('customer_not_ticket_exists')()
return
- @selected = @getSelected()
-
# set page title
@overview = App.Overview.find(overview.id)
@@ -1086,7 +1115,7 @@ class Table extends App.Controller
attribute.title = object.iconTitle()
value
- new App.ControllerTable(
+ @table = new App.ControllerTable(
tableId: "ticket_overview_#{@overview.id}"
overview: @overview.view.s
el: @$('.table-overview')
@@ -1123,8 +1152,6 @@ class Table extends App.Controller
'click': callbackCheckbox
)
- @setSelected(@selected)
-
# start user popups
@userPopups()
@@ -1166,22 +1193,6 @@ class Table extends App.Controller
bulkAll.prop('indeterminate', true)
)
- getSelected: ->
- @ticketIDs = []
- @$('.table-overview').find('[name="bulk"]:checked').each( (index, element) =>
- ticketId = $(element).val()
- @ticketIDs.push ticketId
- )
- @ticketIDs
-
- setSelected: (ticketIDs) ->
- @$('.table-overview').find('[name="bulk"]').each( (index, element) ->
- ticketId = $(element).val()
- for ticketIdSelected in ticketIDs
- if ticketIdSelected is ticketId
- $(element).prop('checked', true)
- )
-
viewmode: (e) =>
e.preventDefault()
@view_mode = $(e.target).data('mode')
@@ -1497,6 +1508,7 @@ class App.OverviewSettings extends App.ControllerModal
App.OverviewListCollection.fetch(@overview.link)
else
App.OverviewIndexCollection.trigger()
+ console.log('TRIGGER', @overview.link)
App.OverviewListCollection.trigger(@overview.link)
# close modal
diff --git a/app/assets/javascripts/app/controllers/widget/user_signup_check.coffee b/app/assets/javascripts/app/controllers/widget/user_signup_check.coffee
index 59fe9f770..d1f69529c 100644
--- a/app/assets/javascripts/app/controllers/widget/user_signup_check.coffee
+++ b/app/assets/javascripts/app/controllers/widget/user_signup_check.coffee
@@ -23,6 +23,7 @@ class Widget extends App.Controller
verify: (userId) ->
return if !userId
+ return if !App.User.exists(userId)
user = App.User.find(userId)
return if user.source isnt 'signup'
return if user.verified is true
diff --git a/app/assets/javascripts/app/lib/app_init/session.coffee b/app/assets/javascripts/app/lib/app_init/session.coffee
index 2a670e8d7..87bf31d2d 100644
--- a/app/assets/javascripts/app/lib/app_init/session.coffee
+++ b/app/assets/javascripts/app/lib/app_init/session.coffee
@@ -5,12 +5,12 @@ class App.Session
_instance ?= new _sessionSingleton
_instance.clear()
- @get: ( key ) ->
+ @get: (key) ->
if _instance == undefined
_instance ?= new _sessionSingleton
_instance.get(key)
- @set: ( user ) ->
+ @set: (user) ->
if _instance == undefined
_instance ?= new _sessionSingleton
_instance.set(user)
@@ -24,11 +24,11 @@ class _sessionSingleton extends Spine.Module
clear: ->
@user = undefined
- get: ( key ) ->
+ get: (key) ->
return if !@user
if key
return @user[key]
@user
- set: ( user ) ->
- @user = user
\ No newline at end of file
+ set: (user) ->
+ @user = user
diff --git a/app/assets/javascripts/app/lib/app_post/_collection_base.coffee b/app/assets/javascripts/app/lib/app_post/_collection_base.coffee
index d031dfa11..ddd758914 100644
--- a/app/assets/javascripts/app/lib/app_post/_collection_base.coffee
+++ b/app/assets/javascripts/app/lib/app_post/_collection_base.coffee
@@ -6,6 +6,7 @@ class App._CollectionSingletonBase
@callbacks = {}
@counter = 0
@key = "collection-#{@event}"
+
# read from cache
cache = App.SessionStorage.get(@key)
if cache
@@ -16,6 +17,9 @@ class App._CollectionSingletonBase
@set(data)
@callback(data)
+ App.Event.bind 'auth:logout', (data) =>
+ @clear(data)
+
get: =>
@collectionData
@@ -79,3 +83,6 @@ class App._CollectionSingletonBase
delete @callbacks[counter]
App.QueueManager.add(@key, callback)
App.QueueManager.run(@key)
+
+ clear: =>
+ @collectionData = undefined
diff --git a/app/assets/javascripts/app/lib/app_post/auth.coffee b/app/assets/javascripts/app/lib/app_post/auth.coffee
index 7e02cd79a..f46c8c6e3 100644
--- a/app/assets/javascripts/app/lib/app_post/auth.coffee
+++ b/app/assets/javascripts/app/lib/app_post/auth.coffee
@@ -76,11 +76,7 @@ class App.Auth
App.Session.init()
# update model definition (needed for not authenticated areas like wizard)
- if data.models
- for model, attributes of data.models
- for attribute in attributes
- App[model].attributes.push attribute.name
- App[model].configure_attributes.push attribute
+ @_updateModelAttributes(data.models)
# set locale
locale = window.navigator.userLanguage || window.navigator.language || 'en-us'
@@ -98,11 +94,7 @@ class App.Auth
App.Event.trigger('clearStore')
# update model definition
- if data.models
- for model, attributes of data.models
- for attribute in attributes
- App[model].attributes.push attribute.name
- App[model].configure_attributes.push attribute
+ @_updateModelAttributes(data.models)
# update config
for key, value of data.config
@@ -135,6 +127,14 @@ class App.Auth
App.Event.trigger('ui:rerender')
App.TaskManager.tasksInitial()
+ @_updateModelAttributes: (models) ->
+ return if _.isEmpty(models)
+
+ for model, attributes of models
+ if App[model]
+ if _.isFunction(App[model].updateAttributes)
+ App[model].updateAttributes(attributes)
+
@_logout: (rerender = true) ->
App.Log.debug 'Auth', '_logout'
@@ -149,6 +149,15 @@ class App.Auth
App.Event.trigger('ui:rerender')
App.Event.trigger('clearStore')
+ # clear all in-memory data of all App.Model's
+ for model_key, model_object of App
+ if _.isFunction(model_object.resetCallbacks)
+ model_object.resetCallbacks()
+ if _.isFunction(model_object.resetAttributes)
+ model_object.resetAttributes()
+ if _.isFunction(model_object.clearInMemory)
+ model_object.clearInMemory()
+
@_loginError: ->
App.Log.debug 'Auth', '_loginError:error'
diff --git a/app/assets/javascripts/app/lib/app_post/overview_list_collection.coffee b/app/assets/javascripts/app/lib/app_post/overview_list_collection.coffee
index b605f5503..871f8b660 100644
--- a/app/assets/javascripts/app/lib/app_post/overview_list_collection.coffee
+++ b/app/assets/javascripts/app/lib/app_post/overview_list_collection.coffee
@@ -14,6 +14,9 @@ class _Singleton
@overview[data.overview.view] = data
@callback(data.overview.view, data)
+ App.Event.bind 'auth:logout', (data) =>
+ @clear(data)
+
get: (view) ->
@overview[view]
@@ -76,6 +79,12 @@ class _Singleton
App.QueueManager.add('ticket_overviews', callback)
App.QueueManager.run('ticket_overviews')
+ clear: =>
+ @overview = {}
+ @callbacks = {}
+ @fetchActive = {}
+ @counter = 0
+
class App.OverviewListCollection
_instance = new _Singleton
diff --git a/app/assets/javascripts/app/models/_application_model.coffee b/app/assets/javascripts/app/models/_application_model.coffee
index 49ad8aac9..b6a3e62ce 100644
--- a/app/assets/javascripts/app/models/_application_model.coffee
+++ b/app/assets/javascripts/app/models/_application_model.coffee
@@ -812,3 +812,29 @@ set new attributes of model (remove already available attributes)
item: item
processData: true
)
+
+ @clearInMemory: ->
+ return if !@className
+
+ # reset attributes to prevent cached forms on relogin
+ if !_.isEmpty(App[@className].org_configure_attributes)
+ App[@className].configure_attributes = App[@className].org_configure_attributes
+
+ # reset cached values of model
+ App[@className].deleteAll()
+
+ @updateAttributes: (attributes) ->
+ return if !@className
+ if _.isEmpty(@org_configure_attributes)
+ @org_configure_attributes = clone(@configure_attributes)
+ for attribute in attributes
+ @attributes.push attribute.name
+ @configure_attributes.push attribute
+
+ @resetAttributes: ->
+ return if _.isEmpty(@org_configure_attributes)
+ @configure_attributes = @org_configure_attributes
+
+ @resetCallbacks: ->
+ @SUBSCRIPTION_ITEM = {}
+ @SUBSCRIPTION_COLLECTION = {}
diff --git a/app/assets/javascripts/app/models/user.coffee b/app/assets/javascripts/app/models/user.coffee
index fd93b1c62..b55d9c695 100644
--- a/app/assets/javascripts/app/models/user.coffee
+++ b/app/assets/javascripts/app/models/user.coffee
@@ -25,7 +25,7 @@ class App.User extends App.Model
]
uiUrl: ->
- '#user/profile/' + @id
+ "#user/profile/#{@id}"
icon: ->
'user'
diff --git a/app/assets/javascripts/app/views/generic/table.jst.eco b/app/assets/javascripts/app/views/generic/table.jst.eco
index 7bfdcbe4c..a9aa675ec 100644
--- a/app/assets/javascripts/app/views/generic/table.jst.eco
+++ b/app/assets/javascripts/app/views/generic/table.jst.eco
@@ -20,9 +20,7 @@
<% for header, i in @headers: %>
<%= " align-#{ header.align }" if header.align %>" style="<% if header.displayWidth: %>width:<%= header.displayWidth %>px<% end %>" data-column-key="<%= header.name %>">
-
- <%- @T(header.display) %>
-
+ <%- @T(header.display) %>
<% if header.sortOrderIcon: %>
<%- @Icon(header.sortOrderIcon[0], header.sortOrderIcon[1]) %>
@@ -36,5 +34,5 @@
<% end %>
- <%- @tableBody %>
+ <%- @tableBody %>
\ No newline at end of file
diff --git a/app/assets/javascripts/app/views/generic/table_row.jst.eco b/app/assets/javascripts/app/views/generic/table_row.jst.eco
index ca85df9d7..1aa07f841 100644
--- a/app/assets/javascripts/app/views/generic/table_row.jst.eco
+++ b/app/assets/javascripts/app/views/generic/table_row.jst.eco
@@ -1,4 +1,4 @@
-
+
<% if @sortable: %>
<%- @Icon('draggable') %> |
<% end %>
diff --git a/app/controllers/integration/exchange_controller.rb b/app/controllers/integration/exchange_controller.rb
index cdb3fa427..1e31e0874 100644
--- a/app/controllers/integration/exchange_controller.rb
+++ b/app/controllers/integration/exchange_controller.rb
@@ -11,7 +11,7 @@ class Integration::ExchangeController < ApplicationController
email: params[:user],
password: params[:password],
)
-
+ client.http.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
{
endpoint: client.try(:autodiscover).try(:ews_url),
}
diff --git a/app/controllers/integration/idoit_controller.rb b/app/controllers/integration/idoit_controller.rb
index ee4960c5e..c217de073 100644
--- a/app/controllers/integration/idoit_controller.rb
+++ b/app/controllers/integration/idoit_controller.rb
@@ -1,8 +1,9 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class Integration::IdoitController < ApplicationController
- prepend_before_action -> { authentication_check(permission: ['agent.integration.idoit', 'admin.integration.idoit']) }, except: [:verify]
+ prepend_before_action -> { authentication_check(permission: ['agent.integration.idoit', 'admin.integration.idoit']) }, except: [:verify, :query, :update]
prepend_before_action -> { authentication_check(permission: ['admin.integration.idoit']) }, only: [:verify]
+ prepend_before_action -> { authentication_check(permission: ['ticket.agent']) }, only: [:query, :update]
def verify
response = ::Idoit.verify(params[:api_token], params[:endpoint], params[:client_id])
diff --git a/app/controllers/long_polling_controller.rb b/app/controllers/long_polling_controller.rb
index d52fda49d..f1ef6554e 100644
--- a/app/controllers/long_polling_controller.rb
+++ b/app/controllers/long_polling_controller.rb
@@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class LongPollingController < ApplicationController
- skip_action_callback :session_update # prevent race conditions
+ skip_before_action :session_update # prevent race conditions
# GET /api/v1/message_send
def message_send
diff --git a/app/models/application_model/can_lookup_search_index_attributes.rb b/app/models/application_model/can_lookup_search_index_attributes.rb
index d2d906f6e..96cff5e8f 100644
--- a/app/models/application_model/can_lookup_search_index_attributes.rb
+++ b/app/models/application_model/can_lookup_search_index_attributes.rb
@@ -55,7 +55,7 @@ returns
}
ignored_attributes = self.class.instance_variable_get(:@search_index_attributes_ignored) || []
- return attributes if ignored_attributes.empty?
+ return attributes if ignored_attributes.blank?
ignored_attributes.each { |attribute|
attributes.delete(attribute.to_s)
diff --git a/app/models/application_model/has_cache.rb b/app/models/application_model/has_cache.rb
index aea7ef61e..4ba51ddb3 100644
--- a/app/models/application_model/has_cache.rb
+++ b/app/models/application_model/has_cache.rb
@@ -41,14 +41,14 @@ module ApplicationModel::HasCache
}
# delete old name / login caches
- if changed?
- if changes.key?('name')
- name = changes['name'][0]
+ if saved_changes?
+ if saved_changes.key?('name')
+ name = saved_changes['name'][0]
key = "#{self.class}::#{name}"
Cache.delete(key)
end
- if changes.key?('login')
- name = changes['login'][0]
+ if saved_changes.key?('login')
+ name = saved_changes['login'][0]
key = "#{self.class}::#{name}"
Cache.delete(key)
end
diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb
index 98d3edddd..9b59f8c21 100644
--- a/app/models/channel/email_parser.rb
+++ b/app/models/channel/email_parser.rb
@@ -475,7 +475,7 @@ returns
# check ignore header
if mail['x-zammad-ignore'.to_sym] == 'true' || mail['x-zammad-ignore'.to_sym] == true
Rails.logger.info "ignored email with msgid '#{mail[:message_id]}' from '#{mail[:from]}' because of x-zammad-ignore header"
- return true
+ return
end
# set interface handle
@@ -514,7 +514,7 @@ returns
set_attributes_by_x_headers(ticket, 'ticket', mail, 'followup')
# save changes set by x-zammad-ticket-followup-* headers
- ticket.save if ticket.changed?
+ ticket.save! if ticket.has_changes_to_save?
state = Ticket::State.find(ticket.state_id)
state_type = Ticket::StateType.find(state.state_type_id)
@@ -650,7 +650,7 @@ returns
def self.sender_properties(from)
data = {}
-
+ return data if from.blank?
begin
list = Mail::AddressList.new(from)
list.addresses.each { |address|
diff --git a/app/models/channel/filter/monitoring_base.rb b/app/models/channel/filter/monitoring_base.rb
index c1370d02b..565ef90c0 100644
--- a/app/models/channel/filter/monitoring_base.rb
+++ b/app/models/channel/filter/monitoring_base.rb
@@ -18,7 +18,8 @@ class Channel::Filter::MonitoringBase
sender = Setting.get("#{integration}_sender")
auto_close = Setting.get("#{integration}_auto_close")
auto_close_state_id = Setting.get("#{integration}_auto_close_state_id")
- state_recovery_match = '(OK|UP)'
+ state_ignore_match = Setting.get("#{integration}_ignore_match") || ''
+ state_recovery_match = Setting.get("#{integration}_recovery_match") || '(OK|UP)'
return if mail[:from].blank?
return if mail[:body].blank?
@@ -26,7 +27,7 @@ class Channel::Filter::MonitoringBase
return if !session_user_id
# check if sender is monitoring
- return if !mail[:from].match(/#{Regexp.quote(sender)}/i)
+ return if !Channel::Filter::Database.match(mail[:from], sender, true, true)
# get mail attibutes like host and state
result = {}
@@ -91,5 +92,18 @@ class Channel::Filter::MonitoringBase
mail[ 'x-zammad-ticket-preferences'.to_sym ][key] = value
}
end
+
+ # ignorte states
+ if state_ignore_match.present? && result['state'].present? && result['state'].match(/#{state_ignore_match}/i)
+ mail[ 'x-zammad-ignore'.to_sym ] = true
+ return true
+ end
+
+ # if now problem exists, just ignore the email
+ if result['state'].present? && result['state'].match(/#{state_recovery_match}/i)
+ mail[ 'x-zammad-ignore'.to_sym ] = true
+ return true
+ end
+
end
end
diff --git a/app/models/concerns/has_activity_stream_log.rb b/app/models/concerns/has_activity_stream_log.rb
index d921945ea..95bd65c29 100644
--- a/app/models/concerns/has_activity_stream_log.rb
+++ b/app/models/concerns/has_activity_stream_log.rb
@@ -32,13 +32,13 @@ log object update activity stream, if configured - will be executed automaticall
=end
def activity_stream_update
- return true if !changed?
+ return true if !saved_changes?
ignored_attributes = self.class.instance_variable_get(:@activity_stream_attributes_ignored) || []
ignored_attributes += %i(created_at updated_at created_by_id updated_by_id)
log = false
- changes.each { |key, _value|
+ saved_changes.each { |key, _value|
next if ignored_attributes.include?(key.to_sym)
log = true
diff --git a/app/models/concerns/has_history.rb b/app/models/concerns/has_history.rb
index 10eeb1128..4aa09a73c 100644
--- a/app/models/concerns/has_history.rb
+++ b/app/models/concerns/has_history.rb
@@ -33,13 +33,13 @@ log object update history with all updated attributes, if configured - will be e
=end
def history_update
- return if !changed?
+ return if !saved_changes?
# return if it's no update
return if new_record?
# new record also triggers update, so ignore new records
- changes = self.changes
+ changes = saved_changes
if history_changes_last_done
history_changes_last_done.each { |key, value|
if changes.key?(key) && changes[key] == value
diff --git a/app/models/locale.rb b/app/models/locale.rb
index 854fd75ce..9381ba46a 100644
--- a/app/models/locale.rb
+++ b/app/models/locale.rb
@@ -99,6 +99,8 @@ all:
},
{
json: true,
+ open_timeout: 8,
+ read_timeout: 24,
}
)
diff --git a/app/models/observer/sla/ticket_rebuild_escalation.rb b/app/models/observer/sla/ticket_rebuild_escalation.rb
index 9ee2f71c0..c267718ec 100644
--- a/app/models/observer/sla/ticket_rebuild_escalation.rb
+++ b/app/models/observer/sla/ticket_rebuild_escalation.rb
@@ -27,7 +27,7 @@ class Observer::Sla::TicketRebuildEscalation < ActiveRecord::Observer
def _check(record)
# return if we run import mode
- return if Setting.get('import_mode') && !Setting.get('import_ignore_sla')
+ return true if Setting.get('import_mode') && !Setting.get('import_ignore_sla')
# check if condition has changed
changed = false
@@ -38,11 +38,11 @@ class Observer::Sla::TicketRebuildEscalation < ActiveRecord::Observer
%w(timezone business_hours default ical_url public_holidays)
end
fields_to_check.each { |item|
- next if !record.changes[item]
- next if record.changes[item][0] == record.changes[item][1]
+ next if !record.saved_change_to_attribute(item)
+ next if record.saved_change_to_attribute(item)[0] == record.saved_change_to_attribute(item)[1]
changed = true
}
- return if !changed
+ return true if !changed
_rebuild(record)
end
diff --git a/app/models/observer/ticket/last_owner_update.rb b/app/models/observer/ticket/last_owner_update.rb
index ab100ba50..e96b5712d 100644
--- a/app/models/observer/ticket/last_owner_update.rb
+++ b/app/models/observer/ticket/last_owner_update.rb
@@ -20,7 +20,7 @@ class Observer::Ticket::LastOwnerUpdate < ActiveRecord::Observer
# check if owner has changed
if type == 'update'
- return true if record.changes['owner_id'].blank?
+ return true if record.changes_to_save['owner_id'].blank?
end
# check if owner is nobody
diff --git a/app/models/observer/ticket/online_notification_seen.rb b/app/models/observer/ticket/online_notification_seen.rb
index dee1774ef..04d3a3285 100644
--- a/app/models/observer/ticket/online_notification_seen.rb
+++ b/app/models/observer/ticket/online_notification_seen.rb
@@ -19,8 +19,8 @@ class Observer::Ticket::OnlineNotificationSeen < ActiveRecord::Observer
return false if Setting.get('import_mode')
# set seen only if state has changes
- return false if record.changes.blank?
- return false if record.changes['state_id'].blank?
+ return false if !record.saved_changes?
+ return false if record.saved_changes['state_id'].blank?
# check if existing online notifications for this ticket should be set to seen
return true if !record.online_notification_seen_state
diff --git a/app/models/observer/ticket/ref_object_touch.rb b/app/models/observer/ticket/ref_object_touch.rb
index bd8007d4c..242de0ed9 100644
--- a/app/models/observer/ticket/ref_object_touch.rb
+++ b/app/models/observer/ticket/ref_object_touch.rb
@@ -18,10 +18,10 @@ class Observer::Ticket::RefObjectTouch < ActiveRecord::Observer
def ref_object_touch(record)
# return if we run import mode
- return if Setting.get('import_mode')
+ return true if Setting.get('import_mode')
# touch old customer if changed
- cutomer_id_changed = record.changes['customer_id']
+ cutomer_id_changed = record.saved_changes['customer_id']
if cutomer_id_changed && cutomer_id_changed[0] != cutomer_id_changed[1]
if cutomer_id_changed[0]
User.find(cutomer_id_changed[0]).touch
@@ -34,7 +34,7 @@ class Observer::Ticket::RefObjectTouch < ActiveRecord::Observer
end
# touch old organization if changed
- organization_id_changed = record.changes['organization_id']
+ organization_id_changed = record.saved_changes['organization_id']
if organization_id_changed && organization_id_changed[0] != organization_id_changed[1]
if organization_id_changed[0]
Organization.find(organization_id_changed[0]).touch
@@ -42,7 +42,7 @@ class Observer::Ticket::RefObjectTouch < ActiveRecord::Observer
end
# touch new/current organization
- return if !record.organization
+ return true if !record.organization
record.organization.touch
end
diff --git a/app/models/observer/ticket/stats_reopen.rb b/app/models/observer/ticket/stats_reopen.rb
index ca363f012..408e3cd48 100644
--- a/app/models/observer/ticket/stats_reopen.rb
+++ b/app/models/observer/ticket/stats_reopen.rb
@@ -19,6 +19,6 @@ class Observer::Ticket::StatsReopen < ActiveRecord::Observer
# return if we run import mode
return if Setting.get('import_mode')
- Stats::TicketReopen.log('Ticket', record.id, record.changes, record.updated_by_id)
+ Stats::TicketReopen.log('Ticket', record.id, record.saved_changes, record.updated_by_id)
end
end
diff --git a/app/models/observer/transaction.rb b/app/models/observer/transaction.rb
index 97651de8f..74754a4b8 100644
--- a/app/models/observer/transaction.rb
+++ b/app/models/observer/transaction.rb
@@ -201,7 +201,7 @@ class Observer::Transaction < ActiveRecord::Observer
# ignore certain attributes
real_changes = {}
- record.changes.each { |key, value|
+ record.changes_to_save.each { |key, value|
next if key == 'updated_at'
next if key == 'first_response_at'
next if key == 'close_at'
diff --git a/app/models/observer/user/ref_object_touch.rb b/app/models/observer/user/ref_object_touch.rb
index 8aa92c765..53352b677 100644
--- a/app/models/observer/user/ref_object_touch.rb
+++ b/app/models/observer/user/ref_object_touch.rb
@@ -22,7 +22,7 @@ class Observer::User::RefObjectTouch < ActiveRecord::Observer
# touch old organization if changed
member_ids = []
- organization_id_changed = record.changes['organization_id']
+ organization_id_changed = record.saved_changes['organization_id']
if organization_id_changed && organization_id_changed[0] != organization_id_changed[1]
if organization_id_changed[0]
diff --git a/app/models/observer/user/ticket_organization.rb b/app/models/observer/user/ticket_organization.rb
index ee238750a..fe3d155da 100644
--- a/app/models/observer/user/ticket_organization.rb
+++ b/app/models/observer/user/ticket_organization.rb
@@ -15,7 +15,7 @@ class Observer::User::TicketOrganization < ActiveRecord::Observer
def check_organization(record)
# check if organization has changed
- return if !record.changes['organization_id']
+ return true if !record.saved_change_to_attribute?('organization_id')
# update last 100 tickets of user
tickets = Ticket.where(customer_id: record.id).limit(100)
diff --git a/app/models/scheduler.rb b/app/models/scheduler.rb
index 844fe5f84..0c5db3386 100644
--- a/app/models/scheduler.rb
+++ b/app/models/scheduler.rb
@@ -12,10 +12,8 @@ class Scheduler < ApplicationModel
Thread.abort_on_exception = true
# reconnect in case db connection is lost
- # See issue #1080
begin
ActiveRecord::Base.connection.reconnect!
- rescue PG::UnableToSend => e # rubocop:disable Lint/HandleExceptions
rescue => e
logger.error "Can't reconnect to database #{e.inspect}"
end
diff --git a/app/models/taskbar.rb b/app/models/taskbar.rb
index cfe9f486e..120abaf12 100644
--- a/app/models/taskbar.rb
+++ b/app/models/taskbar.rb
@@ -104,7 +104,7 @@ class Taskbar < ApplicationModel
end
def notify_clients
- return true if !changes['preferences']
+ return true if !saved_change_to_attribute?('preferences')
data = {
event: 'taskbar:preferences',
data: {
diff --git a/app/models/ticket.rb b/app/models/ticket.rb
index 814949465..2389b0b91 100644
--- a/app/models/ticket.rb
+++ b/app/models/ticket.rb
@@ -1160,7 +1160,7 @@ result
def reset_pending_time
# ignore if no state has changed
- return true if !changes['state_id']
+ return true if !changes_to_save['state_id']
# ignore if new state is blank and
# let handle ActiveRecord the error
diff --git a/app/models/ticket/escalation.rb b/app/models/ticket/escalation.rb
index 4f2f22585..810d72e3b 100644
--- a/app/models/ticket/escalation.rb
+++ b/app/models/ticket/escalation.rb
@@ -76,10 +76,10 @@ returns
# if no escalation is enabled
if !sla || !calendar
- preferences[:escalation_calculation] = {}
# nothing to change
return false if !escalation_at && !first_response_escalation_at && !update_escalation_at && !close_escalation_at
+ preferences['escalation_calculation'] = {}
self.escalation_at = nil
self.first_response_escalation_at = nil
self.escalation_at = nil
@@ -122,7 +122,7 @@ returns
first_response_at_changed = false
end
last_update_at_changed = true
- if escalation_calculation['last_update_at'] == last_update_at && !changes['state_id']
+ if escalation_calculation['last_update_at'] == last_update_at && !saved_change_to_attribute('state_id')
last_update_at_changed = false
end
close_at_changed = true
@@ -352,7 +352,7 @@ returns
).map(&:name)
# add state changes till now
- if add_current && changes['state_id'] && changes['state_id'][0] && changes['state_id'][1]
+ if add_current && saved_change_to_attribute('state_id') && saved_change_to_attribute('state_id')[0] && saved_change_to_attribute('state_id')[1]
last_history_state = nil
history_list.each { |history_item|
next if !history_item['attribute']
@@ -361,14 +361,14 @@ returns
last_history_state = history_item
}
local_updated_at = updated_at
- if changes['updated_at'] && changes['updated_at'][1]
- local_updated_at = changes['updated_at'][1]
+ if saved_change_to_attribute('updated_at') && saved_change_to_attribute('updated_at')[1]
+ local_updated_at = saved_change_to_attribute('updated_at')[1]
end
history_item = {
'attribute' => 'state',
'created_at' => local_updated_at,
- 'value_from' => Ticket::State.find(changes['state_id'][0]).name,
- 'value_to' => Ticket::State.find(changes['state_id'][1]).name,
+ 'value_from' => Ticket::State.find(saved_change_to_attribute('state_id')[0]).name,
+ 'value_to' => Ticket::State.find(saved_change_to_attribute('state_id')[1]).name,
}
if last_history_state
last_history_state = history_item
diff --git a/app/models/translation.rb b/app/models/translation.rb
index 3cea271b7..dde80442a 100644
--- a/app/models/translation.rb
+++ b/app/models/translation.rb
@@ -81,8 +81,8 @@ push translations to online
},
{
json: true,
- open_timeout: 6,
- read_timeout: 16,
+ open_timeout: 8,
+ read_timeout: 24,
}
)
raise "Can't push translations to #{url}: #{result.error}" if !result.success?
diff --git a/app/models/user.rb b/app/models/user.rb
index 8cdbc49a3..0a2cc5dfd 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1055,7 +1055,7 @@ raise 'Minimum one user need to have admin permissions'
def avatar_for_email_check
return true if email.blank?
return true if email !~ /@/
- return true if !changes['email'] && updated_at > Time.zone.now - 10.days
+ return true if !saved_change_to_attribute?('email') && updated_at > Time.zone.now - 10.days
# save/update avatar
avatar = Avatar.auto_detection(
@@ -1106,8 +1106,7 @@ raise 'Minimum one user need to have admin permissions'
# reset login_failed if password is changed
def reset_login_failed
- return true if !changes
- return true if !changes['password']
+ return true if !will_save_change_to_attribute?('password')
self.login_failed = 0
true
end
diff --git a/app/views/tests/table_extended.html.erb b/app/views/tests/table_extended.html.erb
new file mode 100644
index 000000000..eefb9c49e
--- /dev/null
+++ b/app/views/tests/table_extended.html.erb
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/routes/test.rb b/config/routes/test.rb
index 91d738b21..8ccccd6f6 100644
--- a/config/routes/test.rb
+++ b/config/routes/test.rb
@@ -14,6 +14,7 @@ Zammad::Application.routes.draw do
match '/tests_form_column_select', to: 'tests#form_column_select', via: :get
match '/tests_form_searchable_select', to: 'tests#form_searchable_select', via: :get
match '/tests_table', to: 'tests#table', via: :get
+ match '/tests_table_extended', to: 'tests#table_extended', via: :get
match '/tests_html_utils', to: 'tests#html_utils', via: :get
match '/tests_ticket_selector', to: 'tests#ticket_selector', via: :get
match '/tests_taskbar', to: 'tests#taskbar', via: :get
diff --git a/contrib/cleanup.sh b/contrib/cleanup.sh
index 10efac1e9..a4287ae7f 100755
--- a/contrib/cleanup.sh
+++ b/contrib/cleanup.sh
@@ -5,7 +5,3 @@ set -ex
rm app/assets/javascripts/app/controllers/layout_ref.coffee
rm -rf app/assets/javascripts/app/views/layout_ref/
rm app/assets/javascripts/app/controllers/karma.coffee
-rm app/assets/javascripts/app/controllers/report.coffee
-rm app/assets/javascripts/app/controllers/report_profile.coffee
-rm app/assets/javascripts/app/controllers/_integration/check_mk.coffee
-rm app/assets/javascripts/app/controllers/_integration/idoit.coffee
diff --git a/contrib/nginx/zammad.conf b/contrib/nginx/zammad.conf
index 279d35f51..c039880a8 100644
--- a/contrib/nginx/zammad.conf
+++ b/contrib/nginx/zammad.conf
@@ -43,7 +43,7 @@ server {
proxy_set_header CLIENT_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
- proxy_read_timeout 180;
+ proxy_read_timeout 300;
proxy_pass http://zammad;
gzip on;
diff --git a/contrib/nginx/zammad_ssl.conf b/contrib/nginx/zammad_ssl.conf
index de55f36ed..316d65287 100644
--- a/contrib/nginx/zammad_ssl.conf
+++ b/contrib/nginx/zammad_ssl.conf
@@ -134,7 +134,7 @@ server {
proxy_set_header CLIENT_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
- proxy_read_timeout 180;
+ proxy_read_timeout 300;
proxy_pass http://zammad;
gzip on;
diff --git a/lib/idoit.rb b/lib/idoit.rb
index f1fe7f379..271211bf4 100644
--- a/lib/idoit.rb
+++ b/lib/idoit.rb
@@ -42,7 +42,7 @@ returns
"container": "0",
"const": "C__OBJTYPE__SERVICE",
"color": "987384",
- "image": "https://demo.panic.at/i-doit/images/objecttypes/service.jpg",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/service.jpg",
"icon": "images/icons/silk/application_osx_terminal.png",
"cats": "4",
"tree_group": "1",
@@ -56,7 +56,7 @@ returns
"container": "0",
"const": "C__OBJTYPE__APPLICATION",
"color": "E4B9D7",
- "image": "https://demo.panic.at/i-doit/images/objecttypes/application.jpg",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
"icon": "images/icons/silk/application_xp.png",
"cats": "20",
"tree_group": "1",
@@ -71,7 +71,7 @@ or with filter:
"result": [
{
"id": "26",
- "title": "demo.panic.at",
+ "title": "demo.example.com",
"sysid": "SYSID_1485512390",
"type": "59",
"created": "2017-01-27 11:19:24",
@@ -81,7 +81,7 @@ or with filter:
"status": "2",
"cmdb_status": "6",
"cmdb_status_title": "in operation",
- "image": "https://demo.panic.at/i-doit/images/objecttypes/empty.png"
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png"
},
],
@@ -135,6 +135,8 @@ or with filter:
end
def self._url_cleanup(url)
+ url.gsub!(/^[[:space:]]+/, '')
+ url.gsub!(/[[:space:]]+$/, '')
raise "Invalid endpoint '#{url}', need to start with http:// or https://" if url !~ %r{^http(s|)://}i
url = _url_cleanup_baseurl(url)
url = "#{url}/src/jsonrpc.php"
@@ -142,6 +144,8 @@ or with filter:
end
def self._url_cleanup_baseurl(url)
+ url.gsub!(/^[[:space:]]+/, '')
+ url.gsub!(/[[:space:]]+$/, '')
raise "Invalid endpoint '#{url}', need to start with http:// or https://" if url !~ %r{^http(s|)://}i
url.gsub!(%r{src/jsonrpc.php}, '')
url.gsub(%r{([^:])//+}, '\\1/')
diff --git a/lib/import/base_resource.rb b/lib/import/base_resource.rb
index 70761c75b..f96a2aeda 100644
--- a/lib/import/base_resource.rb
+++ b/lib/import/base_resource.rb
@@ -37,7 +37,7 @@ module Import
def changed_attributes
return if @resource.blank?
# dry run
- return @resource.changes if @resource.changed?
+ return @resource.changes_to_save if @resource.has_changes_to_save?
# live run
@resource.previous_changes
end
diff --git a/lib/sequencer/unit/import/common/model/update.rb b/lib/sequencer/unit/import/common/model/update.rb
index fa0947317..1a110a9ef 100644
--- a/lib/sequencer/unit/import/common/model/update.rb
+++ b/lib/sequencer/unit/import/common/model/update.rb
@@ -39,9 +39,9 @@ class Sequencer
def changes
@changes ||= begin
- if instance.changed?
+ if instance.has_changes_to_save?
# dry run
- instance.changes
+ instance.changes_to_save
else
# live run
instance.previous_changes
diff --git a/lib/service/geo_ip/zammad.rb b/lib/service/geo_ip/zammad.rb
index 973879da9..0be67ca54 100644
--- a/lib/service/geo_ip/zammad.rb
+++ b/lib/service/geo_ip/zammad.rb
@@ -4,6 +4,8 @@ require 'cache'
class Service::GeoIp::Zammad
def self.location(address)
+ return {} if address == '127.0.0.1'
+ return {} if address == '::1'
# check cache
cache_key = "zammadgeoip::#{address}"
diff --git a/public/assets/tests/table.js b/public/assets/tests/table.js
index d9aaa7cfd..afc73b58c 100644
--- a/public/assets/tests/table.js
+++ b/public/assets/tests/table.js
@@ -1,5 +1,5 @@
// form
-test( "table test", function() {
+test('table test', function() {
App.i18n.set('de-de')
$('#table').append('
table simple I')
@@ -85,18 +85,18 @@ test( "table test", function() {
}
},
})
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2')
$('#table').append('
table simple II')
el = $('#table2')
@@ -108,18 +108,18 @@ test( "table test", function() {
checkbox: false,
radio: false,
})
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'false', 'check row 1')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'false', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2')
$('#table').append('
table simple III')
el = $('#table3')
@@ -130,16 +130,16 @@ test( "table test", function() {
checkbox: false,
radio: false,
})
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
notEqual( el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
notEqual( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
notEqual( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '?', 'check row 2')
notEqual( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
notEqual( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '?', 'check row 1')
notEqual( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'false', 'check row 1')
@@ -236,60 +236,60 @@ test( "table test", function() {
objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}),
checkbox: true,
})
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Gruppe', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Status', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(9)').text().trim(), 'Erstellt am', 'check header')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 9, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), '', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '4713', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '-', 'check row 2')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(6)').text().trim(), '2 normal', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(7)').text().trim(), 'group 2', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(8)').text().trim(), 'neu', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(9)').text().trim(), '11.07.2014', 'check row 1')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 9, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'group 1', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), 'offen', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 2')
- equal( el.find('tbody > tr:nth-child(3) > td').length, 9, 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), '', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), '', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '4711', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'some title 1', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(4)').text().trim(), 'firstname55 lastname55', 'check row 2')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(5)').text().trim(), 'firstname56 lastname56', 'check row 2')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(7)').text().trim(), 'group 2', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(8)').text().trim(), 'neu', 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 3')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Gruppe', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Status', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(9)').text().trim(), 'Erstellt am', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 9, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), '', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '4713', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '-', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(6)').text().trim(), '2 normal', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(7)').text().trim(), 'group 2', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(8)').text().trim(), 'neu', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(9)').text().trim(), '11.07.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 9, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'group 1', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), 'offen', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 9, 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), '', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), '', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '4711', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'some title 1', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(4)').text().trim(), 'firstname55 lastname55', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(5)').text().trim(), 'firstname56 lastname56', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(7)').text().trim(), 'group 2', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(8)').text().trim(), 'neu', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 3')
el.find('input[name="bulk_all"]').click()
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), true, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), true, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), true, 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), true, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), true, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), true, 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3')
$('#table').append('
table complex II')
el = $('#table5')
@@ -309,55 +309,55 @@ test( "table test", function() {
}
},
})
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Status', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Erstellt am', 'check header')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'group 1', 'check row 1')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 8, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'offen', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), '10.06.2014', 'check row 2')
- equal( el.find('tbody > tr:nth-child(3) > td').length, 1, 'check row 3')
- equal( el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), 'group 2', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td').length, 8, 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), '', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(1)').text().trim(), '', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(2)').text().trim(), '4713', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(5)').text().trim(), '-', 'check row 2')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(6)').text().trim(), '2 normal', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(7)').text().trim(), 'neu', 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(8)').text().trim(), '11.07.2014', 'check row 4')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Status', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Erstellt am', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'group 1', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 8, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'offen', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 1, 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), 'group 2', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td').length, 8, 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), '', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1)').text().trim(), '', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(2)').text().trim(), '4713', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(5)').text().trim(), '-', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(6)').text().trim(), '2 normal', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(7)').text().trim(), 'neu', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(8)').text().trim(), '11.07.2014', 'check row 4')
el.find('input[name="bulk"]:eq(1)').click()
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 1')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), true, 'check row 4')
- equal( el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4')
- equal( el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), '', 'check row 5')
- equal( el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), true, 'check row 4')
+ equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4')
+ equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), '', 'check row 5')
+ equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5')
el.find('tbody > tr:nth-child(5) > td:nth-child(1) label').click()
- equal( el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), true, 'check row 5')
- equal( el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5')
+ equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), true, 'check row 5')
+ equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5')
});
-test( "table test 2", function() {
+test('table test 2', function() {
App.i18n.set('de-de')
$('#table').append('
table with hash')
@@ -413,27 +413,27 @@ test( "table test 2", function() {
model: App.Channel,
objects: App.Channel.search({sortBy:'adapter', order: 'ASC'}),
})
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Löschen', 'check header')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '', 'check row 1')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '', 'check row 2')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Löschen', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '', 'check row 2')
});
-test( "table test 3", function() {
+test('table test 3', function() {
App.i18n.set('de-de')
$('#table').append('
table with link')
@@ -508,31 +508,31 @@ test( "table test 3", function() {
},
},
})
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'richtiger Name', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Some Name', 'check header')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'realname 55', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'email 55', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), '', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('some'), 'value55', 'check row 2')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('xxx'), '55', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'realname 56', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'email 56', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), '', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('some'), 'value56', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('xxx'), '56', 'check row 2')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'richtiger Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Some Name', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'realname 55', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'email 55', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), '', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('some'), 'value55', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('xxx'), '55', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'realname 56', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'email 56', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), '', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('some'), 'value56', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('xxx'), '56', 'check row 2')
});
-test( "table test 4", function() {
+test('table test 4', function() {
App.i18n.set('de-de')
$('#table').append('
table with data')
@@ -554,16 +554,16 @@ test( "table test 4", function() {
objects: data
});
- equal( el.find('table > thead > tr').length, 1, 'row count')
- equal( el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Data', 'check header')
- equal( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
- equal( el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some name 1', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'some data 1', 'check row 1')
- equal( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
- equal( el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:first').text().trim(), 'some name 2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'some data 2', 'check row 2')
- equal( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2')
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Data', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some name 1', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'some data 1', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), 'some name 2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'some data 2', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2')
});
diff --git a/public/assets/tests/table_extended.js b/public/assets/tests/table_extended.js
new file mode 100644
index 000000000..fb8f38834
--- /dev/null
+++ b/public/assets/tests/table_extended.js
@@ -0,0 +1,274 @@
+// initial list
+test('table new - initial list', function() {
+ App.i18n.set('de-de')
+
+ $('#table').append('
table with data')
+ var el = $('#table-new1')
+
+ App.TicketPriority.refresh([
+ {
+ id: 1,
+ name: '1 low',
+ note: 'some note 1',
+ active: true,
+ created_at: '2014-06-10T11:17:34.000Z',
+ },
+ {
+ id: 2,
+ name: '2 normal',
+ note: 'some note 2',
+ active: false,
+ created_at: '2014-06-10T10:17:34.000Z',
+ },
+ ], {clear: true})
+
+ var table = new App.ControllerTable({
+ el: el,
+ overviewAttributes: ['name', 'created_at', 'active'],
+ model: App.TicketPriority,
+ objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}),
+ checkbox: false,
+ radio: false,
+ })
+ //equal(el.find('table').length, 0, 'row count')
+ //table.render()
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3')
+
+ result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})})
+ equal(result[0], 'noChanges')
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+
+ App.TicketPriority.refresh([
+ {
+ id: 1,
+ name: 'Priority',
+ note: 'some note 1',
+ active: true,
+ created_at: '2014-06-10T11:17:34.000Z',
+ },
+ ], {clear: true})
+
+ result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})})
+ equal(result[0], 'fullRender.lenghtChanged')
+ equal(result[1], 2)
+ equal(result[2], 1)
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'Priorität', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 0, 'check row 2')
+
+ App.TicketPriority.refresh([], {clear: true})
+
+ result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})})
+ equal(result[0], 'emptyList')
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1')
+
+ App.TicketPriority.refresh([
+ {
+ id: 1,
+ name: '1 low',
+ note: 'some note 1',
+ active: true,
+ created_at: '2014-06-10T11:17:34.000Z',
+ },
+ {
+ id: 2,
+ name: '2 normal',
+ note: 'some note 2',
+ active: false,
+ created_at: '2014-06-10T10:17:34.000Z',
+ },
+ ], {clear: true})
+
+ result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})})
+ equal(result[0], 'fullRender')
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3')
+
+ App.TicketPriority.refresh([
+ {
+ id: 1,
+ name: '1 low',
+ note: 'some note 1',
+ active: true,
+ created_at: '2014-06-10T11:17:34.000Z',
+ },
+ {
+ id: 2,
+ name: '2 normal',
+ note: 'some note 2',
+ active: false,
+ created_at: '2014-06-10T10:17:34.000Z',
+ },
+ {
+ id: 3,
+ name: '3 high',
+ note: 'some note 3',
+ active: false,
+ created_at: '2014-06-10T10:17:38.000Z',
+ },
+ ], {clear: true})
+
+ result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})})
+ equal(result[0], 'fullRender.lenghtChanged')
+ equal(result[1], 2)
+ equal(result[2], 3)
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4')
+
+ result = table.update({sync: true, orderDirection: 'DESC', orderBy: 'name'})
+ equal(result[0], 'fullRender.contentChanged')
+ equal(result[1], 0)
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '1 niedrig', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4')
+
+ result = table.update({sync: true, orderDirection: 'ASC', orderBy: 'name'})
+ equal(result[0], 'fullRender.contentChanged')
+ equal(result[1], 0)
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4')
+
+ App.TicketPriority.refresh([
+ {
+ id: 1,
+ name: '1 low',
+ note: 'some note 1',
+ active: true,
+ created_at: '2014-06-10T11:17:34.000Z',
+ },
+ {
+ id: 3,
+ name: '3 high',
+ note: 'some note 3',
+ active: false,
+ created_at: '2014-06-10T10:17:38.000Z',
+ },
+ ], {clear: true})
+
+ result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})})
+ equal(result[0], 'fullRender.contentRemoved')
+ equal(result[1], 1)
+ notOk(result[2])
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3')
+
+ result = table.update({sync: true, overviewAttributes: ['name', 'created_at']})
+ equal(result[0], 'fullRender.overviewAttributesChanged')
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header')
+ equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header')
+ equal(el.find('table > thead > tr > th').length, 2, 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 2, 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1')
+ equal(el.find('tbody > tr:nth-child(2) > td').length, 2, 'check row 2')
+ equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3')
+ equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3')
+
+ App.TicketPriority.refresh([], {clear: true})
+
+ result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})})
+ equal(result[0], 'emptyList')
+
+ equal(el.find('table > thead > tr').length, 1, 'row count')
+ equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header')
+ equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1')
+
+})
diff --git a/public/assets/tests/ui.js b/public/assets/tests/ui.js
index 10277383d..b01307a63 100644
--- a/public/assets/tests/ui.js
+++ b/public/assets/tests/ui.js
@@ -109,4 +109,8 @@ test("check pretty date", function() {
result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 30.5));
equal(result, 'in 30 days', 'in 30.5 days')
+ //
+
+
+
});
diff --git a/script/build/test_slice_tests.sh b/script/build/test_slice_tests.sh
index 00f5b7e2f..34e837538 100755
--- a/script/build/test_slice_tests.sh
+++ b/script/build/test_slice_tests.sh
@@ -60,6 +60,7 @@ if [ "$LEVEL" == '1' ]; then
# test/browser/taskbar_session_test.rb
# test/browser/taskbar_task_test.rb
# test/browser/translation_test.rb
+ rm test/browser/user_switch_cache_test.rb
elif [ "$LEVEL" == '2' ]; then
echo "slicing level 2"
@@ -117,6 +118,7 @@ elif [ "$LEVEL" == '2' ]; then
rm test/browser/taskbar_session_test.rb
rm test/browser/taskbar_task_test.rb
rm test/browser/translation_test.rb
+ #rm test/browser/user_switch_cache_test.rb
elif [ "$LEVEL" == '3' ]; then
echo "slicing level 3"
@@ -174,6 +176,7 @@ elif [ "$LEVEL" == '3' ]; then
rm test/browser/taskbar_session_test.rb
rm test/browser/taskbar_task_test.rb
rm test/browser/translation_test.rb
+ rm test/browser/user_switch_cache_test.rb
elif [ "$LEVEL" == '4' ]; then
echo "slicing level 4"
@@ -231,6 +234,7 @@ elif [ "$LEVEL" == '4' ]; then
rm test/browser/taskbar_session_test.rb
rm test/browser/taskbar_task_test.rb
rm test/browser/translation_test.rb
+ rm test/browser/user_switch_cache_test.rb
elif [ "$LEVEL" == '5' ]; then
echo "slicing level 5"
@@ -287,6 +291,7 @@ elif [ "$LEVEL" == '5' ]; then
rm test/browser/taskbar_session_test.rb
rm test/browser/taskbar_task_test.rb
rm test/browser/translation_test.rb
+ rm test/browser/user_switch_cache_test.rb
elif [ "$LEVEL" == '6' ]; then
echo "slicing level 6"
@@ -346,6 +351,7 @@ elif [ "$LEVEL" == '6' ]; then
rm test/browser/taskbar_session_test.rb
rm test/browser/taskbar_task_test.rb
rm test/browser/translation_test.rb
+ rm test/browser/user_switch_cache_test.rb
else
echo "ERROR: Invalid level $LEVEL - 1, 2, 3, 4, 5 or 6 is available"
diff --git a/script/scheduler.rb b/script/scheduler.rb
index 5be7db8c3..fdd2e8523 100755
--- a/script/scheduler.rb
+++ b/script/scheduler.rb
@@ -16,6 +16,12 @@ require 'daemons'
def before_fork
+ # clear all connections before for, reconnect later ActiveRecord::Base.connection.reconnect!
+ # issue #1405 - Scheduler not running because of Bad file descriptor in PGConsumeInput()
+ # https://github.com/zammad/zammad/issues/1405
+ # see also https://bitbucket.org/ged/ruby-pg/issues/260/frequent-crashes-with-multithreading
+ ActiveRecord::Base.clear_all_connections!
+
# remember open file handles
@files_to_reopen = []
ObjectSpace.each_object(File) do |file|
diff --git a/spec/lib/external_sync_spec.rb b/spec/lib/external_sync_spec.rb
index b4f6d973d..14f4b4cd0 100644
--- a/spec/lib/external_sync_spec.rb
+++ b/spec/lib/external_sync_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe ExternalSync do
current_changes: current_changes,
)
- expect(result).to be false
- expect(object.changed?).to be false
+ expect(result).to be false
+ expect(object.has_changes_to_save?).to be false
end
it 'keeps ActiveRecord instance unchanged on local and remote changes' do
@@ -30,8 +30,8 @@ RSpec.describe ExternalSync do
current_changes: current_changes,
)
- expect(result).to be false
- expect(object.changed?).to be false
+ expect(result).to be false
+ expect(object.has_changes_to_save?).to be false
end
it 'changes ActiveRecord instance attribute(s) for remote changes' do
@@ -45,8 +45,8 @@ RSpec.describe ExternalSync do
current_changes: current_changes,
)
- expect(result).to be true
- expect(object.changed?).to be true
+ expect(result).to be true
+ expect(object.has_changes_to_save?).to be true
end
it 'prevents ActiveRecord method calls' do
@@ -61,9 +61,9 @@ RSpec.describe ExternalSync do
current_changes: current_changes,
)
- expect(result).to be false
- expect(object.changed?).to be false
- expect(object.destroyed?).to be false
+ expect(result).to be false
+ expect(object.has_changes_to_save?).to be false
+ expect(object.destroyed?).to be false
end
end
diff --git a/test/browser/aab_unit_test.rb b/test/browser/aab_unit_test.rb
index 6191dfa85..94a960793 100644
--- a/test/browser/aab_unit_test.rb
+++ b/test/browser/aab_unit_test.rb
@@ -118,6 +118,13 @@ class AAbUnitTest < TestCase
value: '0',
)
+ location(url: browser_url + '/tests_table_extended')
+ sleep 4
+ match(
+ css: '.result .failed',
+ value: '0',
+ )
+
location(url: browser_url + '/tests_html_utils')
sleep 4
match(
diff --git a/test/browser/user_switch_cache_test.rb b/test/browser/user_switch_cache_test.rb
new file mode 100644
index 000000000..7b700c7ab
--- /dev/null
+++ b/test/browser/user_switch_cache_test.rb
@@ -0,0 +1,83 @@
+# encoding: utf-8
+require 'browser_test_helper'
+
+class UserSwitchCache < TestCase
+ def test_re_login
+
+ # login as agent and create one ticket
+ @browser = browser_instance
+ login(
+ username: 'agent1@example.com',
+ password: 'test',
+ url: browser_url,
+ )
+ tasks_close_all()
+ ticket1 = ticket_create(
+ data: {
+ customer: 'nico',
+ group: 'Users',
+ title: 'some subject 123äöü - reply test',
+ body: 'some body 123äöü - reply test',
+ },
+ )
+
+ logout()
+
+ # login as customer and verify ticket create screen
+ login(
+ username: 'nicole.braun@zammad.org',
+ password: 'test',
+ url: browser_url,
+ )
+ click(css: 'a[href="#new"]')
+ click(css: 'a[href="#customer_ticket_new"]')
+ sleep 4
+
+ match(
+ css: '#content',
+ value: 'Priority',
+ should_not_match: true,
+ )
+
+ match(
+ css: '#content',
+ value: 'Owner',
+ should_not_match: true,
+ )
+
+ match(
+ css: '#content',
+ value: 'State',
+ )
+
+ logout()
+
+ # login again as customer and verify ticket create screen
+ login(
+ username: 'nicole.braun@zammad.org',
+ password: 'test',
+ url: browser_url,
+ )
+ click(css: 'a[href="#new"]')
+ click(css: 'a[href="#customer_ticket_new"]')
+ sleep 4
+
+ match(
+ css: '#content',
+ value: 'Priority',
+ should_not_match: true,
+ )
+
+ match(
+ css: '#content',
+ value: 'Owner',
+ should_not_match: true,
+ )
+
+ match(
+ css: '#content',
+ value: 'State',
+ )
+
+ end
+end
diff --git a/test/fixtures/idoit/object_types_filter_response.json b/test/fixtures/idoit/object_types_filter_response.json
new file mode 100644
index 000000000..ea22a92b7
--- /dev/null
+++ b/test/fixtures/idoit/object_types_filter_response.json
@@ -0,0 +1,18 @@
+{
+ "jsonrpc": "2.0",
+ "result": [{
+ "id": "26",
+ "title": "demo.example.com",
+ "sysid": "SYSID_1485512390",
+ "type": "59",
+ "created": "2017-01-27 11:19:24",
+ "updated": "2017-01-27 11:19:49",
+ "type_title": "Virtual server",
+ "type_group_title": "Infrastructure",
+ "status": "2",
+ "cmdb_status": "6",
+ "cmdb_status_title": "in operation",
+ "image": "https://idoit.example.com/i-doit/images/objecttypes/empty.png"
+ }],
+ "id": 1
+}
\ No newline at end of file
diff --git a/test/fixtures/idoit/object_types_response.json b/test/fixtures/idoit/object_types_response.json
new file mode 100644
index 000000000..5910e6ba9
--- /dev/null
+++ b/test/fixtures/idoit/object_types_response.json
@@ -0,0 +1,945 @@
+{
+ "jsonrpc": "2.0",
+ "result": [{
+ "id": "1",
+ "title": "System service",
+ "container": "0",
+ "const": "C__OBJTYPE__SERVICE",
+ "color": "987384",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/service.jpg",
+ "icon": "images/icons/silk/application_osx_terminal.png",
+ "cats": "4",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "2",
+ "title": "Application",
+ "container": "0",
+ "const": "C__OBJTYPE__APPLICATION",
+ "color": "E4B9D7",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
+ "icon": "images/icons/silk/application_xp.png",
+ "cats": "20",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "33",
+ "title": "Licenses",
+ "container": "0",
+ "const": "C__OBJTYPE__LICENCE",
+ "color": "EADEAC",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/licence.png",
+ "icon": "images/icons/silk/key.png",
+ "cats": "24",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "35",
+ "title": "Operating System",
+ "container": "0",
+ "const": "C__OBJTYPE__OPERATING_SYSTEM",
+ "color": "838683",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
+ "icon": "images/icons/silk/application_osx.png",
+ "cats": "20",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "56",
+ "title": "Cluster services",
+ "container": "0",
+ "const": "C__OBJTYPE__CLUSTER_SERVICE",
+ "color": "B6BFC9",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
+ "icon": "images/icons/silk/application_cascade.png",
+ "cats": "58",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "61",
+ "title": "DBMS",
+ "container": "0",
+ "const": "C__OBJTYPE__DBMS",
+ "color": "AAAAAA",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/san.png",
+ "icon": "images/icons/silk/database.png",
+ "cats": "62",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "62",
+ "title": "Database schema",
+ "container": "0",
+ "const": "C__OBJTYPE__DATABASE_SCHEMA",
+ "color": "B0C4DE",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
+ "icon": "images/icons/silk/database_table.png",
+ "cats": "60",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "65",
+ "title": "Database instance",
+ "container": "0",
+ "const": "C__OBJTYPE__DATABASE_INSTANCE",
+ "color": "61C384",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/service.jpg",
+ "icon": "images/icons/silk/database_connect.png",
+ "cats": "63",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "66",
+ "title": "Middleware",
+ "container": "0",
+ "const": "C__OBJTYPE__MIDDLEWARE",
+ "color": "EEFFDE",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "middleware.png",
+ "cats": "75",
+ "tree_group": "1",
+ "status": "2",
+ "type_group": "1",
+ "type_group_title": "Software"
+ }, {
+ "id": "3",
+ "title": "Building",
+ "container": "1",
+ "const": "C__OBJTYPE__BUILDING",
+ "color": "D1695E",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/building.png",
+ "icon": "images/icons/silk/building.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "4",
+ "title": "Rack",
+ "container": "1",
+ "const": "C__OBJTYPE__ENCLOSURE",
+ "color": "D3E3FA",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/enclosure.png",
+ "icon": "images/icons/silk/timeline_marker_rotated.png",
+ "cats": "1",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "5",
+ "title": "Server",
+ "container": "0",
+ "const": "C__OBJTYPE__SERVER",
+ "color": "A2BCFA",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/server.png",
+ "icon": "images/icons/silk/server.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "6",
+ "title": "Switch",
+ "container": "0",
+ "const": "C__OBJTYPE__SWITCH",
+ "color": "B8BED1",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/switch.png",
+ "icon": "images/icons/silk/drive_network.png",
+ "cats": "5",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "7",
+ "title": "Router",
+ "container": "0",
+ "const": "C__OBJTYPE__ROUTER",
+ "color": "97D414",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/router.png",
+ "icon": "images/icons/silk/drive_web.png",
+ "cats": "17",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "8",
+ "title": "FC switch",
+ "container": "0",
+ "const": "C__OBJTYPE__FC_SWITCH",
+ "color": "9FC380",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/fcswitch.png",
+ "icon": "images/icons/silk/drive_network.png",
+ "cats": "16",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "9",
+ "title": "Storage system",
+ "container": "0",
+ "const": "C__OBJTYPE__SAN",
+ "color": "F0F0E3",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/san.png",
+ "icon": "images/icons/silk/drive_cd_empty.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "10",
+ "title": "Client",
+ "container": "0",
+ "const": "C__OBJTYPE__CLIENT",
+ "color": "B9E1BE",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/client.png",
+ "icon": "images/icons/silk/computer.png",
+ "cats": "15",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "11",
+ "title": "Printer",
+ "container": "0",
+ "const": "C__OBJTYPE__PRINTER",
+ "color": "4E93BE",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/printer.png",
+ "icon": "images/icons/silk/printer.png",
+ "cats": "18",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "12",
+ "title": "Air Condition System",
+ "container": "0",
+ "const": "C__OBJTYPE__AIR_CONDITION_SYSTEM",
+ "color": "A88AA7",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/aircond.png",
+ "icon": "klima.gif",
+ "cats": "9",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "19",
+ "title": "KVM switch",
+ "container": "0",
+ "const": "C__OBJTYPE__KVM_SWITCH",
+ "color": "7EDF8D",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/router.png",
+ "icon": "images/icons/silk/image_link.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "22",
+ "title": "Monitor",
+ "container": "0",
+ "const": "C__OBJTYPE__MONITOR",
+ "color": "DCE0D7",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/monitor.png",
+ "icon": "images/icons/silk/monitor.png",
+ "cats": "14",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "23",
+ "title": "Appliance",
+ "container": "0",
+ "const": "C__OBJTYPE__APPLIANCE",
+ "color": "6EAEBF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/appliances.png",
+ "icon": "images/icons/silk/drive_disk.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "24",
+ "title": "Telephone system",
+ "container": "0",
+ "const": "C__OBJTYPE__TELEPHONE_SYSTEM",
+ "color": "DDEFFC",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/phonesys.png",
+ "icon": "images/icons/silk/telephone_link.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "25",
+ "title": "Printbox",
+ "container": "0",
+ "const": "C__OBJTYPE__PRINTBOX",
+ "color": "90AD8B",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/printerbox.png",
+ "icon": "images/icons/silk/printer_empty.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "26",
+ "title": "Room",
+ "container": "1",
+ "const": "C__OBJTYPE__ROOM",
+ "color": "E4FF9E",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/room.png",
+ "icon": "room.gif",
+ "cats": "3",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "27",
+ "title": "Wireless Access Point",
+ "container": "0",
+ "const": "C__OBJTYPE__ACCESS_POINT",
+ "color": "C5C8B4",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/wlan.jpg",
+ "icon": "images/icons/silk/television.png",
+ "cats": "13",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "38",
+ "title": "Phone",
+ "container": "0",
+ "const": "C__OBJTYPE__PHONE",
+ "color": "6886B4",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/phone.png",
+ "icon": "images/icons/silk/telephone.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "39",
+ "title": "Host",
+ "container": "0",
+ "const": "C__OBJTYPE__HOST",
+ "color": "DADA5E",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/server.png",
+ "icon": "images/icons/silk/server.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "40",
+ "title": "Cable",
+ "container": "0",
+ "const": "C__OBJTYPE__CABLE",
+ "color": "B39E92",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/fcswitch.png",
+ "icon": "kabel.gif",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "41",
+ "title": "Converter",
+ "container": "0",
+ "const": "C__OBJTYPE__CONVERTER",
+ "color": "CAB97D",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/fcswitch.png",
+ "icon": "images/icons/silk/connect.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "42",
+ "title": "Wiring System",
+ "container": "0",
+ "const": "C__OBJTYPE__WIRING_SYSTEM",
+ "color": "D1695E",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/fcswitch.png",
+ "icon": "images/icons/silk/text_letter_omega.png",
+ "cats": "40",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "43",
+ "title": "Patch Panel",
+ "container": "0",
+ "const": "C__OBJTYPE__PATCH_PANEL",
+ "color": "BCDCB9",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/switch.png",
+ "icon": "images/icons/silk/drive_rename_dotted.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "44",
+ "title": "Amplifier",
+ "container": "0",
+ "const": "C__OBJTYPE__AMPLIFIER",
+ "color": "AF7FF1",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/appliances.png",
+ "icon": "verstaerker.gif",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "46",
+ "title": "Electric power company",
+ "container": "0",
+ "const": "C__OBJTYPE__ESC",
+ "color": "EB8348",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/power.jpg",
+ "icon": "images/icons/silk/lightbulb.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "47",
+ "title": "Emergency power supply",
+ "container": "0",
+ "const": "C__OBJTYPE__EPS",
+ "color": "E1E79E",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/power.jpg",
+ "icon": "nea.gif",
+ "cats": "43",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "48",
+ "title": "Distribution box",
+ "container": "0",
+ "const": "C__OBJTYPE__DISTRIBUTION_BOX",
+ "color": "A5EEA0",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/power.jpg",
+ "icon": "verteiler.gif",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "49",
+ "title": "Power distribution unit",
+ "container": "0",
+ "const": "C__OBJTYPE__PDU",
+ "color": "43CBE1",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/power.jpg",
+ "icon": "pdu.gif",
+ "cats": "64",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "50",
+ "title": "Uninterruptible power supply",
+ "container": "0",
+ "const": "C__OBJTYPE__UPS",
+ "color": "FDD84E",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/power.jpg",
+ "icon": "images/icons/silk/lightning.png",
+ "cats": "42",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "57",
+ "title": "Virtual client",
+ "container": "0",
+ "const": "C__OBJTYPE__VIRTUAL_CLIENT",
+ "color": "9FAA7C",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/client.png",
+ "icon": "images/icons/silk/computer_link.png",
+ "cats": "15",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "58",
+ "title": "Virtual host",
+ "container": "0",
+ "const": "C__OBJTYPE__VIRTUAL_HOST",
+ "color": "E6E9DC",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/server.png",
+ "icon": "images/icons/silk/server_database.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "59",
+ "title": "Virtual server",
+ "container": "0",
+ "const": "C__OBJTYPE__VIRTUAL_SERVER",
+ "color": "6D7F92",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/server.png",
+ "icon": "images/icons/silk/server_chart.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "64",
+ "title": "Replication object",
+ "container": "0",
+ "const": "C__OBJTYPE__REPLICATION",
+ "color": "C9BAEF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/silk/arrow_branch.png",
+ "cats": "71",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "71",
+ "title": "Workplace",
+ "container": "0",
+ "const": "C__OBJTYPE__WORKSTATION",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/client.png",
+ "icon": "images/icons/silk/drive_user.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "73",
+ "title": "Switch chassis",
+ "container": "1",
+ "const": "C__OBJTYPE__SWITCH_CHASSIS",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/enclosure.png",
+ "icon": "images/icons/silk/timeline_marker.png",
+ "cats": "84",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "74",
+ "title": "Blade chassis",
+ "container": "1",
+ "const": "C__OBJTYPE__BLADE_CHASSIS",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/enclosure.png",
+ "icon": "images/icons/silk/timeline_marker.png",
+ "cats": "84",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "75",
+ "title": "Blade server",
+ "container": "0",
+ "const": "C__OBJTYPE__BLADE_SERVER",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/server.png",
+ "icon": "images/icons/silk/drive.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "76",
+ "title": "VoIP telephone",
+ "container": "0",
+ "const": "C__OBJTYPE__VOIP_PHONE",
+ "color": "FF8800",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/phone.png",
+ "icon": "images/icons/silk/phone_sound.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "84",
+ "title": "Country",
+ "container": "1",
+ "const": "C__OBJTYPE__COUNTRY",
+ "color": "ACE177",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/silk/map.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "85",
+ "title": "City",
+ "container": "1",
+ "const": "C__OBJTYPE__CITY",
+ "color": "DFB0E1",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/city.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "88",
+ "title": "Remote Management Controller",
+ "container": "0",
+ "const": "C__OBJTYPE__RM_CONTROLLER",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/",
+ "icon": "images/icons/silk/bullet_picture.png",
+ "tree_group": "2",
+ "status": "2",
+ "type_group": "2",
+ "type_group_title": "Infrastructure"
+ }, {
+ "id": "13",
+ "title": "WAN",
+ "container": "0",
+ "const": "C__OBJTYPE__WAN",
+ "color": "BAE1D2",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/router.png",
+ "icon": "images/icons/silk/weather_clouds.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "14",
+ "title": "Emergency plan",
+ "container": "0",
+ "const": "C__OBJTYPE__EMERGENCY_PLAN",
+ "color": "C4FFF9",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/emergency.jpg",
+ "icon": "images/icons/silk/text_horizontalrule.png",
+ "cats": "8",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "28",
+ "title": "Contract",
+ "container": "0",
+ "const": "C__OBJTYPE__MAINTENANCE",
+ "color": "7AD3C6",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/maintenance.jpg",
+ "icon": "images/icons/silk/text_signature.png",
+ "cats": "81",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "29",
+ "title": "File",
+ "container": "0",
+ "const": "C__OBJTYPE__FILE",
+ "color": "CDFCF6",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
+ "icon": "images/icons/silk/disk.png",
+ "cats": "19",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "31",
+ "title": "Layer 3-Net",
+ "container": "0",
+ "const": "C__OBJTYPE__LAYER3_NET",
+ "color": "7EE0EB",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/wlan.jpg",
+ "icon": "images/icons/silk/world_link.png",
+ "cats": "22",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "32",
+ "title": "Cellular Phone",
+ "container": "0",
+ "const": "C__OBJTYPE__CELL_PHONE_CONTRACT",
+ "color": "F2F3BA",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/appliances.png",
+ "icon": "images/icons/silk/phone.png",
+ "cats": "23",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "36",
+ "title": "Object group",
+ "container": "0",
+ "const": "C__OBJECT_TYPE__GROUP",
+ "color": "E1B9DC",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/printerbox.jpg",
+ "icon": "images/icons/silk/sitemap_color.png",
+ "cats": "25",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "45",
+ "title": "Service",
+ "container": "0",
+ "const": "C__OBJTYPE__IT_SERVICE",
+ "color": "C7F464",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/service.jpg",
+ "icon": "images/icons/silk/chart_pie.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "51",
+ "title": "SAN Zoning",
+ "container": "0",
+ "const": "C__OBJTYPE__SAN_ZONING",
+ "color": "DDE143",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/san.png",
+ "icon": "images/icons/silk/layers.png",
+ "cats": "44",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "55",
+ "title": "Cluster",
+ "container": "0",
+ "const": "C__OBJTYPE__CLUSTER",
+ "color": "9FAAB7",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/server.png",
+ "icon": "images/icons/silk/application_cascade.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "68",
+ "title": "Crypto card",
+ "container": "0",
+ "const": "C__OBJTYPE__KRYPTO_CARD",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
+ "icon": "images/icons/silk/page_white_key.png",
+ "cats": "76",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "69",
+ "title": "SIM card",
+ "container": "0",
+ "const": "C__OBJTYPE__SIM_CARD",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/application.jpg",
+ "icon": "images/icons/silk/page_white_database.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "70",
+ "title": "Layer 2 Net",
+ "container": "0",
+ "const": "C__OBJTYPE__LAYER2_NET",
+ "color": "7EE0EB",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/fcswitch.png",
+ "icon": "images/icons/silk/page_white_gear.png",
+ "cats": "79",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "77",
+ "title": "Supernet",
+ "container": "1",
+ "const": "C__OBJTYPE__SUPERNET",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/wlan.jpg",
+ "icon": "images/icons/silk/world.png",
+ "cats": "22",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "81",
+ "title": "Vehicle",
+ "container": "0",
+ "const": "C__OBJTYPE__VEHICLE",
+ "color": "83C5E1",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/silk/car.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "82",
+ "title": "Aircraft",
+ "container": "0",
+ "const": "C__OBJTYPE__AIRCRAFT",
+ "color": "479FC4",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/airplane.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "83",
+ "title": "VRRP/HSRP Cluster",
+ "container": "0",
+ "const": "C__OBJTYPE__CLUSTER_VRRP_HSRP",
+ "color": "9FAAB7",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/server.png",
+ "icon": "images/icons/silk/application_cascade.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "89",
+ "title": "VRRP",
+ "container": "0",
+ "const": "C__OBJTYPE__VRRP",
+ "color": "ABCDEF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/switch.png",
+ "icon": "images/icons/silk/disconnect.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "90",
+ "title": "Stacking",
+ "container": "0",
+ "const": "C__OBJTYPE__STACKING",
+ "color": "FEDCBA",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/switch.png",
+ "icon": "images/icons/silk/drive_stack.png",
+ "tree_group": "3",
+ "status": "2",
+ "type_group": "3",
+ "type_group_title": "Other"
+ }, {
+ "id": "52",
+ "title": "Organization",
+ "container": "0",
+ "const": "C__OBJTYPE__ORGANIZATION",
+ "color": "82E27E",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/building.png",
+ "icon": "images/icons/silk/sitemap.png",
+ "cats": "45",
+ "tree_group": "1000",
+ "status": "2",
+ "type_group": "1000",
+ "type_group_title": "Contact"
+ }, {
+ "id": "53",
+ "title": "Persons",
+ "container": "0",
+ "const": "C__OBJTYPE__PERSON",
+ "color": "EFAA43",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/tree/person_intern.gif",
+ "cats": "48",
+ "tree_group": "1000",
+ "status": "2",
+ "type_group": "1000",
+ "type_group_title": "Contact"
+ }, {
+ "id": "54",
+ "title": "Person groups",
+ "container": "0",
+ "const": "C__OBJTYPE__PERSON_GROUP",
+ "color": "F3FFEF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/tree/group.gif",
+ "cats": "52",
+ "tree_group": "1000",
+ "status": "2",
+ "type_group": "1000",
+ "type_group_title": "Contact"
+ }, {
+ "id": "78",
+ "title": "Nagios service",
+ "container": "0",
+ "const": "C__OBJTYPE__NAGIOS_SERVICE",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/silk/database.png",
+ "tree_group": "1001",
+ "status": "2",
+ "type_group": "1001",
+ "type_group_title": "Nagios"
+ }, {
+ "id": "79",
+ "title": "Nagios service-template",
+ "container": "0",
+ "const": "C__OBJTYPE__NAGIOS_SERVICE_TPL",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/silk/database.png",
+ "tree_group": "1001",
+ "status": "2",
+ "type_group": "1001",
+ "type_group_title": "Nagios"
+ }, {
+ "id": "80",
+ "title": "Nagios host-template",
+ "container": "0",
+ "const": "C__OBJTYPE__NAGIOS_HOST_TPL",
+ "color": "FFFFFF",
+ "image": "https://demo.example.com/i-doit/images/objecttypes/empty.png",
+ "icon": "images/icons/silk/database.png",
+ "tree_group": "1001",
+ "status": "2",
+ "type_group": "1001",
+ "type_group_title": "Nagios"
+ }],
+ "id": 1
+}
\ No newline at end of file
diff --git a/test/integration/email_helper_test.rb b/test/integration/email_helper_test.rb
index 683ef8bc0..745e6c130 100644
--- a/test/integration/email_helper_test.rb
+++ b/test/integration/email_helper_test.rb
@@ -209,7 +209,7 @@ class EmailHelperTest < ActiveSupport::TestCase
}
)
assert_equal('invalid', result[:result])
- assert_equal('Authentication failed, username incorrect!', result[:message_human])
+ assert_match(/Authentication failed, username incorrect|Authentication failed, invalid credentials/, result[:message_human])
assert_equal('imap.gmail.com', result[:settings][:options][:host])
result = EmailHelper::Probe.inbound(
@@ -225,8 +225,8 @@ class EmailHelperTest < ActiveSupport::TestCase
assert_equal('invalid', result[:result])
# if we have to many failed logins, we need to handle another error message
- if result[:message_human] && !result[:message_human].empty?
- assert_equal('Authentication failed, invalid credentials!', result[:message_human])
+ if result[:message_human].present?
+ assert_match(/Authentication failed, username incorrect|Authentication failed, invalid credentials/, result[:message_human])
else
assert_match(/Web login required/, result[:message])
end
@@ -457,7 +457,7 @@ class EmailHelperTest < ActiveSupport::TestCase
email: mailbox_user,
password: mailbox_password,
)
- assert_equal(nil, result[:reason])
+ assert_nil(result[:reason])
assert_equal('ok', result[:result])
assert_equal('pop.gmail.com', result[:setting][:inbound][:options][:host])
assert_equal('smtp.gmail.com', result[:setting][:outbound][:options][:host])
diff --git a/test/integration/idoit_controller_test.rb b/test/integration/idoit_controller_test.rb
new file mode 100644
index 000000000..f7d376066
--- /dev/null
+++ b/test/integration/idoit_controller_test.rb
@@ -0,0 +1,191 @@
+# encoding: utf-8
+require 'test_helper'
+require 'webmock/minitest'
+
+class IdoitControllerTest < ActionDispatch::IntegrationTest
+ setup do
+
+ stub_request(:any, 'https://images.zammad.com/api/v1/person/image')
+ .to_return(status: 404, body: '', headers: {})
+
+ @token = 'some_token'
+ @endpoint = 'https://idoit.example.com/i-doit/'
+
+ @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
+
+ Setting.set('idoit_integration', true)
+ Setting.set('idoit_config', {
+ api_token: @token,
+ endpoint: @endpoint,
+ client_id: '',
+ })
+ groups = Group.where(name: 'Users')
+ roles = Role.where(name: %w(Agent))
+ agent = User.create_or_update(
+ login: 'idoit-agent@example.com',
+ firstname: 'E',
+ lastname: 'S',
+ email: 'idoit-agent@example.com',
+ password: 'agentpw',
+ active: true,
+ roles: roles,
+ groups: groups,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+ roles = Role.where(name: %w(Agent Admin))
+ admin = User.create_or_update(
+ login: 'idoit-admin@example.com',
+ firstname: 'E',
+ lastname: 'S',
+ email: 'idoit-admin@example.com',
+ password: 'adminpw',
+ active: true,
+ roles: roles,
+ groups: groups,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+
+ customer1 = User.create_or_update(
+ login: 'ticket-idoit-customer1@example.com',
+ firstname: 'CallerId',
+ lastname: 'Customer1',
+ email: 'ticket-idoit-customer1@example.com',
+ password: 'customerpw',
+ active: true,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+
+ end
+
+ test 'unclear urls' do
+
+ agent_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-agent@example.com', 'agentpw')
+ params = {
+ api_token: @token,
+ endpoint: @endpoint,
+ client_id: '',
+ }
+ post '/api/v1/integration/idoit/verify', params: params.to_json, headers: @headers.merge('Authorization' => agent_credentials)
+ assert_response(401)
+ result = JSON.parse(@response.body)
+ assert_equal(Hash, result.class)
+ assert_not(result.blank?)
+ assert_equal('Not authorized (user)!', result['error'])
+
+ stub_request(:post, "#{@endpoint}src/jsonrpc.php")
+ .with(body: "{\"method\":\"cmdb.object_types\",\"params\":{\"apikey\":\"#{@token}\"},\"version\":\"2.0\"}")
+ .to_return(status: 200, body: read_messaage('object_types_response'), headers: {})
+
+ admin_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-admin@example.com', 'adminpw')
+ params = {
+ api_token: @token,
+ endpoint: @endpoint,
+ client_id: '',
+ }
+ post '/api/v1/integration/idoit/verify', params: params.to_json, headers: @headers.merge('Authorization' => admin_credentials)
+ assert_response(200)
+ result = JSON.parse(@response.body)
+ assert_equal(Hash, result.class)
+ assert_not(result.blank?)
+ assert_equal('ok', result['result'])
+ assert(result['response'])
+ assert_equal('2.0', result['response']['jsonrpc'])
+ assert(result['response']['result'])
+
+ params = {
+ api_token: @token,
+ endpoint: " #{@endpoint}/",
+ client_id: '',
+ }
+ post '/api/v1/integration/idoit/verify', params: params.to_json, headers: @headers.merge('Authorization' => admin_credentials)
+ assert_response(200)
+ result = JSON.parse(@response.body)
+ assert_equal(Hash, result.class)
+ assert_not(result.blank?)
+ assert_equal('ok', result['result'])
+ assert(result['response'])
+ assert_equal('2.0', result['response']['jsonrpc'])
+ assert(result['response']['result'])
+
+ end
+
+ test 'list all object types' do
+
+ stub_request(:post, "#{@endpoint}src/jsonrpc.php")
+ .with(body: "{\"method\":\"cmdb.object_types\",\"params\":{\"apikey\":\"#{@token}\"},\"version\":\"2.0\"}")
+ .to_return(status: 200, body: read_messaage('object_types_response'), headers: {})
+
+ agent_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-agent@example.com', 'agentpw')
+ params = {
+ method: 'cmdb.object_types',
+ }
+ post '/api/v1/integration/idoit', params: params.to_json, headers: @headers.merge('Authorization' => agent_credentials)
+ assert_response(200)
+
+ result = JSON.parse(@response.body)
+ assert_equal(Hash, result.class)
+ assert_not(result.blank?)
+ assert_equal('ok', result['result'])
+ assert(result['response'])
+ assert_equal('2.0', result['response']['jsonrpc'])
+ assert(result['response']['result'])
+ assert_equal('1', result['response']['result'][0]['id'])
+ assert_equal('System service', result['response']['result'][0]['title'])
+
+ admin_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-admin@example.com', 'adminpw')
+ params = {
+ method: 'cmdb.object_types',
+ }
+ post '/api/v1/integration/idoit', params: params.to_json, headers: @headers.merge('Authorization' => admin_credentials)
+ assert_response(200)
+
+ result = JSON.parse(@response.body)
+ assert_equal(Hash, result.class)
+ assert_not(result.blank?)
+ assert_equal('ok', result['result'])
+ assert(result['response'])
+ assert_equal('2.0', result['response']['jsonrpc'])
+ assert(result['response']['result'])
+ assert_equal('1', result['response']['result'][0]['id'])
+ assert_equal('System service', result['response']['result'][0]['title'])
+
+ end
+
+ test 'query objects' do
+
+ stub_request(:post, "#{@endpoint}src/jsonrpc.php")
+ .with(body: "{\"method\":\"cmdb.objects\",\"params\":{\"apikey\":\"#{@token}\",\"filter\":{\"ids\":[\"33\"]}},\"version\":\"2.0\"}")
+ .to_return(status: 200, body: read_messaage('object_types_filter_response'), headers: {})
+
+ agent_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-agent@example.com', 'agentpw')
+ params = {
+ method: 'cmdb.objects',
+ filter: {
+ ids: ['33']
+ },
+ }
+ post '/api/v1/integration/idoit', params: params.to_json, headers: @headers.merge('Authorization' => agent_credentials)
+ assert_response(200)
+
+ result = JSON.parse(@response.body)
+ assert_equal(Hash, result.class)
+ assert_not(result.blank?)
+ assert_equal('ok', result['result'])
+ assert(result['response'])
+ assert_equal('2.0', result['response']['jsonrpc'])
+ assert(result['response']['result'])
+ assert_equal('26', result['response']['result'][0]['id'])
+ assert_equal('demo.example.com', result['response']['result'][0]['title'])
+ assert_equal('Virtual server', result['response']['result'][0]['type_title'])
+ assert_equal('in operation', result['response']['result'][0]['cmdb_status_title'])
+
+ end
+
+ def read_messaage(file)
+ File.read("test/fixtures/idoit/#{file}.json")
+ end
+
+end
diff --git a/test/integration/user_device_controller_test.rb b/test/integration/user_device_controller_test.rb
index 2f193237f..25611dd26 100644
--- a/test/integration/user_device_controller_test.rb
+++ b/test/integration/user_device_controller_test.rb
@@ -61,7 +61,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
params = { without_fingerprint: 'none', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params.to_json, @headers
+ post '/api/v1/signin', params: params.to_json, headers: @headers
assert_response(422)
result = JSON.parse(@response.body)
@@ -85,7 +85,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
params = { fingerprint: 'my_finger_print', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params.to_json, @headers
+ post '/api/v1/signin', params: params.to_json, headers: @headers
assert_response(201)
result = JSON.parse(@response.body)
assert_equal(result.class, Hash)
@@ -102,7 +102,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
sleep 2
params = {}
- get '/api/v1/users', params.to_json, @headers
+ get '/api/v1/users', params: params.to_json, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(result.class, Array)
@@ -117,7 +117,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
assert_equal(user_device_last.updated_at.to_s, user_device_first.updated_at.to_s)
params = { fingerprint: 'my_finger_print' }
- get '/api/v1/signshow', params, @headers
+ get '/api/v1/signshow', params: params, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(result.class, Hash)
@@ -135,7 +135,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
ENV['USER_DEVICE_UPDATED_AT'] = (Time.zone.now - 4.hours).to_s
params = {}
- get '/api/v1/users', params.to_json, @headers
+ get '/api/v1/users', params: params.to_json, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(result.class, Array)
@@ -153,7 +153,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
params = {}
- get '/api/v1/users', params.to_json, @headers
+ get '/api/v1/users', params: params.to_json, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
@@ -171,7 +171,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
test '04 - login index with admin with fingerprint - II' do
params = { fingerprint: 'my_finger_print_II', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params.to_json, @headers
+ post '/api/v1/signin', params: params.to_json, headers: @headers
assert_response(201)
result = JSON.parse(@response.body)
@@ -185,7 +185,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
assert(result['config'])
assert('my_finger_print_II', controller.session[:user_device_fingerprint])
- get '/api/v1/users', params.to_json, @headers
+ get '/api/v1/users', params: params.to_json, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(result.class, Array)
@@ -197,7 +197,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
params = { fingerprint: 'my_finger_print_II' }
- get '/api/v1/signshow', params, @headers
+ get '/api/v1/signshow', params: params, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(result.class, Hash)
@@ -214,7 +214,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
params = {}
- get '/api/v1/users', params.to_json, @headers
+ get '/api/v1/users', params: params.to_json, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
@@ -232,7 +232,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
test '05 - login index with admin with fingerprint - II' do
params = { fingerprint: 'my_finger_print_II', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params.to_json, @headers
+ post '/api/v1/signin', params: params.to_json, headers: @headers
assert_response(201)
result = JSON.parse(@response.body)
@@ -253,7 +253,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-admin', 'adminpw')
params = {}
- get '/api/v1/users', params.to_json, @headers.merge('Authorization' => credentials)
+ get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
result = JSON.parse(@response.body)
@@ -267,7 +267,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
sleep 2
params = {}
- get '/api/v1/users', params.to_json, @headers.merge('Authorization' => credentials)
+ get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
result = JSON.parse(@response.body)
@@ -285,7 +285,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
user_device_last.save!
params = {}
- get '/api/v1/users', params, @headers.merge('Authorization' => credentials)
+ get '/api/v1/users', params: params, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
result = JSON.parse(@response.body)
@@ -307,7 +307,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-admin', 'adminpw')
params = {}
- get '/api/v1/users', params.to_json, @headers.merge('Authorization' => credentials)
+ get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
result = JSON.parse(@response.body)
@@ -330,7 +330,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-agent', 'agentpw')
params = {}
- get '/api/v1/users', params.to_json, @headers.merge('Authorization' => credentials)
+ get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
result = JSON.parse(@response.body)
@@ -353,7 +353,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-agent', 'agentpw')
params = {}
- get '/api/v1/users', params.to_json, @headers.merge('Authorization' => credentials)
+ get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
result = JSON.parse(@response.body)
@@ -375,7 +375,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
ENV['SWITCHED_FROM_USER_ID'] = @admin.id.to_s
params = { fingerprint: 'my_finger_print_II', username: 'user-device-agent', password: 'agentpw' }
- post '/api/v1/signin', params.to_json, @headers
+ post '/api/v1/signin', params: params.to_json, headers: @headers
assert_response(201)
result = JSON.parse(@response.body)
@@ -397,7 +397,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
ENV['USER_DEVICE_UPDATED_AT'] = (Time.zone.now - 4.hours).to_s
params = {}
- get '/api/v1/users', params.to_json, @headers
+ get '/api/v1/users', params: params.to_json, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(result.class, Array)
@@ -412,7 +412,7 @@ class UserDeviceControllerTest < ActionDispatch::IntegrationTest
ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
params = {}
- get '/api/v1/users', params.to_json, @headers
+ get '/api/v1/users', params: params.to_json, headers: @headers
assert_response(200)
result = JSON.parse(@response.body)
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 5410c0174..cd46de640 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -62,6 +62,8 @@ class ActiveSupport::TestCase
PostmasterFilter.destroy_all
Ticket.destroy_all
Taskbar.destroy_all
+ Sla.destroy_all
+ Calendar.destroy_all
# reset settings
Setting.all.pluck(:name).each { |name|
diff --git a/test/unit/assets_test.rb b/test/unit/assets_test.rb
index 526144336..6e30b9007 100644
--- a/test/unit/assets_test.rb
+++ b/test/unit/assets_test.rb
@@ -446,7 +446,21 @@ class AssetsTest < ActiveSupport::TestCase
roles: roles,
)
- calendar1 = Calendar.first
+ calendar1 = Calendar.create_or_update(
+ name: 'US 1',
+ timezone: 'America/Los_Angeles',
+ business_hours: {
+ mon: { '09:00' => '17:00' },
+ tue: { '09:00' => '17:00' },
+ wed: { '09:00' => '17:00' },
+ thu: { '09:00' => '17:00' },
+ fri: { '09:00' => '17:00' }
+ },
+ default: true,
+ ical_url: nil,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
ticket_state1 = Ticket::State.find_by(name: 'new')
ticket_state2 = Ticket::State.find_by(name: 'open')
sla = Sla.create_or_update(
diff --git a/test/unit/calendar_test.rb b/test/unit/calendar_test.rb
index 6561e3569..0b33fa1b2 100644
--- a/test/unit/calendar_test.rb
+++ b/test/unit/calendar_test.rb
@@ -61,7 +61,7 @@ class CalendarTest < ActiveSupport::TestCase
assert_equal(true, calendar3.default)
calendar2.default = true
- calendar2.save
+ calendar2.save!
calendar1 = Calendar.find_by(name: 'US 1')
calendar2 = Calendar.find_by(name: 'US 2')
@@ -72,7 +72,7 @@ class CalendarTest < ActiveSupport::TestCase
assert_equal(false, calendar3.default)
calendar2.default = false
- calendar2.save
+ calendar2.save!
calendar1 = Calendar.find_by(name: 'US 1')
calendar2 = Calendar.find_by(name: 'US 2')
@@ -82,12 +82,16 @@ class CalendarTest < ActiveSupport::TestCase
assert_equal(false, calendar2.default)
assert_equal(false, calendar3.default)
- calendar1.destroy
+ calendar1.destroy!
calendar2 = Calendar.find_by(name: 'US 2')
calendar3 = Calendar.find_by(name: 'US 3')
assert_equal(true, calendar2.default)
assert_equal(false, calendar3.default)
+
+ calendar2.destroy!
+ calendar3.destroy!
+
travel_back
end
@@ -237,6 +241,8 @@ class CalendarTest < ActiveSupport::TestCase
assert_equal('Christmas1', calendar1.public_holidays['2019-12-24']['summary'])
assert_nil(calendar1.public_holidays['2020-12-24'])
+ calendar1.destroy!
+
travel_back
end
diff --git a/test/unit/integration_icinga_test.rb b/test/unit/integration_icinga_test.rb
index b10e656ff..2a32377ef 100644
--- a/test/unit/integration_icinga_test.rb
+++ b/test/unit/integration_icinga_test.rb
@@ -8,40 +8,12 @@ class IntegrationIcingaTest < ActiveSupport::TestCase
# http://docs.icinga.org/icinga2/latest/doc/module/icinga2/chapter/monitoring-basics#host-states
# http://docs.icinga.org/icinga2/latest/doc/module/icinga2/chapter/monitoring-basics#service-states
- test 'base tests' do
-
+ setup do
Setting.set('icinga_integration', true)
+ Setting.set('icinga_sender', 'icinga2@monitoring.example.com')
+ end
- # not matching sender
- email_raw_string = "To: support@example.com
-Subject: PROBLEM - host.internal.loc - CPU Load is WARNING
-User-Agent: Heirloom mailx 12.5 7/5/10
-MIME-Version: 1.0
-Content-Type: text/plain; charset=us-ascii
-Content-Transfer-Encoding: quoted-printable
-Message-Id: <20160131094621.29ECD400F29C-icinga-1-0@monitoring.znuny.com>
-From: icinga_not_matching@monitoring.example.com (icinga)
-
-***** Icinga *****
-
-Notification Type: PROBLEM
-
-Service: CPU Load
-Host: host.internal.loc
-Address:=20
-State: WARNING
-
-Date/Time: 2016-01-31 10:46:20 +0100
-
-Additional Info: WARNING - load average: 3.44, 0.99, 0.35
-
-Comment: [] =
-"
-
- ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
- assert_equal('new', ticket_p.state.name)
- assert(ticket_p.preferences)
- assert_not(ticket_p.preferences['icinga'])
+ test 'base tests' do
# RBL check
email_raw_string = "To: support@example.com
@@ -51,7 +23,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-1-1@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga 2 Service Monitoring on apn4711.dc.example.com *****
@@ -82,7 +54,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-1-2@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga 2 Service Monitoring on apn4711.dc.example.com *****
@@ -113,7 +85,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-1-2@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga 2 Service Monitoring on apn4711.dc.example.com *****
@@ -145,7 +117,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-2@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga *****
@@ -179,7 +151,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-3@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga *****
@@ -214,7 +186,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-4@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga *****
@@ -249,7 +221,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-5@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga *****
@@ -284,7 +256,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-5@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga *****
@@ -317,7 +289,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-icinga-5@monitoring.znuny.com>
-From: icinga@monitoring.example.com (icinga)
+From: icinga2@monitoring.example.com (icinga)
***** Icinga *****
@@ -341,9 +313,246 @@ Comment: [] =
assert_equal('apn4711.dc.example.com', ticket_3.preferences['icinga']['host'])
assert_nil(ticket_3_1.preferences['icinga']['service'])
assert_equal('DOWN', ticket_3_1.preferences['icinga']['state'])
+ end
- #Setting.set('icinga_integration', false)
+ test 'not matching sender tests' do
+
+ # not matching sender
+ email_raw_string = "To: support@example.com
+Subject: PROBLEM - host.internal.loc - CPU Load is WARNING
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-icinga-1-0@monitoring.znuny.com>
+From: icinga_not_matching@monitoring.example.com (icinga)
+
+***** Icinga *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address:=20
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info: WARNING - load average: 3.44, 0.99, 0.35
+
+Comment: [] =
+"
+
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_p.state.name)
+ assert(ticket_p.preferences)
+ assert_not(ticket_p.preferences['icinga'])
+
+ Setting.set('icinga_sender', 'regex:icinga2@monitoring.example.com')
+
+ # not matching sender
+ email_raw_string = "To: support@example.com
+Subject: PROBLEM - host.internal.loc - CPU Load is WARNING
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-icinga-1-0@monitoring.znuny.com>
+From: icinga_not_matching@monitoring.example.com (icinga)
+
+***** Icinga *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address:=20
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info: WARNING - load average: 3.44, 0.99, 0.35
+
+Comment: [] =
+"
+
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_p.state.name)
+ assert(ticket_p.preferences)
+ assert_not(ticket_p.preferences['icinga'])
+
+ # not matching sender
+ email_raw_string = "To: support@example.com
+Subject: PROBLEM - host.internal.loc - CPU Load is WARNING
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-icinga-1-0@monitoring.znuny.com>
+Return-Path: bob@example.com
+
+***** Icinga *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address:=20
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info: WARNING - load average: 3.44, 0.99, 0.35
+
+Comment: [] =
+"
+
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_p.state.name)
+ assert(ticket_p.preferences)
+ assert_not(ticket_p.preferences['icinga'])
+ end
+
+ test 'matching sender tests' do
+
+ # matching sender - follow up - CPU Load/host.internal.loc
+ email_raw_string = "To: support@example.com
+Subject: PROBLEM - host.internal.loc - CPU Load is WARNING
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-icinga-4@monitoring.znuny.com>
+From: icinga2@monitoring.example.com (icinga)
+
+***** Icinga *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address:=20
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info: WARNING - load average: 3.44, 0.99, 0.35
+
+Comment: [] =
+"
+
+ ticket_1_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_1_1.state.name)
+ assert(ticket_1_1.preferences)
+ assert(ticket_1_1.preferences['icinga'])
+ assert_equal('host.internal.loc', ticket_1_1.preferences['icinga']['host'])
+ assert_equal('CPU Load', ticket_1_1.preferences['icinga']['service'])
+ assert_equal('WARNING', ticket_1_1.preferences['icinga']['state'])
+
+ Setting.set('icinga_sender', 'regex:icinga2@monitoring.example.com')
+
+ # matching sender I
+ email_raw_string = "To: support@example.com
+Subject: PROBLEM - host1.internal.loc - CPU Load is WARNING
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-icinga-4@monitoring.znuny.com>
+From: icinga2@monitoring.example.com (icinga)
+
+***** Icinga *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host1.internal.loc
+Address:=20
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info: WARNING - load average: 3.44, 0.99, 0.35
+
+Comment: [] =
+"
+
+ ticket_1_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_1_1.state.name)
+ assert(ticket_1_1.preferences)
+ assert(ticket_1_1.preferences['icinga'])
+ assert_equal('host1.internal.loc', ticket_1_1.preferences['icinga']['host'])
+ assert_equal('CPU Load', ticket_1_1.preferences['icinga']['service'])
+ assert_equal('WARNING', ticket_1_1.preferences['icinga']['state'])
+
+ # matching sender I
+ Setting.set('icinga_sender', 'regex:(icinga2|abc123)@monitoring.example.com')
+
+ email_raw_string = "To: support@example.com
+Subject: PROBLEM - host2.internal.loc - CPU Load is WARNING
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-icinga-4@monitoring.znuny.com>
+From: icinga2@monitoring.example.com (icinga)
+
+***** Icinga *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host2.internal.loc
+Address:=20
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info: WARNING - load average: 3.44, 0.99, 0.35
+
+Comment: [] =
+"
+
+ ticket_1_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_1_1.state.name)
+ assert(ticket_1_1.preferences)
+ assert(ticket_1_1.preferences['icinga'])
+ assert_equal('host2.internal.loc', ticket_1_1.preferences['icinga']['host'])
+ assert_equal('CPU Load', ticket_1_1.preferences['icinga']['service'])
+ assert_equal('WARNING', ticket_1_1.preferences['icinga']['state'])
end
+ test 'recover without problem tests' do
+
+ # host up without problem
+ email_raw_string = "To: support@example.com
+Subject: RECOVERY - apn4711.dc.example.com is UP
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-icinga-5@monitoring.znuny.com>
+From: icinga2@monitoring.example.com (icinga)
+
+***** Icinga *****
+
+Notification Type: RECOVERY
+
+Host: apn4711.dc.example.com
+Address: 127.0.0.1
+State: UP
+
+Date/Time: 2017-01-14 12:07:11 +0100
+
+Additional Info: PING OK - Packet loss = 0%, RTA = 21.37 ms
+
+Comment: [] =
+"
+ ticket_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ ticket_count = Ticket.count
+ assert_not(ticket_1)
+ assert_equal(ticket_count, Ticket.count)
+ end
+
end
diff --git a/test/unit/integration_nagios_test.rb b/test/unit/integration_nagios_test.rb
index e4ef19189..4e33aa405 100644
--- a/test/unit/integration_nagios_test.rb
+++ b/test/unit/integration_nagios_test.rb
@@ -6,38 +6,12 @@ class IntegrationNagiosTest < ActiveSupport::TestCase
# according
# https://github.com/NagiosEnterprises/nagioscore/blob/754218e67653929a58938b99ef6b6039b6474fe4/sample-config/template-object/commands.cfg.in#L35
- test 'base tests' do
-
+ setup do
Setting.set('nagios_integration', true)
+ Setting.set('nagios_sender', 'nagios2@monitoring.example.com')
+ end
- # not matching sender
- email_raw_string = "To: support@example.com
-Subject: ** PROBLEM Service Alert: host.internal.loc/CPU Load is WARNING **
-MIME-Version: 1.0
-Content-Type: text/plain; charset=us-ascii
-Content-Transfer-Encoding: quoted-printable
-Message-Id: <20160131094621.29ECD400F29C-nagios-1@monitoring.znuny.com>
-From: nagios_not_matching@monitoring.example.com (nagios)
-
-***** Nagios *****
-
-Notification Type: PROBLEM
-
-Service: CPU Load
-Host: host.internal.loc
-Address: 1.1.1.1
-State: PROBLEM
-
-Date/Time: 2016-01-31 10:46:20 +0100
-
-Additional Info:
-WARNING - load average: 3.44, 0.99, 0.35
-"
-
- ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
- assert_equal('new', ticket_p.state.name)
- assert(ticket_p.preferences)
- assert_not(ticket_p.preferences['nagios'])
+ test 'base tests' do
# matching sender - CPU Load/host.internal.loc
email_raw_string = "To: support@example.com
@@ -46,7 +20,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-nagios-2@monitoring.znuny.com>
-From: nagios@monitoring.example.com (nagios)
+From: nagios2@monitoring.example.com (nagios)
***** Nagios *****
@@ -78,7 +52,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-nagios-3@monitoring.znuny.com>
-From: nagios@monitoring.example.com (nagios)
+From: nagios2@monitoring.example.com (nagios)
***** Nagios *****
@@ -111,7 +85,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-nagios-4@monitoring.znuny.com>
-From: nagios@monitoring.example.com (nagios)
+From: nagios2@monitoring.example.com (nagios)
***** Nagios *****
@@ -144,7 +118,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-nagios-5@monitoring.znuny.com>
-From: nagios@monitoring.example.com (nagios)
+From: nagios2@monitoring.example.com (nagios)
***** Nagios *****
@@ -176,7 +150,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-nagios-5@monitoring.znuny.com>
-From: nagios@monitoring.example.com (nagios)
+From: nagios2@monitoring.example.com (nagios)
***** Nagios *****
@@ -209,7 +183,7 @@ MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Message-Id: <20160131094621.29ECD400F29C-nagios-5@monitoring.znuny.com>
-From: nagios@monitoring.example.com (nagios)
+From: nagios2@monitoring.example.com (nagios)
***** Nagios *****
@@ -238,4 +212,232 @@ Comment: [] =
end
+ test 'not matching sender tests' do
+
+ # not matching sender
+ email_raw_string = "To: support@example.com
+Subject: ** PROBLEM Service Alert: host.internal.loc/CPU Load is WARNING **
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-nagios-1@monitoring.znuny.com>
+From: nagios_not_matching@monitoring.example.com (nagios)
+
+***** Nagios *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address: 1.1.1.1
+State: PROBLEM
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info:
+WARNING - load average: 3.44, 0.99, 0.35
+"
+
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_p.state.name)
+ assert(ticket_p.preferences)
+ assert_not(ticket_p.preferences['nagios'])
+
+ Setting.set('nagios_sender', 'regex:icinga2@monitoring.example.com')
+
+ # not matching sender
+ email_raw_string = "To: support@example.com
+Subject: ** PROBLEM Service Alert: host.internal.loc/CPU Load is WARNING **
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-nagios-1@monitoring.znuny.com>
+From: nagios_not_matching@monitoring.example.com (nagios)
+
+***** Nagios *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address: 1.1.1.1
+State: PROBLEM
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info:
+WARNING - load average: 3.44, 0.99, 0.35
+"
+
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_p.state.name)
+ assert(ticket_p.preferences)
+ assert_not(ticket_p.preferences['nagios'])
+
+ # not matching sender
+ email_raw_string = "To: support@example.com
+Subject: ** PROBLEM Service Alert: host.internal.loc/CPU Load is WARNING **
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-nagios-1@monitoring.znuny.com>
+Return-Path: bob@example.com
+
+***** Nagios *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address: 1.1.1.1
+State: PROBLEM
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info:
+WARNING - load average: 3.44, 0.99, 0.35
+"
+
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_p.state.name)
+ assert(ticket_p.preferences)
+ assert_not(ticket_p.preferences['nagios'])
+ end
+
+ test 'matching sender tests' do
+
+ # matching sender - follow up - CPU Load/host.internal.loc
+ email_raw_string = "To: support@example.com
+Subject: ** PROBLEM Service Alert: host.internal.loc/CPU Load is WARNING **
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-nagios-2@monitoring.znuny.com>
+From: nagios2@monitoring.example.com (nagios)
+
+***** Nagios *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host.internal.loc
+Address: 1.1.1.1
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info:
+WARNING - load average: 3.44, 0.99, 0.35
+"
+
+ ticket_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_1.state.name)
+ assert(ticket_1.preferences)
+ assert(ticket_1.preferences['nagios'])
+ assert_equal('host.internal.loc', ticket_1.preferences['nagios']['host'])
+ assert_equal('CPU Load', ticket_1.preferences['nagios']['service'])
+ assert_equal('WARNING', ticket_1.preferences['nagios']['state'])
+
+ Setting.set('icinga_sender', 'regex:icinga2@monitoring.example.com')
+
+ # matching sender I
+ email_raw_string = "To: support@example.com
+Subject: ** PROBLEM Service Alert: host.internal.loc/CPU Load is WARNING **
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-nagios-2@monitoring.znuny.com>
+From: nagios2@monitoring.example.com (nagios)
+
+***** Nagios *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host1.internal.loc
+Address: 1.1.1.1
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info:
+WARNING - load average: 3.44, 0.99, 0.35
+"
+
+ ticket_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_1.state.name)
+ assert(ticket_1.preferences)
+ assert(ticket_1.preferences['nagios'])
+ assert_equal('host1.internal.loc', ticket_1.preferences['nagios']['host'])
+ assert_equal('CPU Load', ticket_1.preferences['nagios']['service'])
+ assert_equal('WARNING', ticket_1.preferences['nagios']['state'])
+
+ # matching sender I
+ Setting.set('icinga_sender', 'regex:(icinga2|abc123)@monitoring.example.com')
+
+ email_raw_string = "To: support@example.com
+Subject: ** PROBLEM Service Alert: host.internal.loc/CPU Load is WARNING **
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-nagios-2@monitoring.znuny.com>
+From: nagios2@monitoring.example.com (nagios)
+
+***** Nagios *****
+
+Notification Type: PROBLEM
+
+Service: CPU Load
+Host: host2.internal.loc
+Address: 1.1.1.1
+State: WARNING
+
+Date/Time: 2016-01-31 10:46:20 +0100
+
+Additional Info:
+WARNING - load average: 3.44, 0.99, 0.35
+"
+
+ ticket_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ assert_equal('new', ticket_1.state.name)
+ assert(ticket_1.preferences)
+ assert(ticket_1.preferences['nagios'])
+ assert_equal('host2.internal.loc', ticket_1.preferences['nagios']['host'])
+ assert_equal('CPU Load', ticket_1.preferences['nagios']['service'])
+ assert_equal('WARNING', ticket_1.preferences['nagios']['state'])
+
+ end
+
+ test 'recover without problem tests' do
+
+ # host up without problem
+ email_raw_string = "To: support@example.com
+Subject: ** RECOVERY Host Alert: apn4711.dc.example.com is UP **
+User-Agent: Heirloom mailx 12.5 7/5/10
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: quoted-printable
+Message-Id: <20160131094621.29ECD400F29C-nagios-5@monitoring.znuny.com>
+From: nagios2@monitoring.example.com (nagios)
+
+***** Nagios *****
+
+Notification Type: RECOVERY
+
+Host: apn4711.dc.example.com
+Address: 127.0.0.1
+State: UP
+
+Date/Time: 2017-01-14 12:07:11 +0100
+
+Additional Info: PING OK - Packet loss = 0%, RTA = 21.37 ms
+
+Comment: [] =
+"
+ ticket_1, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ ticket_count = Ticket.count
+ assert_not(ticket_1)
+ assert_equal(ticket_count, Ticket.count)
+ end
+
end
diff --git a/test/unit/karma_test.rb b/test/unit/karma_test.rb
index fff87bf49..c53bd09ed 100644
--- a/test/unit/karma_test.rb
+++ b/test/unit/karma_test.rb
@@ -91,7 +91,7 @@ class KarmaTest < ActiveSupport::TestCase
ticket1.updated_by_id = agent1.id
ticket1.updated_at = Time.zone.now - 9.hours
ticket1.created_at = Time.zone.now - 9.hours
- ticket1.save
+ ticket1.save!
# execute object transaction
Observer::Transaction.commit
@@ -113,7 +113,7 @@ class KarmaTest < ActiveSupport::TestCase
ticket1.updated_by_id = agent1.id
ticket1.updated_at = Time.zone.now - 9.hours
ticket1.created_at = Time.zone.now - 9.hours
- ticket1.save
+ ticket1.save!
# execute object transaction
Observer::Transaction.commit
@@ -127,7 +127,7 @@ class KarmaTest < ActiveSupport::TestCase
ticket1.updated_by_id = agent2.id
ticket1.updated_at = Time.zone.now - 9.hours
ticket1.created_at = Time.zone.now - 9.hours
- ticket1.save
+ ticket1.save!
# execute object transaction
Observer::Transaction.commit
@@ -138,7 +138,7 @@ class KarmaTest < ActiveSupport::TestCase
assert_equal(0, Karma.score_by_user(customer1))
ticket1.state = Ticket::State.lookup(name: 'open')
- ticket1.save
+ ticket1.save!
Ticket::Article.create(
ticket_id: ticket1.id,
@@ -169,7 +169,7 @@ class KarmaTest < ActiveSupport::TestCase
Scheduler.worker(true)
ticket1.state = Ticket::State.lookup(name: 'closed')
- ticket1.save
+ ticket1.save!
# execute object transaction
Observer::Transaction.commit
@@ -385,7 +385,7 @@ class KarmaTest < ActiveSupport::TestCase
ticket2.state = Ticket::State.lookup(name: 'pending reminder')
ticket2.pending_time = Time.zone.now - 1.day
- ticket2.save
+ ticket2.save!
Ticket.process_pending
@@ -395,7 +395,7 @@ class KarmaTest < ActiveSupport::TestCase
ticket2.state = Ticket::State.lookup(name: 'pending reminder')
ticket2.pending_time = Time.zone.now - 3.days
- ticket2.save
+ ticket2.save!
Ticket.process_pending
@@ -459,7 +459,7 @@ class KarmaTest < ActiveSupport::TestCase
created_by_id: 1,
)
ticket2.state = Ticket::State.lookup(name: 'open')
- ticket2.save
+ ticket2.save!
Observer::Transaction.commit
Scheduler.worker(true)
@@ -511,10 +511,10 @@ class KarmaTest < ActiveSupport::TestCase
assert_equal('Hero', Karma::User.level_by_score(50_000))
# cleanup
- ticket1.destroy
- ticket2.destroy
- calendar1.destroy
- sla1.destroy
+ ticket1.destroy!
+ ticket2.destroy!
+ calendar1.destroy!
+ sla1.destroy!
end
diff --git a/test/unit/package_test.rb b/test/unit/package_test.rb
index 036f8a285..4ba9d4d59 100644
--- a/test/unit/package_test.rb
+++ b/test/unit/package_test.rb
@@ -33,7 +33,7 @@ class PackageTest < ActiveSupport::TestCase
{
"permission": "644",
"location": "db/addon/unit_test_sample/20121212000001_create_base.rb",
- "content": "Y2xhc3MgQ3JlYXRlQmFzZSA8IEFjdGl2ZVJlY29yZDo6TWlncmF0aW9uDQogIGRlZiBzZWxmLnVw\nDQogICBjcmVhdGVfdGFibGUgOnNhbXBsZV90YWJsZXMgZG8gfHR8DQogICAgICB0LmNvbHVtbiA6\nbmFtZSwgICAgICAgICAgIDpzdHJpbmcsIDpsaW1pdCA9PiAxNTAsICA6bnVsbCA9PiB0cnVlDQog\nICAgICB0LmNvbHVtbiA6ZGF0YSwgICAgICAgICAgIDpzdHJpbmcsIDpsaW1pdCA9PiA1MDAwLCA6\nbnVsbCA9PiB0cnVlDQogICAgZW5kDQogIGVuZA0KDQogIGRlZiBzZWxmLmRvd24NCiAgICBkcm9w\nX3RhYmxlIDpzYW1wbGVfdGFibGVzDQogIGVuZA0KZW5k"
+ "content": "Y2xhc3MgQ3JlYXRlQmFzZSA8IEFjdGl2ZVJlY29yZDo6TWlncmF0aW9uWzQuMl0NCiAgZGVmIHNlbGYudXANCiAgIGNyZWF0ZV90YWJsZSA6c2FtcGxlX3RhYmxlcyBkbyB8dHwNCiAgICAgIHQuY29sdW1uIDpuYW1lLCAgICAgICAgICAgOnN0cmluZywgOmxpbWl0ID0+IDE1MCwgIDpudWxsID0+IHRydWUNCiAgICAgIHQuY29sdW1uIDpkYXRhLCAgICAgICAgICAgOnN0cmluZywgOmxpbWl0ID0+IDUwMDAsIDpudWxsID0+IHRydWUNCiAgICBlbmQNCiAgZW5kDQoNCiAgZGVmIHNlbGYuZG93bg0KICAgIGRyb3BfdGFibGUgOnNhbXBsZV90YWJsZXMNCiAgZW5kDQplbmQ="
}
]
}',
@@ -168,7 +168,7 @@ class PackageTest < ActiveSupport::TestCase
{
"permission": "644",
"location": "db/addon/unit_test_sample/20121212000001_create_base.rb",
- "content": "Y2xhc3MgQ3JlYXRlQmFzZSA8IEFjdGl2ZVJlY29yZDo6TWlncmF0aW9uDQogIGRlZiBzZWxmLnVw\nDQogICBjcmVhdGVfdGFibGUgOnNhbXBsZV90YWJsZXMgZG8gfHR8DQogICAgICB0LmNvbHVtbiA6\nbmFtZSwgICAgICAgICAgIDpzdHJpbmcsIDpsaW1pdCA9PiAxNTAsICA6bnVsbCA9PiB0cnVlDQog\nICAgICB0LmNvbHVtbiA6ZGF0YSwgICAgICAgICAgIDpzdHJpbmcsIDpsaW1pdCA9PiA1MDAwLCA6\nbnVsbCA9PiB0cnVlDQogICAgZW5kDQogIGVuZA0KDQogIGRlZiBzZWxmLmRvd24NCiAgICBkcm9w\nX3RhYmxlIDpzYW1wbGVfdGFibGVzDQogIGVuZA0KZW5k"
+ "content": "Y2xhc3MgQ3JlYXRlQmFzZSA8IEFjdGl2ZVJlY29yZDo6TWlncmF0aW9uWzQuMl0NCiAgZGVmIHNlbGYudXANCiAgIGNyZWF0ZV90YWJsZSA6c2FtcGxlX3RhYmxlcyBkbyB8dHwNCiAgICAgIHQuY29sdW1uIDpuYW1lLCAgICAgICAgICAgOnN0cmluZywgOmxpbWl0ID0+IDE1MCwgIDpudWxsID0+IHRydWUNCiAgICAgIHQuY29sdW1uIDpkYXRhLCAgICAgICAgICAgOnN0cmluZywgOmxpbWl0ID0+IDUwMDAsIDpudWxsID0+IHRydWUNCiAgICBlbmQNCiAgZW5kDQoNCiAgZGVmIHNlbGYuZG93bg0KICAgIGRyb3BfdGFibGUgOnNhbXBsZV90YWJsZXMNCiAgZW5kDQplbmQ="
}
]
}',
@@ -248,7 +248,7 @@ class PackageTest < ActiveSupport::TestCase
{
"permission": "644",
"location": "db/addon/unit_test_sample/20121212000001_create_base.rb",
- "content": "Y2xhc3MgQ3JlYXRlQmFzZSA8IEFjdGl2ZVJlY29yZDo6TWlncmF0aW9uDQogIGRlZiBzZWxmLnVw\nDQogICBjcmVhdGVfdGFibGUgOnNhbXBsZV90YWJsZXMgZG8gfHR8DQogICAgICB0LmNvbHVtbiA6\nbmFtZSwgICAgICAgICAgIDpzdHJpbmcsIDpsaW1pdCA9PiAxNTAsICA6bnVsbCA9PiB0cnVlDQog\nICAgICB0LmNvbHVtbiA6ZGF0YSwgICAgICAgICAgIDpzdHJpbmcsIDpsaW1pdCA9PiA1MDAwLCA6\nbnVsbCA9PiB0cnVlDQogICAgZW5kDQogIGVuZA0KDQogIGRlZiBzZWxmLmRvd24NCiAgICBkcm9w\nX3RhYmxlIDpzYW1wbGVfdGFibGVzDQogIGVuZA0KZW5k"
+ "content": "Y2xhc3MgQ3JlYXRlQmFzZSA8IEFjdGl2ZVJlY29yZDo6TWlncmF0aW9uWzQuMl0NCiAgZGVmIHNlbGYudXANCiAgIGNyZWF0ZV90YWJsZSA6c2FtcGxlX3RhYmxlcyBkbyB8dHwNCiAgICAgIHQuY29sdW1uIDpuYW1lLCAgICAgICAgICAgOnN0cmluZywgOmxpbWl0ID0+IDE1MCwgIDpudWxsID0+IHRydWUNCiAgICAgIHQuY29sdW1uIDpkYXRhLCAgICAgICAgICAgOnN0cmluZywgOmxpbWl0ID0+IDUwMDAsIDpudWxsID0+IHRydWUNCiAgICBlbmQNCiAgZW5kDQoNCiAgZGVmIHNlbGYuZG93bg0KICAgIGRyb3BfdGFibGUgOnNhbXBsZV90YWJsZXMNCiAgZW5kDQplbmQ="
}
]
}',
@@ -304,57 +304,57 @@ class PackageTest < ActiveSupport::TestCase
tests.each { |test|
if test[:action] == 'install'
begin
- package = Package.install( string: test[:zpm] )
+ package = Package.install(string: test[:zpm])
rescue => e
puts 'ERROR: ' + e.inspect
end
if test[:result]
- assert( package, 'install package not successful' )
+ assert(package, 'install package not successful')
issues = package.verify
- assert( !issues, 'package verify not successful' )
+ assert(!issues, 'package verify not successful')
else
- assert( !package, 'install package successful but should not' )
+ assert(!package, 'install package successful but should not')
end
elsif test[:action] == 'reinstall'
begin
- package = Package.reinstall( test[:name] )
+ package = Package.reinstall(test[:name])
rescue
package = false
end
if test[:result]
- assert( package, 'reinstall package not successful' )
+ assert(package, 'reinstall package not successful')
issues = package.verify
- assert( !issues, 'package verify not successful' )
+ assert(!issues, 'package verify not successful')
else
- assert( !package, 'reinstall package successful but should not' )
+ assert(!package, 'reinstall package successful but should not')
end
elsif test[:action] == 'uninstall'
if test[:zpm]
begin
- package = Package.uninstall( string: test[:zpm] )
+ package = Package.uninstall(string: test[:zpm])
rescue
package = false
end
else
begin
- package = Package.uninstall( name: test[:name], version: test[:version] )
+ package = Package.uninstall(name: test[:name], version: test[:version])
rescue
package = false
end
end
if test[:result]
- assert( package, 'uninstall package not successful' )
+ assert(package, 'uninstall package not successful')
else
- assert( !package, 'uninstall package successful but should not' )
+ assert(!package, 'uninstall package successful but should not')
end
elsif test[:action] == 'auto_install'
if test[:zpm]
- if !File.exist?( Rails.root.to_s + '/auto_install/' )
- Dir.mkdir( Rails.root.to_s + '/auto_install/', 0o755)
+ if !File.exist?(Rails.root.to_s + '/auto_install/')
+ Dir.mkdir(Rails.root.to_s + '/auto_install/', 0o755)
end
location = Rails.root.to_s + '/auto_install/unittest.zpm'
- file = File.new( location, 'wb' )
- file.write( test[:zpm] )
+ file = File.new(location, 'wb')
+ file.write(test[:zpm])
file.close
end
begin
@@ -363,22 +363,22 @@ class PackageTest < ActiveSupport::TestCase
success = false
end
if test[:zpm]
- File.delete( location )
+ File.delete(location )
end
end
if test[:verify] && test[:verify][:package]
- exists = Package.where( name: test[:verify][:package][:name], version: test[:verify][:package][:version] ).first
- assert( exists, "package '#{test[:verify][:package][:name]}' is not installed" )
+ exists = Package.where(name: test[:verify][:package][:name], version: test[:verify][:package][:version]).first
+ assert(exists, "package '#{test[:verify][:package][:name]}' is not installed" )
end
next if !test[:verify]
next if !test[:verify][:check_files]
test[:verify][:check_files].each { |item|
- exists = File.exist?( item[:location] )
+ exists = File.exist?(item[:location])
if item[:result]
- assert( exists, "'#{item[:location]}' exists" )
+ assert(exists, "'#{item[:location]}' exists" )
else
- assert( !exists, "'#{item[:location]}' doesn't exists" )
+ assert(!exists, "'#{item[:location]}' doesn't exists" )
end
}
}
diff --git a/test/unit/ticket_escalation_test.rb b/test/unit/ticket_escalation_test.rb
new file mode 100644
index 000000000..a79be51ca
--- /dev/null
+++ b/test/unit/ticket_escalation_test.rb
@@ -0,0 +1,129 @@
+# encoding: utf-8
+require 'test_helper'
+
+class TicketEscalationTest < ActiveSupport::TestCase
+ test 'ticket create' do
+ ticket = Ticket.new(
+ title: 'some value 123',
+ group: Group.lookup(name: 'Users'),
+ customer_id: 2,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+ ticket.save!
+ assert(ticket, 'ticket created')
+ assert_not(ticket.escalation_at)
+ assert_not(ticket.has_changes_to_save?)
+
+ article = Ticket::Article.create!(
+ ticket_id: ticket.id,
+ type_id: Ticket::Article::Type.find_by(name: 'note').id,
+ sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
+ body: 'some body',
+ internal: false,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+ assert_not(article.has_changes_to_save?)
+ assert_not(ticket.has_changes_to_save?)
+
+ calendar = Calendar.create_or_update(
+ name: 'Escalation Test',
+ timezone: 'Europe/Berlin',
+ business_hours: {
+ mon: {
+ active: true,
+ timeframes: [ ['00:00', '23:59'] ]
+ },
+ tue: {
+ active: true,
+ timeframes: [ ['00:00', '23:59'] ]
+ },
+ wed: {
+ active: true,
+ timeframes: [ ['00:00', '23:59'] ]
+ },
+ thu: {
+ active: true,
+ timeframes: [ ['00:00', '23:59'] ]
+ },
+ fri: {
+ active: true,
+ timeframes: [ ['00:00', '23:59'] ]
+ },
+ sat: {
+ active: true,
+ timeframes: [ ['00:00', '23:59'] ]
+ },
+ sun: {
+ active: true,
+ timeframes: [ ['00:00', '23:59'] ]
+ },
+ },
+ default: true,
+ ical_url: nil,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+
+ sla = Sla.create_or_update(
+ name: 'test sla 1',
+ condition: {
+ 'ticket.title' => {
+ operator: 'contains',
+ value: 'some value 123',
+ },
+ },
+ first_response_time: 60,
+ update_time: 180,
+ solution_time: 240,
+ calendar_id: calendar.id,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+
+ ticket = Ticket.new(
+ title: 'some value 123',
+ group: Group.lookup(name: 'Users'),
+ customer_id: 2,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+ ticket.save!
+ assert(ticket, 'ticket created')
+ ticket_escalation_at = ticket.escalation_at
+ assert(ticket.escalation_at)
+ assert_not(ticket.has_changes_to_save?)
+
+ article = Ticket::Article.create!(
+ ticket_id: ticket.id,
+ type_id: Ticket::Article::Type.find_by(name: 'note').id,
+ sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
+ body: 'some body',
+ internal: false,
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+ assert_not(article.has_changes_to_save?)
+ assert_not(ticket.has_changes_to_save?)
+
+ travel 1.second
+
+ sla.first_response_time = 30
+ sla.save!
+
+ ticket.save!
+ assert_not(ticket.has_changes_to_save?)
+ assert(ticket.escalation_at)
+ assert_not_equal(ticket_escalation_at.to_s, ticket.escalation_at.to_s)
+
+ sla.destroy!
+ calendar.destroy!
+
+ ticket.save!
+ assert_not(ticket.has_changes_to_save?)
+ assert_not(ticket.escalation_at)
+
+ end
+
+end
diff --git a/test/unit/ticket_overview_out_of_office_test.rb b/test/unit/ticket_overview_out_of_office_test.rb
index bbd7ca464..f1901f628 100644
--- a/test/unit/ticket_overview_out_of_office_test.rb
+++ b/test/unit/ticket_overview_out_of_office_test.rb
@@ -224,8 +224,6 @@ class TicketOverviewOutOfOfficeTest < ActiveSupport::TestCase
@agent1.out_of_office_replacement_id = @agent2.id
@agent1.save!
- p User.where(active: true, out_of_office: true, out_of_office_replacement_id: @agent2.id)
- p User.where(active: true, out_of_office: true, out_of_office_replacement_id: @agent2.id).where('out_of_office_start_at <= ? AND out_of_office_end_at >= ?', Time.zone.today, Time.zone.today)
assert_equal(@agent2.out_of_office_agent_of.count, 1)
assert(@agent2.out_of_office_agent_of[0])
assert_equal(@agent2.out_of_office_agent_of[0].id, @agent1.id)
diff --git a/test/unit/ticket_sla_test.rb b/test/unit/ticket_sla_test.rb
index 3f0c45454..fa17d4eb9 100644
--- a/test/unit/ticket_sla_test.rb
+++ b/test/unit/ticket_sla_test.rb
@@ -497,6 +497,8 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_equal(ticket.last_contact_agent_at.to_s, article_outbound.created_at.to_s, 'ticket.last_contact_agent_at verify - inbound')
assert_equal(ticket.first_response_at.to_s, article_outbound.created_at.to_s, 'ticket.first_response_at verify - inbound')
assert_nil(ticket.close_at, 'ticket.close_at verify - inbound')
+ calendar1.destroy!
+ calendar2.destroy!
end
test 'ticket sla + selector' do
@@ -605,6 +607,7 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_nil(ticket.close_in_min, 'ticket.close_in_min')
assert_nil(ticket.close_diff_in_min, 'ticket.close_diff_in_min')
+ calendar1.destroy!
end
test 'ticket sla + timezone + holiday' do
@@ -849,12 +852,13 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_equal(ticket.update_escalation_at.gmtime.to_s, '2015-09-23 08:30:00 UTC', 'ticket.update_escalation_at verify 1')
assert_equal(ticket.close_escalation_at.gmtime.to_s, '2015-09-23 09:30:00 UTC', 'ticket.close_escalation_at verify 1')
- delete = sla.destroy
+ delete = sla.destroy!
assert(delete, 'sla destroy')
- delete = ticket.destroy
+ delete = ticket.destroy!
assert(delete, 'ticket destroy')
+ calendar.destroy!
end
test 'ticket escalation suspend close reopen bug' do
@@ -1043,13 +1047,15 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_nil(ticket2.first_response_in_min, 'ticket2.first_response_in_min verify 3')
assert_nil(ticket2.first_response_diff_in_min, 'ticket2.first_response_diff_in_min verify 3')
- delete = sla.destroy
+ delete = sla.destroy!
assert(delete, 'sla destroy')
- delete = ticket1.destroy
+ delete = ticket1.destroy!
assert(delete, 'ticket1 destroy')
- delete = ticket2.destroy
+ delete = ticket2.destroy!
assert(delete, 'ticket2 destroy')
+
+ calendar.destroy!
end
test 'ticket escalation suspend' do
@@ -1552,12 +1558,13 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_equal(ticket.close_in_min, 60, 'ticket.close_in_min verify 3')
assert_equal(ticket.close_diff_in_min, 180, 'ticket.close_diff_in_min# verify 3')
- delete = sla.destroy
+ delete = sla.destroy!
assert(delete, 'sla destroy')
- delete = ticket.destroy
+ delete = ticket.destroy!
assert(delete, 'ticket destroy')
+ calendar.destroy!
end
test 'ticket ticket.title and article.subject' do
@@ -1718,12 +1725,13 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_nil(ticket.close_in_min, 'ticket.close_in_min verify 3')
assert_nil(ticket.close_diff_in_min, 'ticket.close_diff_in_min# verify 3')
- delete = sla.destroy
+ delete = sla.destroy!
assert(delete, 'sla destroy')
- delete = ticket.destroy
+ delete = ticket.destroy!
assert(delete, 'ticket destroy')
+ calendar.destroy!
end
test 'ticket sla + holiday 222' do
@@ -1943,11 +1951,13 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_equal(ticket.update_escalation_at.gmtime.to_s, '2016-11-09 10:26:36 UTC', 'ticket.update_escalation_at verify 1')
assert_nil(ticket.close_escalation_at, 'ticket.close_escalation_at verify 1')
- delete = sla.destroy
+ delete = sla.destroy!
assert(delete, 'sla destroy')
- delete = ticket.destroy
+ delete = ticket.destroy!
assert(delete, 'ticket destroy')
+
+ calendar.destroy!
end
test 'ticket sla + observer check' do
@@ -2124,11 +2134,13 @@ class TicketSlaTest < ActiveSupport::TestCase
assert_equal(ticket.update_escalation_at.gmtime.to_s, '2016-11-07 15:26:36 UTC', 'ticket.update_escalation_at verify 1')
assert_nil(ticket.close_escalation_at, 'ticket.close_escalation_at verify 1')
- delete = sla.destroy
+ delete = sla.destroy!
assert(delete, 'sla destroy')
- delete = ticket.destroy
+ delete = ticket.destroy!
assert(delete, 'ticket destroy')
+
+ calendar.destroy!
end
end
|