Refactoring: Port System > Objects browser tests to capybara.

This commit is contained in:
Martin Gruner 2021-09-21 09:29:59 +02:00
parent f520667489
commit 3be8f6d032
6 changed files with 357 additions and 1265 deletions

View file

@ -14,8 +14,6 @@ if [ "$LEVEL" == '1' ]; then
rm test/browser/admin_channel_email_test.rb
rm test/browser/admin_calendar_sla_test.rb
rm test/browser/admin_drag_drop_to_new_group_test.rb
rm test/browser/admin_object_manager_test.rb
rm test/browser/admin_object_manager_tree_select_test.rb
rm test/browser/admin_overview_test.rb
rm test/browser/admin_permissions_granular_vs_full_test.rb
rm test/browser/admin_role_test.rb
@ -84,8 +82,6 @@ elif [ "$LEVEL" == '2' ]; then
rm test/browser/admin_channel_email_test.rb
rm test/browser/admin_calendar_sla_test.rb
rm test/browser/admin_drag_drop_to_new_group_test.rb
rm test/browser/admin_object_manager_test.rb
rm test/browser/admin_object_manager_tree_select_test.rb
rm test/browser/admin_overview_test.rb
rm test/browser/admin_permissions_granular_vs_full_test.rb
#rm test/browser/admin_role_test.rb
@ -154,8 +150,6 @@ elif [ "$LEVEL" == '3' ]; then
rm test/browser/admin_channel_email_test.rb
rm test/browser/admin_calendar_sla_test.rb
rm test/browser/admin_drag_drop_to_new_group_test.rb
rm test/browser/admin_object_manager_test.rb
rm test/browser/admin_object_manager_tree_select_test.rb
rm test/browser/admin_overview_test.rb
rm test/browser/admin_permissions_granular_vs_full_test.rb
rm test/browser/admin_role_test.rb
@ -224,8 +218,6 @@ elif [ "$LEVEL" == '4' ]; then
rm test/browser/admin_channel_email_test.rb
rm test/browser/admin_calendar_sla_test.rb
rm test/browser/admin_drag_drop_to_new_group_test.rb
rm test/browser/admin_object_manager_test.rb
rm test/browser/admin_object_manager_tree_select_test.rb
rm test/browser/admin_overview_test.rb
rm test/browser/admin_permissions_granular_vs_full_test.rb
rm test/browser/admin_role_test.rb
@ -293,8 +285,6 @@ elif [ "$LEVEL" == '5' ]; then
# test/browser/admin_channel_email_test.rb
# test/browser/admin_calendar_sla_test.rb
# rm test/browser/admin_drag_drop_to_new_group_test.rb
# test/browser/admin_object_manager_test.rb
# test/browser/admin_object_manager_tree_select_test.rb
# test/browser/admin_overview_test.rb
# rm test/browser/admin_permissions_granular_vs_full_test.rb
rm test/browser/admin_role_test.rb
@ -365,8 +355,6 @@ elif [ "$LEVEL" == '6' ]; then
rm test/browser/admin_channel_email_test.rb
rm test/browser/admin_calendar_sla_test.rb
rm test/browser/admin_drag_drop_to_new_group_test.rb
rm test/browser/admin_object_manager_test.rb
rm test/browser/admin_object_manager_tree_select_test.rb
rm test/browser/admin_overview_test.rb
rm test/browser/admin_permissions_granular_vs_full_test.rb
rm test/browser/admin_role_test.rb

View file

@ -2,7 +2,7 @@
require 'rails_helper'
RSpec.describe 'System > Sla', type: :system do
RSpec.describe 'Manage > Sla', type: :system do
before do
ensure_websocket do
visit 'manage/slas'

View file

@ -2,7 +2,7 @@
require 'rails_helper'
RSpec.describe 'Manage > Maintenance', type: :system do
RSpec.describe 'System > Maintenance', type: :system do
context 'when maintenance login is used' do
context 'when maintenance login will be activated', authenticated_as: :authenticate do
def authenticate

View file

