123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- RSpec.describe 'Ticket > Update > Simultaneously with two different user', type: :system do
- let(:group) { Group.find_by(name: 'Users') }
- let(:ticket) { create(:ticket, group: group) }
- let(:agent) { User.find_by(login: 'agent1@example.com') }
- # rubocop:disable RSpec/InstanceVariable
- define :have_avatar do |expected|
- chain(:changed, :text)
- match do
- elem = find_element
- return false if elem.nil?
- return true if !@icon && !@no_icon
- return elem.has_no_css? '.icon' if @no_icon
- elem.has_css? ".icon-#{@icon}"
- end
- def find_element
- if expected.is_a? User
- actual.find "#{base_selector}#{select_by_user}"
- else
- actual.find base_selector, text: expected
- end
- rescue
- nil
- end
- match_when_negated do
- if expected.is_a? User
- return actual.has_no_css? "#{base_selector}#{select_by_user}"
- end
- actual.has_no_css? base_selector, text: expected
- end
- chain :changed! do
- @changed = true
- end
- chain :with_icon do |icon|
- @icon = icon
- end
- chain :with_no_icon! do
- @no_icon = true
- end
- def select_by_user
- "[data-id='#{expected.id}']"
- end
- def base_selector
- changed_class = @changed ? 'changed' : 'not-changed'
- ".js-attributeBar .js-avatar .avatar--#{changed_class}"
- end
- end
- # rubocop:enable RSpec/InstanceVariable
- def check_taskbar_tab(ticket_id, title: nil, modified: false)
- tab_data_key = "Ticket-#{ticket_id}"
- if title
- taskbar_tab = find(".tasks .task[data-key='#{tab_data_key}']")
- expect(taskbar_tab).to have_css('.nav-tab-name', text: title)
- end
- if modified
- expect(page).to have_css(".tasks .task[data-key='#{tab_data_key}'].is-modified")
- else
- expect(page).to have_no_css(".tasks .task[data-key='#{tab_data_key}'].is-modified")
- end
- end
- context 'when two different users are simultaneously in one ticket' do
- before do
- visit "#ticket/zoom/#{ticket.id}"
- using_session(:second_browser) do
- login(
- username: agent.login,
- password: 'test',
- )
- visit "#ticket/zoom/#{ticket.id}"
- end
- end
- it 'avatar from other user should be visible in ticket zoom' do
- expect(page).to have_avatar('AT')
- using_session(:second_browser) do
- expect(page).to have_avatar('TA')
- end
- end
- it 'check changes from the first user and added changes from the second user' do
- within(:active_content) do
- find('.js-textarea').send_keys('some note')
- expect(page).to have_css('.js-reset')
- end
- expect(page).to have_avatar('AT')
- using_session(:second_browser) do
- expect(page).to have_avatar('TA').changed!
- within(:active_content) do
- find('.js-textarea').send_keys('some other note')
- expect(page).to have_css('.js-reset')
- end
- end
- expect(page).to have_avatar('AT').changed!
- using_session(:second_browser) do
- within(:active_content) do
- click '.js-attributeBar .js-submit'
- expect(page).to have_no_css('.js-reset')
- expect(page).to have_css('.article-content', text: 'some other note')
- end
- expect(page).to have_avatar('TA').changed!
- end
- expect(page).to have_avatar('AT')
- check_taskbar_tab(ticket.id, title: ticket.title, modified: true)
- within(:active_content) do
- expect(page).to have_css('.article-content', text: 'some other note')
- click '.js-attributeBar .js-submit'
- expect(page).to have_no_css('.js-reset')
- expect(page).to have_css('.article-content', text: 'some note')
- end
- using_session(:second_browser) do
- expect(page).to have_avatar('TA')
- expect(page).to have_css('.article-content', text: 'some note')
- check_taskbar_tab(ticket.id, title: ticket.title, modified: true)
- end
- # Reload browsers and check if state is correct.
- refresh
- using_session(:second_browser) do
- refresh
- expect(page).to have_avatar('TA')
- expect(page).to have_no_css('.js-reset')
- end
- expect(page).to have_avatar('AT')
- expect(page).to have_no_css('.js-reset')
- end
- it 'check refresh for unsaved changes and reset after refresh' do
- using_session(:second_browser) do
- within(:active_content) do
- find('.js-textarea').send_keys('some other note')
- expect(page).to have_css('.js-reset')
- end
- expect(page).to have_avatar('TA')
- # We need to wait for the auto save feature.
- wait.until do
- Taskbar.find_by(key: "Ticket-#{ticket.id}", user_id: agent.id).state_changed?
- end
- refresh
- end
- expect(page).to have_avatar('AT').changed!
- using_session(:second_browser) do
- refresh
- within(:active_content) do
- click '.js-reset'
- expect(page).to have_css('.js-textarea', text: '')
- end
- end
- expect(page).to have_avatar('AT')
- end
- it 'change title with second user' do
- find('.js-textarea').send_keys('some note')
- using_session(:second_browser) do
- find('.js-textarea').send_keys('some other note')
- find('.ticketZoom-header .js-objectTitle').set('TTTsome level 2 <b>subject</b> 123äöü')
- # Click in the body field, to trigger the title update.
- find('.js-textarea').send_keys('trigger title')
- expect(page).to have_css('.js-objectTitle', text: 'TTTsome level 2 <b>subject</b> 123äöü')
- check_taskbar_tab(ticket.id, title: 'TTTsome level 2 <b>subject</b> 123äöü')
- expect(page).to have_css('.js-textarea', text: 'some other note')
- end
- expect(page).to have_css('.js-objectTitle', text: 'TTTsome level 2 <b>subject</b> 123äöü')
- expect(page).to have_css('.js-textarea', text: 'some note')
- check_taskbar_tab(ticket.id, title: 'TTTsome level 2 <b>subject</b> 123äöü', modified: true)
- # Refresh and check that modified flag is gone
- refresh
- check_taskbar_tab(ticket.id, title: 'TTTsome level 2 <b>subject</b> 123äöü', modified: false)
- end
- end
- context 'when working on multiple platforms', authenticated_as: :user do
- let(:ticket) { create(:ticket) }
- let(:user) { create(:agent, groups: [ticket.group]) }
- let(:another_user) { create(:agent, groups: [ticket.group]) }
- let(:key) { "Ticket-#{ticket.id}" }
- let(:path) { "ticket/zoom/#{ticket.id}" }
- let(:taskbar_mobile) { create(:taskbar, user: user, app: :mobile, key: key) }
- let(:taskbar_desktop) { create(:taskbar, user: user, app: :desktop, key: key) }
- let(:another_taskbar_mobile) { create(:taskbar, user: another_user, app: :mobile, key: key) }
- let(:another_taskbar_desktop) { create(:taskbar, user: another_user, app: :desktop, key: key) }
- context 'when looking on a ticket' do
- before do
- taskbar_desktop
- visit path
- end
- it 'does not show current user' do
- expect(page).not_to have_avatar(user)
- end
- end
- context 'when another user is looking on desktop' do
- before do
- another_taskbar_desktop
- taskbar_desktop
- visit path
- end
- it 'shows another user' do
- expect(page).to have_avatar(another_user).with_no_icon!
- end
- end
- context 'when another user is looking on mobile' do
- before do
- another_taskbar_mobile
- taskbar_desktop
- visit path
- end
- it 'shows another user' do
- expect(page).to have_avatar(another_user).with_icon(:mobile)
- end
- end
- context 'when another user is looking on mobile and desktop' do
- before do
- another_taskbar_mobile
- another_taskbar_desktop
- taskbar_desktop
- visit path
- end
- it 'shows another user' do
- expect(page).to have_avatar(another_user).with_no_icon!
- end
- end
- context 'when another user is editing on desktop' do
- before do
- another_taskbar_desktop.update!(state: { a: 1 })
- taskbar_desktop
- visit path
- end
- it 'shows another user' do
- expect(page).to have_avatar(another_user).with_icon(:pen).changed!
- end
- end
- context 'when another user is editing on mobile' do
- before do
- another_taskbar_mobile.update!(state: { a: 1 })
- taskbar_desktop
- visit path
- end
- it 'shows another user' do
- expect(page).to have_avatar(another_user).with_icon(:pen).changed!
- end
- end
- context 'when same user is looking on mobile too' do
- before do
- taskbar_mobile
- taskbar_desktop
- visit path
- end
- it 'shows same user' do
- expect(page).not_to have_avatar(user)
- end
- end
- context 'when same user is editing' do
- before do
- taskbar_desktop.update!(state: { a: 1 })
- visit path
- end
- it 'do not show same user' do
- expect(page).not_to have_avatar(user)
- end
- end
- context 'when same user is editing on mobile' do
- before do
- taskbar_mobile.update!(state: { a: 1 })
- taskbar_desktop
- visit path
- end
- it 'shows same user' do
- expect(page).to have_avatar(user).with_icon(:'mobile-edit').changed!
- end
- end
- end
- end
|