From bd9bd8a8aede0add1635644f66df5a6de12288ed Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 9 Jun 2013 00:35:18 +0200 Subject: [PATCH] Fixed some taskbar issues. Moved to events for auth:login/auth:logout. --- .../app/controllers/task_widget.js.coffee | 18 ++-- .../app/lib/app_post/auth.js.coffee | 30 ++----- .../lib/app_post/interface_handle.js.coffee | 4 + .../app/lib/app_post/store.js.coffee | 7 +- .../app/lib/app_post/task_manager.js.coffee | 15 ++-- .../app/lib/app_post/websocket.js.coffee | 4 + doc/app_events.txt | 33 +++++++ script/websocket-server.rb | 22 +++-- ...askbar_test.rb => taskbar_session_test.rb} | 72 +--------------- test/browser/taskbar_task_test.rb | 86 +++++++++++++++++++ test/browser_test_helper.rb | 31 ++++++- 11 files changed, 200 insertions(+), 122 deletions(-) create mode 100644 doc/app_events.txt rename test/browser/{taskbar_test.rb => taskbar_session_test.rb} (61%) create mode 100644 test/browser/taskbar_task_test.rb diff --git a/app/assets/javascripts/app/controllers/task_widget.js.coffee b/app/assets/javascripts/app/controllers/task_widget.js.coffee index 6bbd529ce..7b092309e 100644 --- a/app/assets/javascripts/app/controllers/task_widget.js.coffee +++ b/app/assets/javascripts/app/controllers/task_widget.js.coffee @@ -6,14 +6,22 @@ class App.TaskWidget extends App.Controller super @render() - # rerender view - App.Event.bind 'ui:rerender', (data) => + # render on generic ui call + App.Event.bind 'ui:rerender', => @render() - # rebuild taskbar widget - App.Event.bind 'auth', (user) => - App.TaskManager.reset() + # render view + App.Event.bind 'task:render', (data) => + @render() + + # render on login + App.Event.bind 'auth:login', (user) => + @render() + + # reset current tasks on logout + App.Event.bind 'auth:logout', => @el.html('') + App.TaskManager.reset() # only do take over check after spool messages are finised App.Event.bind 'spool:sent', (data) => diff --git a/app/assets/javascripts/app/lib/app_post/auth.js.coffee b/app/assets/javascripts/app/lib/app_post/auth.js.coffee index 8ce427d19..5d48da346 100644 --- a/app/assets/javascripts/app/lib/app_post/auth.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/auth.js.coffee @@ -9,9 +9,6 @@ class App.Auth data: JSON.stringify(params.data), success: (data, status, xhr) => - # clear store - App.Store.clear('all') - # set login (config, session, ...) @_login(data) @@ -67,11 +64,9 @@ class App.Auth # empty session App.Session.init() - # update websocked auth info - App.WebSocket.auth() - # rebuild navbar with new navbar items App.Event.trigger( 'auth' ) + App.Event.trigger( 'auth:logout' ) App.Event.trigger( 'ui:rerender' ) return false; @@ -88,6 +83,8 @@ class App.Auth for key, value of data.session App.Session.set( key, value ) + App.Event.trigger( 'auth', data.session ) + # init of i18n preferences = App.Session.get( 'preferences' ) if preferences && preferences.locale @@ -100,11 +97,7 @@ class App.Auth for key, value of data.default_collections App[key].refresh( value, options: { clear: true } ) - # update websocked auth info - App.WebSocket.auth() - - # rebuild navbar with user data - App.Event.trigger( 'auth', data.session ) + App.Event.trigger( 'auth:login', data.session ) App.Event.trigger( 'ui:rerender' ) @@ -114,14 +107,8 @@ class App.Auth # empty session App.Session.init() - # update websocket auth info - App.WebSocket.auth() - - # clear store - App.Store.clear('all') - - # rebuild navbar App.Event.trigger( 'auth' ) + App.Event.trigger( 'auth:logout' ) App.Event.trigger( 'ui:rerender' ) @_loginError: (xhr, statusText, error) -> @@ -130,12 +117,7 @@ class App.Auth # empty session App.Session.init() - # update websocked auth info - App.WebSocket.auth() - - # clear store - App.Store.clear('all') - # rebuild navbar App.Event.trigger( 'auth' ) + App.Event.trigger( 'auth:logout' ) App.Event.trigger( 'ui:rerender' ) diff --git a/app/assets/javascripts/app/lib/app_post/interface_handle.js.coffee b/app/assets/javascripts/app/lib/app_post/interface_handle.js.coffee index a8202256f..6a33cf20d 100644 --- a/app/assets/javascripts/app/lib/app_post/interface_handle.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/interface_handle.js.coffee @@ -3,6 +3,8 @@ class App.Run extends App.Controller super @el = $('#app') + @trigger('app:ready') + # init collections App.Collection.init() @@ -13,11 +15,13 @@ class App.Run extends App.Controller App.Auth.loginCheck() # start widgets + @trigger('widget:init') widgets = App.Config.get( 'Widgets' ) if widgets for key, widget of widgets @el.append('
') new widget( el: @el.find("##{key}") ) + @trigger('widget:ready') # bind to fill selected text into App.ClipBoard.bind( @el ) diff --git a/app/assets/javascripts/app/lib/app_post/store.js.coffee b/app/assets/javascripts/app/lib/app_post/store.js.coffee index a18b4e29a..c0312f6cf 100644 --- a/app/assets/javascripts/app/lib/app_post/store.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/store.js.coffee @@ -37,6 +37,11 @@ class _Singleton @support = false # @support = false + # clear store on every login/logout + if @support + App.Event.bind 'auth', => + @clear('all') + # write to local storage write: (key, value) -> @store[key] = value @@ -82,4 +87,4 @@ class _Singleton # list.push key for key of window.localStorage list.push key - list \ No newline at end of file + list diff --git a/app/assets/javascripts/app/lib/app_post/task_manager.js.coffee b/app/assets/javascripts/app/lib/app_post/task_manager.js.coffee index 0d72490fa..db63548c6 100644 --- a/app/assets/javascripts/app/lib/app_post/task_manager.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/task_manager.js.coffee @@ -153,8 +153,7 @@ class _Singleton extends App.Controller # start worker for task if not exists @startController(key, callback, params, state, to_not_show) - App.Event.trigger 'ui:rerender' - App.Event.trigger 'ui:rerender:content' + App.Event.trigger 'task:render' return key startController: (key, callback, params, state, to_not_show) => @@ -218,7 +217,7 @@ class _Singleton extends App.Controller worker.release() @workersStarted[ key ] = false task.destroy() - App.Event.trigger 'ui:rerender' + App.Event.trigger 'task:render' notify: ( key ) => task = @get( key ) @@ -226,7 +225,7 @@ class _Singleton extends App.Controller throw "No such task with '#{key}' to notify" task.notify = true task.save() - App.Event.trigger 'ui:rerender' + App.Event.trigger 'task:render' reorder: ( order ) => prio = 0 @@ -241,15 +240,17 @@ class _Singleton extends App.Controller reset: => App.Taskbar.deleteAll() - App.Event.trigger 'ui:rerender' + App.Event.trigger 'task:render' clientId: => if !@clientIdInt - @clientIdInt = Math.floor( Math.random() * 99999999 ) + @clientIdInt = Math.floor( Math.random() * 99999999 ) @clientIdInt tasksInitial: => # reopen tasks + App.Event.trigger 'taskbar:init' + # App.Taskbar.fetch() tasks = @all() return if !tasks @@ -277,3 +278,5 @@ class _Singleton extends App.Controller task_count * 500 ) + App.Event.trigger 'taskbar:ready' + diff --git a/app/assets/javascripts/app/lib/app_post/websocket.js.coffee b/app/assets/javascripts/app/lib/app_post/websocket.js.coffee index e3b64e0ed..7f9988bf3 100644 --- a/app/assets/javascripts/app/lib/app_post/websocket.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/websocket.js.coffee @@ -47,6 +47,10 @@ class _Singleton extends App.Controller constructor: (@args) -> super + # on auth, send new auth data to server + App.Event.bind 'auth', => + @auth() + # bind to send messages App.Event.bind 'ws:send', (data) => @send(data) diff --git a/doc/app_events.txt b/doc/app_events.txt new file mode 100644 index 000000000..8a5c81c0c --- /dev/null +++ b/doc/app_events.txt @@ -0,0 +1,33 @@ +1) App Boot + +1.1) app:ready + +1.2) collection:init +1.2.1) collection:ready + +1.3) websocket:init +1.3.1) spool:sent +1.3.2) session:takenover +1.3.3) websocket:ready + +1.4) auth +1.4.1) auth:login +1.4.2) auth:logout + +1.5) widget:init +1.5.1) widget:ready + + +2) Task +2.1) taskbar:init +2.2) taskbar:ready +2.2) +trigger + remove -> task:render + notify -> task:render + reset -> task:render + +3) generic events +ui:rerender -> rebuild all views +ui:rerender:content -> rebuild obly content view + diff --git a/script/websocket-server.rb b/script/websocket-server.rb index 6c97d755e..91a9614d7 100755 --- a/script/websocket-server.rb +++ b/script/websocket-server.rb @@ -147,7 +147,6 @@ EventMachine.run { log 'error', "can't parse spool message: #{ message }, #{ e.inspect }" next end - # add spool attribute to push spool info to clients message_parsed['data']['spool'] = true msg = JSON.generate( message_parsed ) @@ -156,8 +155,8 @@ EventMachine.run { if !data['timestamp'] || data['timestamp'] < message[:timestamp] # spool to recipient list - if message[:msg_object]['recipient'] && message[:msg_object]['recipient']['user_id'] - message[:msg_object]['recipient']['user_id'].each { |user_id| + if message_parsed['data']['recipient'] && message_parsed['data']['recipient']['user_id'] + message_parsed['data']['recipient']['user_id'].each { |user_id| if @clients[client_id][:session]['id'] == user_id log 'notice', "send spool to (user_id=#{user_id})", client_id @clients[client_id][:websocket].send( "[#{ msg }]" ) @@ -194,19 +193,18 @@ EventMachine.run { client_list = Session.list client_list.each {|local_client_id, local_client| if local_client_id.to_s != client_id.to_s - # broadcast to recipient list - if data['recipient'] - if data['recipient'].class != Hash - log 'error', "recipient attribute isn't a hash '#{ data['recipient'].inspect }'" + if data['data']['recipient'] + if data['data']['recipient'].class != Hash + log 'error', "recipient attribute isn't a hash '#{ data['data']['recipient'].inspect }'" else - if !data['recipient'].has_key?('user_id') - log 'error', "need recipient.user_id attribute '#{ data['recipient'].inspect }'" + if !data['data']['recipient'].has_key?('user_id') + log 'error', "need recipient.user_id attribute '#{ data['data']['recipient'].inspect }'" else - if data['recipient']['user_id'].class != Array - log 'error', "recipient.user_id attribute isn't an array '#{ data['recipient']['user_id'].inspect }'" + if data['data']['recipient']['user_id'].class != Array + log 'error', "recipient.user_id attribute isn't an array '#{ data['data']['recipient']['user_id'].inspect }'" else - data['recipient']['user_id'].each { |user_id| + data['data']['recipient']['user_id'].each { |user_id| if local_client[:user][:id].to_i == user_id.to_i log 'notice', "send broadcast to (user_id=#{user_id})", local_client_id if local_client[:meta][:type] == 'websocket' && @clients[ local_client_id ] diff --git a/test/browser/taskbar_test.rb b/test/browser/taskbar_session_test.rb similarity index 61% rename from test/browser/taskbar_test.rb rename to test/browser/taskbar_session_test.rb index 97531791d..b07cd6e44 100644 --- a/test/browser/taskbar_test.rb +++ b/test/browser/taskbar_session_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require 'browser_test_helper' -class TaskbarTest < TestCase +class TaskbarSessionTest < TestCase def test_current_session_a_same_agent tests = [ { @@ -106,74 +106,4 @@ class TaskbarTest < TestCase browser_double_test(tests) end - def test_persistant_task_a - tests = [ - { - :name => 'persistant task', - :action => [ - { - :execute => 'click', - :css => 'a[href="#new"]', - }, - { - :execute => 'click', - :css => 'a[href="#ticket_create/call_inbound"]', - }, - { - :execute => 'wait', - :value => 5, - }, - { - :execute => 'check', - :css => '.active .ticket_create', - :result => true, - }, - { - :execute => 'set', - :css => '.active .ticket_create input[name="subject"]', - :value => 'some test AAA', - }, - { - :execute => 'wait', - :value => 20, - }, - ], - }, - ] - browser_signle_test_with_login(tests, { :username => 'agent1@example.com' }) - end - def test_persistant_task_b - tests = [ - { - :name => 'persistant task', - :action => [ - { - :execute => 'wait', - :value => 6, - }, - { - :execute => 'click', - :css => '.task', - }, - { - :execute => 'match', - :css => 'body', - :value => 'some test AAA', - :match_result => true, - }, - { - :execute => 'click', - :css => '.taskbar [data-type="close"]', - }, - { - :execute => 'match', - :css => 'body', - :value => 'some test AAA', - :match_result => false, - }, - ], - }, - ] - browser_signle_test_with_login(tests, { :username => 'agent1@example.com' }) - end end diff --git a/test/browser/taskbar_task_test.rb b/test/browser/taskbar_task_test.rb new file mode 100644 index 000000000..3f1ae301b --- /dev/null +++ b/test/browser/taskbar_task_test.rb @@ -0,0 +1,86 @@ +# encoding: utf-8 +require 'browser_test_helper' + +class TaskbarTaskTest < TestCase + def test_persistant_task_a + tests = [ + { + :name => 'persistant task', + :action => [ + { + :execute => 'wait', + :value => 2, + }, + { + :execute => 'close_all_tasks', + }, + { + :execute => 'wait', + :value => 1, + }, + { + :execute => 'click', + :css => 'a[href="#new"]', + }, + { + :execute => 'click', + :css => 'a[href="#ticket_create/call_inbound"]', + }, + { + :execute => 'wait', + :value => 3, + }, + { + :execute => 'check', + :css => '.active .ticket_create', + :result => true, + }, + { + :execute => 'set', + :css => '.active .ticket_create input[name="subject"]', + :value => 'some test AAA', + }, + { + :execute => 'wait', + :value => 20, + }, + ], + }, + ] + browser_signle_test_with_login(tests, { :username => 'agent1@example.com' }) + end + def test_persistant_task_b + tests = [ + { + :name => 'persistant task', + :action => [ + { + :execute => 'wait', + :value => 4, + }, + { + :execute => 'click', + :css => '.task', + }, + { + :execute => 'match', + :css => 'body', + :value => 'some test AAA', + :match_result => true, + }, + { + :execute => 'click', + :css => '.taskbar [data-type="close"]', + }, + { + :execute => 'match', + :css => 'body', + :value => 'some test AAA', + :match_result => false, + }, + ], + }, + ] + browser_signle_test_with_login(tests, { :username => 'agent1@example.com' }) + end +end diff --git a/test/browser_test_helper.rb b/test/browser_test_helper.rb index 5464820b9..9ddad431f 100644 --- a/test/browser_test_helper.rb +++ b/test/browser_test_helper.rb @@ -158,11 +158,15 @@ class TestCase < Test::Unit::TestCase end instance.close end - + def browser_element_action(test, action, instance) if action[:css] begin - element = instance.find_element( { :css => action[:css] } ) + if action[:range] == 'all' + element = instance.find_elements( { :css => action[:css] } ) + else + element = instance.find_element( { :css => action[:css] } ) + end rescue element = nil end @@ -179,6 +183,20 @@ class TestCase < Test::Unit::TestCase end elsif action[:element] == :alert element = instance.switch_to.alert + elsif action[:execute] == 'close_all_tasks' + while true + begin + element = instance.find_element( { :css => '.taskbar [data-type="close"]' } ) + if element + element.click + sleep 0.8 + else + break + end + rescue + break + end + end else assert( false, "(#{test[:name]}) unknow selector for '#{action[:element]}'" ) end @@ -195,7 +213,13 @@ class TestCase < Test::Unit::TestCase dropdown = Selenium::WebDriver::Support::Select.new(element) dropdown.select_by(:text, action[:value]) elsif action[:execute] == 'click' - element.click + if element.class == Array + element.each {|item| + item.click + } + else + element.click + end elsif action[:execute] == 'accept' element.accept elsif action[:execute] == 'dismiss' @@ -263,6 +287,7 @@ class TestCase < Test::Unit::TestCase end end elsif action[:execute] == 'check' + elsif action[:execute] == 'close_all_tasks' else assert( false, "(#{test[:name]}) unknow action '#{action[:execute]}'" ) end