@ -2,139 +2,387 @@
require 'rails_helper'
# https://github.com/zammad/zammad/issues/266
RSpec.describe 'Admin Panel > Objects', type: :system do
before do
visit '/#system/object_manager'
end
RSpec.describe 'System > Objects', type: :system do
it 'verifies option creation order of new tree select options' do
context 'when trying to create invalid attributes' do
RSpec.shared_examples 'cannot create new object attribute' do |name, error_message|
context "when trying to create a new attibute '#{name}'" do
before do
visit '/#system/object_manager'
page.find('.js-new').click
end
# create new field
page.find('.js-new').click
# set meta information
fill_in 'Name', with: 'tree1'
fill_in 'Display', with: 'tree1'
page.find('select[name=data_type]').select('Tree Select')
# create 3 childs
first_add_child = page.first('div.js-addChild')
first_add_child.click
first_add_child.click
first_add_child.click
# create 1 top level node sibling
page.first('div.js-addRow').click
# create 3 childs for the new top level node
page.all('div.js-addChild').last.click
page.all('div.js-addChild').last.click
page.all('div.js-addChild').last.click
# create new top level nodes by first and second top level node
add_rows = page.all('div.js-addRow')
add_rows[0].click
add_rows[4].click
# add numbers to all inputs to verify order in config later
number = 1
page.all('input.js-key').each do |input|
input.send_keys(number)
number += 1
it "fails with '#{error_message}'" do
within '.modal' do
fill_in 'name', with: name || 'fallback'
fill_in 'display', with: 'Not allowed'
click '.js-submit'
expect(find('.js-alert')).to have_text(error_message)
end
end
end
end
page.find('.js-submit').click
expected_data_options = { 'options' =>
[{ 'name' => '1',
'value' => '1',
'children' => [{ 'name' => '2', 'value' => '1::2' }, { 'name' => '3', 'value' => '1::3' }, { 'name' => '4', 'value' => '1::4' }] },
{ 'name' => '5', 'value' => '5' },
{ 'name' => '6',
'value' => '6',
'children' =>
[{ 'name' => '7',
'value' => '6::7',
'children' => [{ 'name' => '8', 'value' => '6::7::8', 'children' => [{ 'name' => '9', 'value' => '6::7::8::9' }] }] }] },
{ 'name' => '10', 'value' => '10' }],
'default' => '',
'null' => true,
'relation' => '',
'nulloption' => true,
'maxlength' => 255 }
expect(ObjectManager::Attribute.last.data_option).to eq(expected_data_options)
include_examples 'cannot create new object attribute', 'customer_id', 'Object already exists!'
['some_other_id', 'some_other_ids', 'some spaces'].each do |name|
include_examples 'cannot create new object attribute', name, 'are not allowed'
end
end
it 'checks smart defaults for select field' do
page.find('.js-new').click
fill_in 'Name', with: 'select1'
find('input[name=display]').set('select1')
page.find('select[name=data_type]').select('Select')
page.first('div.js-add').click
page.first('div.js-add').click
page.first('div.js-add').click
counter = 0
page.all('.js-key').each do |field|
field.set(counter)
counter += 1
context 'when creating but then discarding fields again' do
before do
visit '/#system/object_manager'
end
page.all('.js-value')[-2].set('special 2')
page.find('.js-submit').click
expected_data_options = {
'0' => '0',
'1' => '1',
'2' => 'special 2',
}
expect(ObjectManager::Attribute.last.data_option['options']).to eq(expected_data_options)
it 'discards the changes again' do
page.find('.js-new').click
within '.modal' do
fill_in 'name', with: 'new_field'
fill_in 'display', with: 'New field'
click '.js-submit'
end
click '.js-discard'
expect(page).to have_no_css('.js-discard')
end
end
it 'checks smart defaults for boolean field' do
page.find('.js-new').click
context 'when creating and removing a field with migration', db_strategy: :reset do
RSpec.shared_examples 'create and remove field with migration' do |data_type|
context "for data_type '#{data_type}'" do
before do
visit '/#system/object_manager'
end
fill_in 'Name', with: 'bool1'
find('input[name=display]').set('bool1')
it 'creates and removes the field correctly' do
# Create
page.find('.js-new').click
within '.modal' do
fill_in 'name', with: 'new_field'
fill_in 'display', with: 'New field'
select data_type, from: 'data_type'
click '.js-submit'
end
expect(page).to have_text('New field')
expect(page).to have_text('Database Update required')
click '.js-execute', wait: 7.minutes
expect(page).to have_text('Zammad need a restart')
page.refresh
page.find('select[name=data_type]').select('Boolean')
page.find('.js-valueFalse').set('HELL NOO')
page.find('.js-submit').click
# Update
click 'tbody tr:last-child'
within '.modal' do
fill_in 'display', with: 'New field updated'
click '.js-submit'
end
expect(page).to have_text('New field updated')
expect(page).to have_text('Database Update required')
click '.js-execute', wait: 7.minutes
expect(page).to have_text('please reload your browser')
page.refresh
expected_data_options = {
true => 'yes',
false => 'HELL NOO',
}
# Delete
click 'tbody tr:last-child .js-delete'
expect(page).to have_text('Database Update required')
click '.js-execute', wait: 7.minutes
expect(page).to have_text('Zammad need a restart')
expect(page).to have_no_text('New field updated')
end
end
end
expect(ObjectManager::Attribute.last.data_option['options']).to eq(expected_data_options)
['Text', 'Select', 'Integer', 'Datetime', 'Date', 'Boolean', 'Tree Select'].each do |data_type|
include_examples 'create and remove field with migration', data_type
end
end
it 'checks default boolean value visibility' do
page.find('.js-new').click
context 'when creating and modifying tree select fields', db_strategy: :reset do
fill_in 'Name', with: 'bool1'
find('input[name=display]').set('Bool 1')
let(:object_attribute) do
attribute = create(:object_manager_attribute_tree_select, name: 'undeletable_field', display: 'Undeletable Field', position: 999)
ObjectManager::Attribute.migration_execute
attribute
end
page.find('select[name=data_type]').select('Boolean')
choose('data_option::default', option: 'true')
page.find('.js-submit').click
it 'creates and updates the fields correctly' do
# Create the field via API.
object_attribute
visit '/#system/object_manager'
page.refresh
click 'tbody tr:last-child'
td = page.find(:css, 'td', text: 'bool1')
tr = td.find(:xpath, './parent::tr')
# Add two new attributes to the field.
2.times do |i|
click '.modal tbody tr:last-child .js-addRow'
find('.modal tbody tr:last-child .js-key').fill_in(with: "new tree option #{i}")
end
click '.js-submit'
tr.click
expect(page).to have_text('Database Update required')
click '.js-execute', wait: 7.minutes
expect(page).to have_text('please reload your browser')
page.refresh
expect(page).to have_checked_field('data_option::default', with: 'true')
# Check that the attributes were correctly saved.
expect(ObjectManager::Attribute.last.data_option[:options][-2..]).to eq([{ 'name' => 'new tree option 0', 'value' => 'new tree option 0' }, { 'name' => 'new tree option 1', 'value' => 'new tree option 1' }])
end
end
context 'when trying to delete undeletable fields', db_strategy: :reset do
let(:object_attribute) do
attribute = create(:object_manager_attribute_text, name: 'undeletable_field', display: 'Undeletable Field', position: 999)
ObjectManager::Attribute.migration_execute
attribute
end
before do
create(:overview, condition: {
"ticket.#{object_attribute.name}" => {
operator: 'is',
value: 'dummy',
},
})
visit '/#system/object_manager'
end
it 'field referenced by an overview is not deletable' do
expect(page).to have_text(object_attribute.display)
expect(page).to have_css('tbody tr:last-child span.is-disabled .icon-trash')
end
end
context 'when checking field sorting', db_strategy: :reset do
# lexicographically ordered list of option strings
let(:options) { %w[0 000.000 1 100.100 100.200 2 200.100 200.200 3 ä b n ö p sr ß st t ü v] }
let(:options_hash) { options.reverse.collect { |o| [o, o] }.to_h }
let(:object_attribute) do
attribute = create(:object_manager_attribute_select, data_option: { options: options_hash, default: 0 }, position: 999)
ObjectManager::Attribute.migration_execute
attribute
end
it 'preserves the sorting correctly' do
object_attribute
page.refresh
visit '/#system/object_manager'
click 'tbody tr:last-child'
sorted_dialog_values = all('table.settings-list tbody tr td:first-child input').map(&:value).reject { |x| x == '' }
expect(sorted_dialog_values).to eq(options)
visit '/#ticket/create'
sorted_ticket_values = all("select[name=#{object_attribute.name}] option").map(&:value).reject { |x| x == '' }
expect(sorted_ticket_values).to eq(options)
end
end
context 'when checking selection options removal', db_strategy: :reset do
let(:options) { %w[äöü cat delete dog ß].index_with { |x| "#{x.capitalize} Display" } }
let(:options_no_dog) { options.except('dog') }
let(:options_no_dog_no_delete) { options_no_dog.except('delete') }
let(:screens) { { 'create_middle' => { 'ticket.agent'=>{ 'shown' => true, 'required' => false, 'item_class' => 'column' } }, 'edit' => { 'ticket.agent'=>{ 'shown' => true, 'required' => false } } } }
let(:object_attribute) do
attribute = create(:object_manager_attribute_select, data_option: { options: options, default: 0 }, screens: screens, position: 999)
ObjectManager::Attribute.migration_execute
attribute
end
it 'handles removed options correctly' do
object_attribute
page.refresh
# Make sure option is present in the first place.
ticket = create(:ticket, group: Group.find_by(name: 'Users'), object_attribute.name => 'delete')
visit "/#ticket/zoom/#{ticket.id}"
sorted_ticket_values = all("select[name=#{object_attribute.name}] option").map(&:value).reject { |x| x == '' }
expect(sorted_ticket_values).to eq(options.keys)
expect(find("select[name=#{object_attribute.name}] option:checked").value).to eq('delete')
expect(find("select[name=#{object_attribute.name}] option:checked").text).to eq('Delete Display')
# Remove 'delete' and 'dog' options from field via GUI to make sure that the :historical_options attribute is saved.
visit '/#system/object_manager'
click 'tbody tr:last-child'
within '.modal' do
2.times { find('tr:nth-child(3) .icon-trash').click }
click '.js-submit'
end
expect(page).to have_text('Database Update required')
click '.js-execute', wait: 7.minutes
expect(page).to have_text('please reload your browser')
sleep 1 # Not sure why this is neede to pick up the new config in subsequent screens.
page.refresh
# Make sure option is still available in already saved ticket, even though the option was removed from the object attribute.
# This is done via the :historical_options.
visit "/#ticket/zoom/#{ticket.id}"
sorted_ticket_values = all("select[name=#{object_attribute.name}] option").map(&:value).reject { |x| x == '' }
expect(sorted_ticket_values).to eq(options_no_dog.keys)
expect(find("select[name=#{object_attribute.name}] option:checked").value).to eq('delete')
expect(find("select[name=#{object_attribute.name}] option:checked").text).to eq('Delete Display')
# Make sure deleted option is missing for new tickets.
visit '/#ticket/create'
sorted_ticket_values = all("select[name=#{object_attribute.name}] option").map(&:value).reject { |x| x == '' }
expect(sorted_ticket_values).to eq(options_no_dog_no_delete.keys)
end
end
context 'when checking boolean user attributes', db_strategy: :reset do
let(:organization_object_attribute) do
attribute = create(:object_manager_attribute_boolean, object_name: 'Organization', data_option: { default: true, options: { true => 'organization:true', false => 'organization:false' } }, screens: screens, position: 999)
ObjectManager::Attribute.migration_execute
attribute
end
let(:user_object_attribute) do
attribute = create(:object_manager_attribute_boolean, object_name: 'User', data_option: { default: true, options: { true => 'user:true', false => 'user:false' } }, screens: screens, position: 999)
ObjectManager::Attribute.migration_execute
attribute
end
let(:organization) { create(:organization, organization_object_attribute.name => false) }
let(:customer) { create(:customer, user_object_attribute.name => false, organization: organization) }
let(:screens) { { 'create' => { 'ticket.agent'=>{ 'shown' => true, 'required' => false, 'item_class' => 'column' } }, 'edit' => { 'ticket.agent'=>{ 'shown' => true, 'required' => false } }, 'view' => { 'ticket.agent'=>{ 'shown' => true, 'required' => false } } } }
let(:ticket) { create(:ticket, group: Group.find_by(name: 'Users'), customer: customer) }
it 'shows user and organization attributes even if they are set to false' do
organization_object_attribute
user_object_attribute
page.refresh
visit "/#ticket/zoom/#{ticket.id}"
click('.content.active .tabsSidebar-tab[data-tab="organization"]')
expect(page).to have_text('organization:false')
click('.content.active .tabsSidebar-tab[data-tab="customer"]')
expect(page).to have_text('user:false')
end
end
context 'when creating new fields' do
before do
visit '/#system/object_manager'
page.find('.js-new').click
end
it 'verifies option creation order of new tree select options' do
# set meta information
fill_in 'Name', with: 'tree1'
fill_in 'Display', with: 'tree1'
page.find('select[name=data_type]').select('Tree Select')
# create 3 childs
first_add_child = page.first('div.js-addChild')
first_add_child.click
first_add_child.click
first_add_child.click
# create 1 top level node sibling
page.first('div.js-addRow').click
# create 3 childs for the new top level node
page.all('div.js-addChild').last.click
page.all('div.js-addChild').last.click
page.all('div.js-addChild').last.click
# create new top level nodes by first and second top level node
add_rows = page.all('div.js-addRow')
add_rows[0].click
add_rows[4].click
# add numbers to all inputs to verify order in config later
number = 1
page.all('input.js-key').each do |input|
input.send_keys(number)
number += 1
end
page.find('.js-submit').click
expected_data_options = { 'options' =>
[{ 'name' => '1',
'value' => '1',
'children' => [{ 'name' => '2', 'value' => '1::2' }, { 'name' => '3', 'value' => '1::3' }, { 'name' => '4', 'value' => '1::4' }] },
{ 'name' => '5', 'value' => '5' },
{ 'name' => '6',
'value' => '6',
'children' =>
[{ 'name' => '7',
'value' => '6::7',
'children' => [{ 'name' => '8', 'value' => '6::7::8', 'children' => [{ 'name' => '9', 'value' => '6::7::8::9' }] }] }] },
{ 'name' => '10', 'value' => '10' }],
'default' => '',
'null' => true,
'relation' => '',
'nulloption' => true,
'maxlength' => 255 }
expect(ObjectManager::Attribute.last.data_option).to eq(expected_data_options)
end
it 'checks smart defaults for select field' do
fill_in 'Name', with: 'select1'
find('input[name=display]').set('select1')
page.find('select[name=data_type]').select('Select')
page.first('div.js-add').click
page.first('div.js-add').click
page.first('div.js-add').click
counter = 0
page.all('.js-key').each do |field|
field.set(counter)
counter += 1
end
page.all('.js-value')[-2].set('special 2')
page.find('.js-submit').click
expected_data_options = {
'0' => '0',
'1' => '1',
'2' => 'special 2',
}
expect(ObjectManager::Attribute.last.data_option['options']).to eq(expected_data_options)
end
it 'checks smart defaults for boolean field' do
fill_in 'Name', with: 'bool1'
find('input[name=display]').set('bool1')
page.find('select[name=data_type]').select('Boolean')
page.find('.js-valueFalse').set('HELL NOO')
page.find('.js-submit').click
expected_data_options = {
true => 'yes',
false => 'HELL NOO',
}
expect(ObjectManager::Attribute.last.data_option['options']).to eq(expected_data_options)
end
it 'checks default boolean value visibility' do
fill_in 'Name', with: 'bool1'
find('input[name=display]').set('Bool 1')
page.find('select[name=data_type]').select('Boolean')
choose('data_option::default', option: 'true')
page.find('.js-submit').click
td = page.find(:css, 'td', text: 'bool1')
tr = td.find(:xpath, './parent::tr')
tr.click
expect(page).to have_checked_field('data_option::default', with: 'true')
end
end
# https://github.com/zammad/zammad/issues/3647
context 'when setting Min/Max values for integer' do
before do
visit '/#system/object_manager'
page.find('.js-new').click
in_modal disappears: false do

