Improved object manager browser tests.

This commit is contained in:
Martin Edenhofer 2016-05-26 10:14:51 +02:00
parent bf0d4d7fa2
commit eae8ead41c
8 changed files with 284 additions and 111 deletions

View file

@ -6,11 +6,10 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
updateDataMap = (localParams, localAttribute, localAttributes, localClassname, localForm, localA) => updateDataMap = (localParams, localAttribute, localAttributes, localClassname, localForm, localA) =>
localItem = localForm.closest('.js-data') localItem = localForm.closest('.js-data')
values = [] console.log('updateDataMap', attribute, params)
values = {a: 123, b: 'aaa'}
element = $(App.view("object_manager/attribute/#{localParams.data_type}")( element = $(App.view("object_manager/attribute/#{localParams.data_type}")(
attribute: attribute attribute: attribute
values: values params: params
)) ))
@[localParams.data_type](element, localParams, params) @[localParams.data_type](element, localParams, params)
localItem.find('.js-dataMap').html(element) localItem.find('.js-dataMap').html(element)
@ -20,10 +19,10 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
datetime: 'Datetime' datetime: 'Datetime'
date: 'Date' date: 'Date'
input: 'Text' input: 'Text'
# select: 'Select' select: 'Select'
# boolean: 'Boolean' boolean: 'Boolean'
# integer: 'Integer' integer: 'Integer'
# autocompletion: 'Autocompletion (AJAX remote URL)' autocompletion: 'Autocompletion (AJAX remote URL)'
configureAttributes = [ configureAttributes = [
{ name: attribute.name, display: '', tag: 'select', null: false, options: options, translate: true, default: 'input', disabled: attribute.disabled }, { name: attribute.name, display: '', tag: 'select', null: false, options: options, translate: true, default: 'input', disabled: attribute.disabled },
@ -149,7 +148,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
params: params params: params
) )
configureAttributes = [ configureAttributes = [
{ name: 'data_option::type', display: 'Type', tag: 'select', null: false, default: 'text', options: {text: 'Text', phone: 'Phone', fax: 'Fax', email: 'Email', url: 'Url'}, translate: true }, { name: 'data_option::type', display: 'Type', tag: 'select', null: false, default: 'text', options: {text: 'Text', tel: 'Phone', email: 'Email', url: 'Url'}, translate: true },
] ]
inputType = new App.ControllerForm( inputType = new App.ControllerForm(
model: model:
@ -267,6 +266,27 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
item.find('.js-integerMax').html(integerMax.form) item.find('.js-integerMax').html(integerMax.form)
@select: (item, localParams, params) -> @select: (item, localParams, params) ->
item.find('.js-add').on('click', (e) ->
addRow = $(e.target).closest('tr')
key = addRow.find('.js-key').val()
value = addRow.find('.js-value').val()
addRow.find('.js-selected[value]').attr('value', key)
selected = addRow.find('.js-selected').prop('checked')
newRow = item.find('.js-template').clone().removeClass('js-template')
newRow.find('.js-key').val(key)
newRow.find('.js-value').val(value)
newRow.find('.js-value[value]').attr('name', "data_option::options::#{key}")
newRow.find('.js-selected').prop('checked', selected)
newRow.find('.js-selected').val(key)
newRow.find('.js-selected').attr('name', 'data_option::default')
item.find('.js-Table tr').last().before(newRow)
addRow.find('.js-key').val('')
addRow.find('.js-value').val('')
addRow.find('.js-selected').prop('checked', false)
)
item.on('click', '.js-remove', (e) ->
$(e.target).closest('tr').remove()
)
@boolean: (item, localParams, params) -> @boolean: (item, localParams, params) ->

View file

@ -2,7 +2,7 @@
<div class="js-selectDefault"></div> <div class="js-selectDefault"></div>
<div class="js-selectOption"></div> <div class="js-selectOption"></div>
<table class="settings-list" style="width: 100%;"> <table class="settings-list js-Table" style="width: 100%;">
<thead> <thead>
<tr> <tr>
<th><%- @T('Key') %> <th><%- @T('Key') %>
@ -11,31 +11,46 @@
<th style="width: 30px"><%- @T('Action') %> <th style="width: 30px"><%- @T('Action') %>
</thead> </thead>
<tbody> <tbody>
<% for key, display of @values: %> <% if @params.data_option && @params.data_option.options: %>
<tr> <% for key, display of @params.data_option.options: %>
<td class="settings-list-control-cell"> <tr>
<input class="form-control form-control--small js-summary" type="text" name="summary" value="<%= key %>" required/> <td class="settings-list-control-cell">
<td class="settings-list-control-cell"> <input class="form-control form-control--small js-key" type="text" value="<%= key %>" required/>
<input class="form-control form-control--small js-summary" type="text" name="summary" value="<%= display %>" required/> <td class="settings-list-control-cell">
<td class="settings-list-row-control"> <input class="form-control form-control--small js-value" type="text" value="<%= display %>" name="data_option::options::<%= key %>" required/>
<input class="" type="radio" /> <td class="settings-list-row-control">
<td class="settings-list-row-control"> <input class="js-selected" type="radio" name="data_option::default" value="<%= key %>" <% if @params.data_option.default is key: %>checked<% end %>/>
<div class="btn btn--text js-remove"> <td class="settings-list-row-control">
<%- @Icon('trash') %> <%- @T('Remove') %> <div class="btn btn--text js-remove">
</div> <%- @Icon('trash') %> <%- @T('Remove') %>
</div>
<% end %>
<% end %> <% end %>
<tr> <tr>
<td class="settings-list-control-cell"> <td class="settings-list-control-cell">
<input class="form-control form-control--small js-summary" type="text" placeholder="<%- @T('Key') %>"/> <input class="form-control form-control--small js-key" type="text" placeholder="<%- @T('Key') %>"/>
<td class="settings-list-control-cell"> <td class="settings-list-control-cell">
<input class="form-control form-control--small js-summary" type="text" placeholder="<%- @T('Display') %>"/> <input class="form-control form-control--small js-value" type="text" placeholder="<%- @T('Display') %>"/>
<td class="settings-list-row-control"> <td class="settings-list-row-control">
<input class="" type="radio" /> <input class="js-selected" type="radio"/>
<td class="settings-list-row-control"> <td class="settings-list-row-control">
<div class="btn btn--text btn--create js-add"> <div class="btn btn--text btn--create js-add">
<%- @Icon('plus-small') %> <%- @T('Add') %> <%- @Icon('plus-small') %> <%- @T('Add') %>
</div> </div>
</tbody> </tbody>
</table> </table>
<table class="hidden">
<tbody>
<tr class="js-template">
<td class="settings-list-control-cell">
<input class="form-control form-control--small js-key" type="text" value="" required/>
<td class="settings-list-control-cell">
<input class="form-control form-control--small js-value" type="text" value="" required/>
<td class="settings-list-row-control">
<input class="js-selected" type="radio" name="data_option::default"/>
<td class="settings-list-row-control">
<div class="btn btn--text js-remove">
<%- @Icon('trash') %> <%- @T('Remove') %>
</div>
</table>
</div> </div>

View file

@ -110,6 +110,9 @@ class ObjectManagerAttributesController < ApplicationController
private private
def check_params def check_params
if params[:data_option] && !params[:data_option].key?(:default)
params[:data_option][:default] = ''
end
return if !params[:data_option][:null].nil? return if !params[:data_option][:null].nil?
params[:data_option][:null] = true params[:data_option][:null] = true
end end

View file

@ -103,6 +103,7 @@ possible types
'aa' => 'aa (comment)', 'aa' => 'aa (comment)',
'bb' => 'bb (comment)', 'bb' => 'bb (comment)',
}, },
nulloption: true,
null: false, null: false,
multiple: false, # currently only "false" supported multiple: false, # currently only "false" supported
translate: true, # optional translate: true, # optional
@ -485,7 +486,7 @@ returns
if attribute.to_delete if attribute.to_delete
if model.column_names.include?(attribute.name) if model.column_names.include?(attribute.name)
ActiveRecord::Migration.remove_column model.table_name, attribute.name ActiveRecord::Migration.remove_column model.table_name, attribute.name
model.reset_column_information reset_database_info(model)
end end
execute_count += 1 execute_count += 1
attribute.destroy attribute.destroy
@ -538,7 +539,7 @@ returns
# restart processes # restart processes
attribute.to_migrate = false attribute.to_migrate = false
attribute.save! attribute.save!
model.reset_column_information reset_database_info(model)
execute_count += 1 execute_count += 1
next next
end end
@ -586,22 +587,22 @@ returns
attribute.to_delete = false attribute.to_delete = false
attribute.save! attribute.save!
model.reset_column_information reset_database_info(model)
execute_count += 1 execute_count += 1
} }
# sent reload to clients # sent reload to clients
if execute_count != 0 if execute_count != 0
pid = fork do AppVersion.set(true)
$stdout.reopen('out.txt', 'w')
$stderr.reopen('err.txt', 'w')
AppControl.restart
end
end end
true true
end end
def self.reset_database_info(model)
model.connection.schema_cache.clear!
model.reset_column_information
end
def check_name def check_name
return if !name return if !name
if name =~ /_(id|ids)$/i || name =~ /^id$/i if name =~ /_(id|ids)$/i || name =~ /^id$/i
@ -652,6 +653,9 @@ returns
if data_type == 'select' || data_type == 'checkbox' if data_type == 'select' || data_type == 'checkbox'
raise 'Need data_option[:default] param' if data_option[:default].nil? raise 'Need data_option[:default] param' if data_option[:default].nil?
raise 'Invalid data_option[:options] or data_option[:relation] param' if data_option[:options].nil? && data_option[:relation].nil? raise 'Invalid data_option[:options] or data_option[:relation] param' if data_option[:options].nil? && data_option[:relation].nil?
if !data_option.key?(:nulloption)
data_option[:nulloption] = true
end
end end
if data_type == 'boolean' if data_type == 'boolean'

