123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- require 'system/examples/text_modules_examples'
- 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, :required_screen,
- data_option: {
- options: {
- 'name 1': 'name 1',
- 'name 2': 'name 2',
- },
- default: '',
- null: false,
- relation: '',
- maxlength: 255,
- nulloption: true,
- })
- # 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', text: ticket.number)
- select('closed', from: 'state_id')
- click('.js-attributeBar .js-submit')
- expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]')
- end
- # the update should have failed and thus the ticket is still in the new state
- expect(ticket.reload.state.name).to eq('new')
- within(:active_content) do
- # update should work now
- find(".edit [name=#{attribute.name}]").select('name 2')
- click('.js-attributeBar .js-submit')
- expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]')
- end
- ticket.reload
- expect(ticket[attribute.name]).to eq('name 2')
- expect(ticket.state.name).to eq('closed')
- end
- end
- context 'when updating a ticket date attribute', db_strategy: :reset do
- let!(:date_attribute) do
- create_attribute(
- :object_manager_attribute_date,
- name: 'example_date',
- screens: {
- create: {
- 'ticket.agent' => {
- shown: true
- },
- },
- edit: {
- 'ticket.agent' => {
- shown: true
- }
- },
- view: {
- 'ticket.agent' => {
- shown: true
- },
- }
- },
- data_option: {
- 'future' => true,
- 'past' => false,
- 'diff' => 0,
- 'null' => true,
- }
- )
- end
- let(:ticket) { create(:ticket, group: group, "#{date_attribute.name}": '2018-02-28') }
- it 'set date attribute to empty' do
- visit "#ticket/zoom/#{ticket.id}"
- within(:active_content) do
- check_date_field_value(date_attribute.name, '02/28/2018')
- set_date_field_value(date_attribute.name, '')
- click('.js-attributeBar .js-submit')
- expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]')
- ticket.reload
- expect(ticket[date_attribute.name]).to be_nil
- end
- end
- end
- 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, :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,
- },
- "ticket.#{attribute.name}" => {
- value: attribute_value,
- },
- },
- 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_css('.js-objectNumber', text: ticket.number)
- expect(page).to have_field(attribute.name, with: '', visible: :hidden)
- 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).to have_no_css('.js-submitDropdown .js-submit[disabled]')
- end
- expect(page).to have_field(attribute.name, with: attribute_value, visible: :hidden)
- 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
- 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_css('.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).to have_no_css('.js-submitDropdown .js-submit[disabled]')
- end
- expect(page).to have_css('.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 be(true)
- end
- end
- end
- context 'when merging tickets' do
- let!(:user) { create(:user) }
- let!(:origin_ticket) { create(:ticket, group: group) }
- let!(:target_ticket) { create(:ticket, group: group) }
- before do
- origin_ticket.merge_to(ticket_id: target_ticket.id, user_id: user.id)
- end
- # Issue #2469 - Add information "Ticket merged" to History
- it 'tickets history of both tickets should show the merge event' do
- visit "#ticket/zoom/#{origin_ticket.id}"
- within(:active_content) do
- expect(page).to have_css('.js-actions .dropdown-toggle')
- click '.js-actions .dropdown-toggle'
- click '.js-actions .dropdown-menu [data-type="ticket-history"]'
- in_modal do
- expect(page).to have_content "this ticket was merged into ticket ##{target_ticket.number}"
- expect(page).to have_link "##{target_ticket.number}", href: "#ticket/zoom/#{target_ticket.id}"
- end
- visit "#ticket/zoom/#{target_ticket.id}"
- expect(page).to have_css('.js-actions .dropdown-toggle')
- click '.js-actions .dropdown-toggle'
- click '.js-actions .dropdown-menu [data-type="ticket-history"]'
- in_modal do
- expect(page).to have_content("ticket ##{origin_ticket.number} was merged into this ticket")
- expect(page).to have_link "##{origin_ticket.number}", href: "#ticket/zoom/#{origin_ticket.id}"
- end
- end
- end
- # Issue #2960 - Ticket removal of merged / linked tickets doesn't remove references
- context 'when the merged origin ticket is deleted' do
- before do
- origin_ticket.destroy
- end
- it 'shows the target ticket history' do
- visit "#ticket/zoom/#{target_ticket.id}"
- within(:active_content) do
- expect(page).to have_css('.js-actions .dropdown-toggle')
- click '.js-actions .dropdown-toggle'
- click '.js-actions .dropdown-menu [data-type="ticket-history"]'
- end
- in_modal do
- expect(page).to have_text "##{origin_ticket.number} #{origin_ticket.title}"
- end
- end
- end
- # Issue #2960 - Ticket removal of merged / linked tickets doesn't remove references
- context 'when the merged target ticket is deleted' do
- before do
- target_ticket.destroy
- end
- it 'shows the origin history' do
- visit "#ticket/zoom/#{origin_ticket.id}"
- within(:active_content) do
- expect(page).to have_css('.js-actions .dropdown-toggle')
- click '.js-actions .dropdown-toggle'
- click '.js-actions .dropdown-menu [data-type="ticket-history"]'
- end
- in_modal do
- expect(page).to have_text "##{target_ticket.number} #{target_ticket.title}"
- end
- end
- end
- end
- context 'when closing taskbar tab for ticket' do
- it 'close task bar entry after some changes in ticket update form' do
- visit "#ticket/zoom/#{ticket.id}"
- within(:active_content) do
- find('.js-textarea').send_keys('some note')
- end
- taskbar_tab_close("Ticket-#{ticket.id}")
- end
- end
- context 'when using text modules' do
- include_examples 'text modules', path: "#ticket/zoom/#{Ticket.first.id}", ticket: Ticket.first
- context 'when owner is used in a text module and was updated in the ticket', authenticated_as: :authenticate do
- let(:user) { User.find_by(email: 'agent1@example.com') }
- let(:another_user) { create(:agent, groups: [Group.find_by(name: 'Users')]) }
- let(:ticket) { create(:ticket, group: group, owner: user) }
- let(:text_module) { create(:text_module, name: 'firstlast', keywords: 'firstlast', content: '#{ticket.owner.firstname} #{ticket.owner.lastname}') } # rubocop:disable Lint/InterpolationCheck
- def authenticate
- ticket && text_module && another_user
- true
- end
- def select_text_module
- find(:richtext).send_keys(':')
- find(:richtext).send_keys(':')
- find(:richtext).send_keys('firstlast')
- expect(page).to have_selector(:text_module, text_module.id)
- find(:richtext).send_keys(:enter)
- end
- it 'updates used data' do
- visit "#ticket/zoom/#{ticket.id}"
- expect(page).to have_field('owner_id', with: user.id)
- within(:active_content) do
- select_text_module
- expect(find(:richtext).text).to include("#{user.firstname} #{user.lastname}")
- select another_user.fullname, from: 'Owner'
- find('.js-submit').click
- expect(ticket.reload.owner_id).to eq(another_user.id)
- select_text_module
- expect(find(:richtext).text).to include("#{another_user.firstname} #{another_user.lastname}")
- end
- end
- end
- end
- context 'when using macros' do
- include_examples 'macros', path: "#ticket/zoom/#{Ticket.first.id}"
- end
- context 'when group will be changed' do
- let(:user) { User.find_by(email: 'agent1@example.com') }
- let(:ticket) { create(:ticket, group: group, owner: user) }
- it 'check that owner resets after group change' do
- visit "#ticket/zoom/#{ticket.id}"
- expect(page).to have_field('owner_id', with: user.id)
- set_tree_select_value('group_id', '') # empty selection
- expect(page).to have_field('owner_id', with: '')
- end
- end
- end
|