Browse Source

Improved object manager browser tests.

Martin Edenhofer 8 years ago
parent
commit
eae8ead41c

+ 28 - 8
app/assets/javascripts/app/controllers/_ui_element/object_manager_attribute.coffee

@@ -6,11 +6,10 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
 
     updateDataMap = (localParams, localAttribute, localAttributes, localClassname, localForm, localA) =>
       localItem = localForm.closest('.js-data')
-      values = []
-      values = {a: 123, b: 'aaa'}
+      console.log('updateDataMap', attribute, params)
       element = $(App.view("object_manager/attribute/#{localParams.data_type}")(
         attribute: attribute
-        values: values
+        params: params
       ))
       @[localParams.data_type](element, localParams, params)
       localItem.find('.js-dataMap').html(element)
@@ -20,10 +19,10 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
       datetime: 'Datetime'
       date: 'Date'
       input: 'Text'
-    #  select: 'Select'
-    #  boolean: 'Boolean'
-    #  integer: 'Integer'
-    #  autocompletion: 'Autocompletion (AJAX remote URL)'
+      select: 'Select'
+      boolean: 'Boolean'
+      integer: 'Integer'
+      autocompletion: 'Autocompletion (AJAX remote URL)'
 
     configureAttributes = [
       { 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
     )
     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(
       model:
@@ -267,6 +266,27 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
     item.find('.js-integerMax').html(integerMax.form)
 
   @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) ->
 

+ 31 - 16
app/assets/javascripts/app/views/object_manager/attribute/select.jst.eco

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

+ 3 - 0
app/controllers/object_manager_attributes_controller.rb

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

+ 13 - 9
app/models/object_manager/attribute.rb

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

+ 4 - 2
lib/sessions.rb

@@ -351,7 +351,7 @@ send message to all authenticated client
 
 returns
 
-  true|false
+  [array_with_client_ids_of_recipients]
 
 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)
 
     # list all current clients
+    recipients = []
     client_list = sessions
     client_list.each {|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
       end
       Sessions.send(client_id, data)
+      recipients.push client_id
     }
-    true
+    recipients
   end
 
 =begin

+ 69 - 75
test/browser/admin_object_manager_test.rb

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

+ 96 - 0
test/browser_test_helper.rb

@@ -2717,6 +2717,13 @@ wait untill text in selector disabppears
     data: {
       name: 'field_name' + random,
       display: 'Display Name of Field',
+      data_type: 'Text', # Text|Select|...
+      data_option: {
+        options: {
+          'aa' => 'AA',
+          'bb' => 'BB',
+        },
+      },
     },
     error: 'already exists'
   )
@@ -2753,6 +2760,26 @@ wait untill text in selector disabppears
     element = instance.find_elements(css: '.modal input[name=display]')[0]
     element.clear
     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
     if params[:error]
       sleep 4
@@ -2782,6 +2809,75 @@ wait untill text in selector disabppears
     raise 'object manager attribute creation failed'
   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)
     string_quoted = string
     string_quoted.gsub!(/&/, '&amp;')

+ 39 - 0
test/unit/object_manager_test.rb

@@ -368,6 +368,45 @@ class ObjectManagerTest < ActiveSupport::TestCase
     }
     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
 
   test 'b object manager attribute' do