From 899613421489617990b3caf58b179afbd5576daf Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 26 Nov 2019 11:40:23 +0100 Subject: [PATCH] Fixed issue #542 - Cant add new articles via Macro. --- .../app/controllers/ticket_zoom.coffee | 3 +- .../javascripts/app/models/ticket.coffee | 21 +++ spec/system/ticket/update_spec.rb | 167 ++++++++++++------ 3 files changed, 138 insertions(+), 53 deletions(-) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee index c61a5242d..d0457204a 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -766,6 +766,7 @@ class App.TicketZoom extends App.Controller return ticketParams = @formParam(@$('.edit')) + articleParams = @articleNew.params() # validate ticket # we need to use the full ticket because @@ -784,6 +785,7 @@ class App.TicketZoom extends App.Controller App.Ticket.macro( macro: macro.perform ticket: ticket + article: articleParams callback: tagAdd: (tag) => return if !@sidebarWidget @@ -832,7 +834,6 @@ class App.TicketZoom extends App.Controller @autosaveStart() return - articleParams = @articleNew.params() if articleParams && articleParams.body article = new App.TicketArticle article.load(articleParams) diff --git a/app/assets/javascripts/app/models/ticket.coffee b/app/assets/javascripts/app/models/ticket.coffee index bd9466947..f16fcf114 100644 --- a/app/assets/javascripts/app/models/ticket.coffee +++ b/app/assets/javascripts/app/models/ticket.coffee @@ -114,6 +114,8 @@ class App.Ticket extends App.Model @macro: (params) -> for key, content of params.macro attributes = key.split('.') + + # apply ticket changes if attributes[0] is 'ticket' # apply tag changes @@ -142,6 +144,25 @@ class App.Ticket extends App.Model else params.ticket[attributes[1]] = content.value + # apply article changes + else if attributes[0] is 'article' + + # preload required attributes + if attributes[1] + type = App.TicketArticleType.findByAttribute('name', attributes[1]) + if type + params.article.type_id = type.id + if !content.sender_id + sender = App.TicketArticleSender.findByAttribute('name', 'Agent') + if sender + content.sender_id = sender.id + if !content.from + content.from = App.Session.get('login') + + # apply direct value changes + for articleKey, aricleValue of content + params.article[articleKey] = aricleValue + # check if selector is matching @selector: (ticket, selector) -> return true if _.isEmpty(selector) diff --git a/spec/system/ticket/update_spec.rb b/spec/system/ticket/update_spec.rb index 7b93b1020..459ee3310 100644 --- a/spec/system/ticket/update_spec.rb +++ b/spec/system/ticket/update_spec.rb @@ -6,12 +6,13 @@ require 'system/examples/macros_examples' RSpec.describe 'Ticket Update', type: :system do let(:group) { Group.find_by(name: 'Users') } + let(:ticket) { create(:ticket, group: group) } # Regression test for issue #2242 - mandatory fields can be empty (or "-") on ticket update context 'when updating a ticket without its required select attributes' do it 'frontend checks reject the update', db_strategy: :reset do # setup and migrate a required select attribute - attribute = create_attribute :object_manager_attribute_select, + attribute = create_attribute(:object_manager_attribute_select, screens: attributes_for(:required_screen), data_option: { options: { @@ -23,15 +24,14 @@ RSpec.describe 'Ticket Update', type: :system do relation: '', maxlength: 255, nulloption: true, - } + }) # create a new ticket and attempt to update its state without the required select attribute - ticket = create :ticket, group: group visit "#ticket/zoom/#{ticket.id}" within(:active_content) do - expect(page).to have_css('.js-objectNumber', wait: 2) + expect(page).to have_selector('.js-objectNumber', text: ticket.number) - select 'closed', from: 'state_id' + select('closed', from: 'state_id') click('.js-attributeBar .js-submit') expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]', wait: 2) end @@ -50,60 +50,123 @@ RSpec.describe 'Ticket Update', type: :system do expect(ticket[attribute.name]).to eq('name 2') expect(ticket.state.name).to eq('closed') end + end - it 'with macro and required tree_select field', db_strategy: :reset do - # setup and migrate a required select attribute - attribute = create_attribute :object_manager_attribute_tree_select, - screens: attributes_for(:required_screen), - data_option: { - options: [ - { - name: 'name 1', - value: 'name 1', - }, - { - name: 'name 2', - value: 'name 2', - }, - ], - default: '', - null: false, - relation: '', - maxlength: 255, - nulloption: true, - } + context 'when updating a ticket with macro' do + context 'when required tree_select field is present' do + it 'performs no validation (#2492)', db_strategy: :reset do + # setup and migrate a required select attribute + attribute = create_attribute(:object_manager_attribute_tree_select, + screens: attributes_for(:required_screen), + data_option: { + options: [ + { + name: 'name 1', + value: 'name 1', + }, + { + name: 'name 2', + value: 'name 2', + }, + ], + default: '', + null: false, + relation: '', + maxlength: 255, + nulloption: true, + }) - attribute_value = 'name 2' - state = Ticket::State.by_category(:closed).first - macro = create(:macro, - perform: { - 'ticket.state_id' => { - value: state.id, + attribute_value = 'name 2' + state = Ticket::State.by_category(:closed).first + macro = create(:macro, + perform: { + 'ticket.state_id' => { + value: state.id, + }, + "ticket.#{attribute.name}" => { + value: attribute_value, + }, }, - "ticket.#{attribute.name}" => { - value: attribute_value, - }, - }) + ux_flow_next_up: 'none',) - # refresh browser to get macro accessible - refresh + # refresh browser to get macro accessible + refresh - # create a new ticket and attempt to update its state without the required select attribute - ticket = create(:ticket, group: group) - visit "#ticket/zoom/#{ticket.id}" + # create a new ticket and attempt to update its state without the required select attribute + visit "#ticket/zoom/#{ticket.id}" - within(:active_content) do - expect(page).to have_css('.js-objectNumber', wait: 2) + within(:active_content) do + expect(page).to have_selector('.js-objectNumber', text: ticket.number) - click('.js-openDropdownMacro') - click(".js-dropdownActionMacro[data-id=\"#{macro.id}\"]") - expect(page).not_to have_css('.js-submitDropdown .js-submit[disabled]', wait: 2) + expect(page).to have_field(attribute.name, with: '', visible: false) + expect(page).to have_select('state_id', + selected: 'new', + options: ['new', 'closed', 'open', 'pending close', 'pending reminder']) + + click('.js-openDropdownMacro') + click(".js-dropdownActionMacro[data-id=\"#{macro.id}\"]") + expect(page).not_to have_css('.js-submitDropdown .js-submit[disabled]', wait: 2) + end + + expect(page).to have_field(attribute.name, with: attribute_value, visible: false) + expect(page).to have_select('state_id', + selected: 'closed', + options: ['closed', 'open', 'pending close', 'pending reminder']) + + # the update should not have failed and thus the ticket is in closed state + ticket.reload + expect(ticket[attribute.name]).to eq(attribute_value) + expect(ticket.state.name).to eq(state.name) end + end - # the update should not have failed and thus the ticket is in closed state - ticket.reload - expect(ticket[attribute.name]).to eq(attribute_value) - expect(ticket.state.name).to eq(state.name) + context 'when macro has article configured' do + it 'creates an article with the configured attributes' do + state = Ticket::State.find_by(name: 'closed') + macro = create(:macro, + perform: { + 'ticket.state_id' => { + value: state.id, + }, + 'article.note' => { + 'body' => 'test body', + 'internal' => 'true', + 'subject' => 'test sub' + }, + }, + ux_flow_next_up: 'none',) + + # refresh browser to get macro accessible + refresh + + # create a new ticket and attempt to update its state without the required select attribute + visit "#ticket/zoom/#{ticket.id}" + + within(:active_content) do + expect(page).to have_selector('.js-objectNumber', text: ticket.number) + expect(page).to have_select('state_id', + selected: 'new', + options: ['new', 'closed', 'open', 'pending close', 'pending reminder']) + + click('.js-openDropdownMacro') + click(".js-dropdownActionMacro[data-id=\"#{macro.id}\"]") + expect(page).not_to have_css('.js-submitDropdown .js-submit[disabled]', wait: 2) + end + + expect(page).to have_selector('.content.active .article-content', text: 'test body') + expect(page).to have_select('state_id', + selected: 'closed', + options: ['closed', 'open', 'pending close', 'pending reminder']) + + # the update should not have failed and thus the ticket is in closed state + ticket.reload + expect(ticket.state.name).to eq(state.name) + article = ticket.articles.last + expect(article).to be_present + expect(article.body).to eq('test body') + expect(article.subject).to eq('test sub') + expect(article.internal).to eq(true) + end end end @@ -140,10 +203,10 @@ RSpec.describe 'Ticket Update', type: :system do end context 'when using text modules' do - include_examples 'text modules', path: "#ticket/zoom/#{Ticket.first.id}" + include_examples 'text modules', path: "#ticket/zoom/#{Ticket.first.id}" end context 'when using macros' do - include_examples 'macros', path: "#ticket/zoom/#{Ticket.first.id}" + include_examples 'macros', path: "#ticket/zoom/#{Ticket.first.id}" end end