View file

@ -351,7 +351,7 @@ send message to all authenticated client
returns returns
true|false [array_with_client_ids_of_recipients]
broadcase also to not authenticated client broadcase also to not authenticated client
@ -366,6 +366,7 @@ broadcase also not to sender
def self.broadcast(data, recipient = 'autenticated', sender_user_id = nil) def self.broadcast(data, recipient = 'autenticated', sender_user_id = nil)
# list all current clients # list all current clients
recipients = []
client_list = sessions client_list = sessions
client_list.each {|client_id| client_list.each {|client_id|
session = Sessions.get(client_id) session = Sessions.get(client_id)
@ -380,8 +381,9 @@ broadcase also not to sender
next if session[:user] && session[:user]['id'] && session[:user]['id'].to_i == sender_user_id.to_i next if session[:user] && session[:user]['id'] && session[:user]['id'].to_i == sender_user_id.to_i
end end
Sessions.send(client_id, data) Sessions.send(client_id, data)
recipients.push client_id
} }
true recipients
end end
=begin =begin

View file

@ -12,95 +12,55 @@ class AdminObjectManagerTest < TestCase
) )
tasks_close_all() tasks_close_all()
click(css: 'a[href="#manage"]')
click(css: 'a[href="#system/object_manager"]')
click(css: '#content .js-new')
modal_ready()
# already existing # already existing
set( object_manager_attribute_create(
css: '.modal input[name="name"]', data: {
value: 'customer_id', name: 'customer_id',
) display: 'Customer Should Not Creatable',
set( data_type: 'Text',
css: '.modal input[name="display"]', },
value: 'Customer Should Not Creatable', error: 'already exists'
)
click(css: '.modal button.js-submit')
sleep 4
watch_for(
css: '.modal',
value: '(already exists)',
) )
# invalid name # invalid name
set( object_manager_attribute_create(
css: '.modal input[name="name"]', data: {
value: 'some_other_id', name: 'some_other_id',
) display: 'Should Not Creatable',
set( data_type: 'Text',
css: '.modal input[name="display"]', },
value: 'Should Not Creatable', error: 'are not allowed'
)
click(css: '.modal button.js-submit')
sleep 4
watch_for(
css: '.modal',
value: '(are not allowed)',
) )
# invalid name # invalid name
set( object_manager_attribute_create(
css: '.modal input[name="name"]', data: {
value: 'some_other_ids', name: 'some_other_ids',
) display: 'Should Not Creatable',
set( data_type: 'Text',
css: '.modal input[name="display"]', },
value: 'Should Not Creatable', error: 'are not allowed'
)
click(css: '.modal button.js-submit')
sleep 4
watch_for(
css: '.modal',
value: '(are not allowed)',
) )
# invalid name # invalid name
set( object_manager_attribute_create(
css: '.modal input[name="name"]', data: {
value: 'some spaces', name: 'some spaces',
display: 'Should Not Creatable',
data_type: 'Text',
},
error: 'are not allowed'
) )
set(
css: '.modal input[name="display"]',
value: 'Should Not Creatable',
)
click(css: '.modal button.js-submit')
sleep 4
watch_for(
css: '.modal',
value: '(are not allowed)',
)
click(css: '.modal .js-close')
modal_ready()
# valid name # valid name
click(css: '#content .js-new') object_manager_attribute_create(
modal_ready() data: {
set( name: 'browser_test1',
css: '.modal input[name="name"]', display: 'Browser Test 1',
value: 'browser_test1', data_type: 'Text',
) },
set(
css: '.modal input[name="display"]',
value: 'Browser Test 1',
)
click(css: '.modal button.js-submit')
watch_for(
css: '#content table',
value: 'browser_test1',
) )
watch_for( watch_for(
css: '#content', css: '#content',
value: 'Database Update required', value: 'Database Update required',
@ -180,4 +140,38 @@ class AdminObjectManagerTest < TestCase
) )
end end
def test_basic_b
@browser = browser_instance
login(
username: 'master@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',
},
},
},
)
sleep 10
object_manager_attribute_discard_changes
#object_manager_attribute_delete(
# data: {
# name: 'browser_test2',
# },
#)
end
end end