View file

@ -1,933 +0,0 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'browser_test_helper'
class AdminObjectManagerTest < TestCase
def test_basic_a
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
# already existing
object_manager_attribute_create(
data: {
name: 'customer_id',
display: 'Customer Should Not Creatable',
data_type: 'Text',
},
error: 'already exists'
)
# invalid name
object_manager_attribute_create(
data: {
name: 'some_other_id',
display: 'Should Not Creatable',
data_type: 'Text',
},
error: 'are not allowed'
)
# invalid name
object_manager_attribute_create(
data: {
name: 'some_other_ids',
display: 'Should Not Creatable',
data_type: 'Text',
},
error: 'are not allowed'
)
# invalid name
object_manager_attribute_create(
data: {
name: 'some spaces',
display: 'Should Not Creatable',
data_type: 'Text',
},
error: 'are not allowed'
)
# valid name
object_manager_attribute_create(
data: {
name: 'browser_test1',
display: 'Browser Test 1',
data_type: 'Text',
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
# create new ticket
ticket_create(
data: {
customer: 'nico',
group: 'Users',
priority: '2 normal',
state: 'open',
title: 'ticket attribute test #1',
body: 'ticket attribute test #1',
},
# custom_data_select: {
# key1: 'some value',
# },
custom_data_input: {
browser_test1: 'some value öäüß',
},
disable_group_check: true,
)
# update ticket
ticket_update(
data: {},
# custom_data_select: {
# key1: 'some value',
# },
custom_data_input: {
browser_test1: 'some value ABC',
},
)
# discard new attribute
click(css: 'a[href="#manage"]')
click(css: 'a[href="#system/object_manager"]')
watch_for(
css: '.content.active table',
value: 'browser_test1',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
object_manager_attribute_delete(
data: {
name: 'browser_test1',
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
watch_for(
css: '.content.active table',
value: 'browser_test1',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
match_not(
css: '.content.active table',
value: 'browser_test1',
)
end
def test_basic_b
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
object_manager_attribute_create(
data: {
name: 'browser_test2',
display: 'Browser Test 2',
data_type: 'Select',
data_option: {
options: {
'aa' => 'AA',
'bb' => 'BB',
},
},
},
)
object_manager_attribute_discard_changes
sleep 4
object_manager_attribute_create(
data: {
name: 'browser_test2',
display: 'Browser Test 2',
data_type: 'Text',
# data_option: {
# default: 'xxx',
# },
},
)
object_manager_attribute_create(
data: {
name: 'browser_test3',
display: 'Browser Test 3',
data_type: 'Select',
data_option: {
options: {
'aa' => 'AA',
'bb' => 'BB',
'cc' => 'CC',
},
},
},
)
object_manager_attribute_create(
data: {
name: 'browser_test4',
display: 'Browser Test 4',
data_type: 'Integer',
# data_option: {
# default: 'xxx',
# min: 15,
# max: 99,
# },
},
)
object_manager_attribute_create(
data: {
name: 'browser_test5',
display: 'Browser Test 5',
data_type: 'Datetime',
# data_option: {
# future: true,
# past: true,
# diff: 24
# },
},
)
object_manager_attribute_create(
data: {
name: 'browser_test6',
display: 'Browser Test 6',
data_type: 'Date',
# data_option: {
# future: true,
# past: true,
# diff: 24
# },
},
)
# rubocop:disable Lint/BooleanSymbol
object_manager_attribute_create(
data: {
name: 'browser_test7',
display: 'Browser Test 7',
data_type: 'Boolean',
data_option: {
options: {
true: 'YES',
false: 'NO',
},
# default: true,
},
},
)
# rubocop:enable Lint/BooleanSymbol
watch_for(
css: '.content.active',
value: 'Database Update required',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
# create new ticket
ticket_create(
data: {
customer: 'nico',
group: 'Users',
priority: '2 normal',
state: 'open',
title: 'ticket attribute test all #1',
body: 'ticket attribute test all #1',
},
custom_data_select: {
browser_test3: 'CC',
browser_test7: 'NO',
},
custom_data_input: {
browser_test2: 'some value öäüß',
browser_test4: '25',
},
disable_group_check: true,
)
ticket_verify(
data: {
title: 'ticket attribute test all #1',
custom_data_select: {
browser_test3: 'CC',
browser_test7: 'NO',
},
custom_data_input: {
browser_test2: 'some value öäüß',
browser_test4: '25',
},
},
)
object_manager_attribute_delete(
data: {
name: 'browser_test2',
},
)
object_manager_attribute_delete(
data: {
name: 'browser_test3',
},
)
object_manager_attribute_delete(
data: {
name: 'browser_test4',
},
)
object_manager_attribute_delete(
data: {
name: 'browser_test5',
},
)
object_manager_attribute_delete(
data: {
name: 'browser_test6',
},
)
object_manager_attribute_delete(
data: {
name: 'browser_test7',
},
)
sleep 1
object_manager_attribute_migrate
match_not(
css: '.content.active',
value: 'Database Update required',
)
match_not(
css: '.content.active table',
value: 'browser_test2',
)
match_not(
css: '.content.active table',
value: 'browser_test3',
)
match_not(
css: '.content.active table',
value: 'browser_test4',
)
match_not(
css: '.content.active table',
value: 'browser_test5',
)
match_not(
css: '.content.active table',
value: 'browser_test6',
)
match_not(
css: '.content.active table',
value: 'browser_test7',
)
end
def test_basic_c
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
# valid name
object_manager_attribute_create(
data: {
name: 'browser_update_test1',
display: 'Browser Update Test 1',
data_type: 'Text',
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
# valid name
object_manager_attribute_update(
data: {
name: 'browser_update_test1',
display: 'Browser Update Test 2',
data_type: 'Text',
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'configuration of Zammad has changed',
)
click(css: '.modal .js-submit')
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
object_manager_attribute_delete(
data: {
name: 'browser_update_test1',
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
watch_for(
css: '.content.active table',
value: 'browser_update_test1',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
match_not(
css: '.content.active table',
value: 'browser_update_test1',
)
end
def test_that_attributes_with_references_should_have_a_disabled_delete_button
@browser = instance = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
# create two new attributes
object_manager_attribute_create(
data: {
name: 'deletable_attribute',
display: 'Deletable Attribute',
data_type: 'Text',
},
)
object_manager_attribute_create(
data: {
name: 'undeletable_attribute',
display: 'Undeletable Attribute',
data_type: 'Text',
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
# create a new overview that references the undeletable_attribute
overview_create(
browser: instance,
data: {
name: 'test_overview',
roles: ['Agent'],
selector: {
'Undeletable Attribute' => 'DUMMY',
},
'order::direction' => 'down',
'text_input' => true,
}
)
click(
browser: instance,
css: 'a[href="#manage"]',
mute_log: true,
)
click(
browser: instance,
css: '.content.active a[href="#system/object_manager"]',
mute_log: true,
)
30.times do
deletable_attribute = instance.find_elements(xpath: '//td[text()="deletable_attribute"]/following-sibling::*[2]')[0]
break if deletable_attribute
sleep 1
end
sleep 1
deletable_attribute = instance.find_elements(xpath: '//td[text()="deletable_attribute"]/following-sibling::*[2]')[0]
assert_not_nil(deletable_attribute)
deletable_attribute_html = deletable_attribute.attribute('innerHTML')
assert(deletable_attribute_html.include?('title="Delete"'))
assert(deletable_attribute_html.include?('href="#"'))
assert(deletable_attribute_html.exclude?('cannot be deleted'))
undeletable_attribute = instance.find_elements(xpath: '//td[text()="undeletable_attribute"]/following-sibling::*[2]')[0]
assert_not_nil(undeletable_attribute)
undeletable_attribute_html = undeletable_attribute.attribute('innerHTML')
assert(undeletable_attribute_html.include?('Overview'))
assert(undeletable_attribute_html.include?('test_overview'))
assert(undeletable_attribute_html.include?('cannot be deleted'))
assert(undeletable_attribute_html.exclude?('href="#"'))
end
def test_proper_sorting_of_select_attributes
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
# lexicographically ordered list of option strings
options = %w[0 000.000 1 100.100 100.200 2 200.100 200.200 3 ä b n ö p sr ß st t ü v]
options_hash = options.reverse.collect { |o| [o, o] }.to_h
object_manager_attribute_create(
data: {
name: 'select_attributes_sorting_test',
display: 'Select Attributes Sorting Test',
data_type: 'Select',
data_option: { options: options_hash },
},
)
sleep 2
# open the select attribute that we just created
execute(js: "$(\".content.active td:contains('select_attributes_sorting_test')\").first().click()")
sleep 3
unsorted_locations = options.map do |key|
[get_location(xpath: "//input[@value='#{key}']").y, key]
end
log("unsorted_locations = #{unsorted_locations.inspect}")
sorted_locations = unsorted_locations.sort_by(&:first).map(&:second)
log("sorted_locations = #{sorted_locations.inspect}")
assert_equal options, sorted_locations
# close the attribute modal
click(css: '.modal button.js-submit')
watch_for(
css: '.content.active',
value: 'Database Update required',
)
watch_for(
css: '.content.active table',
value: 'select_attributes_sorting_test',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 7.minutes,
)
sleep 5
watch_for(
css: '.content.active',
)
# create a new ticket and check whether the select attributes are correctly sorted or not
click(
css: 'a[href="#ticket/create"]',
mute_log: true,
)
watch_for(
css: 'select[name="select_attributes_sorting_test"]',
)
select_element = @browser.find_elements(css: 'select[name="select_attributes_sorting_test"]')[0]
unsorted_options = select_element.find_elements(xpath: './*').map(&:text).reject { |x| x == '-' }
log unsorted_options.inspect
assert_equal options, unsorted_options
object_manager_attribute_delete(
data: {
name: 'select_attributes_sorting_test',
},
)
object_manager_attribute_migrate
end
def test_deleted_select_attributes
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
options = %w[äöü cat delete dog ß].index_with { |x| "#{x.capitalize} Display" }
options_no_dog = options.except('dog')
options_no_dog_no_delete = options_no_dog.except('delete')
tasks_close_all
object_manager_attribute_create(
data: {
name: 'select_attributes_delete_test',
display: 'Select Attributes Delete Test',
data_type: 'Select',
data_option: {
options: options,
},
},
)
object_manager_attribute_migrate
ticket_create(
data: {
customer: 'nico',
group: 'Users',
title: 'select_attributes_delete_test',
body: 'select_attributes_delete_test',
},
custom_data_select: {
select_attributes_delete_test: 'Delete Display',
},
disable_group_check: true,
)
watch_for(
css: '.content.active select[name="select_attributes_delete_test"]',
)
# confirm that all options and their display values are there and are in the correct order
select_element = @browser.find_elements(css: '.content.active select[name="select_attributes_delete_test"]')[0]
unsorted_options = select_element.find_elements(xpath: './*').map { |o| o.attribute('value') }.reject { |x| x == '' }
assert_equal options.keys, unsorted_options
unsorted_display_options = select_element.find_elements(xpath: './*').map(&:text).reject { |x| x == '-' }
assert_equal options.values, unsorted_display_options
# confirm that the "delete" option is selected and that its display text is indeed "Delete Display"
selected_option = select_element.find_elements(css: 'option:checked')[0]
assert_equal 'delete', selected_option.attribute('value')
assert_equal 'Delete Display', selected_option.text
object_manager_attribute_update(
data: {
name: 'select_attributes_delete_test',
data_option: {
options: options_no_dog_no_delete,
},
},
)
object_manager_attribute_migrate
screenshot(comment: 'deleted_select_attributes_before_click')
# open the previously created ticket and verify its attribute selection
click(
xpath: '//a/div[contains(text(),"select_attributes_delete_test")]',
)
# confirm that all options and their display values are there and are in the correct order
select_element = @browser.find_elements(css: '.content.active select[name="select_attributes_delete_test"]')[0]
unsorted_options = select_element.find_elements(xpath: './*').map { |o| o.attribute('value') }.reject { |x| x == '' }
assert_equal options_no_dog.keys, unsorted_options
unsorted_display_options = select_element.find_elements(xpath: './*').map(&:text).reject { |x| x == '-' }
assert_equal options_no_dog.values, unsorted_display_options
# confirm that the "delete" option is still selected and that its display text is still indeed "Delete Display"
selected_option = select_element.find_elements(css: 'option:checked')[0]
assert_equal 'delete', selected_option.attribute('value')
assert_equal 'Delete Display', selected_option.text
# create a new ticket and check that the deleted options no longer appear
click(
css: 'a[href="#ticket/create"]',
mute_log: true,
)
watch_for(
css: 'select[name="select_attributes_delete_test"]',
)
select_element = @browser.find_elements(css: 'select[name="select_attributes_delete_test"]')[0]
unsorted_options = select_element.find_elements(xpath: './*').map { |o| o.attribute('value') }.reject { |x| x == '' }
assert_equal options_no_dog_no_delete.keys, unsorted_options
unsorted_display_options = select_element.find_elements(xpath: './*').map(&:text).reject { |x| x == '-' }
assert_equal options_no_dog_no_delete.values, unsorted_display_options
object_manager_attribute_delete(
data: {
name: 'select_attributes_delete_test',
},
)
object_manager_attribute_migrate
end
# verify fix for issue #2233 - Boolean object set to false is not visible
# verify fix for issue #2277 - Note is not shown for customer / organisations if it's empty
def test_false_boolean_attributes_gets_displayed_for_organizations
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
object_manager_attribute_create(
data: {
object: 'Organization',
name: 'bool_test',
display: 'bool_test',
data_type: 'Boolean',
data_option: {
options: {
# rubocop:disable Lint/BooleanSymbol
true: 'YES',
false: 'NO',
# rubocop:enable Lint/BooleanSymbol
}
},
},
)
object_manager_attribute_create(
data: {
object: 'Organization',
name: 'text_test',
display: 'text_test',
data_type: 'Text',
},
)
object_manager_attribute_migrate
ticket_open_by_title(title: 'select')
click(css: '.content.active .tabsSidebar-tab[data-tab="organization"]')
click(css: '.content.active .sidebar[data-tab="organization"] .js-actions .dropdown-toggle')
click(css: '.content.active .sidebar[data-tab="organization"] .js-actions [data-type="organization-edit"]')
modal_ready
select(css: '.content.active .modal select[name="bool_test"]', value: 'NO')
click(css: '.content.active .modal .js-submit')
modal_disappear
watch_for(
css: '.content.active .sidebar[data-tab="organization"] .sidebar-content',
value: 'bool_test',
)
match_not(
css: '.content.active .sidebar[data-tab="organization"] .sidebar-content',
value: 'text_test',
)
match(
css: '.content.active .sidebar[data-tab="organization"] .sidebar-content',
value: 'note',
)
object_manager_attribute_delete(
data: {
object: 'Organization',
name: 'bool_test',
},
)
object_manager_attribute_delete(
data: {
object: 'Organization',
name: 'text_test',
},
)
object_manager_attribute_migrate
end
# verify fix for issue #2233 - Boolean object set to false is not visible
# verify fix for issue #2277 - Note is not shown for customer / organisations if it's empty
def test_false_boolean_attributes_gets_displayed_for_users
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
object_manager_attribute_create(
data: {
object: 'User',
name: 'bool_test',
display: 'bool_test',
data_type: 'Boolean',
data_option: {
options: {
# rubocop:disable Lint/BooleanSymbol
true: 'YES',
false: 'NO',
# rubocop:enable Lint/BooleanSymbol
}
},
},
)
object_manager_attribute_create(
data: {
object: 'User',
name: 'text_test',
display: 'text_test',
data_type: 'Text',
},
)
object_manager_attribute_migrate
ticket_open_by_title(title: 'select')
click(css: '.content.active .tabsSidebar-tab[data-tab="customer"]')
click(css: '.content.active .sidebar[data-tab="customer"] .js-actions .dropdown-toggle')
click(css: '.content.active .sidebar[data-tab="customer"] .js-actions [data-type="customer-edit"]')
modal_ready
select(css: '.content.active .modal select[name="bool_test"]', value: 'NO')
click(css: '.content.active .modal .js-submit')
modal_disappear
watch_for(
css: '.content.active .sidebar[data-tab="customer"] .sidebar-content',
value: 'bool_test',
)
match_not(
css: '.content.active .sidebar[data-tab="customer"] .sidebar-content',
value: 'text_test',
)
match(
css: '.content.active .sidebar[data-tab="customer"] .sidebar-content',
value: 'note',
)
object_manager_attribute_delete(
data: {
object: 'User',
name: 'bool_test',
},
)
object_manager_attribute_delete(
data: {
object: 'User',
name: 'text_test',
},
)
object_manager_attribute_migrate
end
end

View file

@ -1,211 +0,0 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'browser_test_helper'
class AdminObjectManagerTreeSelectTest < TestCase
def test_basic_a
@browser = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
object_manager_attribute_create(
data: {
name: 'browser_test_tree_select1',
display: 'Browser Test TreeSelect1',
data_type: 'Tree Select',
data_option: {
options: {
'Incident' => {
'Hardware' => {
'Monitor' => {},
'Mouse' => {},
'Keyboard' => {},
},
'Softwareproblem' => {
'CRM' => {},
'EDI' => {},
'SAP' => {
'Authentication' => {},
'Not reachable' => {},
},
'MS Office' => {
'Excel' => {},
'PowerPoint' => {},
'Word' => {},
'Outlook' => {},
},
},
},
'Service request' => {
'New software requirement' => {},
'New hardware' => {},
'Consulting' => {},
},
'Change request' => {},
},
},
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 240,
)
sleep 5
watch_for(
css: '.content.active',
)
# discard new attribute
click(css: 'a[href="#manage"]')
click(css: 'a[href="#system/object_manager"]')
watch_for(
css: '.content.active table',
value: 'browser_test_tree_select1',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
object_manager_attribute_delete(
data: {
name: 'browser_test_tree_select1',
},
)
watch_for(
css: '.content.active',
value: 'Database Update required',
)
watch_for(
css: '.content.active table',
value: 'browser_test_tree_select1',
)
click(css: '.content.active .tab-pane.active div.js-execute')
watch_for(
css: '.modal',
value: 'restart',
)
watch_for_disappear(
css: '.modal',
timeout: 240,
)
sleep 5
watch_for(
css: '.content.active',
)
match_not(
css: '.content.active',
value: 'Database Update required',
)
match_not(
css: '.content.active table',
value: 'browser_test_tree_select1',
)
end
# verify the fix for issue #2206 - Unable to modify tree_select attributes with fresh 2.6
def test_modify_tree_select_attributes
@browser = instance = browser_instance
login(
username: 'admin@example.com',
password: 'test',
url: browser_url,
)
tasks_close_all
object_manager_attribute_create(
data: {
name: 'browser_test_tree_select2',
display: 'Browser Test TreeSelect2',
data_type: 'Tree Select',
data_option: {
options: {
'Incident' => {
'Hardware' => {
'Monitor' => {},
'Mouse' => {},
},
},
'Service request' => {
'New software requirement' => {},
'New hardware' => {},
},
'Change request' => {},
},
},
},
)
object_manager_attribute_migrate
# open the newly created tree_select and add some new options
object_manager_attribute_update(
data: {
name: 'browser_test_tree_select2',
},
do_not_submit: true,
)
# add two new first level entries
2.times do |i|
instance.find_elements(css: '.modal .js-treeTable .js-key').last.click
element = instance.find_elements(css: '.modal .js-treeTable .js-key').last
element.clear
element.send_keys("new tree option #{i}")
end
click(
css: '.modal button.js-submit'
)
modal_disappear
object_manager_attribute_migrate
# open the tree select again and check that the newly added options are there
watch_for(
css: '.content.active table',
value: 'browser_test_tree_select2',
)
object_manager_attribute_update(
data: {
name: 'browser_test_tree_select2',
},
do_not_submit: true,
)
2.times do |i|
exists(
css: '.modal .js-treeTable',
value: "new tree option #{i}",
)
end
modal_close
# clean up and confirm the deletion of newly created attributes
object_manager_attribute_delete(
data: {
name: 'browser_test_tree_select2',
},
)
object_manager_attribute_migrate
match_not(
css: '.content.active table',
value: 'browser_test_tree_select2',
)
end
end