123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- RSpec.describe 'Ticket zoom > Checklist', authenticated_as: :authenticate, current_user_id: 1, type: :system do
- let(:action_user) { create(:agent, groups: Group.all) }
- let(:other_agent) { create(:agent, groups: Group.all) }
- let(:ticket) { create(:ticket, group: Group.first) }
- def authenticate
- Setting.set('checklist', true)
- action_user
- end
- def perform_item_action(id, action)
- page.find(".checklistShow tr[data-id='#{id}'] .js-action").click
- page.find(".checklistShow tr[data-id='#{id}'] li[data-table-action='#{action}']").click
- end
- def perform_checklist_action(text)
- click '.sidebar[data-tab=checklist] .js-actions'
- click_on text
- end
- before do
- visit "#ticket/zoom/#{ticket.id}"
- end
- it 'does show the sidebar for the checklists' do
- expect(page).to have_css('.tabsSidebar-tab[data-tab=checklist]')
- Setting.set('checklist', false)
- expect(page).to have_no_css('.tabsSidebar-tab[data-tab=checklist]')
- end
- it 'does create a checklist' do
- click '.tabsSidebar-tab[data-tab=checklist]'
- expect(page).to have_button('Add empty checklist')
- click_on('Add empty checklist')
- expect(page).to have_no_button('Add empty checklist')
- wait.until { ticket.reload.checklist.present? }
- end
- it 'does show handle subscriptions for badge when sidebar is not opened' do
- create(:checklist, ticket: ticket)
- expect(page).to have_css(".tabsSidebar-tab[data-tab='checklist'] .js-tabCounter", text: ticket.checklist.items.count)
- end
- context 'when checklist exists' do
- let(:checklist) { create(:checklist, ticket: ticket, name: 'Capybara checklist') }
- let(:item) { checklist.items.last }
- before do
- checklist
- click '.tabsSidebar-tab[data-tab=checklist]'
- wait.until { page.text.include?(checklist.name.upcase) } # checklist name is shown in all-caps
- await_empty_ajax_queue
- end
- it 'does show handle subscriptions' do
- item.update(text: SecureRandom.uuid)
- expect(page).to have_text(item.text)
- item.destroy
- expect(page).to have_no_text(item.text)
- checklist.destroy
- expect(page).to have_button('Add empty checklist')
- end
- it 'does remove the checklist' do
- perform_checklist_action('Remove checklist')
- click_on 'delete'
- expect(page).to have_text('Add empty checklist')
- end
- it 'does rename the checklist' do
- perform_checklist_action('Rename checklist')
- checklist_name = SecureRandom.uuid
- find('#checklistTitleEditText').fill_in with: checklist_name, fill_options: { clear: :backspace }
- page.find('.js-confirm').click
- wait.until { checklist.reload.name == checklist_name }
- end
- it 'does add item' do
- find('.checklistShowButtons .js-add').click
- wait.until { checklist.items.last.text == '' }
- end
- it 'does check item' do
- perform_item_action(item.id, 'check')
- wait.until { item.reload.checked == true }
- end
- it 'does uncheck item' do
- item.update(checked: true)
- expect(page).to have_css(".checklistShow tr[data-id='#{item.id}'] .js-checkbox:checked", visible: :all)
- perform_item_action(item.id, 'check')
- wait.until { item.reload.checked == false }
- end
- it 'does edit item' do
- perform_item_action(item.id, 'edit')
- item_text = SecureRandom.uuid
- find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
- page.find('.js-confirm').click
- wait.until { item.reload.text == item_text }
- end
- it 'does edit item with a ticket link' do
- perform_item_action(item.id, 'edit')
- item_text = "Ticket##{Ticket.first.number}"
- find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
- page.find('.js-confirm').click
- expect(page).to have_link(Ticket.first.title)
- end
- it 'does reorder item' do
- click_on 'Reorder'
- first_item = checklist.items.first
- last_item = checklist.items.last
- element = page.find(".checklistShow tr[data-id='#{first_item.id}'] .draggable")
- element.drag_to(page.find(".checklistShow tr[data-id='#{last_item.id}'] .draggable"))
- click_on 'Save'
- wait.until { page.text.index(first_item.text) > page.text.index(last_item.text) }
- wait.until { checklist.reload.sorted_item_ids.last.to_s == first_item.id.to_s }
- end
- it 'does not abort edit when subscription is updating but including it afterwards' do
- perform_item_action(item.id, 'edit')
- item_text = SecureRandom.uuid
- find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
- other_item_text = SecureRandom.uuid
- # simulate other users change
- UserInfo.with_user_id(other_agent.id) do
- checklist.items.create!(text: other_item_text)
- end
- # the new item will be shown right away
- expect(page).to have_text(other_item_text)
- # it's important that the old edit mode does not abort
- page.find('.js-confirm').click
- # then both items are shown in the UI
- expect(page).to have_text(item_text)
- expect(page).to have_text(other_item_text)
- end
- it 'does delete item' do
- perform_item_action(item.id, 'delete')
- click_on 'delete'
- wait.until { Checklist::Item.find_by(id: item.id).blank? }
- end
- context 'with links' do
- let(:checklist) do
- checklist = create(:checklist, ticket: ticket)
- checklist.items.last.update(text: 'http://google.de test')
- checklist
- end
- it 'does edit item with link' do
- expect(page).to have_link('google.de')
- perform_item_action(item.id, 'edit')
- item_text = SecureRandom.uuid
- find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
- page.find('.js-confirm').click
- wait.until { item.reload.text == item_text }
- end
- end
- context 'with ticket links' do
- context 'with access' do
- let(:ticket_link) { create(:ticket, title: SecureRandom.uuid, group: Group.first) }
- let(:checklist) do
- checklist = create(:checklist, ticket: ticket)
- checklist.items.last.update(text: "Ticket##{ticket_link.number}")
- checklist
- end
- it 'does show link to the ticket' do
- expect(page).to have_link(ticket_link.title)
- end
- end
- context 'without access' do
- let(:ticket_link) { create(:ticket, title: SecureRandom.uuid) }
- let(:checklist) do
- checklist = create(:checklist, ticket: ticket)
- checklist.items.last.update(text: "Ticket##{ticket_link.number}")
- checklist
- end
- it 'does show the not authorized for the item' do
- expect(page).to have_text('Not authorized')
- end
- end
- end
- end
- context 'when using a checklist template' do
- let(:checklist_template) { create(:checklist_template) }
- before do
- checklist_template
- click '.tabsSidebar-tab[data-tab=checklist]'
- wait.until { page.find('[name="checklist_template_id"]') }
- await_empty_ajax_queue
- end
- it 'does add checklist from template' do
- expect(page).to have_button('Add from a template')
- expect(page).to have_select('checklist_template_id')
- # Sometimes, by clicking the button, nothing happens.
- sleep 0.1
- click_on('Add from a template')
- wait.until { page.has_content?('Please select a checklist template.') }
- select checklist_template.name, from: 'checklist_template_id'
- wait.until { page.has_no_content?('Please select a checklist template.') }
- click_on('Add from a template')
- wait.until { ticket.reload.checklist.present? }
- expect(ticket.checklist.items.count).to eq(checklist_template.items.count)
- checklist_template.items.each do |item|
- expect(page).to have_text(item.text)
- end
- end
- end
- context 'when checklist modal on submit' do
- let(:checklist) { create(:checklist, ticket: ticket, name: SecureRandom.uuid) }
- def authenticate
- pre_auth
- true
- end
- context 'when activated and set' do
- let(:pre_auth) do
- Setting.set('checklist', true)
- checklist
- end
- it 'does show modal' do
- select 'closed', from: 'State'
- click '.js-submit'
- expect(page).to have_text('You have unchecked items in the checklist')
- end
- it 'does switch to sidebar' do
- select 'closed', from: 'State'
- click '.js-submit'
- page.find('.modal-footer .js-submit').click
- expect(page).to have_text(checklist.name.upcase)
- end
- context 'when ticket is closed' do
- let(:pre_auth) do
- Setting.set('checklist', true)
- checklist
- other_agent
- ticket.update(state: Ticket::State.find_by(name: 'closed'))
- end
- it 'does not show modal' do
- select other_agent.fullname, from: 'Owner'
- click '.js-submit'
- wait.until { ticket.reload.owner.fullname == other_agent.fullname }
- expect(page).to have_no_text('You have unchecked items in the checklist')
- end
- end
- context 'when time accounting is also activated' do
- let(:pre_auth) do
- Setting.set('checklist', true)
- Setting.set('time_accounting', true)
- checklist
- end
- it 'does show both modals' do
- find('.articleNewEdit-body').send_keys('New article')
- select 'closed', from: 'State'
- click '.js-submit'
- expect(page.find('.modal-body')).to have_text('You have unchecked items in the checklist')
- page.find('.modal-footer .js-skip').click
- expect(page.find('.modal-body')).to have_text('Accounted Time'.upcase)
- page.find('.modal-footer .js-skip').click
- wait.until { ticket.reload.state.name == 'closed' }
- end
- end
- end
- context 'when deactivated and set' do
- let(:pre_auth) do
- Setting.set('checklist', false)
- checklist
- end
- it 'does not show modal' do
- select 'closed', from: 'State'
- click '.js-submit'
- wait.until { ticket.reload.state.name == 'closed' }
- expect(page).to have_no_text('You have unchecked items in the checklist')
- end
- end
- context 'when activated and completed' do
- let(:pre_auth) do
- Setting.set('checklist', true)
- checklist.items.map { |item| item.update(checked: true) }
- end
- it 'does not show modal' do
- select 'closed', from: 'State'
- click '.js-submit'
- wait.until { ticket.reload.state.name == 'closed' }
- expect(page).to have_no_text('You have unchecked items in the checklist')
- end
- end
- context 'when activated and no checklist' do
- let(:pre_auth) do
- Setting.set('checklist', true)
- end
- it 'does not show modal' do
- select 'closed', from: 'State'
- click '.js-submit'
- wait.until { ticket.reload.state.name == 'closed' }
- expect(page).to have_no_text('You have unchecked items in the checklist')
- end
- end
- end
- describe 'Checklist badge counter does not update when linked tickets change state. #5319' do
- let(:ticket) do
- ticket = create(:ticket, group: Group.first)
- checklist = create(:checklist, ticket: ticket)
- checklist.items.last.update(text: "Ticket##{ticket_link.number}")
- ticket
- end
- let(:ticket_link) { create(:ticket, group: Group.first) }
- it 'does update for badge when sidebar is not opened and same user updates related tickets' do
- ticket_link.update!(state: Ticket::State.find_by(name: 'closed'), updated_by: action_user)
- expect(page).to have_css(".tabsSidebar-tab[data-tab='checklist'] .js-tabCounter", text: ticket.checklist.incomplete)
- end
- end
- # https://github.com/zammad/zammad/issues/5405
- describe 'Checklist counter shows real state of inaccessible linked tickets' do
- let(:ticket_link) { create(:ticket, group: create(:group)) }
- let(:ticket) { create(:ticket, group: Group.first) }
- let(:checklist) do
- create(:checklist, ticket: ticket)
- .tap { |checklist| checklist.items.last.update(text: "Ticket##{ticket_link.number}") }
- end
- before { checklist }
- it 'does update for badge when sidebar is not opened and same user updates related tickets' do
- expect(page)
- .to have_css(".tabsSidebar-tab[data-tab='checklist'] .js-tabCounter", text: ticket.checklist.incomplete)
- .and(have_css('.js-checklist-state .ticket-meta-highlighted', text: "#{ticket.checklist.complete} of #{ticket.checklist.total}"))
- end
- end
- end
|