View file

@ -2717,6 +2717,13 @@ wait untill text in selector disabppears
data: { data: {
name: 'field_name' + random, name: 'field_name' + random,
display: 'Display Name of Field', display: 'Display Name of Field',
data_type: 'Text', # Text|Select|...
data_option: {
options: {
'aa' => 'AA',
'bb' => 'BB',
},
},
}, },
error: 'already exists' error: 'already exists'
) )
@ -2753,6 +2760,26 @@ wait untill text in selector disabppears
element = instance.find_elements(css: '.modal input[name=display]')[0] element = instance.find_elements(css: '.modal input[name=display]')[0]
element.clear element.clear
element.send_keys(data[:display]) element.send_keys(data[:display])
select(
browser: instance,
css: '.modal select[name="data_type"]',
value: data[:data_type],
mute_log: true,
)
if data[:data_option]
if data[:data_option][:options]
data[:data_option][:options].each {|key, value|
element = instance.find_elements(css: '.modal .js-Table .js-key').last
element.clear
element.send_keys(key)
element = instance.find_elements(css: '.modal .js-Table .js-value').last
element.clear
element.send_keys(value)
element = instance.find_elements(css: '.modal .js-Table .js-add')[0]
element.click
}
end
end
instance.find_elements(css: '.modal button.js-submit')[0].click instance.find_elements(css: '.modal button.js-submit')[0].click
if params[:error] if params[:error]
sleep 4 sleep 4
@ -2782,6 +2809,75 @@ wait untill text in selector disabppears
raise 'object manager attribute creation failed' raise 'object manager attribute creation failed'
end end
=begin
object_manager_attribute_delete(
browser: browser2,
data: {
name: 'field_name' + random,
},
)
=end
def object_manager_attribute_delete(params = {})
switch_window_focus(params)
log('object_manager_attribute_delete', params)
click(
browser: instance,
css: 'a[href="#manage"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[href="#system/object_manager"]',
mute_log: true,
)
sleep 4
instance = params[:browser] || @browser
data = params[:data]
r = instance.execute_script("$(\"#content td:contains('#{data[:name]}')\").first().closest('tr').find('.js-delete').click()")
p "rrr #{r.inspect}"
end
=begin
object_manager_attribute_discard_changes(
browser: browser2,
)
=end
def object_manager_attribute_discard_changes(params = {})
switch_window_focus(params)
log('object_manager_attribute_discard_changes', params)
instance = params[:browser] || @browser
click(
browser: instance,
css: 'a[href="#manage"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[href="#system/object_manager"]',
mute_log: true,
)
sleep 4
element = instance.find_elements(css: '#content .js-discard').first
element.click
watch_for_disappear(
browser: instance,
css: '#content .js-discard',
)
end
def quote(string) def quote(string)
string_quoted = string string_quoted = string
string_quoted.gsub!(/&/, '&amp;') string_quoted.gsub!(/&/, '&amp;')

View file

@ -368,6 +368,45 @@ class ObjectManagerTest < ActiveSupport::TestCase
} }
assert_equal(false, ObjectManager::Attribute.pending_migration?) assert_equal(false, ObjectManager::Attribute.pending_migration?)
assert_raises(RuntimeError) {
attribute16 = ObjectManager::Attribute.add(
object: 'Ticket',
name: 'test16',
display: 'Test 16',
data_type: 'integer',
data_option: {
default: 2,
min: 1,
max: 999,
},
active: true,
screens: {},
position: 20,
created_by_id: 1,
updated_by_id: 1,
)
}
assert_equal(false, ObjectManager::Attribute.pending_migration?)
assert_raises(RuntimeError) {
attribute17 = ObjectManager::Attribute.add(
object: 'Ticket',
name: 'test17',
display: 'Test 17',
data_type: 'integer',
data_option: {
default: 2,
min: 1,
},
active: true,
screens: {},
position: 20,
created_by_id: 1,
updated_by_id: 1,
)
}
assert_equal(false, ObjectManager::Attribute.pending_migration?)
end end
test 'b object manager attribute' do test 'b object manager attribute' do