From 77d147efafaf488610442454f1ae4ebf27393ee3 Mon Sep 17 00:00:00 2001 From: Mantas Masalskis Date: Thu, 14 Oct 2021 16:35:12 +0200 Subject: [PATCH] Maintenance: Improves QUnit tests usability --- app/controllers/tests_controller.rb | 14 + app/views/layouts/application.html.erb | 2 +- app/views/layouts/tests.html.erb | 22 + app/views/tests/color_object.html.erb | 13 - app/views/tests/core.html.erb | 14 - app/views/tests/form.html.erb | 14 - .../tests/form_autocompletion_ajax.html.erb | 21 - app/views/tests/form_color.html.erb | 21 - app/views/tests/form_column_select.html.erb | 21 - app/views/tests/form_core_workflow.html.erb | 21 - app/views/tests/form_datetime.html.erb | 21 - app/views/tests/form_extended.html.erb | 21 - app/views/tests/form_find.html.erb | 13 - .../tests/form_searchable_select.html.erb | 21 - app/views/tests/form_skip_rendering.html.erb | 21 - app/views/tests/form_sla_times.html.erb | 21 - .../tests/form_ticket_perform_action.html.erb | 21 - app/views/tests/form_timer.html.erb | 21 - app/views/tests/form_tree_select.html.erb | 21 - app/views/tests/form_trim.html.erb | 13 - app/views/tests/form_validation.html.erb | 21 - app/views/tests/html_utils.html.erb | 13 - app/views/tests/i18n.html.erb | 13 - app/views/tests/image_service.html.erb | 15 - app/views/tests/kb_video_embeding.html.erb | 13 - app/views/tests/local_storage.html.erb | 16 - app/views/tests/model.html.erb | 15 - app/views/tests/model_binding.html.erb | 15 - app/views/tests/model_ticket.html.erb | 15 - app/views/tests/model_ui.html.erb | 14 - app/views/tests/session.html.erb | 15 - app/views/tests/show.html.erb | 1 + app/views/tests/table.html.erb | 16 - app/views/tests/table_extended.html.erb | 16 - app/views/tests/taskbar.html.erb | 16 - app/views/tests/text_module.html.erb | 24 - app/views/tests/ticket_macro.html.erb | 11 - app/views/tests/ticket_selector.html.erb | 14 - app/views/tests/ui.html.erb | 14 - config/brakeman.ignore | 20 + config/routes/test.rb | 44 +- public/assets/tests/color_object.js | 21 - public/assets/tests/form_find.js | 59 - public/assets/tests/i18n.js | 230 - public/assets/tests/local_storage.js | 65 - public/assets/tests/model_ui.js | 110 - public/assets/tests/qunit-1.21.0.js | 4125 --------- .../{qunit-1.21.0.css => qunit-2.17.2.css} | 291 +- public/assets/tests/qunit-2.17.2.js | 7392 +++++++++++++++++ public/assets/tests/qunit/color_object.js | 21 + public/assets/tests/{ => qunit}/core.js | 185 +- public/assets/tests/{ => qunit}/form.js | 510 +- .../{ => qunit}/form_autocompletion_ajax.js | 16 +- public/assets/tests/{ => qunit}/form_color.js | 26 +- .../tests/{ => qunit}/form_column_select.js | 8 +- .../tests/{ => qunit}/form_core_workflow.js | 30 +- .../assets/tests/{ => qunit}/form_datetime.js | 12 +- .../assets/tests/{ => qunit}/form_extended.js | 66 +- public/assets/tests/qunit/form_find.js | 59 + .../{ => qunit}/form_searchable_select.js | 44 +- .../tests/{ => qunit}/form_skip_rendering.js | 6 +- .../tests/{ => qunit}/form_sla_times.js | 24 +- .../{ => qunit}/form_ticket_perform_action.js | 58 +- public/assets/tests/{ => qunit}/form_timer.js | 15 +- .../tests/{ => qunit}/form_tree_select.js | 36 +- public/assets/tests/{ => qunit}/form_trim.js | 4 +- .../tests/{ => qunit}/form_validation.js | 142 +- public/assets/tests/{ => qunit}/html_utils.js | 872 +- public/assets/tests/qunit/i18n.js | 230 + .../assets/tests/{ => qunit}/image_service.js | 8 +- .../tests/{ => qunit}/kb_video_embeding.js | 30 +- public/assets/tests/qunit/local_storage.js | 65 + public/assets/tests/{ => qunit}/model.js | 70 +- .../assets/tests/{ => qunit}/model_binding.js | 22 +- .../assets/tests/{ => qunit}/model_ticket.js | 30 +- public/assets/tests/qunit/model_ui.js | 110 + public/assets/tests/qunit/session.js | 82 + public/assets/tests/qunit/table.js | 844 ++ public/assets/tests/qunit/table_extended.js | 1777 ++++ public/assets/tests/qunit/taskbar.js | 316 + .../assets/tests/{ => qunit}/text_module.js | 28 +- .../assets/tests/{ => qunit}/ticket_macro.js | 6 +- .../tests/{ => qunit}/ticket_selector.js | 318 +- public/assets/tests/{ => qunit}/ui.js | 172 +- public/assets/tests/session.js | 82 - .../tests/{syn-0.14.1.js => syn-0.15.0.js} | 150 +- public/assets/tests/table.js | 844 -- public/assets/tests/table_extended.js | 1777 ---- public/assets/tests/taskbar.js | 316 - spec/system/js/q_unit_spec.rb | 206 +- 90 files changed, 12748 insertions(+), 9860 deletions(-) create mode 100644 app/views/layouts/tests.html.erb delete mode 100644 app/views/tests/color_object.html.erb delete mode 100644 app/views/tests/core.html.erb delete mode 100644 app/views/tests/form_autocompletion_ajax.html.erb delete mode 100644 app/views/tests/form_color.html.erb delete mode 100644 app/views/tests/form_column_select.html.erb delete mode 100644 app/views/tests/form_core_workflow.html.erb delete mode 100644 app/views/tests/form_datetime.html.erb delete mode 100644 app/views/tests/form_extended.html.erb delete mode 100644 app/views/tests/form_searchable_select.html.erb delete mode 100644 app/views/tests/form_skip_rendering.html.erb delete mode 100644 app/views/tests/form_sla_times.html.erb delete mode 100644 app/views/tests/form_ticket_perform_action.html.erb delete mode 100644 app/views/tests/form_timer.html.erb delete mode 100644 app/views/tests/form_tree_select.html.erb delete mode 100644 app/views/tests/form_validation.html.erb delete mode 100644 app/views/tests/i18n.html.erb delete mode 100644 app/views/tests/image_service.html.erb delete mode 100644 app/views/tests/kb_video_embeding.html.erb delete mode 100644 app/views/tests/local_storage.html.erb delete mode 100644 app/views/tests/model.html.erb delete mode 100644 app/views/tests/model_binding.html.erb delete mode 100644 app/views/tests/model_ticket.html.erb delete mode 100644 app/views/tests/model_ui.html.erb delete mode 100644 app/views/tests/session.html.erb create mode 100644 app/views/tests/show.html.erb delete mode 100644 app/views/tests/table.html.erb delete mode 100644 app/views/tests/table_extended.html.erb delete mode 100644 app/views/tests/taskbar.html.erb delete mode 100644 app/views/tests/text_module.html.erb delete mode 100644 app/views/tests/ticket_macro.html.erb delete mode 100644 app/views/tests/ticket_selector.html.erb delete mode 100644 app/views/tests/ui.html.erb delete mode 100644 public/assets/tests/color_object.js delete mode 100644 public/assets/tests/form_find.js delete mode 100644 public/assets/tests/i18n.js delete mode 100644 public/assets/tests/local_storage.js delete mode 100644 public/assets/tests/model_ui.js delete mode 100644 public/assets/tests/qunit-1.21.0.js rename public/assets/tests/{qunit-1.21.0.css => qunit-2.17.2.css} (53%) create mode 100644 public/assets/tests/qunit-2.17.2.js create mode 100644 public/assets/tests/qunit/color_object.js rename public/assets/tests/{ => qunit}/core.js (66%) rename public/assets/tests/{ => qunit}/form.js (69%) rename public/assets/tests/{ => qunit}/form_autocompletion_ajax.js (73%) rename public/assets/tests/{ => qunit}/form_color.js (70%) rename public/assets/tests/{ => qunit}/form_column_select.js (89%) rename public/assets/tests/{ => qunit}/form_core_workflow.js (52%) rename public/assets/tests/{ => qunit}/form_datetime.js (51%) rename public/assets/tests/{ => qunit}/form_extended.js (88%) create mode 100644 public/assets/tests/qunit/form_find.js rename public/assets/tests/{ => qunit}/form_searchable_select.js (84%) rename public/assets/tests/{ => qunit}/form_skip_rendering.js (62%) rename public/assets/tests/{ => qunit}/form_sla_times.js (62%) rename public/assets/tests/{ => qunit}/form_ticket_perform_action.js (88%) rename public/assets/tests/{ => qunit}/form_timer.js (87%) rename public/assets/tests/{ => qunit}/form_tree_select.js (87%) rename public/assets/tests/{ => qunit}/form_trim.js (81%) rename public/assets/tests/{ => qunit}/form_validation.js (57%) rename public/assets/tests/{ => qunit}/html_utils.js (88%) create mode 100644 public/assets/tests/qunit/i18n.js rename public/assets/tests/{ => qunit}/image_service.js (92%) rename public/assets/tests/{ => qunit}/kb_video_embeding.js (52%) create mode 100644 public/assets/tests/qunit/local_storage.js rename public/assets/tests/{ => qunit}/model.js (63%) rename public/assets/tests/{ => qunit}/model_binding.js (61%) rename public/assets/tests/{ => qunit}/model_ticket.js (75%) create mode 100644 public/assets/tests/qunit/model_ui.js create mode 100644 public/assets/tests/qunit/session.js create mode 100644 public/assets/tests/qunit/table.js create mode 100644 public/assets/tests/qunit/table_extended.js create mode 100644 public/assets/tests/qunit/taskbar.js rename public/assets/tests/{ => qunit}/text_module.js (67%) rename public/assets/tests/{ => qunit}/ticket_macro.js (89%) rename public/assets/tests/{ => qunit}/ticket_selector.js (69%) rename public/assets/tests/{ => qunit}/ui.js (62%) delete mode 100644 public/assets/tests/session.js rename public/assets/tests/{syn-0.14.1.js => syn-0.15.0.js} (96%) delete mode 100644 public/assets/tests/table.js delete mode 100644 public/assets/tests/table_extended.js delete mode 100644 public/assets/tests/taskbar.js diff --git a/app/controllers/tests_controller.rb b/app/controllers/tests_controller.rb index 49d51bf2a..0214c0316 100644 --- a/app/controllers/tests_controller.rb +++ b/app/controllers/tests_controller.rb @@ -4,6 +4,20 @@ class TestsController < ApplicationController prepend_before_action -> { authentication_check_only } + layout 'tests', except: %i[wait raised_exception] + + def show + @filename = params[:name] + + if lookup_context.exists? @filename, 'tests' + render @filename + elsif @filename.starts_with? 'form' + render 'form' + else + render + end + end + # GET /test/wait def wait sleep params[:sec].to_i diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ceecf4b89..65fffa551 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -17,7 +17,7 @@ -<%= yield %> + <%= content_for?(:content) ? yield(:content) : yield %> diff --git a/app/views/layouts/tests.html.erb b/app/views/layouts/tests.html.erb new file mode 100644 index 000000000..2a9ff254d --- /dev/null +++ b/app/views/layouts/tests.html.erb @@ -0,0 +1,22 @@ +<% content_for :content do %> + + <%= javascript_include_tag "/assets/tests/qunit-2.17.2.js", + "/assets/tests/sinon-9.2.4", + "/assets/tests/syn-0.15.0", + "/assets/tests/qunit/#{@filename}.js", + nonce: true %> + + + + <%= yield %> +<% end %> + +<%= render template: 'layouts/application' %> diff --git a/app/views/tests/color_object.html.erb b/app/views/tests/color_object.html.erb deleted file mode 100644 index 4ee602d32..000000000 --- a/app/views/tests/color_object.html.erb +++ /dev/null @@ -1,13 +0,0 @@ - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/color_object.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
diff --git a/app/views/tests/core.html.erb b/app/views/tests/core.html.erb deleted file mode 100644 index c702f8a88..000000000 --- a/app/views/tests/core.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/core.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- diff --git a/app/views/tests/form.html.erb b/app/views/tests/form.html.erb index 8cfcddffc..5e41330ed 100644 --- a/app/views/tests/form.html.erb +++ b/app/views/tests/form.html.erb @@ -1,21 +1,7 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> -
-
diff --git a/app/views/tests/form_autocompletion_ajax.html.erb b/app/views/tests/form_autocompletion_ajax.html.erb deleted file mode 100644 index b0d71a826..000000000 --- a/app/views/tests/form_autocompletion_ajax.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_autocompletion_ajax.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_color.html.erb b/app/views/tests/form_color.html.erb deleted file mode 100644 index 9cfc4d668..000000000 --- a/app/views/tests/form_color.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/syn-0.14.1.js", "/assets/tests/form_color.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
- diff --git a/app/views/tests/form_column_select.html.erb b/app/views/tests/form_column_select.html.erb deleted file mode 100644 index 5ec2e2227..000000000 --- a/app/views/tests/form_column_select.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_column_select.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_core_workflow.html.erb b/app/views/tests/form_core_workflow.html.erb deleted file mode 100644 index 832ef8215..000000000 --- a/app/views/tests/form_core_workflow.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_core_workflow.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_datetime.html.erb b/app/views/tests/form_datetime.html.erb deleted file mode 100644 index b66259a08..000000000 --- a/app/views/tests/form_datetime.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_datetime.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_extended.html.erb b/app/views/tests/form_extended.html.erb deleted file mode 100644 index 42938d319..000000000 --- a/app/views/tests/form_extended.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_extended.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_find.html.erb b/app/views/tests/form_find.html.erb index 0e2ab5fa3..797a7ff4d 100644 --- a/app/views/tests/form_find.html.erb +++ b/app/views/tests/form_find.html.erb @@ -1,16 +1,3 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_find.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> -
diff --git a/app/views/tests/form_searchable_select.html.erb b/app/views/tests/form_searchable_select.html.erb deleted file mode 100644 index 370046bfc..000000000 --- a/app/views/tests/form_searchable_select.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_searchable_select.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_skip_rendering.html.erb b/app/views/tests/form_skip_rendering.html.erb deleted file mode 100644 index 4338f5a29..000000000 --- a/app/views/tests/form_skip_rendering.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/syn-0.14.1.js", "/assets/tests/form_skip_rendering.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
- diff --git a/app/views/tests/form_sla_times.html.erb b/app/views/tests/form_sla_times.html.erb deleted file mode 100644 index 2f161a66d..000000000 --- a/app/views/tests/form_sla_times.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/syn-0.14.1.js", "/assets/tests/form_sla_times.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
- diff --git a/app/views/tests/form_ticket_perform_action.html.erb b/app/views/tests/form_ticket_perform_action.html.erb deleted file mode 100644 index e7c26d10a..000000000 --- a/app/views/tests/form_ticket_perform_action.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_ticket_perform_action.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_timer.html.erb b/app/views/tests/form_timer.html.erb deleted file mode 100644 index 7a425a1c2..000000000 --- a/app/views/tests/form_timer.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_timer.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_tree_select.html.erb b/app/views/tests/form_tree_select.html.erb deleted file mode 100644 index 10252b9b0..000000000 --- a/app/views/tests/form_tree_select.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_tree_select.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/form_trim.html.erb b/app/views/tests/form_trim.html.erb index 53ce96ad3..034d9dc34 100644 --- a/app/views/tests/form_trim.html.erb +++ b/app/views/tests/form_trim.html.erb @@ -1,16 +1,3 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_trim.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> -
diff --git a/app/views/tests/form_validation.html.erb b/app/views/tests/form_validation.html.erb deleted file mode 100644 index 0595cb3c4..000000000 --- a/app/views/tests/form_validation.html.erb +++ /dev/null @@ -1,21 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_validation.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
- -
-
diff --git a/app/views/tests/html_utils.html.erb b/app/views/tests/html_utils.html.erb index 652eb5973..ed428fc17 100644 --- a/app/views/tests/html_utils.html.erb +++ b/app/views/tests/html_utils.html.erb @@ -1,16 +1,3 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/html_utils.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> -
diff --git a/app/views/tests/i18n.html.erb b/app/views/tests/i18n.html.erb deleted file mode 100644 index ba8e3a65e..000000000 --- a/app/views/tests/i18n.html.erb +++ /dev/null @@ -1,13 +0,0 @@ - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/i18n.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
diff --git a/app/views/tests/image_service.html.erb b/app/views/tests/image_service.html.erb deleted file mode 100644 index 555e4f0c6..000000000 --- a/app/views/tests/image_service.html.erb +++ /dev/null @@ -1,15 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/image_service.js", nonce: true %> - - - - - -
- diff --git a/app/views/tests/kb_video_embeding.html.erb b/app/views/tests/kb_video_embeding.html.erb deleted file mode 100644 index 9fc1cea68..000000000 --- a/app/views/tests/kb_video_embeding.html.erb +++ /dev/null @@ -1,13 +0,0 @@ - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/kb_video_embeding.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
diff --git a/app/views/tests/local_storage.html.erb b/app/views/tests/local_storage.html.erb deleted file mode 100644 index 68f65a404..000000000 --- a/app/views/tests/local_storage.html.erb +++ /dev/null @@ -1,16 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/local_storage.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- - diff --git a/app/views/tests/model.html.erb b/app/views/tests/model.html.erb deleted file mode 100644 index d418fa133..000000000 --- a/app/views/tests/model.html.erb +++ /dev/null @@ -1,15 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- diff --git a/app/views/tests/model_binding.html.erb b/app/views/tests/model_binding.html.erb deleted file mode 100644 index a1ca3713e..000000000 --- a/app/views/tests/model_binding.html.erb +++ /dev/null @@ -1,15 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_binding.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- diff --git a/app/views/tests/model_ticket.html.erb b/app/views/tests/model_ticket.html.erb deleted file mode 100644 index 27166aa42..000000000 --- a/app/views/tests/model_ticket.html.erb +++ /dev/null @@ -1,15 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_ticket.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- diff --git a/app/views/tests/model_ui.html.erb b/app/views/tests/model_ui.html.erb deleted file mode 100644 index 3452c5332..000000000 --- a/app/views/tests/model_ui.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/sinon-9.2.4", "/assets/tests/model_ui.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
diff --git a/app/views/tests/session.html.erb b/app/views/tests/session.html.erb deleted file mode 100644 index ae886f8c6..000000000 --- a/app/views/tests/session.html.erb +++ /dev/null @@ -1,15 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/session.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- diff --git a/app/views/tests/show.html.erb b/app/views/tests/show.html.erb new file mode 100644 index 000000000..25439b6b5 --- /dev/null +++ b/app/views/tests/show.html.erb @@ -0,0 +1 @@ +
diff --git a/app/views/tests/table.html.erb b/app/views/tests/table.html.erb deleted file mode 100644 index b275c5d83..000000000 --- a/app/views/tests/table.html.erb +++ /dev/null @@ -1,16 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/table.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
diff --git a/app/views/tests/table_extended.html.erb b/app/views/tests/table_extended.html.erb deleted file mode 100644 index c206be011..000000000 --- a/app/views/tests/table_extended.html.erb +++ /dev/null @@ -1,16 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/table_extended.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
diff --git a/app/views/tests/taskbar.html.erb b/app/views/tests/taskbar.html.erb deleted file mode 100644 index 74ec95b60..000000000 --- a/app/views/tests/taskbar.html.erb +++ /dev/null @@ -1,16 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/taskbar.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
diff --git a/app/views/tests/text_module.html.erb b/app/views/tests/text_module.html.erb deleted file mode 100644 index dbfca44a9..000000000 --- a/app/views/tests/text_module.html.erb +++ /dev/null @@ -1,24 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/text_module.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
- -
-
-
-
-
-
- -
-
diff --git a/app/views/tests/ticket_macro.html.erb b/app/views/tests/ticket_macro.html.erb deleted file mode 100644 index f10752d67..000000000 --- a/app/views/tests/ticket_macro.html.erb +++ /dev/null @@ -1,11 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/sinon-9.2.4", "/assets/tests/ticket_macro.js", nonce: true %> - - - -
diff --git a/app/views/tests/ticket_selector.html.erb b/app/views/tests/ticket_selector.html.erb deleted file mode 100644 index a00908d02..000000000 --- a/app/views/tests/ticket_selector.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/ticket_selector.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
diff --git a/app/views/tests/ui.html.erb b/app/views/tests/ui.html.erb deleted file mode 100644 index 6d68e5d74..000000000 --- a/app/views/tests/ui.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - -<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/ui.js", nonce: true %> - - - -<%= javascript_tag nonce: true do -%> -<% end -%> - -
diff --git a/config/brakeman.ignore b/config/brakeman.ignore index 5dac02a60..04b5a06bf 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -520,6 +520,26 @@ "confidence": "Medium", "note": "Admin configured RegExp" }, + { + "warning_type": "Dynamic Render Path", + "warning_code": 15, + "fingerprint": "c52f57d32456c9ab6dba6dfc93bd8effa16829a87a9ce9368da83a35fc6cf1a7", + "check_name": "Render", + "message": "Render path contains parameter value", + "file": "app/controllers/tests_controller.rb", + "line": 13, + "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/", + "code": "render(action => params[:name], {})", + "render_path": null, + "location": { + "type": "method", + "class": "TestsController", + "method": "show" + }, + "user_input": "params[:name]", + "confidence": "High", + "note": "Running QUnit tests" + }, { "warning_type": "SSL Verification Bypass", "warning_code": 71, diff --git a/config/routes/test.rb b/config/routes/test.rb index eebd02eac..536302512 100644 --- a/config/routes/test.rb +++ b/config/routes/test.rb @@ -1,43 +1,11 @@ # Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/ -Zammad::Application.routes.draw do +if !Rails.env.production? + Zammad::Application.routes.draw do + get '/tests_:name', to: 'tests#show' - match '/tests_core', to: 'tests#core', via: :get - match '/tests_session', to: 'tests#session', via: :get - match '/tests_local_storage', to: 'tests#local_storage', via: :get - match '/tests_ui', to: 'tests#ui', via: :get - match '/tests_i18n', to: 'tests#i18n', via: :get - match '/tests_model', to: 'tests#model', via: :get - match '/tests_model_binding', to: 'tests#model_binding', via: :get - match '/tests_model_ui', to: 'tests#model_ui', via: :get - match '/tests_model_ticket', to: 'tests#model_ticket', via: :get - match '/tests_form', to: 'tests#form', via: :get - match '/tests_form_tree_select', to: 'tests#form_tree_select', via: :get - match '/tests_form_find', to: 'tests#form_find', via: :get - match '/tests_form_trim', to: 'tests#form_trim', via: :get - match '/tests_form_extended', to: 'tests#form_extended', via: :get - match '/tests_form_timer', to: 'tests#form_timer', via: :get - match '/tests_form_color', to: 'tests#form_color', via: :get - match '/tests_form_validation', to: 'tests#form_validation', via: :get - match '/tests_form_column_select', to: 'tests#form_column_select', via: :get - match '/tests_form_searchable_select', to: 'tests#form_searchable_select', via: :get - match '/tests_form_autocompletion_ajax', to: 'tests#form_autocompletion_ajax', via: :get - match '/tests_form_ticket_perform_action', to: 'tests#form_ticket_perform_action', via: :get - match '/tests_form_sla_times', to: 'tests#form_sla_times', via: :get - match '/tests_form_skip_rendering', to: 'tests#form_skip_rendering', via: :get - match '/tests_form_datetime', to: 'tests#form_datetime', via: :get - match '/tests_form_core_workflow', to: 'tests#form_core_workflow', via: :get - match '/tests_table', to: 'tests#table', via: :get - match '/tests_table_extended', to: 'tests#table_extended', via: :get - match '/tests_html_utils', to: 'tests#html_utils', via: :get - match '/tests_ticket_macro', to: 'tests#ticket_macro', via: :get - match '/tests_ticket_selector', to: 'tests#ticket_selector', via: :get - match '/tests_taskbar', to: 'tests#taskbar', via: :get - match '/tests_image_service', to: 'tests#image_service', via: :get - match '/tests_text_module', to: 'tests#text_module', via: :get - match '/tests_color_object', to: 'tests#color_object', via: :get - match '/tests_kb_video_embeding', to: 'tests#kb_video_embeding', via: :get - match '/tests/wait/:sec', to: 'tests#wait', via: :get - match '/tests/raised_exception', to: 'tests#error_raised_exception', via: :get + match '/tests/wait/:sec', to: 'tests#wait', via: :get + match '/tests/raised_exception', to: 'tests#error_raised_exception', via: :get + end end diff --git a/public/assets/tests/color_object.js b/public/assets/tests/color_object.js deleted file mode 100644 index 2e0e0c7c1..000000000 --- a/public/assets/tests/color_object.js +++ /dev/null @@ -1,21 +0,0 @@ -test('test color object', function() { - let hex = new App.ColorObject('#09f609') - let hsl = new App.ColorObject([0.5, 0.2, 0.3]) - - deepEqual(hex.asHslArray(), [1/3, 0.9294117647058824, 0.5], 'HEX converted to HSL components') - deepEqual(hsl.asHslArray(), [0.5, 0.2, 0.3], 'HSL components returned as original input') - equal(hex.asString(), '#09f609', 'HEX represented as original input') - equal(hsl.asString(), 'hsl(180,20%,30%)', 'HSL components represented as HSL string') - - hex.updateWithString('#fff') - equal(hex.asString(), '#fff', 'color updated') - - hsl.updateWithHslComponent(0.25, 1) - deepEqual(hsl.asHslArray(), [0.5, 0.25, 0.3], 'given HSL component updated') - - deepEqual(Array.from(App.ColorObject.anyToRgb('#ff0000')), [255, 0, 0, 255], 'any to RGB') - deepEqual(App.ColorObject.anyToHslArray('#ff0000'), [0,1,0.5], 'any to HSL components') - equal(App.ColorObject.anyToHslString('#ff0000'), 'hsl(0,100%,50%)', 'any to HSL string') - deepEqual(App.ColorObject.rgbToHslArray([255, 0, 0]), [0,1,0.5], 'RGB to HSL components') - equal(App.ColorObject.hslArrayToHslString([0.5, 0.25, 0.3]), 'hsl(180,25%,30%)', 'HSL components to HSL string') -}) diff --git a/public/assets/tests/form_find.js b/public/assets/tests/form_find.js deleted file mode 100644 index 697d398c9..000000000 --- a/public/assets/tests/form_find.js +++ /dev/null @@ -1,59 +0,0 @@ - -// form -test( "find form check", function() { - - $('#forms').append('

find form check

') - var form1 = App.ControllerForm.findForm($('#form1')) - equal(form1.is('form'), true) - - $('#forms').append('

find form check

') - var form2 = App.ControllerForm.findForm($('#form2 .js-input')) - equal(form2.is('form'), true) - - $('#forms').append('

find form check

') - var form3 = App.ControllerForm.findForm($('#form3 .js-button')) - equal(form3.is('form'), true) - App.ControllerForm.disable($('#form3 .js-button')) - equal($('#form3 .js-button').prop('readonly'), true) - equal($('#form3 .js-button').prop('disabled'), true) - equal($('#form3 .js-input').prop('readonly'), true) - equal($('#form3 .js-input').prop('disabled'), false) - - App.ControllerForm.enable($('#form3 .js-button')) - equal($('#form3 .js-button').prop('readonly'), false) - equal($('#form3 .js-button').prop('disabled'), false) - equal($('#form3 .js-input').prop('readonly'), false) - equal($('#form3 .js-input').prop('disabled'), false) - - $('#forms').append('

find form check by only disable button

') - var form31 = App.ControllerForm.findForm($('#form31 .js-button')) - - App.ControllerForm.disable($('#form31 .js-button'), 'button') - - equal($('#form31 .js-button').prop('readonly'), true) - equal($('#form31 .js-button').prop('disabled'), true) - equal($('#form31 .js-input').prop('readonly'), false) - equal($('#form31 .js-input').prop('disabled'), false) - - App.ControllerForm.enable($('#form31 .js-button')) - equal($('#form31 .js-button').prop('readonly'), false) - equal($('#form31 .js-button').prop('disabled'), false) - equal($('#form31 .js-input').prop('readonly'), false) - equal($('#form31 .js-input').prop('disabled'), false) - - $('#forms').append('

find form check

') - var form4 = App.ControllerForm.findForm($('#form4 .js-button')) - equal(form4.is('form'), false) - App.ControllerForm.disable($('#form4 .js-button')) - equal($('#form4 .js-button').prop('readonly'), true) - equal($('#form4 .js-button').prop('disabled'), true) - equal($('#form4 .js-input').prop('readonly'), false) - equal($('#form4 .js-input').prop('disabled'), false) - - App.ControllerForm.enable($('#form4 .js-button')) - equal($('#form4 .js-button').prop('readonly'), false) - equal($('#form4 .js-button').prop('disabled'), false) - equal($('#form4 .js-input').prop('readonly'), false) - equal($('#form4 .js-input').prop('disabled'), false) - -}); diff --git a/public/assets/tests/i18n.js b/public/assets/tests/i18n.js deleted file mode 100644 index 0b994235f..000000000 --- a/public/assets/tests/i18n.js +++ /dev/null @@ -1,230 +0,0 @@ -test('i18n .detectBrowserLocale', function() { - var original_userLanguage = window.navigator.userLanguage - var original_language = window.navigator.language - var original_languages = window.navigator.languages - - var reset = function(){ - window.navigator.userLanguage = original_userLanguage - window.navigator.language = original_language - window.navigator.languages = original_languages - } - - var mock = function(languages, language, userLanguage){ - Object.defineProperty(window.navigator, 'language', {value: language, configurable: true }); - Object.defineProperty(window.navigator, 'languages', {value: languages, configurable: true }); - Object.defineProperty(window.navigator, 'userLanguage', {value: userLanguage, configurable: true }); - } - - mock(undefined, undefined, undefined) - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(undefined, undefined, 'non-existant'); - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(undefined, undefined, 'en'); - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(undefined, undefined, 'lt'); - equal(App.i18n.detectBrowserLocale(), 'lt') - - mock(undefined, 'lt', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'lt') - - mock(undefined, 'en', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(['en'], 'lt', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(['en-us'], 'lt', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(['en-US'], 'lt', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(['lt', 'en-US'], 'lt', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'lt') - - mock(['en-GB', 'en-US'], 'lt', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'en-gb') - - mock(['en-XYZ'], 'lt', 'lv'); - equal(App.i18n.detectBrowserLocale(), 'en-us') - - mock(['xyz', 'lt'], 'lv', undefined); - equal(App.i18n.detectBrowserLocale(), 'lt') - - reset() - - // i18n - test('i18n', function() { - - // de - App.i18n.set('de-de') - var translated = App.i18n.translateContent('yes') - equal(translated, 'ja', 'de-de - yes / ja translated correctly') - - translated = App.i18n.translatePlain('yes') - equal(translated, 'ja', 'de-de - yes / ja translated correctly') - - translated = App.i18n.translateInline('yes') - equal(translated, 'ja', 'de-de - yes / ja translated correctly') - - translated = App.i18n.translateContent('%s ago', 123); - equal(translated, 'vor 123', 'de-de - %s') - - translated = App.i18n.translateContent('%s ago', 'quote') - equal(translated, 'vor <b>quote</b>', 'de-de - %s - quote') - - translated = App.i18n.translateContent('%s %s test', 123, 'xxx |B|') - equal(translated, '123 xxx |B| test', 'de-de - %s %s') - - translated = App.i18n.translateContent('|%s| %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'de-de - *%s* %s') - - translated = App.i18n.translateContent('||%s|| %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'de-de - *%s* %s') - - translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'de-de - _%s_ %s') - - translated = App.i18n.translateContent('§%s§ %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'de-de - §%s§ %s') - - translated = App.i18n.translateContent('//%s// %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'de-de - //%s// %s') - - translated = App.i18n.translateContent('\'%s\' %s test', 123, 'xxx') - equal(translated, ''123' xxx test', 'de-de - \'%s\' %s') - - translated = App.i18n.translateContent('//*äöüß') - equal(translated, '<test&now>//*äöüß', 'de - //*äöüß') - - translated = App.i18n.translateContent('some link [to what ever](http://lalala)') - equal(translated, 'some link to what ever', 'de-de - link') - - translated = App.i18n.translateContent('some link [to what ever](%s)', 'http://lalala') - equal(translated, 'some link to what ever', 'de-de - link') - - translated = App.i18n.translateContent('Enables user authentication via %s. Register your app first at [%s](%s).', 'XXX', 'YYY', 'http://lalala') - equal(translated, 'Aktivieren der Benutzeranmeldung über XXX. Registriere Deine Anwendung zuerst über YYY.', 'en-us - link') - - var time_local = new Date(); - var offset = time_local.getTimezoneOffset(); - var timestamp = App.i18n.translateTimestamp('2012-11-06T21:07:24Z', offset); - equal(timestamp, '06.11.2012 21:07', 'de-de - timestamp translated correctly') - - var timestamp = App.i18n.translateTimestamp('2021-02-08 09:13:20 UTC', offset); - equal(timestamp, '08.02.2021 09:13', 'de-de - timestamp translated correctly with UTC format') - - timestamp = App.i18n.translateTimestamp('', offset); - equal(timestamp, '', 'de-de - timestamp translated correctly') - - timestamp = App.i18n.translateTimestamp(null, offset); - equal(timestamp, null, 'de-de - timestamp translated correctly') - - timestamp = App.i18n.translateTimestamp(undefined, offset); - equal(timestamp, undefined, 'de-de - timestamp translated correctly') - - var date = App.i18n.translateDate('2012-11-06', 0) - equal(date, '06.11.2012', 'de-de - date translated correctly') - - date = App.i18n.translateDate('', 0) - equal(date, '', 'de-de - date translated correctly') - - date = App.i18n.translateDate(null, 0) - equal(date, null, 'de-de - date translated correctly') - - date = App.i18n.translateDate(undefined, 0) - equal(date, undefined, 'de-de - date translated correctly') - - // en - App.i18n.set('en-us') - translated = App.i18n.translateContent('yes') - equal(translated, 'yes', 'en-us - yes translated correctly') - - translated = App.i18n.translatePlain('yes') - equal(translated, 'yes', 'en-us - yes translated correctly') - - translated = App.i18n.translateInline('yes') - equal(translated, 'yes', 'en-us - yes translated correctly') - - translated = App.i18n.translateContent('%s ago', 123); - equal(translated, '123 ago', 'en-us - %s') - - translated = App.i18n.translateContent('%s ago', 'quote') - equal(translated, '<b>quote</b> ago', 'en-us - %s - qupte') - - translated = App.i18n.translateContent('%s %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'en-us - %s %s') - - translated = App.i18n.translateContent('|%s| %s test', 123, 'xxx |B|') - equal(translated, '123 xxx |B| test', 'en-us - *%s* %s') - - translated = App.i18n.translateContent('||%s|| %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'en-us - *%s* %s') - - translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'en-us - _%s_ %s') - - translated = App.i18n.translateContent('§%s§ %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'en-us - §%s§ %s') - - translated = App.i18n.translateContent('Here you can search for tickets, customers and organizations. Use the wildcard §*§ to find everything. E. g. §smi*§ or §rosent*l§. You also can use ||double quotes|| for searching phrases §"some phrase"§.') - equal(translated, 'Here you can search for tickets, customers and organizations. Use the wildcard * to find everything. E. g. smi* or rosent*l. You also can use double quotes for searching phrases "some phrase".', 'en-us - §§ §§ §§ || §§') - - translated = App.i18n.translateContent('//%s// %s test', 123, 'xxx') - equal(translated, '123 xxx test', 'en-us - //%s// %s') - - translated = App.i18n.translateContent('\'%s\' %s test', 123, 'xxx') - equal(translated, ''123' xxx test', 'en-us - \'%s\' %s') - - translated = App.i18n.translateContent('') - equal(translated, '<test&now>', 'en-us - ') - - translated = App.i18n.translateContent('some link [to what ever](http://lalala)') - equal(translated, 'some link to what ever', 'en-us - link') - - translated = App.i18n.translateContent('some link [to what ever](%s)', 'http://lalala') - equal(translated, 'some link to what ever', 'en-us - link') - - translated = App.i18n.translateContent('Enables user authentication via %s. Register your app first at [%s](%s).', 'XXX', 'YYY', 'http://lalala') - equal(translated, 'Enables user authentication via XXX. Register your app first at YYY.', 'en-us - link') - - timestamp = App.i18n.translateTimestamp('2012-11-06T21:07:24Z', offset) - equal(timestamp, '11/06/2012 21:07', 'en - timestamp translated correctly') - - timestamp = App.i18n.translateTimestamp('', offset); - equal(timestamp, '', 'en - timestamp translated correctly') - - timestamp = App.i18n.translateTimestamp(null, offset); - equal(timestamp, null, 'en - timestamp translated correctly') - - timestamp = App.i18n.translateTimestamp(undefined, offset); - equal(timestamp, undefined, 'en - timestamp translated correctly') - - date = App.i18n.translateDate('2012-11-06', 0) - equal(date, '11/06/2012', 'en - date translated correctly') - - date = App.i18n.translateDate('', 0) - equal(date, '', 'en - date translated correctly') - - date = App.i18n.translateDate(null, 0) - equal(date, null, 'en - date translated correctly') - - date = App.i18n.translateDate(undefined, 0) - equal(date, undefined, 'en - date translated correctly') - - // locale alias test - // de - App.i18n.set('de') - var translated = App.i18n.translateContent('yes') - equal(translated, 'ja', 'de - yes / ja translated correctly') - - // locale detection test - // de-ch - App.i18n.set('de-ch') - var translated = App.i18n.translateContent('yes') - equal(translated, 'ja', 'de - yes / ja translated correctly') - }); -}) diff --git a/public/assets/tests/local_storage.js b/public/assets/tests/local_storage.js deleted file mode 100644 index 5e5a87918..000000000 --- a/public/assets/tests/local_storage.js +++ /dev/null @@ -1,65 +0,0 @@ -window.onload = function() { - -test('Test item removal from local storage', function() { - var key = 'test_key_1' - var value = 'test_value_1' - - App.LocalStorage.set(key, value) - - equal(App.LocalStorage.get(key), value) - - App.LocalStorage.delete(key) - - equal(App.LocalStorage.get(key), undefined) -}); - -test('Test user-specific item removal from local storage', function() { - var key = 'test_key_2' - var value = 'test_value_2' - var user_id = 2 - - App.LocalStorage.set(key, value, user_id) - - equal(App.LocalStorage.get(key, user_id), value) - - App.LocalStorage.delete(key, user_id) - - equal(App.LocalStorage.get(key, user_id), undefined) -}); - -test('Test key lookup', function() { - App.LocalStorage.clear() - - var key = 'test_key_3' - var value = 'test_value_3' - var user_id = 2 - var alt_key = 'test_alt_key_3' - - // verify no keys initially - equal(App.LocalStorage.keys().length, 0) - - App.LocalStorage.set(key, value, user_id) - - // has 1 key in total - equal(App.LocalStorage.keys().length, 1) - - // doesn't return anything with wrong prefix - equal(App.LocalStorage.keys('a').length, 0) - - // doesn't return anything since user id not given - equal(App.LocalStorage.keys('test').length, 0) - - // correct - equal(App.LocalStorage.keys('test', user_id).length, 1) - - // verify value - equal(App.LocalStorage.keys('test', user_id)[0].match(key + '$'), key) - - App.LocalStorage.set(alt_key, value) - - // returns 1 key without user id - equal(App.LocalStorage.keys('test').length, 1) - equal(App.LocalStorage.keys('test')[0], alt_key) -}); - -} diff --git a/public/assets/tests/model_ui.js b/public/assets/tests/model_ui.js deleted file mode 100644 index 5b8158d08..000000000 --- a/public/assets/tests/model_ui.js +++ /dev/null @@ -1,110 +0,0 @@ -window.onload = function() { - -// model -test( "model ui basic tests", function() { - - // load ref object - App.Collection.loadAssets({ - TicketState: { - 1: { - name: 'new', id: 1, updated_at: "2014-11-07T23:43:08.000Z", - }, - 2: { - name: 'open', id: 2, updated_at: "2014-11-07T23:43:08.000Z", - }, - 3: { - name: 'closed <>&', id: 3, updated_at: "2014-11-07T23:43:08.000Z", - }, - }, - }) - - // create ticket - var attribute1 = { - name: 'date', display: 'date 1', tag: 'date', null: true - }; - App.Ticket.configure_attributes.push( attribute1 ) - var attribute2 = { - name: 'textarea', display: 'textarea 1', tag: 'textarea', null: true - }; - App.Ticket.configure_attributes.push( attribute2 ) - var attribute3 = { - name: 'link1', display: 'link 1', linktemplate: 'http://zammad.com', tag: 'input', null: true, translate: true - }; - App.Ticket.configure_attributes.push( attribute3 ) - var attribute4 = { - name: 'link2', display: 'link 1', linktemplate: 'http://zammad.com', tag: 'input', null: true - }; - App.Ticket.configure_attributes.push( attribute4 ) - - var ticket = new App.Ticket() - ticket.load({ - id: 1000, - title: 'some title <>&', - state_id: 2, - updated_at: '2014-11-07T23:43:08.000Z', - date: '2015-02-07', - textarea: "some new\nline", - link1: 'closed', - link2: 'closed', - }) - - App.i18n.set('en-us') - equal( App.viewPrint( ticket, 'id' ), 1000) - equal( App.viewPrint( ticket, 'title' ), 'some title <>&') - equal( App.viewPrint( ticket, 'state' ), 'open') - equal( App.viewPrint( ticket, 'state_id' ), 'open') - equal( App.viewPrint( ticket, 'not_existing' ), '-') - equal( App.viewPrint( ticket, 'updated_at' ), '') - equal( App.viewPrint( ticket, 'date' ), '02/07/2015') - equal( App.viewPrint( ticket, 'textarea' ), '
some new
line
') - equal( App.viewPrint( ticket, 'link1' ), 'closed') - equal( App.viewPrint( ticket, 'link2' ), 'closed') - - let stub = sinon.stub(App.Config, 'get') - stub.withArgs('timezone_default').returns('Example/Timezone') - let attr = App.Ticket.configure_attributes.find(e => { return e.name == 'updated_at' }) - attr.include_timezone = true - - equal( App.viewPrint( ticket, 'updated_at' ), '') - - attr.include_timezone = false - stub.restore() - - App.i18n.set('de-de') - equal( App.viewPrint( ticket, 'id' ), 1000) - equal( App.viewPrint( ticket, 'title' ), 'some title <>&') - equal( App.viewPrint( ticket, 'state' ), 'offen') - equal( App.viewPrint( ticket, 'state_id' ), 'offen') - equal( App.viewPrint( ticket, 'not_existing' ), '-') - equal( App.viewPrint( ticket, 'updated_at' ), '') - equal( App.viewPrint( ticket, 'date' ), '07.02.2015') - equal( App.viewPrint( ticket, 'textarea' ), '
some new
line
') - equal( App.viewPrint( ticket, 'link1' ), 'geschlossen') - equal( App.viewPrint( ticket, 'link2' ), 'closed') - - - App.i18n.set('en-us') - ticket.state_id = 3 - equal( App.viewPrint( ticket, 'state' ), 'closed <>&') - equal( App.viewPrint( ticket, 'state_id' ), 'closed <>&') - - App.i18n.set('de') - equal( App.viewPrint( ticket, 'state' ), 'closed <>&') - equal( App.viewPrint( ticket, 'state_id' ), 'closed <>&') - - // normal string - data = { - a: 1, - b: 'abc', - c: { - displayName: function() { return "my displayName <>&" } - }, - } - equal( App.viewPrint( data, 'a' ), 1) - equal( App.viewPrint( data, 'b' ), 'abc') - equal( App.viewPrint( data, 'c' ), 'my displayName <>&') - -}); - - -} diff --git a/public/assets/tests/qunit-1.21.0.js b/public/assets/tests/qunit-1.21.0.js deleted file mode 100644 index 2d740f1b8..000000000 --- a/public/assets/tests/qunit-1.21.0.js +++ /dev/null @@ -1,4125 +0,0 @@ -/*! - * QUnit 1.21.0 - * https://qunitjs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2016-02-01T13:07Z - */ - -(function( global ) { - -var QUnit = {}; - -var Date = global.Date; -var now = Date.now || function() { - return new Date().getTime(); -}; - -var setTimeout = global.setTimeout; -var clearTimeout = global.clearTimeout; - -// Store a local window from the global to allow direct references. -var window = global.window; - -var defined = { - document: window && window.document !== undefined, - setTimeout: setTimeout !== undefined, - sessionStorage: (function() { - var x = "qunit-test-string"; - try { - sessionStorage.setItem( x, x ); - sessionStorage.removeItem( x ); - return true; - } catch ( e ) { - return false; - } - }() ) -}; - -var fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" ); -var globalStartCalled = false; -var runStarted = false; - -var toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty; - -// returns a new Array with the elements that are in a but not in b -function diff( a, b ) { - var i, j, - result = a.slice(); - - for ( i = 0; i < result.length; i++ ) { - for ( j = 0; j < b.length; j++ ) { - if ( result[ i ] === b[ j ] ) { - result.splice( i, 1 ); - i--; - break; - } - } - } - return result; -} - -// from jquery.js -function inArray( elem, array ) { - if ( array.indexOf ) { - return array.indexOf( elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; -} - -/** - * Makes a clone of an object using only Array or Object as base, - * and copies over the own enumerable properties. - * - * @param {Object} obj - * @return {Object} New object with only the own properties (recursively). - */ -function objectValues ( obj ) { - var key, val, - vals = QUnit.is( "array", obj ) ? [] : {}; - for ( key in obj ) { - if ( hasOwn.call( obj, key ) ) { - val = obj[ key ]; - vals[ key ] = val === Object( val ) ? objectValues( val ) : val; - } - } - return vals; -} - -function extend( a, b, undefOnly ) { - for ( var prop in b ) { - if ( hasOwn.call( b, prop ) ) { - - // Avoid "Member not found" error in IE8 caused by messing with window.constructor - // This block runs on every environment, so `global` is being used instead of `window` - // to avoid errors on node. - if ( prop !== "constructor" || a !== global ) { - if ( b[ prop ] === undefined ) { - delete a[ prop ]; - } else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) { - a[ prop ] = b[ prop ]; - } - } - } - } - - return a; -} - -function objectType( obj ) { - if ( typeof obj === "undefined" ) { - return "undefined"; - } - - // Consider: typeof null === object - if ( obj === null ) { - return "null"; - } - - var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ), - type = match && match[ 1 ]; - - switch ( type ) { - case "Number": - if ( isNaN( obj ) ) { - return "nan"; - } - return "number"; - case "String": - case "Boolean": - case "Array": - case "Set": - case "Map": - case "Date": - case "RegExp": - case "Function": - case "Symbol": - return type.toLowerCase(); - } - if ( typeof obj === "object" ) { - return "object"; - } -} - -// Safe object type checking -function is( type, obj ) { - return QUnit.objectType( obj ) === type; -} - -var getUrlParams = function() { - var i, current; - var urlParams = {}; - var location = window.location; - var params = location.search.slice( 1 ).split( "&" ); - var length = params.length; - - if ( params[ 0 ] ) { - for ( i = 0; i < length; i++ ) { - current = params[ i ].split( "=" ); - current[ 0 ] = decodeURIComponent( current[ 0 ] ); - - // allow just a key to turn on a flag, e.g., test.html?noglobals - current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; - if ( urlParams[ current[ 0 ] ] ) { - urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] ); - } else { - urlParams[ current[ 0 ] ] = current[ 1 ]; - } - } - } - - return urlParams; -}; - -// Doesn't support IE6 to IE9, it will return undefined on these browsers -// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack -function extractStacktrace( e, offset ) { - offset = offset === undefined ? 4 : offset; - - var stack, include, i; - - if ( e.stack ) { - stack = e.stack.split( "\n" ); - if ( /^error$/i.test( stack[ 0 ] ) ) { - stack.shift(); - } - if ( fileName ) { - include = []; - for ( i = offset; i < stack.length; i++ ) { - if ( stack[ i ].indexOf( fileName ) !== -1 ) { - break; - } - include.push( stack[ i ] ); - } - if ( include.length ) { - return include.join( "\n" ); - } - } - return stack[ offset ]; - - // Support: Safari <=6 only - } else if ( e.sourceURL ) { - - // exclude useless self-reference for generated Error objects - if ( /qunit.js$/.test( e.sourceURL ) ) { - return; - } - - // for actual exceptions, this is useful - return e.sourceURL + ":" + e.line; - } -} - -function sourceFromStacktrace( offset ) { - var error = new Error(); - - // Support: Safari <=7 only, IE <=10 - 11 only - // Not all browsers generate the `stack` property for `new Error()`, see also #636 - if ( !error.stack ) { - try { - throw error; - } catch ( err ) { - error = err; - } - } - - return extractStacktrace( error, offset ); -} - -/** - * Config object: Maintain internal state - * Later exposed as QUnit.config - * `config` initialized at top of scope - */ -var config = { - // The queue of tests to run - queue: [], - - // block until document ready - blocking: true, - - // by default, run previously failed tests first - // very useful in combination with "Hide passed tests" checked - reorder: true, - - // by default, modify document.title when suite is done - altertitle: true, - - // HTML Reporter: collapse every test except the first failing test - // If false, all failing tests will be expanded - collapse: true, - - // by default, scroll to top of the page when suite is done - scrolltop: true, - - // depth up-to which object will be dumped - maxDepth: 5, - - // when enabled, all tests must call expect() - requireExpects: false, - - // add checkboxes that are persisted in the query-string - // when enabled, the id is set to `true` as a `QUnit.config` property - urlConfig: [ - { - id: "hidepassed", - label: "Hide passed tests", - tooltip: "Only show tests and assertions that fail. Stored as query-strings." - }, - { - id: "noglobals", - label: "Check for Globals", - tooltip: "Enabling this will test if any test introduces new properties on the " + - "global object (`window` in Browsers). Stored as query-strings." - }, - { - id: "notrycatch", - label: "No try-catch", - tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " + - "exceptions in IE reasonable. Stored as query-strings." - } - ], - - // Set of all modules. - modules: [], - - // Stack of nested modules - moduleStack: [], - - // The first unnamed module - currentModule: { - name: "", - tests: [] - }, - - callbacks: {} -}; - -var urlParams = defined.document ? getUrlParams() : {}; - -// Push a loose unnamed module to the modules collection -config.modules.push( config.currentModule ); - -if ( urlParams.filter === true ) { - delete urlParams.filter; -} - -// String search anywhere in moduleName+testName -config.filter = urlParams.filter; - -config.testId = []; -if ( urlParams.testId ) { - // Ensure that urlParams.testId is an array - urlParams.testId = decodeURIComponent( urlParams.testId ).split( "," ); - for (var i = 0; i < urlParams.testId.length; i++ ) { - config.testId.push( urlParams.testId[ i ] ); - } -} - -var loggingCallbacks = {}; - -// Register logging callbacks -function registerLoggingCallbacks( obj ) { - var i, l, key, - callbackNames = [ "begin", "done", "log", "testStart", "testDone", - "moduleStart", "moduleDone" ]; - - function registerLoggingCallback( key ) { - var loggingCallback = function( callback ) { - if ( objectType( callback ) !== "function" ) { - throw new Error( - "QUnit logging methods require a callback function as their first parameters." - ); - } - - config.callbacks[ key ].push( callback ); - }; - - // DEPRECATED: This will be removed on QUnit 2.0.0+ - // Stores the registered functions allowing restoring - // at verifyLoggingCallbacks() if modified - loggingCallbacks[ key ] = loggingCallback; - - return loggingCallback; - } - - for ( i = 0, l = callbackNames.length; i < l; i++ ) { - key = callbackNames[ i ]; - - // Initialize key collection of logging callback - if ( objectType( config.callbacks[ key ] ) === "undefined" ) { - config.callbacks[ key ] = []; - } - - obj[ key ] = registerLoggingCallback( key ); - } -} - -function runLoggingCallbacks( key, args ) { - var i, l, callbacks; - - callbacks = config.callbacks[ key ]; - for ( i = 0, l = callbacks.length; i < l; i++ ) { - callbacks[ i ]( args ); - } -} - -// DEPRECATED: This will be removed on 2.0.0+ -// This function verifies if the loggingCallbacks were modified by the user -// If so, it will restore it, assign the given callback and print a console warning -function verifyLoggingCallbacks() { - var loggingCallback, userCallback; - - for ( loggingCallback in loggingCallbacks ) { - if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) { - - userCallback = QUnit[ loggingCallback ]; - - // Restore the callback function - QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ]; - - // Assign the deprecated given callback - QUnit[ loggingCallback ]( userCallback ); - - if ( global.console && global.console.warn ) { - global.console.warn( - "QUnit." + loggingCallback + " was replaced with a new value.\n" + - "Please, check out the documentation on how to apply logging callbacks.\n" + - "Reference: https://api.qunitjs.com/category/callbacks/" - ); - } - } - } -} - -( function() { - if ( !defined.document ) { - return; - } - - // `onErrorFnPrev` initialized at top of scope - // Preserve other handlers - var onErrorFnPrev = window.onerror; - - // Cover uncaught exceptions - // Returning true will suppress the default browser handler, - // returning false will let it run. - window.onerror = function( error, filePath, linerNr ) { - var ret = false; - if ( onErrorFnPrev ) { - ret = onErrorFnPrev( error, filePath, linerNr ); - } - - // Treat return value as window.onerror itself does, - // Only do our handling if not suppressed. - if ( ret !== true ) { - if ( QUnit.config.current ) { - if ( QUnit.config.current.ignoreGlobalErrors ) { - return true; - } - QUnit.pushFailure( error, filePath + ":" + linerNr ); - } else { - QUnit.test( "global failure", extend(function() { - QUnit.pushFailure( error, filePath + ":" + linerNr ); - }, { validTest: true } ) ); - } - return false; - } - - return ret; - }; -} )(); - -QUnit.urlParams = urlParams; - -// Figure out if we're running the tests from a server or not -QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" ); - -// Expose the current QUnit version -QUnit.version = "1.21.0"; - -extend( QUnit, { - - // call on start of module test to prepend name to all tests - module: function( name, testEnvironment, executeNow ) { - var module, moduleFns; - var currentModule = config.currentModule; - - if ( arguments.length === 2 ) { - if ( testEnvironment instanceof Function ) { - executeNow = testEnvironment; - testEnvironment = undefined; - } - } - - // DEPRECATED: handles setup/teardown functions, - // beforeEach and afterEach should be used instead - if ( testEnvironment && testEnvironment.setup ) { - testEnvironment.beforeEach = testEnvironment.setup; - delete testEnvironment.setup; - } - if ( testEnvironment && testEnvironment.teardown ) { - testEnvironment.afterEach = testEnvironment.teardown; - delete testEnvironment.teardown; - } - - module = createModule(); - - moduleFns = { - beforeEach: setHook( module, "beforeEach" ), - afterEach: setHook( module, "afterEach" ) - }; - - if ( executeNow instanceof Function ) { - config.moduleStack.push( module ); - setCurrentModule( module ); - executeNow.call( module.testEnvironment, moduleFns ); - config.moduleStack.pop(); - module = module.parentModule || currentModule; - } - - setCurrentModule( module ); - - function createModule() { - var parentModule = config.moduleStack.length ? - config.moduleStack.slice( -1 )[ 0 ] : null; - var moduleName = parentModule !== null ? - [ parentModule.name, name ].join( " > " ) : name; - var module = { - name: moduleName, - parentModule: parentModule, - tests: [] - }; - - var env = {}; - if ( parentModule ) { - extend( env, parentModule.testEnvironment ); - delete env.beforeEach; - delete env.afterEach; - } - extend( env, testEnvironment ); - module.testEnvironment = env; - - config.modules.push( module ); - return module; - } - - function setCurrentModule( module ) { - config.currentModule = module; - } - - }, - - // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0. - asyncTest: asyncTest, - - test: test, - - skip: skip, - - only: only, - - // DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0. - // In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior. - start: function( count ) { - var globalStartAlreadyCalled = globalStartCalled; - - if ( !config.current ) { - globalStartCalled = true; - - if ( runStarted ) { - throw new Error( "Called start() outside of a test context while already started" ); - } else if ( globalStartAlreadyCalled || count > 1 ) { - throw new Error( "Called start() outside of a test context too many times" ); - } else if ( config.autostart ) { - throw new Error( "Called start() outside of a test context when " + - "QUnit.config.autostart was true" ); - } else if ( !config.pageLoaded ) { - - // The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it - config.autostart = true; - return; - } - } else { - - // If a test is running, adjust its semaphore - config.current.semaphore -= count || 1; - - // If semaphore is non-numeric, throw error - if ( isNaN( config.current.semaphore ) ) { - config.current.semaphore = 0; - - QUnit.pushFailure( - "Called start() with a non-numeric decrement.", - sourceFromStacktrace( 2 ) - ); - return; - } - - // Don't start until equal number of stop-calls - if ( config.current.semaphore > 0 ) { - return; - } - - // throw an Error if start is called more often than stop - if ( config.current.semaphore < 0 ) { - config.current.semaphore = 0; - - QUnit.pushFailure( - "Called start() while already started (test's semaphore was 0 already)", - sourceFromStacktrace( 2 ) - ); - return; - } - } - - resumeProcessing(); - }, - - // DEPRECATED: QUnit.stop() will be removed in QUnit 2.0. - stop: function( count ) { - - // If there isn't a test running, don't allow QUnit.stop() to be called - if ( !config.current ) { - throw new Error( "Called stop() outside of a test context" ); - } - - // If a test is running, adjust its semaphore - config.current.semaphore += count || 1; - - pauseProcessing(); - }, - - config: config, - - is: is, - - objectType: objectType, - - extend: extend, - - load: function() { - config.pageLoaded = true; - - // Initialize the configuration options - extend( config, { - stats: { all: 0, bad: 0 }, - moduleStats: { all: 0, bad: 0 }, - started: 0, - updateRate: 1000, - autostart: true, - filter: "" - }, true ); - - config.blocking = false; - - if ( config.autostart ) { - resumeProcessing(); - } - }, - - stack: function( offset ) { - offset = ( offset || 0 ) + 2; - return sourceFromStacktrace( offset ); - } -}); - -registerLoggingCallbacks( QUnit ); - -function begin() { - var i, l, - modulesLog = []; - - // If the test run hasn't officially begun yet - if ( !config.started ) { - - // Record the time of the test run's beginning - config.started = now(); - - verifyLoggingCallbacks(); - - // Delete the loose unnamed module if unused. - if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) { - config.modules.shift(); - } - - // Avoid unnecessary information by not logging modules' test environments - for ( i = 0, l = config.modules.length; i < l; i++ ) { - modulesLog.push({ - name: config.modules[ i ].name, - tests: config.modules[ i ].tests - }); - } - - // The test run is officially beginning now - runLoggingCallbacks( "begin", { - totalTests: Test.count, - modules: modulesLog - }); - } - - config.blocking = false; - process( true ); -} - -function process( last ) { - function next() { - process( last ); - } - var start = now(); - config.depth = ( config.depth || 0 ) + 1; - - while ( config.queue.length && !config.blocking ) { - if ( !defined.setTimeout || config.updateRate <= 0 || - ( ( now() - start ) < config.updateRate ) ) { - if ( config.current ) { - - // Reset async tracking for each phase of the Test lifecycle - config.current.usedAsync = false; - } - config.queue.shift()(); - } else { - setTimeout( next, 13 ); - break; - } - } - config.depth--; - if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { - done(); - } -} - -function pauseProcessing() { - config.blocking = true; - - if ( config.testTimeout && defined.setTimeout ) { - clearTimeout( config.timeout ); - config.timeout = setTimeout(function() { - if ( config.current ) { - config.current.semaphore = 0; - QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) ); - } else { - throw new Error( "Test timed out" ); - } - resumeProcessing(); - }, config.testTimeout ); - } -} - -function resumeProcessing() { - runStarted = true; - - // A slight delay to allow this iteration of the event loop to finish (more assertions, etc.) - if ( defined.setTimeout ) { - setTimeout(function() { - if ( config.current && config.current.semaphore > 0 ) { - return; - } - if ( config.timeout ) { - clearTimeout( config.timeout ); - } - - begin(); - }, 13 ); - } else { - begin(); - } -} - -function done() { - var runtime, passed; - - config.autorun = true; - - // Log the last module results - if ( config.previousModule ) { - runLoggingCallbacks( "moduleDone", { - name: config.previousModule.name, - tests: config.previousModule.tests, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all, - runtime: now() - config.moduleStats.started - }); - } - delete config.previousModule; - - runtime = now() - config.started; - passed = config.stats.all - config.stats.bad; - - runLoggingCallbacks( "done", { - failed: config.stats.bad, - passed: passed, - total: config.stats.all, - runtime: runtime - }); -} - -function setHook( module, hookName ) { - if ( module.testEnvironment === undefined ) { - module.testEnvironment = {}; - } - - return function( callback ) { - module.testEnvironment[ hookName ] = callback; - }; -} - -var focused = false; -var priorityCount = 0; - -function Test( settings ) { - var i, l; - - ++Test.count; - - extend( this, settings ); - this.assertions = []; - this.semaphore = 0; - this.usedAsync = false; - this.module = config.currentModule; - this.stack = sourceFromStacktrace( 3 ); - - // Register unique strings - for ( i = 0, l = this.module.tests; i < l.length; i++ ) { - if ( this.module.tests[ i ].name === this.testName ) { - this.testName += " "; - } - } - - this.testId = generateHash( this.module.name, this.testName ); - - this.module.tests.push({ - name: this.testName, - testId: this.testId - }); - - if ( settings.skip ) { - - // Skipped tests will fully ignore any sent callback - this.callback = function() {}; - this.async = false; - this.expected = 0; - } else { - this.assert = new Assert( this ); - } -} - -Test.count = 0; - -Test.prototype = { - before: function() { - if ( - - // Emit moduleStart when we're switching from one module to another - this.module !== config.previousModule || - - // They could be equal (both undefined) but if the previousModule property doesn't - // yet exist it means this is the first test in a suite that isn't wrapped in a - // module, in which case we'll just emit a moduleStart event for 'undefined'. - // Without this, reporters can get testStart before moduleStart which is a problem. - !hasOwn.call( config, "previousModule" ) - ) { - if ( hasOwn.call( config, "previousModule" ) ) { - runLoggingCallbacks( "moduleDone", { - name: config.previousModule.name, - tests: config.previousModule.tests, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all, - runtime: now() - config.moduleStats.started - }); - } - config.previousModule = this.module; - config.moduleStats = { all: 0, bad: 0, started: now() }; - runLoggingCallbacks( "moduleStart", { - name: this.module.name, - tests: this.module.tests - }); - } - - config.current = this; - - if ( this.module.testEnvironment ) { - delete this.module.testEnvironment.beforeEach; - delete this.module.testEnvironment.afterEach; - } - this.testEnvironment = extend( {}, this.module.testEnvironment ); - - this.started = now(); - runLoggingCallbacks( "testStart", { - name: this.testName, - module: this.module.name, - testId: this.testId - }); - - if ( !config.pollution ) { - saveGlobal(); - } - }, - - run: function() { - var promise; - - config.current = this; - - if ( this.async ) { - QUnit.stop(); - } - - this.callbackStarted = now(); - - if ( config.notrycatch ) { - runTest( this ); - return; - } - - try { - runTest( this ); - } catch ( e ) { - this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " + - this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); - - // else next test will carry the responsibility - saveGlobal(); - - // Restart the tests if they're blocking - if ( config.blocking ) { - QUnit.start(); - } - } - - function runTest( test ) { - promise = test.callback.call( test.testEnvironment, test.assert ); - test.resolvePromise( promise ); - } - }, - - after: function() { - checkPollution(); - }, - - queueHook: function( hook, hookName ) { - var promise, - test = this; - return function runHook() { - config.current = test; - if ( config.notrycatch ) { - callHook(); - return; - } - try { - callHook(); - } catch ( error ) { - test.pushFailure( hookName + " failed on " + test.testName + ": " + - ( error.message || error ), extractStacktrace( error, 0 ) ); - } - - function callHook() { - promise = hook.call( test.testEnvironment, test.assert ); - test.resolvePromise( promise, hookName ); - } - }; - }, - - // Currently only used for module level hooks, can be used to add global level ones - hooks: function( handler ) { - var hooks = []; - - function processHooks( test, module ) { - if ( module.parentModule ) { - processHooks( test, module.parentModule ); - } - if ( module.testEnvironment && - QUnit.objectType( module.testEnvironment[ handler ] ) === "function" ) { - hooks.push( test.queueHook( module.testEnvironment[ handler ], handler ) ); - } - } - - // Hooks are ignored on skipped tests - if ( !this.skip ) { - processHooks( this, this.module ); - } - return hooks; - }, - - finish: function() { - config.current = this; - if ( config.requireExpects && this.expected === null ) { - this.pushFailure( "Expected number of assertions to be defined, but expect() was " + - "not called.", this.stack ); - } else if ( this.expected !== null && this.expected !== this.assertions.length ) { - this.pushFailure( "Expected " + this.expected + " assertions, but " + - this.assertions.length + " were run", this.stack ); - } else if ( this.expected === null && !this.assertions.length ) { - this.pushFailure( "Expected at least one assertion, but none were run - call " + - "expect(0) to accept zero assertions.", this.stack ); - } - - var i, - bad = 0; - - this.runtime = now() - this.started; - config.stats.all += this.assertions.length; - config.moduleStats.all += this.assertions.length; - - for ( i = 0; i < this.assertions.length; i++ ) { - if ( !this.assertions[ i ].result ) { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - - runLoggingCallbacks( "testDone", { - name: this.testName, - module: this.module.name, - skipped: !!this.skip, - failed: bad, - passed: this.assertions.length - bad, - total: this.assertions.length, - runtime: this.runtime, - - // HTML Reporter use - assertions: this.assertions, - testId: this.testId, - - // Source of Test - source: this.stack, - - // DEPRECATED: this property will be removed in 2.0.0, use runtime instead - duration: this.runtime - }); - - // QUnit.reset() is deprecated and will be replaced for a new - // fixture reset function on QUnit 2.0/2.1. - // It's still called here for backwards compatibility handling - QUnit.reset(); - - config.current = undefined; - }, - - queue: function() { - var priority, - test = this; - - if ( !this.valid() ) { - return; - } - - function run() { - - // each of these can by async - synchronize([ - function() { - test.before(); - }, - - test.hooks( "beforeEach" ), - function() { - test.run(); - }, - - test.hooks( "afterEach" ).reverse(), - - function() { - test.after(); - }, - function() { - test.finish(); - } - ]); - } - - // Prioritize previously failed tests, detected from sessionStorage - priority = QUnit.config.reorder && defined.sessionStorage && - +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName ); - - return synchronize( run, priority ); - }, - - push: function( result, actual, expected, message, negative ) { - var source, - details = { - module: this.module.name, - name: this.testName, - result: result, - message: message, - actual: actual, - expected: expected, - testId: this.testId, - negative: negative || false, - runtime: now() - this.started - }; - - if ( !result ) { - source = sourceFromStacktrace(); - - if ( source ) { - details.source = source; - } - } - - runLoggingCallbacks( "log", details ); - - this.assertions.push({ - result: !!result, - message: message - }); - }, - - pushFailure: function( message, source, actual ) { - if ( !( this instanceof Test ) ) { - throw new Error( "pushFailure() assertion outside test context, was " + - sourceFromStacktrace( 2 ) ); - } - - var details = { - module: this.module.name, - name: this.testName, - result: false, - message: message || "error", - actual: actual || null, - testId: this.testId, - runtime: now() - this.started - }; - - if ( source ) { - details.source = source; - } - - runLoggingCallbacks( "log", details ); - - this.assertions.push({ - result: false, - message: message - }); - }, - - resolvePromise: function( promise, phase ) { - var then, message, - test = this; - if ( promise != null ) { - then = promise.then; - if ( QUnit.objectType( then ) === "function" ) { - QUnit.stop(); - then.call( - promise, - function() { QUnit.start(); }, - function( error ) { - message = "Promise rejected " + - ( !phase ? "during" : phase.replace( /Each$/, "" ) ) + - " " + test.testName + ": " + ( error.message || error ); - test.pushFailure( message, extractStacktrace( error, 0 ) ); - - // else next test will carry the responsibility - saveGlobal(); - - // Unblock - QUnit.start(); - } - ); - } - } - }, - - valid: function() { - var filter = config.filter, - regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec( filter ), - module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(), - fullName = ( this.module.name + ": " + this.testName ); - - function testInModuleChain( testModule ) { - var testModuleName = testModule.name ? testModule.name.toLowerCase() : null; - if ( testModuleName === module ) { - return true; - } else if ( testModule.parentModule ) { - return testInModuleChain( testModule.parentModule ); - } else { - return false; - } - } - - // Internally-generated tests are always valid - if ( this.callback && this.callback.validTest ) { - return true; - } - - if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) { - return false; - } - - if ( module && !testInModuleChain( this.module ) ) { - return false; - } - - if ( !filter ) { - return true; - } - - return regexFilter ? - this.regexFilter( !!regexFilter[1], regexFilter[2], regexFilter[3], fullName ) : - this.stringFilter( filter, fullName ); - }, - - regexFilter: function( exclude, pattern, flags, fullName ) { - var regex = new RegExp( pattern, flags ); - var match = regex.test( fullName ); - - return match !== exclude; - }, - - stringFilter: function( filter, fullName ) { - filter = filter.toLowerCase(); - fullName = fullName.toLowerCase(); - - var include = filter.charAt( 0 ) !== "!"; - if ( !include ) { - filter = filter.slice( 1 ); - } - - // If the filter matches, we need to honour include - if ( fullName.indexOf( filter ) !== -1 ) { - return include; - } - - // Otherwise, do the opposite - return !include; - } -}; - -// Resets the test setup. Useful for tests that modify the DOM. -/* -DEPRECATED: Use multiple tests instead of resetting inside a test. -Use testStart or testDone for custom cleanup. -This method will throw an error in 2.0, and will be removed in 2.1 -*/ -QUnit.reset = function() { - - // Return on non-browser environments - // This is necessary to not break on node tests - if ( !defined.document ) { - return; - } - - var fixture = defined.document && document.getElementById && - document.getElementById( "qunit-fixture" ); - - if ( fixture ) { - fixture.innerHTML = config.fixture; - } -}; - -QUnit.pushFailure = function() { - if ( !QUnit.config.current ) { - throw new Error( "pushFailure() assertion outside test context, in " + - sourceFromStacktrace( 2 ) ); - } - - // Gets current test obj - var currentTest = QUnit.config.current; - - return currentTest.pushFailure.apply( currentTest, arguments ); -}; - -// Based on Java's String.hashCode, a simple but not -// rigorously collision resistant hashing function -function generateHash( module, testName ) { - var hex, - i = 0, - hash = 0, - str = module + "\x1C" + testName, - len = str.length; - - for ( ; i < len; i++ ) { - hash = ( ( hash << 5 ) - hash ) + str.charCodeAt( i ); - hash |= 0; - } - - // Convert the possibly negative integer hash code into an 8 character hex string, which isn't - // strictly necessary but increases user understanding that the id is a SHA-like hash - hex = ( 0x100000000 + hash ).toString( 16 ); - if ( hex.length < 8 ) { - hex = "0000000" + hex; - } - - return hex.slice( -8 ); -} - -function synchronize( callback, priority ) { - var last = !priority; - - if ( QUnit.objectType( callback ) === "array" ) { - while ( callback.length ) { - synchronize( callback.shift() ); - } - return; - } - - if ( priority ) { - config.queue.splice( priorityCount++, 0, callback ); - } else { - config.queue.push( callback ); - } - - if ( config.autorun && !config.blocking ) { - process( last ); - } -} - -function saveGlobal() { - config.pollution = []; - - if ( config.noglobals ) { - for ( var key in global ) { - if ( hasOwn.call( global, key ) ) { - - // in Opera sometimes DOM element ids show up here, ignore them - if ( /^qunit-test-output/.test( key ) ) { - continue; - } - config.pollution.push( key ); - } - } - } -} - -function checkPollution() { - var newGlobals, - deletedGlobals, - old = config.pollution; - - saveGlobal(); - - newGlobals = diff( config.pollution, old ); - if ( newGlobals.length > 0 ) { - QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) ); - } - - deletedGlobals = diff( old, config.pollution ); - if ( deletedGlobals.length > 0 ) { - QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) ); - } -} - -// Will be exposed as QUnit.asyncTest -function asyncTest( testName, expected, callback ) { - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - QUnit.test( testName, expected, callback, true ); -} - -// Will be exposed as QUnit.test -function test( testName, expected, callback, async ) { - if ( focused ) { return; } - - var newTest; - - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - newTest = new Test({ - testName: testName, - expected: expected, - async: async, - callback: callback - }); - - newTest.queue(); -} - -// Will be exposed as QUnit.skip -function skip( testName ) { - if ( focused ) { return; } - - var test = new Test({ - testName: testName, - skip: true - }); - - test.queue(); -} - -// Will be exposed as QUnit.only -function only( testName, expected, callback, async ) { - var newTest; - - if ( focused ) { return; } - - QUnit.config.queue.length = 0; - focused = true; - - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - newTest = new Test({ - testName: testName, - expected: expected, - async: async, - callback: callback - }); - - newTest.queue(); -} - -function Assert( testContext ) { - this.test = testContext; -} - -// Assert helpers -QUnit.assert = Assert.prototype = { - - // Specify the number of expected assertions to guarantee that failed test - // (no assertions are run at all) don't slip through. - expect: function( asserts ) { - if ( arguments.length === 1 ) { - this.test.expected = asserts; - } else { - return this.test.expected; - } - }, - - // Increment this Test's semaphore counter, then return a function that - // decrements that counter a maximum of once. - async: function( count ) { - var test = this.test, - popped = false, - acceptCallCount = count; - - if ( typeof acceptCallCount === "undefined" ) { - acceptCallCount = 1; - } - - test.semaphore += 1; - test.usedAsync = true; - pauseProcessing(); - - return function done() { - - if ( popped ) { - test.pushFailure( "Too many calls to the `assert.async` callback", - sourceFromStacktrace( 2 ) ); - return; - } - acceptCallCount -= 1; - if ( acceptCallCount > 0 ) { - return; - } - - test.semaphore -= 1; - popped = true; - resumeProcessing(); - }; - }, - - // Exports test.push() to the user API - push: function( /* result, actual, expected, message, negative */ ) { - var assert = this, - currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current; - - // Backwards compatibility fix. - // Allows the direct use of global exported assertions and QUnit.assert.* - // Although, it's use is not recommended as it can leak assertions - // to other tests from async tests, because we only get a reference to the current test, - // not exactly the test where assertion were intended to be called. - if ( !currentTest ) { - throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) ); - } - - if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) { - currentTest.pushFailure( "Assertion after the final `assert.async` was resolved", - sourceFromStacktrace( 2 ) ); - - // Allow this assertion to continue running anyway... - } - - if ( !( assert instanceof Assert ) ) { - assert = currentTest.assert; - } - return assert.test.push.apply( assert.test, arguments ); - }, - - ok: function( result, message ) { - message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " + - QUnit.dump.parse( result ) ); - this.push( !!result, result, true, message ); - }, - - notOk: function( result, message ) { - message = message || ( !result ? "okay" : "failed, expected argument to be falsy, was: " + - QUnit.dump.parse( result ) ); - this.push( !result, result, false, message ); - }, - - equal: function( actual, expected, message ) { - /*jshint eqeqeq:false */ - this.push( expected == actual, actual, expected, message ); - }, - - notEqual: function( actual, expected, message ) { - /*jshint eqeqeq:false */ - this.push( expected != actual, actual, expected, message, true ); - }, - - propEqual: function( actual, expected, message ) { - actual = objectValues( actual ); - expected = objectValues( expected ); - this.push( QUnit.equiv( actual, expected ), actual, expected, message ); - }, - - notPropEqual: function( actual, expected, message ) { - actual = objectValues( actual ); - expected = objectValues( expected ); - this.push( !QUnit.equiv( actual, expected ), actual, expected, message, true ); - }, - - deepEqual: function( actual, expected, message ) { - this.push( QUnit.equiv( actual, expected ), actual, expected, message ); - }, - - notDeepEqual: function( actual, expected, message ) { - this.push( !QUnit.equiv( actual, expected ), actual, expected, message, true ); - }, - - strictEqual: function( actual, expected, message ) { - this.push( expected === actual, actual, expected, message ); - }, - - notStrictEqual: function( actual, expected, message ) { - this.push( expected !== actual, actual, expected, message, true ); - }, - - "throws": function( block, expected, message ) { - var actual, expectedType, - expectedOutput = expected, - ok = false, - currentTest = ( this instanceof Assert && this.test ) || QUnit.config.current; - - // 'expected' is optional unless doing string comparison - if ( message == null && typeof expected === "string" ) { - message = expected; - expected = null; - } - - currentTest.ignoreGlobalErrors = true; - try { - block.call( currentTest.testEnvironment ); - } catch (e) { - actual = e; - } - currentTest.ignoreGlobalErrors = false; - - if ( actual ) { - expectedType = QUnit.objectType( expected ); - - // we don't want to validate thrown error - if ( !expected ) { - ok = true; - expectedOutput = null; - - // expected is a regexp - } else if ( expectedType === "regexp" ) { - ok = expected.test( errorString( actual ) ); - - // expected is a string - } else if ( expectedType === "string" ) { - ok = expected === errorString( actual ); - - // expected is a constructor, maybe an Error constructor - } else if ( expectedType === "function" && actual instanceof expected ) { - ok = true; - - // expected is an Error object - } else if ( expectedType === "object" ) { - ok = actual instanceof expected.constructor && - actual.name === expected.name && - actual.message === expected.message; - - // expected is a validation function which returns true if validation passed - } else if ( expectedType === "function" && expected.call( {}, actual ) === true ) { - expectedOutput = null; - ok = true; - } - } - - currentTest.assert.push( ok, actual, expectedOutput, message ); - } -}; - -// Provide an alternative to assert.throws(), for environments that consider throws a reserved word -// Known to us are: Closure Compiler, Narwhal -(function() { - /*jshint sub:true */ - Assert.prototype.raises = Assert.prototype[ "throws" ]; -}()); - -function errorString( error ) { - var name, message, - resultErrorString = error.toString(); - if ( resultErrorString.substring( 0, 7 ) === "[object" ) { - name = error.name ? error.name.toString() : "Error"; - message = error.message ? error.message.toString() : ""; - if ( name && message ) { - return name + ": " + message; - } else if ( name ) { - return name; - } else if ( message ) { - return message; - } else { - return "Error"; - } - } else { - return resultErrorString; - } -} - -// Test for equality any JavaScript type. -// Author: Philippe Rathé -QUnit.equiv = (function() { - - // Stack to decide between skip/abort functions - var callers = []; - - // Stack to avoiding loops from circular referencing - var parents = []; - var parentsB = []; - - var getProto = Object.getPrototypeOf || function( obj ) { - - /*jshint proto: true */ - return obj.__proto__; - }; - - function useStrictEquality( b, a ) { - - // To catch short annotation VS 'new' annotation of a declaration. e.g.: - // `var i = 1;` - // `var j = new Number(1);` - if ( typeof a === "object" ) { - a = a.valueOf(); - } - if ( typeof b === "object" ) { - b = b.valueOf(); - } - - return a === b; - } - - function compareConstructors( a, b ) { - var protoA = getProto( a ); - var protoB = getProto( b ); - - // Comparing constructors is more strict than using `instanceof` - if ( a.constructor === b.constructor ) { - return true; - } - - // Ref #851 - // If the obj prototype descends from a null constructor, treat it - // as a null prototype. - if ( protoA && protoA.constructor === null ) { - protoA = null; - } - if ( protoB && protoB.constructor === null ) { - protoB = null; - } - - // Allow objects with no prototype to be equivalent to - // objects with Object as their constructor. - if ( ( protoA === null && protoB === Object.prototype ) || - ( protoB === null && protoA === Object.prototype ) ) { - return true; - } - - return false; - } - - function getRegExpFlags( regexp ) { - return "flags" in regexp ? regexp.flags : regexp.toString().match( /[gimuy]*$/ )[ 0 ]; - } - - var callbacks = { - "string": useStrictEquality, - "boolean": useStrictEquality, - "number": useStrictEquality, - "null": useStrictEquality, - "undefined": useStrictEquality, - "symbol": useStrictEquality, - "date": useStrictEquality, - - "nan": function() { - return true; - }, - - "regexp": function( b, a ) { - return a.source === b.source && - - // Include flags in the comparison - getRegExpFlags( a ) === getRegExpFlags( b ); - }, - - // - skip when the property is a method of an instance (OOP) - // - abort otherwise, - // initial === would have catch identical references anyway - "function": function() { - var caller = callers[ callers.length - 1 ]; - return caller !== Object && typeof caller !== "undefined"; - }, - - "array": function( b, a ) { - var i, j, len, loop, aCircular, bCircular; - - len = a.length; - if ( len !== b.length ) { - // safe and faster - return false; - } - - // Track reference to avoid circular references - parents.push( a ); - parentsB.push( b ); - for ( i = 0; i < len; i++ ) { - loop = false; - for ( j = 0; j < parents.length; j++ ) { - aCircular = parents[ j ] === a[ i ]; - bCircular = parentsB[ j ] === b[ i ]; - if ( aCircular || bCircular ) { - if ( a[ i ] === b[ i ] || aCircular && bCircular ) { - loop = true; - } else { - parents.pop(); - parentsB.pop(); - return false; - } - } - } - if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) { - parents.pop(); - parentsB.pop(); - return false; - } - } - parents.pop(); - parentsB.pop(); - return true; - }, - - "set": function( b, a ) { - var aArray, bArray; - - aArray = []; - a.forEach( function( v ) { - aArray.push( v ); - }); - bArray = []; - b.forEach( function( v ) { - bArray.push( v ); - }); - - return innerEquiv( bArray, aArray ); - }, - - "map": function( b, a ) { - var aArray, bArray; - - aArray = []; - a.forEach( function( v, k ) { - aArray.push( [ k, v ] ); - }); - bArray = []; - b.forEach( function( v, k ) { - bArray.push( [ k, v ] ); - }); - - return innerEquiv( bArray, aArray ); - }, - - "object": function( b, a ) { - var i, j, loop, aCircular, bCircular; - - // Default to true - var eq = true; - var aProperties = []; - var bProperties = []; - - if ( compareConstructors( a, b ) === false ) { - return false; - } - - // Stack constructor before traversing properties - callers.push( a.constructor ); - - // Track reference to avoid circular references - parents.push( a ); - parentsB.push( b ); - - // Be strict: don't ensure hasOwnProperty and go deep - for ( i in a ) { - loop = false; - for ( j = 0; j < parents.length; j++ ) { - aCircular = parents[ j ] === a[ i ]; - bCircular = parentsB[ j ] === b[ i ]; - if ( aCircular || bCircular ) { - if ( a[ i ] === b[ i ] || aCircular && bCircular ) { - loop = true; - } else { - eq = false; - break; - } - } - } - aProperties.push( i ); - if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) { - eq = false; - break; - } - } - - parents.pop(); - parentsB.pop(); - - // Unstack, we are done - callers.pop(); - - for ( i in b ) { - - // Collect b's properties - bProperties.push( i ); - } - - // Ensures identical properties name - return eq && innerEquiv( aProperties.sort(), bProperties.sort() ); - } - }; - - function typeEquiv( a, b ) { - var type = QUnit.objectType( a ); - return QUnit.objectType( b ) === type && callbacks[ type ]( b, a ); - } - - // The real equiv function - function innerEquiv( a, b ) { - - // We're done when there's nothing more to compare - if ( arguments.length < 2 ) { - return true; - } - - // Require type-specific equality - return ( a === b || typeEquiv( a, b ) ) && - - // ...across all consecutive argument pairs - ( arguments.length === 2 || innerEquiv.apply( this, [].slice.call( arguments, 1 ) ) ); - } - - return innerEquiv; -}()); - -// Based on jsDump by Ariel Flesler -// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html -QUnit.dump = (function() { - function quote( str ) { - return "\"" + str.toString().replace( /\\/g, "\\\\" ).replace( /"/g, "\\\"" ) + "\""; - } - function literal( o ) { - return o + ""; - } - function join( pre, arr, post ) { - var s = dump.separator(), - base = dump.indent(), - inner = dump.indent( 1 ); - if ( arr.join ) { - arr = arr.join( "," + s + inner ); - } - if ( !arr ) { - return pre + post; - } - return [ pre, inner + arr, base + post ].join( s ); - } - function array( arr, stack ) { - var i = arr.length, - ret = new Array( i ); - - if ( dump.maxDepth && dump.depth > dump.maxDepth ) { - return "[object Array]"; - } - - this.up(); - while ( i-- ) { - ret[ i ] = this.parse( arr[ i ], undefined, stack ); - } - this.down(); - return join( "[", ret, "]" ); - } - - var reName = /^function (\w+)/, - dump = { - - // objType is used mostly internally, you can fix a (custom) type in advance - parse: function( obj, objType, stack ) { - stack = stack || []; - var res, parser, parserType, - inStack = inArray( obj, stack ); - - if ( inStack !== -1 ) { - return "recursion(" + ( inStack - stack.length ) + ")"; - } - - objType = objType || this.typeOf( obj ); - parser = this.parsers[ objType ]; - parserType = typeof parser; - - if ( parserType === "function" ) { - stack.push( obj ); - res = parser.call( this, obj, stack ); - stack.pop(); - return res; - } - return ( parserType === "string" ) ? parser : this.parsers.error; - }, - typeOf: function( obj ) { - var type; - if ( obj === null ) { - type = "null"; - } else if ( typeof obj === "undefined" ) { - type = "undefined"; - } else if ( QUnit.is( "regexp", obj ) ) { - type = "regexp"; - } else if ( QUnit.is( "date", obj ) ) { - type = "date"; - } else if ( QUnit.is( "function", obj ) ) { - type = "function"; - } else if ( obj.setInterval !== undefined && - obj.document !== undefined && - obj.nodeType === undefined ) { - type = "window"; - } else if ( obj.nodeType === 9 ) { - type = "document"; - } else if ( obj.nodeType ) { - type = "node"; - } else if ( - - // native arrays - toString.call( obj ) === "[object Array]" || - - // NodeList objects - ( typeof obj.length === "number" && obj.item !== undefined && - ( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null && - obj[ 0 ] === undefined ) ) ) - ) { - type = "array"; - } else if ( obj.constructor === Error.prototype.constructor ) { - type = "error"; - } else { - type = typeof obj; - } - return type; - }, - separator: function() { - return this.multiline ? this.HTML ? "
" : "\n" : this.HTML ? " " : " "; - }, - // extra can be a number, shortcut for increasing-calling-decreasing - indent: function( extra ) { - if ( !this.multiline ) { - return ""; - } - var chr = this.indentChar; - if ( this.HTML ) { - chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); - } - return new Array( this.depth + ( extra || 0 ) ).join( chr ); - }, - up: function( a ) { - this.depth += a || 1; - }, - down: function( a ) { - this.depth -= a || 1; - }, - setParser: function( name, parser ) { - this.parsers[ name ] = parser; - }, - // The next 3 are exposed so you can use them - quote: quote, - literal: literal, - join: join, - // - depth: 1, - maxDepth: QUnit.config.maxDepth, - - // This is the list of parsers, to modify them, use dump.setParser - parsers: { - window: "[Window]", - document: "[Document]", - error: function( error ) { - return "Error(\"" + error.message + "\")"; - }, - unknown: "[Unknown]", - "null": "null", - "undefined": "undefined", - "function": function( fn ) { - var ret = "function", - - // functions never have name in IE - name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ]; - - if ( name ) { - ret += " " + name; - } - ret += "( "; - - ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" ); - return join( ret, dump.parse( fn, "functionCode" ), "}" ); - }, - array: array, - nodelist: array, - "arguments": array, - object: function( map, stack ) { - var keys, key, val, i, nonEnumerableProperties, - ret = []; - - if ( dump.maxDepth && dump.depth > dump.maxDepth ) { - return "[object Object]"; - } - - dump.up(); - keys = []; - for ( key in map ) { - keys.push( key ); - } - - // Some properties are not always enumerable on Error objects. - nonEnumerableProperties = [ "message", "name" ]; - for ( i in nonEnumerableProperties ) { - key = nonEnumerableProperties[ i ]; - if ( key in map && inArray( key, keys ) < 0 ) { - keys.push( key ); - } - } - keys.sort(); - for ( i = 0; i < keys.length; i++ ) { - key = keys[ i ]; - val = map[ key ]; - ret.push( dump.parse( key, "key" ) + ": " + - dump.parse( val, undefined, stack ) ); - } - dump.down(); - return join( "{", ret, "}" ); - }, - node: function( node ) { - var len, i, val, - open = dump.HTML ? "<" : "<", - close = dump.HTML ? ">" : ">", - tag = node.nodeName.toLowerCase(), - ret = open + tag, - attrs = node.attributes; - - if ( attrs ) { - for ( i = 0, len = attrs.length; i < len; i++ ) { - val = attrs[ i ].nodeValue; - - // IE6 includes all attributes in .attributes, even ones not explicitly - // set. Those have values like undefined, null, 0, false, "" or - // "inherit". - if ( val && val !== "inherit" ) { - ret += " " + attrs[ i ].nodeName + "=" + - dump.parse( val, "attribute" ); - } - } - } - ret += close; - - // Show content of TextNode or CDATASection - if ( node.nodeType === 3 || node.nodeType === 4 ) { - ret += node.nodeValue; - } - - return ret + open + "/" + tag + close; - }, - - // function calls it internally, it's the arguments part of the function - functionArgs: function( fn ) { - var args, - l = fn.length; - - if ( !l ) { - return ""; - } - - args = new Array( l ); - while ( l-- ) { - - // 97 is 'a' - args[ l ] = String.fromCharCode( 97 + l ); - } - return " " + args.join( ", " ) + " "; - }, - // object calls it internally, the key part of an item in a map - key: quote, - // function calls it internally, it's the content of the function - functionCode: "[code]", - // node calls it internally, it's a html attribute value - attribute: quote, - string: quote, - date: quote, - regexp: literal, - number: literal, - "boolean": literal - }, - // if true, entities are escaped ( <, >, \t, space and \n ) - HTML: false, - // indentation unit - indentChar: " ", - // if true, items in a collection, are separated by a \n, else just a space. - multiline: true - }; - - return dump; -}()); - -// back compat -QUnit.jsDump = QUnit.dump; - -// For browser, export only select globals -if ( defined.document ) { - - // Deprecated - // Extend assert methods to QUnit and Global scope through Backwards compatibility - (function() { - var i, - assertions = Assert.prototype; - - function applyCurrent( current ) { - return function() { - var assert = new Assert( QUnit.config.current ); - current.apply( assert, arguments ); - }; - } - - for ( i in assertions ) { - QUnit[ i ] = applyCurrent( assertions[ i ] ); - } - })(); - - (function() { - var i, l, - keys = [ - "test", - "module", - "expect", - "asyncTest", - "start", - "stop", - "ok", - "notOk", - "equal", - "notEqual", - "propEqual", - "notPropEqual", - "deepEqual", - "notDeepEqual", - "strictEqual", - "notStrictEqual", - "throws", - "raises" - ]; - - for ( i = 0, l = keys.length; i < l; i++ ) { - window[ keys[ i ] ] = QUnit[ keys[ i ] ]; - } - })(); - - window.QUnit = QUnit; -} - -// For nodejs -if ( typeof module !== "undefined" && module && module.exports ) { - module.exports = QUnit; - - // For consistency with CommonJS environments' exports - module.exports.QUnit = QUnit; -} - -// For CommonJS with exports, but without module.exports, like Rhino -if ( typeof exports !== "undefined" && exports ) { - exports.QUnit = QUnit; -} - -if ( typeof define === "function" && define.amd ) { - define( function() { - return QUnit; - } ); - QUnit.config.autostart = false; -} - -/* - * This file is a modified version of google-diff-match-patch's JavaScript implementation - * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js), - * modifications are licensed as more fully set forth in LICENSE.txt. - * - * The original source of google-diff-match-patch is attributable and licensed as follows: - * - * Copyright 2006 Google Inc. - * https://code.google.com/p/google-diff-match-patch/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * More Info: - * https://code.google.com/p/google-diff-match-patch/ - * - * Usage: QUnit.diff(expected, actual) - * - */ -QUnit.diff = ( function() { - function DiffMatchPatch() { - } - - // DIFF FUNCTIONS - - /** - * The data structure representing a diff is an array of tuples: - * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] - * which means: delete 'Hello', add 'Goodbye' and keep ' world.' - */ - var DIFF_DELETE = -1, - DIFF_INSERT = 1, - DIFF_EQUAL = 0; - - /** - * Find the differences between two texts. Simplifies the problem by stripping - * any common prefix or suffix off the texts before diffing. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {boolean=} optChecklines Optional speedup flag. If present and false, - * then don't run a line-level diff first to identify the changed areas. - * Defaults to true, which does a faster, slightly less optimal diff. - * @return {!Array.} Array of diff tuples. - */ - DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines ) { - var deadline, checklines, commonlength, - commonprefix, commonsuffix, diffs; - - // The diff must be complete in up to 1 second. - deadline = ( new Date() ).getTime() + 1000; - - // Check for null inputs. - if ( text1 === null || text2 === null ) { - throw new Error( "Null input. (DiffMain)" ); - } - - // Check for equality (speedup). - if ( text1 === text2 ) { - if ( text1 ) { - return [ - [ DIFF_EQUAL, text1 ] - ]; - } - return []; - } - - if ( typeof optChecklines === "undefined" ) { - optChecklines = true; - } - - checklines = optChecklines; - - // Trim off common prefix (speedup). - commonlength = this.diffCommonPrefix( text1, text2 ); - commonprefix = text1.substring( 0, commonlength ); - text1 = text1.substring( commonlength ); - text2 = text2.substring( commonlength ); - - // Trim off common suffix (speedup). - commonlength = this.diffCommonSuffix( text1, text2 ); - commonsuffix = text1.substring( text1.length - commonlength ); - text1 = text1.substring( 0, text1.length - commonlength ); - text2 = text2.substring( 0, text2.length - commonlength ); - - // Compute the diff on the middle block. - diffs = this.diffCompute( text1, text2, checklines, deadline ); - - // Restore the prefix and suffix. - if ( commonprefix ) { - diffs.unshift( [ DIFF_EQUAL, commonprefix ] ); - } - if ( commonsuffix ) { - diffs.push( [ DIFF_EQUAL, commonsuffix ] ); - } - this.diffCleanupMerge( diffs ); - return diffs; - }; - - /** - * Reduce the number of edits by eliminating operationally trivial equalities. - * @param {!Array.} diffs Array of diff tuples. - */ - DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) { - var changes, equalities, equalitiesLength, lastequality, - pointer, preIns, preDel, postIns, postDel; - changes = false; - equalities = []; // Stack of indices where equalities are found. - equalitiesLength = 0; // Keeping our own length var is faster in JS. - /** @type {?string} */ - lastequality = null; - // Always equal to diffs[equalities[equalitiesLength - 1]][1] - pointer = 0; // Index of current position. - // Is there an insertion operation before the last equality. - preIns = false; - // Is there a deletion operation before the last equality. - preDel = false; - // Is there an insertion operation after the last equality. - postIns = false; - // Is there a deletion operation after the last equality. - postDel = false; - while ( pointer < diffs.length ) { - - // Equality found. - if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { - if ( diffs[ pointer ][ 1 ].length < 4 && ( postIns || postDel ) ) { - - // Candidate found. - equalities[ equalitiesLength++ ] = pointer; - preIns = postIns; - preDel = postDel; - lastequality = diffs[ pointer ][ 1 ]; - } else { - - // Not a candidate, and can never become one. - equalitiesLength = 0; - lastequality = null; - } - postIns = postDel = false; - - // An insertion or deletion. - } else { - - if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) { - postDel = true; - } else { - postIns = true; - } - - /* - * Five types to be split: - * ABXYCD - * AXCD - * ABXC - * AXCD - * ABXC - */ - if ( lastequality && ( ( preIns && preDel && postIns && postDel ) || - ( ( lastequality.length < 2 ) && - ( preIns + preDel + postIns + postDel ) === 3 ) ) ) { - - // Duplicate record. - diffs.splice( - equalities[ equalitiesLength - 1 ], - 0, - [ DIFF_DELETE, lastequality ] - ); - - // Change second copy to insert. - diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT; - equalitiesLength--; // Throw away the equality we just deleted; - lastequality = null; - if ( preIns && preDel ) { - // No changes made which could affect previous entry, keep going. - postIns = postDel = true; - equalitiesLength = 0; - } else { - equalitiesLength--; // Throw away the previous equality. - pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1; - postIns = postDel = false; - } - changes = true; - } - } - pointer++; - } - - if ( changes ) { - this.diffCleanupMerge( diffs ); - } - }; - - /** - * Convert a diff array into a pretty HTML report. - * @param {!Array.} diffs Array of diff tuples. - * @param {integer} string to be beautified. - * @return {string} HTML representation. - */ - DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) { - var op, data, x, - html = []; - for ( x = 0; x < diffs.length; x++ ) { - op = diffs[ x ][ 0 ]; // Operation (insert, delete, equal) - data = diffs[ x ][ 1 ]; // Text of change. - switch ( op ) { - case DIFF_INSERT: - html[ x ] = "" + data + ""; - break; - case DIFF_DELETE: - html[ x ] = "" + data + ""; - break; - case DIFF_EQUAL: - html[ x ] = "" + data + ""; - break; - } - } - return html.join( "" ); - }; - - /** - * Determine the common prefix of two strings. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the start of each - * string. - */ - DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) { - var pointermid, pointermax, pointermin, pointerstart; - // Quick check for common null cases. - if ( !text1 || !text2 || text1.charAt( 0 ) !== text2.charAt( 0 ) ) { - return 0; - } - // Binary search. - // Performance analysis: https://neil.fraser.name/news/2007/10/09/ - pointermin = 0; - pointermax = Math.min( text1.length, text2.length ); - pointermid = pointermax; - pointerstart = 0; - while ( pointermin < pointermid ) { - if ( text1.substring( pointerstart, pointermid ) === - text2.substring( pointerstart, pointermid ) ) { - pointermin = pointermid; - pointerstart = pointermin; - } else { - pointermax = pointermid; - } - pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin ); - } - return pointermid; - }; - - /** - * Determine the common suffix of two strings. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the end of each string. - */ - DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) { - var pointermid, pointermax, pointermin, pointerend; - // Quick check for common null cases. - if ( !text1 || - !text2 || - text1.charAt( text1.length - 1 ) !== text2.charAt( text2.length - 1 ) ) { - return 0; - } - // Binary search. - // Performance analysis: https://neil.fraser.name/news/2007/10/09/ - pointermin = 0; - pointermax = Math.min( text1.length, text2.length ); - pointermid = pointermax; - pointerend = 0; - while ( pointermin < pointermid ) { - if ( text1.substring( text1.length - pointermid, text1.length - pointerend ) === - text2.substring( text2.length - pointermid, text2.length - pointerend ) ) { - pointermin = pointermid; - pointerend = pointermin; - } else { - pointermax = pointermid; - } - pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin ); - } - return pointermid; - }; - - /** - * Find the differences between two texts. Assumes that the texts do not - * have any common prefix or suffix. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {boolean} checklines Speedup flag. If false, then don't run a - * line-level diff first to identify the changed areas. - * If true, then run a faster, slightly less optimal diff. - * @param {number} deadline Time when the diff should be complete by. - * @return {!Array.} Array of diff tuples. - * @private - */ - DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) { - var diffs, longtext, shorttext, i, hm, - text1A, text2A, text1B, text2B, - midCommon, diffsA, diffsB; - - if ( !text1 ) { - // Just add some text (speedup). - return [ - [ DIFF_INSERT, text2 ] - ]; - } - - if ( !text2 ) { - // Just delete some text (speedup). - return [ - [ DIFF_DELETE, text1 ] - ]; - } - - longtext = text1.length > text2.length ? text1 : text2; - shorttext = text1.length > text2.length ? text2 : text1; - i = longtext.indexOf( shorttext ); - if ( i !== -1 ) { - // Shorter text is inside the longer text (speedup). - diffs = [ - [ DIFF_INSERT, longtext.substring( 0, i ) ], - [ DIFF_EQUAL, shorttext ], - [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ] - ]; - // Swap insertions for deletions if diff is reversed. - if ( text1.length > text2.length ) { - diffs[ 0 ][ 0 ] = diffs[ 2 ][ 0 ] = DIFF_DELETE; - } - return diffs; - } - - if ( shorttext.length === 1 ) { - // Single character string. - // After the previous speedup, the character can't be an equality. - return [ - [ DIFF_DELETE, text1 ], - [ DIFF_INSERT, text2 ] - ]; - } - - // Check to see if the problem can be split in two. - hm = this.diffHalfMatch( text1, text2 ); - if ( hm ) { - // A half-match was found, sort out the return data. - text1A = hm[ 0 ]; - text1B = hm[ 1 ]; - text2A = hm[ 2 ]; - text2B = hm[ 3 ]; - midCommon = hm[ 4 ]; - // Send both pairs off for separate processing. - diffsA = this.DiffMain( text1A, text2A, checklines, deadline ); - diffsB = this.DiffMain( text1B, text2B, checklines, deadline ); - // Merge the results. - return diffsA.concat( [ - [ DIFF_EQUAL, midCommon ] - ], diffsB ); - } - - if ( checklines && text1.length > 100 && text2.length > 100 ) { - return this.diffLineMode( text1, text2, deadline ); - } - - return this.diffBisect( text1, text2, deadline ); - }; - - /** - * Do the two texts share a substring which is at least half the length of the - * longer text? - * This speedup can produce non-minimal diffs. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {Array.} Five element Array, containing the prefix of - * text1, the suffix of text1, the prefix of text2, the suffix of - * text2 and the common middle. Or null if there was no match. - * @private - */ - DiffMatchPatch.prototype.diffHalfMatch = function( text1, text2 ) { - var longtext, shorttext, dmp, - text1A, text2B, text2A, text1B, midCommon, - hm1, hm2, hm; - - longtext = text1.length > text2.length ? text1 : text2; - shorttext = text1.length > text2.length ? text2 : text1; - if ( longtext.length < 4 || shorttext.length * 2 < longtext.length ) { - return null; // Pointless. - } - dmp = this; // 'this' becomes 'window' in a closure. - - /** - * Does a substring of shorttext exist within longtext such that the substring - * is at least half the length of longtext? - * Closure, but does not reference any external variables. - * @param {string} longtext Longer string. - * @param {string} shorttext Shorter string. - * @param {number} i Start index of quarter length substring within longtext. - * @return {Array.} Five element Array, containing the prefix of - * longtext, the suffix of longtext, the prefix of shorttext, the suffix - * of shorttext and the common middle. Or null if there was no match. - * @private - */ - function diffHalfMatchI( longtext, shorttext, i ) { - var seed, j, bestCommon, prefixLength, suffixLength, - bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB; - // Start with a 1/4 length substring at position i as a seed. - seed = longtext.substring( i, i + Math.floor( longtext.length / 4 ) ); - j = -1; - bestCommon = ""; - while ( ( j = shorttext.indexOf( seed, j + 1 ) ) !== -1 ) { - prefixLength = dmp.diffCommonPrefix( longtext.substring( i ), - shorttext.substring( j ) ); - suffixLength = dmp.diffCommonSuffix( longtext.substring( 0, i ), - shorttext.substring( 0, j ) ); - if ( bestCommon.length < suffixLength + prefixLength ) { - bestCommon = shorttext.substring( j - suffixLength, j ) + - shorttext.substring( j, j + prefixLength ); - bestLongtextA = longtext.substring( 0, i - suffixLength ); - bestLongtextB = longtext.substring( i + prefixLength ); - bestShorttextA = shorttext.substring( 0, j - suffixLength ); - bestShorttextB = shorttext.substring( j + prefixLength ); - } - } - if ( bestCommon.length * 2 >= longtext.length ) { - return [ bestLongtextA, bestLongtextB, - bestShorttextA, bestShorttextB, bestCommon - ]; - } else { - return null; - } - } - - // First check if the second quarter is the seed for a half-match. - hm1 = diffHalfMatchI( longtext, shorttext, - Math.ceil( longtext.length / 4 ) ); - // Check again based on the third quarter. - hm2 = diffHalfMatchI( longtext, shorttext, - Math.ceil( longtext.length / 2 ) ); - if ( !hm1 && !hm2 ) { - return null; - } else if ( !hm2 ) { - hm = hm1; - } else if ( !hm1 ) { - hm = hm2; - } else { - // Both matched. Select the longest. - hm = hm1[ 4 ].length > hm2[ 4 ].length ? hm1 : hm2; - } - - // A half-match was found, sort out the return data. - text1A, text1B, text2A, text2B; - if ( text1.length > text2.length ) { - text1A = hm[ 0 ]; - text1B = hm[ 1 ]; - text2A = hm[ 2 ]; - text2B = hm[ 3 ]; - } else { - text2A = hm[ 0 ]; - text2B = hm[ 1 ]; - text1A = hm[ 2 ]; - text1B = hm[ 3 ]; - } - midCommon = hm[ 4 ]; - return [ text1A, text1B, text2A, text2B, midCommon ]; - }; - - /** - * Do a quick line-level diff on both strings, then rediff the parts for - * greater accuracy. - * This speedup can produce non-minimal diffs. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {number} deadline Time when the diff should be complete by. - * @return {!Array.} Array of diff tuples. - * @private - */ - DiffMatchPatch.prototype.diffLineMode = function( text1, text2, deadline ) { - var a, diffs, linearray, pointer, countInsert, - countDelete, textInsert, textDelete, j; - // Scan the text on a line-by-line basis first. - a = this.diffLinesToChars( text1, text2 ); - text1 = a.chars1; - text2 = a.chars2; - linearray = a.lineArray; - - diffs = this.DiffMain( text1, text2, false, deadline ); - - // Convert the diff back to original text. - this.diffCharsToLines( diffs, linearray ); - // Eliminate freak matches (e.g. blank lines) - this.diffCleanupSemantic( diffs ); - - // Rediff any replacement blocks, this time character-by-character. - // Add a dummy entry at the end. - diffs.push( [ DIFF_EQUAL, "" ] ); - pointer = 0; - countDelete = 0; - countInsert = 0; - textDelete = ""; - textInsert = ""; - while ( pointer < diffs.length ) { - switch ( diffs[ pointer ][ 0 ] ) { - case DIFF_INSERT: - countInsert++; - textInsert += diffs[ pointer ][ 1 ]; - break; - case DIFF_DELETE: - countDelete++; - textDelete += diffs[ pointer ][ 1 ]; - break; - case DIFF_EQUAL: - // Upon reaching an equality, check for prior redundancies. - if ( countDelete >= 1 && countInsert >= 1 ) { - // Delete the offending records and add the merged ones. - diffs.splice( pointer - countDelete - countInsert, - countDelete + countInsert ); - pointer = pointer - countDelete - countInsert; - a = this.DiffMain( textDelete, textInsert, false, deadline ); - for ( j = a.length - 1; j >= 0; j-- ) { - diffs.splice( pointer, 0, a[ j ] ); - } - pointer = pointer + a.length; - } - countInsert = 0; - countDelete = 0; - textDelete = ""; - textInsert = ""; - break; - } - pointer++; - } - diffs.pop(); // Remove the dummy entry at the end. - - return diffs; - }; - - /** - * Find the 'middle snake' of a diff, split the problem in two - * and return the recursively constructed diff. - * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {number} deadline Time at which to bail if not yet complete. - * @return {!Array.} Array of diff tuples. - * @private - */ - DiffMatchPatch.prototype.diffBisect = function( text1, text2, deadline ) { - var text1Length, text2Length, maxD, vOffset, vLength, - v1, v2, x, delta, front, k1start, k1end, k2start, - k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2; - // Cache the text lengths to prevent multiple calls. - text1Length = text1.length; - text2Length = text2.length; - maxD = Math.ceil( ( text1Length + text2Length ) / 2 ); - vOffset = maxD; - vLength = 2 * maxD; - v1 = new Array( vLength ); - v2 = new Array( vLength ); - // Setting all elements to -1 is faster in Chrome & Firefox than mixing - // integers and undefined. - for ( x = 0; x < vLength; x++ ) { - v1[ x ] = -1; - v2[ x ] = -1; - } - v1[ vOffset + 1 ] = 0; - v2[ vOffset + 1 ] = 0; - delta = text1Length - text2Length; - // If the total number of characters is odd, then the front path will collide - // with the reverse path. - front = ( delta % 2 !== 0 ); - // Offsets for start and end of k loop. - // Prevents mapping of space beyond the grid. - k1start = 0; - k1end = 0; - k2start = 0; - k2end = 0; - for ( d = 0; d < maxD; d++ ) { - // Bail out if deadline is reached. - if ( ( new Date() ).getTime() > deadline ) { - break; - } - - // Walk the front path one step. - for ( k1 = -d + k1start; k1 <= d - k1end; k1 += 2 ) { - k1Offset = vOffset + k1; - if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) { - x1 = v1[ k1Offset + 1 ]; - } else { - x1 = v1[ k1Offset - 1 ] + 1; - } - y1 = x1 - k1; - while ( x1 < text1Length && y1 < text2Length && - text1.charAt( x1 ) === text2.charAt( y1 ) ) { - x1++; - y1++; - } - v1[ k1Offset ] = x1; - if ( x1 > text1Length ) { - // Ran off the right of the graph. - k1end += 2; - } else if ( y1 > text2Length ) { - // Ran off the bottom of the graph. - k1start += 2; - } else if ( front ) { - k2Offset = vOffset + delta - k1; - if ( k2Offset >= 0 && k2Offset < vLength && v2[ k2Offset ] !== -1 ) { - // Mirror x2 onto top-left coordinate system. - x2 = text1Length - v2[ k2Offset ]; - if ( x1 >= x2 ) { - // Overlap detected. - return this.diffBisectSplit( text1, text2, x1, y1, deadline ); - } - } - } - } - - // Walk the reverse path one step. - for ( k2 = -d + k2start; k2 <= d - k2end; k2 += 2 ) { - k2Offset = vOffset + k2; - if ( k2 === -d || ( k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) { - x2 = v2[ k2Offset + 1 ]; - } else { - x2 = v2[ k2Offset - 1 ] + 1; - } - y2 = x2 - k2; - while ( x2 < text1Length && y2 < text2Length && - text1.charAt( text1Length - x2 - 1 ) === - text2.charAt( text2Length - y2 - 1 ) ) { - x2++; - y2++; - } - v2[ k2Offset ] = x2; - if ( x2 > text1Length ) { - // Ran off the left of the graph. - k2end += 2; - } else if ( y2 > text2Length ) { - // Ran off the top of the graph. - k2start += 2; - } else if ( !front ) { - k1Offset = vOffset + delta - k2; - if ( k1Offset >= 0 && k1Offset < vLength && v1[ k1Offset ] !== -1 ) { - x1 = v1[ k1Offset ]; - y1 = vOffset + x1 - k1Offset; - // Mirror x2 onto top-left coordinate system. - x2 = text1Length - x2; - if ( x1 >= x2 ) { - // Overlap detected. - return this.diffBisectSplit( text1, text2, x1, y1, deadline ); - } - } - } - } - } - // Diff took too long and hit the deadline or - // number of diffs equals number of characters, no commonality at all. - return [ - [ DIFF_DELETE, text1 ], - [ DIFF_INSERT, text2 ] - ]; - }; - - /** - * Given the location of the 'middle snake', split the diff in two parts - * and recurse. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {number} x Index of split point in text1. - * @param {number} y Index of split point in text2. - * @param {number} deadline Time at which to bail if not yet complete. - * @return {!Array.} Array of diff tuples. - * @private - */ - DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) { - var text1a, text1b, text2a, text2b, diffs, diffsb; - text1a = text1.substring( 0, x ); - text2a = text2.substring( 0, y ); - text1b = text1.substring( x ); - text2b = text2.substring( y ); - - // Compute both diffs serially. - diffs = this.DiffMain( text1a, text2a, false, deadline ); - diffsb = this.DiffMain( text1b, text2b, false, deadline ); - - return diffs.concat( diffsb ); - }; - - /** - * Reduce the number of edits by eliminating semantically trivial equalities. - * @param {!Array.} diffs Array of diff tuples. - */ - DiffMatchPatch.prototype.diffCleanupSemantic = function( diffs ) { - var changes, equalities, equalitiesLength, lastequality, - pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1, - lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2; - changes = false; - equalities = []; // Stack of indices where equalities are found. - equalitiesLength = 0; // Keeping our own length var is faster in JS. - /** @type {?string} */ - lastequality = null; - // Always equal to diffs[equalities[equalitiesLength - 1]][1] - pointer = 0; // Index of current position. - // Number of characters that changed prior to the equality. - lengthInsertions1 = 0; - lengthDeletions1 = 0; - // Number of characters that changed after the equality. - lengthInsertions2 = 0; - lengthDeletions2 = 0; - while ( pointer < diffs.length ) { - if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found. - equalities[ equalitiesLength++ ] = pointer; - lengthInsertions1 = lengthInsertions2; - lengthDeletions1 = lengthDeletions2; - lengthInsertions2 = 0; - lengthDeletions2 = 0; - lastequality = diffs[ pointer ][ 1 ]; - } else { // An insertion or deletion. - if ( diffs[ pointer ][ 0 ] === DIFF_INSERT ) { - lengthInsertions2 += diffs[ pointer ][ 1 ].length; - } else { - lengthDeletions2 += diffs[ pointer ][ 1 ].length; - } - // Eliminate an equality that is smaller or equal to the edits on both - // sides of it. - if ( lastequality && ( lastequality.length <= - Math.max( lengthInsertions1, lengthDeletions1 ) ) && - ( lastequality.length <= Math.max( lengthInsertions2, - lengthDeletions2 ) ) ) { - - // Duplicate record. - diffs.splice( - equalities[ equalitiesLength - 1 ], - 0, - [ DIFF_DELETE, lastequality ] - ); - - // Change second copy to insert. - diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT; - - // Throw away the equality we just deleted. - equalitiesLength--; - - // Throw away the previous equality (it needs to be reevaluated). - equalitiesLength--; - pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1; - - // Reset the counters. - lengthInsertions1 = 0; - lengthDeletions1 = 0; - lengthInsertions2 = 0; - lengthDeletions2 = 0; - lastequality = null; - changes = true; - } - } - pointer++; - } - - // Normalize the diff. - if ( changes ) { - this.diffCleanupMerge( diffs ); - } - - // Find any overlaps between deletions and insertions. - // e.g: abcxxxxxxdef - // -> abcxxxdef - // e.g: xxxabcdefxxx - // -> defxxxabc - // Only extract an overlap if it is as big as the edit ahead or behind it. - pointer = 1; - while ( pointer < diffs.length ) { - if ( diffs[ pointer - 1 ][ 0 ] === DIFF_DELETE && - diffs[ pointer ][ 0 ] === DIFF_INSERT ) { - deletion = diffs[ pointer - 1 ][ 1 ]; - insertion = diffs[ pointer ][ 1 ]; - overlapLength1 = this.diffCommonOverlap( deletion, insertion ); - overlapLength2 = this.diffCommonOverlap( insertion, deletion ); - if ( overlapLength1 >= overlapLength2 ) { - if ( overlapLength1 >= deletion.length / 2 || - overlapLength1 >= insertion.length / 2 ) { - // Overlap found. Insert an equality and trim the surrounding edits. - diffs.splice( - pointer, - 0, - [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ] - ); - diffs[ pointer - 1 ][ 1 ] = - deletion.substring( 0, deletion.length - overlapLength1 ); - diffs[ pointer + 1 ][ 1 ] = insertion.substring( overlapLength1 ); - pointer++; - } - } else { - if ( overlapLength2 >= deletion.length / 2 || - overlapLength2 >= insertion.length / 2 ) { - - // Reverse overlap found. - // Insert an equality and swap and trim the surrounding edits. - diffs.splice( - pointer, - 0, - [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ] - ); - - diffs[ pointer - 1 ][ 0 ] = DIFF_INSERT; - diffs[ pointer - 1 ][ 1 ] = - insertion.substring( 0, insertion.length - overlapLength2 ); - diffs[ pointer + 1 ][ 0 ] = DIFF_DELETE; - diffs[ pointer + 1 ][ 1 ] = - deletion.substring( overlapLength2 ); - pointer++; - } - } - pointer++; - } - pointer++; - } - }; - - /** - * Determine if the suffix of one string is the prefix of another. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the end of the first - * string and the start of the second string. - * @private - */ - DiffMatchPatch.prototype.diffCommonOverlap = function( text1, text2 ) { - var text1Length, text2Length, textLength, - best, length, pattern, found; - // Cache the text lengths to prevent multiple calls. - text1Length = text1.length; - text2Length = text2.length; - // Eliminate the null case. - if ( text1Length === 0 || text2Length === 0 ) { - return 0; - } - // Truncate the longer string. - if ( text1Length > text2Length ) { - text1 = text1.substring( text1Length - text2Length ); - } else if ( text1Length < text2Length ) { - text2 = text2.substring( 0, text1Length ); - } - textLength = Math.min( text1Length, text2Length ); - // Quick check for the worst case. - if ( text1 === text2 ) { - return textLength; - } - - // Start by looking for a single character match - // and increase length until no match is found. - // Performance analysis: https://neil.fraser.name/news/2010/11/04/ - best = 0; - length = 1; - while ( true ) { - pattern = text1.substring( textLength - length ); - found = text2.indexOf( pattern ); - if ( found === -1 ) { - return best; - } - length += found; - if ( found === 0 || text1.substring( textLength - length ) === - text2.substring( 0, length ) ) { - best = length; - length++; - } - } - }; - - /** - * Split two texts into an array of strings. Reduce the texts to a string of - * hashes where each Unicode character represents one line. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {{chars1: string, chars2: string, lineArray: !Array.}} - * An object containing the encoded text1, the encoded text2 and - * the array of unique strings. - * The zeroth element of the array of unique strings is intentionally blank. - * @private - */ - DiffMatchPatch.prototype.diffLinesToChars = function( text1, text2 ) { - var lineArray, lineHash, chars1, chars2; - lineArray = []; // e.g. lineArray[4] === 'Hello\n' - lineHash = {}; // e.g. lineHash['Hello\n'] === 4 - - // '\x00' is a valid character, but various debuggers don't like it. - // So we'll insert a junk entry to avoid generating a null character. - lineArray[ 0 ] = ""; - - /** - * Split a text into an array of strings. Reduce the texts to a string of - * hashes where each Unicode character represents one line. - * Modifies linearray and linehash through being a closure. - * @param {string} text String to encode. - * @return {string} Encoded string. - * @private - */ - function diffLinesToCharsMunge( text ) { - var chars, lineStart, lineEnd, lineArrayLength, line; - chars = ""; - // Walk the text, pulling out a substring for each line. - // text.split('\n') would would temporarily double our memory footprint. - // Modifying text would create many large strings to garbage collect. - lineStart = 0; - lineEnd = -1; - // Keeping our own length variable is faster than looking it up. - lineArrayLength = lineArray.length; - while ( lineEnd < text.length - 1 ) { - lineEnd = text.indexOf( "\n", lineStart ); - if ( lineEnd === -1 ) { - lineEnd = text.length - 1; - } - line = text.substring( lineStart, lineEnd + 1 ); - lineStart = lineEnd + 1; - - if ( lineHash.hasOwnProperty ? lineHash.hasOwnProperty( line ) : - ( lineHash[ line ] !== undefined ) ) { - chars += String.fromCharCode( lineHash[ line ] ); - } else { - chars += String.fromCharCode( lineArrayLength ); - lineHash[ line ] = lineArrayLength; - lineArray[ lineArrayLength++ ] = line; - } - } - return chars; - } - - chars1 = diffLinesToCharsMunge( text1 ); - chars2 = diffLinesToCharsMunge( text2 ); - return { - chars1: chars1, - chars2: chars2, - lineArray: lineArray - }; - }; - - /** - * Rehydrate the text in a diff from a string of line hashes to real lines of - * text. - * @param {!Array.} diffs Array of diff tuples. - * @param {!Array.} lineArray Array of unique strings. - * @private - */ - DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) { - var x, chars, text, y; - for ( x = 0; x < diffs.length; x++ ) { - chars = diffs[ x ][ 1 ]; - text = []; - for ( y = 0; y < chars.length; y++ ) { - text[ y ] = lineArray[ chars.charCodeAt( y ) ]; - } - diffs[ x ][ 1 ] = text.join( "" ); - } - }; - - /** - * Reorder and merge like edit sections. Merge equalities. - * Any edit section can move as long as it doesn't cross an equality. - * @param {!Array.} diffs Array of diff tuples. - */ - DiffMatchPatch.prototype.diffCleanupMerge = function( diffs ) { - var pointer, countDelete, countInsert, textInsert, textDelete, - commonlength, changes, diffPointer, position; - diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end. - pointer = 0; - countDelete = 0; - countInsert = 0; - textDelete = ""; - textInsert = ""; - commonlength; - while ( pointer < diffs.length ) { - switch ( diffs[ pointer ][ 0 ] ) { - case DIFF_INSERT: - countInsert++; - textInsert += diffs[ pointer ][ 1 ]; - pointer++; - break; - case DIFF_DELETE: - countDelete++; - textDelete += diffs[ pointer ][ 1 ]; - pointer++; - break; - case DIFF_EQUAL: - // Upon reaching an equality, check for prior redundancies. - if ( countDelete + countInsert > 1 ) { - if ( countDelete !== 0 && countInsert !== 0 ) { - // Factor out any common prefixes. - commonlength = this.diffCommonPrefix( textInsert, textDelete ); - if ( commonlength !== 0 ) { - if ( ( pointer - countDelete - countInsert ) > 0 && - diffs[ pointer - countDelete - countInsert - 1 ][ 0 ] === - DIFF_EQUAL ) { - diffs[ pointer - countDelete - countInsert - 1 ][ 1 ] += - textInsert.substring( 0, commonlength ); - } else { - diffs.splice( 0, 0, [ DIFF_EQUAL, - textInsert.substring( 0, commonlength ) - ] ); - pointer++; - } - textInsert = textInsert.substring( commonlength ); - textDelete = textDelete.substring( commonlength ); - } - // Factor out any common suffixies. - commonlength = this.diffCommonSuffix( textInsert, textDelete ); - if ( commonlength !== 0 ) { - diffs[ pointer ][ 1 ] = textInsert.substring( textInsert.length - - commonlength ) + diffs[ pointer ][ 1 ]; - textInsert = textInsert.substring( 0, textInsert.length - - commonlength ); - textDelete = textDelete.substring( 0, textDelete.length - - commonlength ); - } - } - // Delete the offending records and add the merged ones. - if ( countDelete === 0 ) { - diffs.splice( pointer - countInsert, - countDelete + countInsert, [ DIFF_INSERT, textInsert ] ); - } else if ( countInsert === 0 ) { - diffs.splice( pointer - countDelete, - countDelete + countInsert, [ DIFF_DELETE, textDelete ] ); - } else { - diffs.splice( - pointer - countDelete - countInsert, - countDelete + countInsert, - [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ] - ); - } - pointer = pointer - countDelete - countInsert + - ( countDelete ? 1 : 0 ) + ( countInsert ? 1 : 0 ) + 1; - } else if ( pointer !== 0 && diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL ) { - - // Merge this equality with the previous one. - diffs[ pointer - 1 ][ 1 ] += diffs[ pointer ][ 1 ]; - diffs.splice( pointer, 1 ); - } else { - pointer++; - } - countInsert = 0; - countDelete = 0; - textDelete = ""; - textInsert = ""; - break; - } - } - if ( diffs[ diffs.length - 1 ][ 1 ] === "" ) { - diffs.pop(); // Remove the dummy entry at the end. - } - - // Second pass: look for single edits surrounded on both sides by equalities - // which can be shifted sideways to eliminate an equality. - // e.g: ABAC -> ABAC - changes = false; - pointer = 1; - - // Intentionally ignore the first and last element (don't need checking). - while ( pointer < diffs.length - 1 ) { - if ( diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL && - diffs[ pointer + 1 ][ 0 ] === DIFF_EQUAL ) { - - diffPointer = diffs[ pointer ][ 1 ]; - position = diffPointer.substring( - diffPointer.length - diffs[ pointer - 1 ][ 1 ].length - ); - - // This is a single edit surrounded by equalities. - if ( position === diffs[ pointer - 1 ][ 1 ] ) { - - // Shift the edit over the previous equality. - diffs[ pointer ][ 1 ] = diffs[ pointer - 1 ][ 1 ] + - diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer ][ 1 ].length - - diffs[ pointer - 1 ][ 1 ].length ); - diffs[ pointer + 1 ][ 1 ] = - diffs[ pointer - 1 ][ 1 ] + diffs[ pointer + 1 ][ 1 ]; - diffs.splice( pointer - 1, 1 ); - changes = true; - } else if ( diffPointer.substring( 0, diffs[ pointer + 1 ][ 1 ].length ) === - diffs[ pointer + 1 ][ 1 ] ) { - - // Shift the edit over the next equality. - diffs[ pointer - 1 ][ 1 ] += diffs[ pointer + 1 ][ 1 ]; - diffs[ pointer ][ 1 ] = - diffs[ pointer ][ 1 ].substring( diffs[ pointer + 1 ][ 1 ].length ) + - diffs[ pointer + 1 ][ 1 ]; - diffs.splice( pointer + 1, 1 ); - changes = true; - } - } - pointer++; - } - // If shifts were made, the diff needs reordering and another shift sweep. - if ( changes ) { - this.diffCleanupMerge( diffs ); - } - }; - - return function( o, n ) { - var diff, output, text; - diff = new DiffMatchPatch(); - output = diff.DiffMain( o, n ); - diff.diffCleanupEfficiency( output ); - text = diff.diffPrettyHtml( output ); - - return text; - }; -}() ); - -// Get a reference to the global object, like window in browsers -}( (function() { - return this; -})() )); - -(function() { - -// Don't load the HTML Reporter on non-Browser environments -if ( typeof window === "undefined" || !window.document ) { - return; -} - -// Deprecated QUnit.init - Ref #530 -// Re-initialize the configuration options -QUnit.init = function() { - var tests, banner, result, qunit, - config = QUnit.config; - - config.stats = { all: 0, bad: 0 }; - config.moduleStats = { all: 0, bad: 0 }; - config.started = 0; - config.updateRate = 1000; - config.blocking = false; - config.autostart = true; - config.autorun = false; - config.filter = ""; - config.queue = []; - - // Return on non-browser environments - // This is necessary to not break on node tests - if ( typeof window === "undefined" ) { - return; - } - - qunit = id( "qunit" ); - if ( qunit ) { - qunit.innerHTML = - "

" + escapeText( document.title ) + "

" + - "

" + - "
" + - "

" + - "
    "; - } - - tests = id( "qunit-tests" ); - banner = id( "qunit-banner" ); - result = id( "qunit-testresult" ); - - if ( tests ) { - tests.innerHTML = ""; - } - - if ( banner ) { - banner.className = ""; - } - - if ( result ) { - result.parentNode.removeChild( result ); - } - - if ( tests ) { - result = document.createElement( "p" ); - result.id = "qunit-testresult"; - result.className = "result"; - tests.parentNode.insertBefore( result, tests ); - result.innerHTML = "Running...
     "; - } -}; - -var config = QUnit.config, - collapseNext = false, - hasOwn = Object.prototype.hasOwnProperty, - defined = { - document: window.document !== undefined, - sessionStorage: (function() { - var x = "qunit-test-string"; - try { - sessionStorage.setItem( x, x ); - sessionStorage.removeItem( x ); - return true; - } catch ( e ) { - return false; - } - }()) - }, - modulesList = []; - -/** -* Escape text for attribute or text content. -*/ -function escapeText( s ) { - if ( !s ) { - return ""; - } - s = s + ""; - - // Both single quotes and double quotes (for attributes) - return s.replace( /['"<>&]/g, function( s ) { - switch ( s ) { - case "'": - return "'"; - case "\"": - return """; - case "<": - return "<"; - case ">": - return ">"; - case "&": - return "&"; - } - }); -} - -/** - * @param {HTMLElement} elem - * @param {string} type - * @param {Function} fn - */ -function addEvent( elem, type, fn ) { - if ( elem.addEventListener ) { - - // Standards-based browsers - elem.addEventListener( type, fn, false ); - } else if ( elem.attachEvent ) { - - // support: IE <9 - elem.attachEvent( "on" + type, function() { - var event = window.event; - if ( !event.target ) { - event.target = event.srcElement || document; - } - - fn.call( elem, event ); - }); - } -} - -/** - * @param {Array|NodeList} elems - * @param {string} type - * @param {Function} fn - */ -function addEvents( elems, type, fn ) { - var i = elems.length; - while ( i-- ) { - addEvent( elems[ i ], type, fn ); - } -} - -function hasClass( elem, name ) { - return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0; -} - -function addClass( elem, name ) { - if ( !hasClass( elem, name ) ) { - elem.className += ( elem.className ? " " : "" ) + name; - } -} - -function toggleClass( elem, name ) { - if ( hasClass( elem, name ) ) { - removeClass( elem, name ); - } else { - addClass( elem, name ); - } -} - -function removeClass( elem, name ) { - var set = " " + elem.className + " "; - - // Class name may appear multiple times - while ( set.indexOf( " " + name + " " ) >= 0 ) { - set = set.replace( " " + name + " ", " " ); - } - - // trim for prettiness - elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" ); -} - -function id( name ) { - return defined.document && document.getElementById && document.getElementById( name ); -} - -function getUrlConfigHtml() { - var i, j, val, - escaped, escapedTooltip, - selection = false, - len = config.urlConfig.length, - urlConfigHtml = ""; - - for ( i = 0; i < len; i++ ) { - val = config.urlConfig[ i ]; - if ( typeof val === "string" ) { - val = { - id: val, - label: val - }; - } - - escaped = escapeText( val.id ); - escapedTooltip = escapeText( val.tooltip ); - - if ( config[ val.id ] === undefined ) { - config[ val.id ] = QUnit.urlParams[ val.id ]; - } - - if ( !val.value || typeof val.value === "string" ) { - urlConfigHtml += ""; - } else { - urlConfigHtml += ""; - } - } - - return urlConfigHtml; -} - -// Handle "click" events on toolbar checkboxes and "change" for select menus. -// Updates the URL with the new state of `config.urlConfig` values. -function toolbarChanged() { - var updatedUrl, value, - field = this, - params = {}; - - // Detect if field is a select menu or a checkbox - if ( "selectedIndex" in field ) { - value = field.options[ field.selectedIndex ].value || undefined; - } else { - value = field.checked ? ( field.defaultValue || true ) : undefined; - } - - params[ field.name ] = value; - updatedUrl = setUrl( params ); - - if ( "hidepassed" === field.name && "replaceState" in window.history ) { - config[ field.name ] = value || false; - if ( value ) { - addClass( id( "qunit-tests" ), "hidepass" ); - } else { - removeClass( id( "qunit-tests" ), "hidepass" ); - } - - // It is not necessary to refresh the whole page - window.history.replaceState( null, "", updatedUrl ); - } else { - window.location = updatedUrl; - } -} - -function setUrl( params ) { - var key, - querystring = "?"; - - params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params ); - - for ( key in params ) { - if ( hasOwn.call( params, key ) ) { - if ( params[ key ] === undefined ) { - continue; - } - querystring += encodeURIComponent( key ); - if ( params[ key ] !== true ) { - querystring += "=" + encodeURIComponent( params[ key ] ); - } - querystring += "&"; - } - } - return location.protocol + "//" + location.host + - location.pathname + querystring.slice( 0, -1 ); -} - -function applyUrlParams() { - var selectedModule, - modulesList = id( "qunit-modulefilter" ), - filter = id( "qunit-filter-input" ).value; - - selectedModule = modulesList ? - decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) : - undefined; - - window.location = setUrl({ - module: ( selectedModule === "" ) ? undefined : selectedModule, - filter: ( filter === "" ) ? undefined : filter, - - // Remove testId filter - testId: undefined - }); -} - -function toolbarUrlConfigContainer() { - var urlConfigContainer = document.createElement( "span" ); - - urlConfigContainer.innerHTML = getUrlConfigHtml(); - addClass( urlConfigContainer, "qunit-url-config" ); - - // For oldIE support: - // * Add handlers to the individual elements instead of the container - // * Use "click" instead of "change" for checkboxes - addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged ); - addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged ); - - return urlConfigContainer; -} - -function toolbarLooseFilter() { - var filter = document.createElement( "form" ), - label = document.createElement( "label" ), - input = document.createElement( "input" ), - button = document.createElement( "button" ); - - addClass( filter, "qunit-filter" ); - - label.innerHTML = "Filter: "; - - input.type = "text"; - input.value = config.filter || ""; - input.name = "filter"; - input.id = "qunit-filter-input"; - - button.innerHTML = "Go"; - - label.appendChild( input ); - - filter.appendChild( label ); - filter.appendChild( button ); - addEvent( filter, "submit", function( ev ) { - applyUrlParams(); - - if ( ev && ev.preventDefault ) { - ev.preventDefault(); - } - - return false; - }); - - return filter; -} - -function toolbarModuleFilterHtml() { - var i, - moduleFilterHtml = ""; - - if ( !modulesList.length ) { - return false; - } - - modulesList.sort(function( a, b ) { - return a.localeCompare( b ); - }); - - moduleFilterHtml += "" + - ""; - - return moduleFilterHtml; -} - -function toolbarModuleFilter() { - var toolbar = id( "qunit-testrunner-toolbar" ), - moduleFilter = document.createElement( "span" ), - moduleFilterHtml = toolbarModuleFilterHtml(); - - if ( !toolbar || !moduleFilterHtml ) { - return false; - } - - moduleFilter.setAttribute( "id", "qunit-modulefilter-container" ); - moduleFilter.innerHTML = moduleFilterHtml; - - addEvent( moduleFilter.lastChild, "change", applyUrlParams ); - - toolbar.appendChild( moduleFilter ); -} - -function appendToolbar() { - var toolbar = id( "qunit-testrunner-toolbar" ); - - if ( toolbar ) { - toolbar.appendChild( toolbarUrlConfigContainer() ); - toolbar.appendChild( toolbarLooseFilter() ); - } -} - -function appendHeader() { - var header = id( "qunit-header" ); - - if ( header ) { - header.innerHTML = "" + header.innerHTML + " "; - } -} - -function appendBanner() { - var banner = id( "qunit-banner" ); - - if ( banner ) { - banner.className = ""; - } -} - -function appendTestResults() { - var tests = id( "qunit-tests" ), - result = id( "qunit-testresult" ); - - if ( result ) { - result.parentNode.removeChild( result ); - } - - if ( tests ) { - tests.innerHTML = ""; - result = document.createElement( "p" ); - result.id = "qunit-testresult"; - result.className = "result"; - tests.parentNode.insertBefore( result, tests ); - result.innerHTML = "Running...
     "; - } -} - -function storeFixture() { - var fixture = id( "qunit-fixture" ); - if ( fixture ) { - config.fixture = fixture.innerHTML; - } -} - -function appendFilteredTest() { - var testId = QUnit.config.testId; - if ( !testId || testId.length <= 0 ) { - return ""; - } - return "
    Rerunning selected tests: " + testId.join(", ") + - " " + "Run all tests" + "
    "; -} - -function appendUserAgent() { - var userAgent = id( "qunit-userAgent" ); - - if ( userAgent ) { - userAgent.innerHTML = ""; - userAgent.appendChild( - document.createTextNode( - "QUnit " + QUnit.version + "; " + navigator.userAgent - ) - ); - } -} - -function appendTestsList( modules ) { - var i, l, x, z, test, moduleObj; - - for ( i = 0, l = modules.length; i < l; i++ ) { - moduleObj = modules[ i ]; - - if ( moduleObj.name ) { - modulesList.push( moduleObj.name ); - } - - for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) { - test = moduleObj.tests[ x ]; - - appendTest( test.name, test.testId, moduleObj.name ); - } - } -} - -function appendTest( name, testId, moduleName ) { - var title, rerunTrigger, testBlock, assertList, - tests = id( "qunit-tests" ); - - if ( !tests ) { - return; - } - - title = document.createElement( "strong" ); - title.innerHTML = getNameHtml( name, moduleName ); - - rerunTrigger = document.createElement( "a" ); - rerunTrigger.innerHTML = "Rerun"; - rerunTrigger.href = setUrl({ testId: testId }); - - testBlock = document.createElement( "li" ); - testBlock.appendChild( title ); - testBlock.appendChild( rerunTrigger ); - testBlock.id = "qunit-test-output-" + testId; - - assertList = document.createElement( "ol" ); - assertList.className = "qunit-assert-list"; - - testBlock.appendChild( assertList ); - - tests.appendChild( testBlock ); -} - -// HTML Reporter initialization and load -QUnit.begin(function( details ) { - var qunit = id( "qunit" ); - - // Fixture is the only one necessary to run without the #qunit element - storeFixture(); - - if ( qunit ) { - qunit.innerHTML = - "

    " + escapeText( document.title ) + "

    " + - "

    " + - "
    " + - appendFilteredTest() + - "

    " + - "
      "; - } - - appendHeader(); - appendBanner(); - appendTestResults(); - appendUserAgent(); - appendToolbar(); - appendTestsList( details.modules ); - toolbarModuleFilter(); - - if ( qunit && config.hidepassed ) { - addClass( qunit.lastChild, "hidepass" ); - } -}); - -QUnit.done(function( details ) { - var i, key, - banner = id( "qunit-banner" ), - tests = id( "qunit-tests" ), - html = [ - "Tests completed in ", - details.runtime, - " milliseconds.
      ", - "", - details.passed, - " assertions of ", - details.total, - " passed, ", - details.failed, - " failed." - ].join( "" ); - - if ( banner ) { - banner.className = details.failed ? "qunit-fail" : "qunit-pass"; - } - - if ( tests ) { - id( "qunit-testresult" ).innerHTML = html; - } - - if ( config.altertitle && defined.document && document.title ) { - - // show ✖ for good, ✔ for bad suite result in title - // use escape sequences in case file gets loaded with non-utf-8-charset - document.title = [ - ( details.failed ? "\u2716" : "\u2714" ), - document.title.replace( /^[\u2714\u2716] /i, "" ) - ].join( " " ); - } - - // clear own sessionStorage items if all tests passed - if ( config.reorder && defined.sessionStorage && details.failed === 0 ) { - for ( i = 0; i < sessionStorage.length; i++ ) { - key = sessionStorage.key( i++ ); - if ( key.indexOf( "qunit-test-" ) === 0 ) { - sessionStorage.removeItem( key ); - } - } - } - - // scroll back to top to show results - if ( config.scrolltop && window.scrollTo ) { - window.scrollTo( 0, 0 ); - } -}); - -function getNameHtml( name, module ) { - var nameHtml = ""; - - if ( module ) { - nameHtml = "" + escapeText( module ) + ": "; - } - - nameHtml += "" + escapeText( name ) + ""; - - return nameHtml; -} - -QUnit.testStart(function( details ) { - var running, testBlock, bad; - - testBlock = id( "qunit-test-output-" + details.testId ); - if ( testBlock ) { - testBlock.className = "running"; - } else { - - // Report later registered tests - appendTest( details.name, details.testId, details.module ); - } - - running = id( "qunit-testresult" ); - if ( running ) { - bad = QUnit.config.reorder && defined.sessionStorage && - +sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name ); - - running.innerHTML = ( bad ? - "Rerunning previously failed test:
      " : - "Running:
      " ) + - getNameHtml( details.name, details.module ); - } - -}); - -function stripHtml( string ) { - // strip tags, html entity and whitespaces - return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/\"/g, "").replace(/\s+/g, ""); -} - -QUnit.log(function( details ) { - var assertList, assertLi, - message, expected, actual, diff, - showDiff = false, - testItem = id( "qunit-test-output-" + details.testId ); - - if ( !testItem ) { - return; - } - - message = escapeText( details.message ) || ( details.result ? "okay" : "failed" ); - message = "" + message + ""; - message += "@ " + details.runtime + " ms"; - - // pushFailure doesn't provide details.expected - // when it calls, it's implicit to also not show expected and diff stuff - // Also, we need to check details.expected existence, as it can exist and be undefined - if ( !details.result && hasOwn.call( details, "expected" ) ) { - if ( details.negative ) { - expected = escapeText( "NOT " + QUnit.dump.parse( details.expected ) ); - } else { - expected = escapeText( QUnit.dump.parse( details.expected ) ); - } - - actual = escapeText( QUnit.dump.parse( details.actual ) ); - message += ""; - - if ( actual !== expected ) { - - message += ""; - - // Don't show diff if actual or expected are booleans - if ( !( /^(true|false)$/.test( actual ) ) && - !( /^(true|false)$/.test( expected ) ) ) { - diff = QUnit.diff( expected, actual ); - showDiff = stripHtml( diff ).length !== - stripHtml( expected ).length + - stripHtml( actual ).length; - } - - // Don't show diff if expected and actual are totally different - if ( showDiff ) { - message += ""; - } - } else if ( expected.indexOf( "[object Array]" ) !== -1 || - expected.indexOf( "[object Object]" ) !== -1 ) { - message += ""; - } - - if ( details.source ) { - message += ""; - } - - message += "
      Expected:
      " +
      -			expected +
      -			"
      Result:
      " +
      -				actual + "
      Diff:
      " +
      -					diff + "
      Message: " + - "Diff suppressed as the depth of object is more than current max depth (" + - QUnit.config.maxDepth + ").

      Hint: Use QUnit.dump.maxDepth to " + - " run with a higher max depth or " + - "Rerun without max depth.

      Source:
      " +
      -				escapeText( details.source ) + "
      "; - - // this occurs when pushFailure is set and we have an extracted stack trace - } else if ( !details.result && details.source ) { - message += "" + - "" + - "
      Source:
      " +
      -			escapeText( details.source ) + "
      "; - } - - assertList = testItem.getElementsByTagName( "ol" )[ 0 ]; - - assertLi = document.createElement( "li" ); - assertLi.className = details.result ? "pass" : "fail"; - assertLi.innerHTML = message; - assertList.appendChild( assertLi ); -}); - -QUnit.testDone(function( details ) { - var testTitle, time, testItem, assertList, - good, bad, testCounts, skipped, sourceName, - tests = id( "qunit-tests" ); - - if ( !tests ) { - return; - } - - testItem = id( "qunit-test-output-" + details.testId ); - - assertList = testItem.getElementsByTagName( "ol" )[ 0 ]; - - good = details.passed; - bad = details.failed; - - // store result when possible - if ( config.reorder && defined.sessionStorage ) { - if ( bad ) { - sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad ); - } else { - sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name ); - } - } - - if ( bad === 0 ) { - - // Collapse the passing tests - addClass( assertList, "qunit-collapsed" ); - } else if ( bad && config.collapse && !collapseNext ) { - - // Skip collapsing the first failing test - collapseNext = true; - } else { - - // Collapse remaining tests - addClass( assertList, "qunit-collapsed" ); - } - - // testItem.firstChild is the test name - testTitle = testItem.firstChild; - - testCounts = bad ? - "" + bad + ", " + "" + good + ", " : - ""; - - testTitle.innerHTML += " (" + testCounts + - details.assertions.length + ")"; - - if ( details.skipped ) { - testItem.className = "skipped"; - skipped = document.createElement( "em" ); - skipped.className = "qunit-skipped-label"; - skipped.innerHTML = "skipped"; - testItem.insertBefore( skipped, testTitle ); - } else { - addEvent( testTitle, "click", function() { - toggleClass( assertList, "qunit-collapsed" ); - }); - - testItem.className = bad ? "fail" : "pass"; - - time = document.createElement( "span" ); - time.className = "runtime"; - time.innerHTML = details.runtime + " ms"; - testItem.insertBefore( time, assertList ); - } - - // Show the source of the test when showing assertions - if ( details.source ) { - sourceName = document.createElement( "p" ); - sourceName.innerHTML = "Source: " + details.source; - addClass( sourceName, "qunit-source" ); - if ( bad === 0 ) { - addClass( sourceName, "qunit-collapsed" ); - } - addEvent( testTitle, "click", function() { - toggleClass( sourceName, "qunit-collapsed" ); - }); - testItem.appendChild( sourceName ); - } -}); - -if ( defined.document ) { - - // Avoid readyState issue with phantomjs - // Ref: #818 - var notPhantom = ( function( p ) { - return !( p && p.version && p.version.major > 0 ); - } )( window.phantom ); - - if ( notPhantom && document.readyState === "complete" ) { - QUnit.load(); - } else { - addEvent( window, "load", QUnit.load ); - } -} else { - config.pageLoaded = true; - config.autorun = true; -} - -})(); diff --git a/public/assets/tests/qunit-1.21.0.css b/public/assets/tests/qunit-2.17.2.css similarity index 53% rename from public/assets/tests/qunit-1.21.0.css rename to public/assets/tests/qunit-2.17.2.css index b23d647a2..e31bf0c5e 100644 --- a/public/assets/tests/qunit-1.21.0.css +++ b/public/assets/tests/qunit-2.17.2.css @@ -1,16 +1,25 @@ /*! - * QUnit 1.21.0 + * QUnit 2.17.2 * https://qunitjs.com/ * - * Copyright jQuery Foundation and other contributors + * Copyright OpenJS Foundation and other contributors * Released under the MIT license * https://jquery.org/license - * - * Date: 2016-02-01T13:07Z */ /** Font Family and Sizes */ +/* Style our buttons in a simple way, uninfluenced by the styles + the tested app might load. Don't affect buttons in #qunit-fixture! + https://github.com/qunitjs/qunit/pull/1395 + https://github.com/qunitjs/qunit/issues/1437 */ +#qunit-testrunner-toolbar button, +#qunit-testresult button { + font-size: initial; + border: initial; + background-color: buttonface; +} + #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult { font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; } @@ -27,12 +36,39 @@ } -/** Header */ +/** Fixed headers with scrollable tests */ + +@supports (display: flex) or (display: -webkit-box) { + @media (min-height: 500px) { + #qunit { + position: fixed; + left: 0px; + right: 0px; + top: 0px; + bottom: 0px; + padding: 8px; + display: -webkit-box; + display: flex; + flex-direction: column; + } + + #qunit-tests { + overflow: scroll; + } + + #qunit-banner { + flex: 5px 0 0; + } + } +} + + +/** Header (excluding toolbar) */ #qunit-header { padding: 0.5em 0 0.5em 1em; - color: #8699A4; + color: #C2CCD1; background-color: #0D3349; font-size: 1.5em; @@ -44,7 +80,7 @@ #qunit-header a { text-decoration: none; - color: #C2CCD1; + color: inherit; } #qunit-header a:hover, @@ -52,51 +88,165 @@ color: #FFF; } -#qunit-testrunner-toolbar label { - display: inline-block; - padding: 0 0.5em 0 0.1em; -} - #qunit-banner { height: 5px; } +#qunit-filteredTest { + padding: 0.5em 1em 0.5em 1em; + color: #366097; + background-color: #F4FF77; +} + +#qunit-userAgent { + padding: 0.5em 1em 0.5em 1em; + color: #FFF; + background-color: #2B81AF; + text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; +} + + +/** Toolbar */ + #qunit-testrunner-toolbar { padding: 0.5em 1em 0.5em 1em; color: #5E740B; background-color: #EEE; - overflow: hidden; } -#qunit-filteredTest { - padding: 0.5em 1em 0.5em 1em; - background-color: #F4FF77; - color: #366097; +#qunit-testrunner-toolbar .clearfix { + height: 0; + clear: both; } -#qunit-userAgent { - padding: 0.5em 1em 0.5em 1em; - background-color: #2B81AF; - color: #FFF; - text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; -} - -#qunit-modulefilter-container { - float: right; - padding: 0.2em; -} - -.qunit-url-config { +#qunit-testrunner-toolbar label { display: inline-block; - padding: 0.1em; } -.qunit-filter { - display: block; +#qunit-testrunner-toolbar input[type=checkbox], +#qunit-testrunner-toolbar input[type=radio] { + margin: 3px; + vertical-align: -2px; +} + +#qunit-testrunner-toolbar input[type=text] { + box-sizing: border-box; + height: 1.6em; +} + +#qunit-toolbar-filters { float: right; +} + +.qunit-url-config, +.qunit-filter, +#qunit-modulefilter { + display: inline-block; + line-height: 2.1em; +} + +.qunit-filter, +#qunit-modulefilter { + position: relative; margin-left: 1em; } +.qunit-url-config label { + margin-right: 0.5em; +} + +#qunit-modulefilter-search { + box-sizing: border-box; + min-width: 400px; +} + +#qunit-modulefilter-search-container:after { + position: absolute; + right: 0.3em; + content: "\25bc"; + color: black; +} + +#qunit-modulefilter-dropdown { + /* align with #qunit-modulefilter-search */ + box-sizing: border-box; + min-width: 400px; + position: absolute; + right: 0; + top: 50%; + margin-top: 0.8em; + + border: 1px solid #D3D3D3; + border-top: none; + border-radius: 0 0 .25em .25em; + color: #0D3349; + background-color: #F5F5F5; + z-index: 99; +} + +#qunit-modulefilter-dropdown a { + color: inherit; + text-decoration: none; +} + +#qunit-modulefilter-dropdown .clickable.checked { + font-weight: bold; + color: #0D3349; + background-color: #E2F0F7; +} + +#qunit-modulefilter-dropdown .clickable:hover { + color: #FFF; + background-color: #0D3349; +} + +#qunit-modulefilter-actions { + display: block; + overflow: auto; + + /* align with #qunit-modulefilter-dropdown-list */ + font: smaller/1.5em sans-serif; +} + +#qunit-modulefilter-dropdown #qunit-modulefilter-actions > * { + box-sizing: border-box; + max-height: 2.8em; + display: block; + padding: 0.4em; +} + +#qunit-modulefilter-dropdown #qunit-modulefilter-actions > button { + float: right; + font: inherit; +} + +#qunit-modulefilter-dropdown #qunit-modulefilter-actions > :last-child { + /* insert padding to align with checkbox margins */ + padding-left: 3px; +} + +#qunit-modulefilter-dropdown-list { + max-height: 200px; + overflow-y: auto; + margin: 0; + border-top: 2px groove threedhighlight; + padding: 0.4em 0 0; + font: smaller/1.5em sans-serif; +} + +#qunit-modulefilter-dropdown-list li { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#qunit-modulefilter-dropdown-list .clickable { + display: block; + padding-left: 0.15em; + padding-right: 0.5em; +} + + /** Tests: Pass/Fail */ #qunit-tests { @@ -116,7 +266,8 @@ #qunit-tests li.running, #qunit-tests li.pass, #qunit-tests li.fail, -#qunit-tests li.skipped { +#qunit-tests li.skipped, +#qunit-tests li.aborted { display: list-item; } @@ -125,7 +276,7 @@ } #qunit-tests.hidepass li.running, -#qunit-tests.hidepass li.pass { +#qunit-tests.hidepass li.pass:not(.todo) { visibility: hidden; position: absolute; width: 0; @@ -145,17 +296,12 @@ #qunit-tests li a { padding: 0.5em; - color: #C2CCD1; - text-decoration: none; -} - -#qunit-tests li p a { - padding: 0.25em; - color: #6B6464; + color: inherit; + text-decoration: underline; } #qunit-tests li a:hover, #qunit-tests li a:focus { - color: #000; + color: #0D3349; } #qunit-tests li .runtime { @@ -202,20 +348,20 @@ } #qunit-tests del { - background-color: #E0F2BE; color: #374E0C; + background-color: #E0F2BE; text-decoration: none; } #qunit-tests ins { - background-color: #FFCACA; color: #500; + background-color: #FFCACA; text-decoration: none; } /*** Test Counts */ -#qunit-tests b.counts { color: #000; } +#qunit-tests b.counts { color: #0D3349; } #qunit-tests b.passed { color: #5E740B; } #qunit-tests b.failed { color: #710909; } @@ -228,15 +374,22 @@ /*** Passing Styles */ + +#qunit-tests .pass { + color: #2F68DA; + background-color: #E2F0F7; +} + +#qunit-tests .pass .test-name { + color: #366097; +} + #qunit-tests li li.pass { color: #3C510C; background-color: #FFF; border-left: 10px solid #C6E746; } -#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } -#qunit-tests .pass .test-name { color: #366097; } - #qunit-tests .pass .test-actual, #qunit-tests .pass .test-expected { color: #999; } @@ -244,6 +397,11 @@ /*** Failing Styles */ +#qunit-tests .fail { + color: #000; + background-color: #EE5757; +} + #qunit-tests li li.fail { color: #710909; background-color: #FFF; @@ -255,21 +413,21 @@ border-radius: 0 0 5px 5px; } -#qunit-tests .fail { color: #000; background-color: #EE5757; } -#qunit-tests .fail .test-name, -#qunit-tests .fail .module-name { color: #000; } - #qunit-tests .fail .test-actual { color: #EE5757; } #qunit-tests .fail .test-expected { color: #008000; } #qunit-banner.qunit-fail { background-color: #EE5757; } + +/*** Aborted tests */ +#qunit-tests .aborted { color: #000; background-color: orange; } /*** Skipped tests */ #qunit-tests .skipped { background-color: #EBECE9; } +#qunit-tests .qunit-todo-label, #qunit-tests .qunit-skipped-label { background-color: #F4FF77; display: inline-block; @@ -280,19 +438,38 @@ margin: -0.4em 0.4em -0.4em 0; } +#qunit-tests .qunit-todo-label { + background-color: #EEE; +} + /** Result */ #qunit-testresult { - padding: 0.5em 1em 0.5em 1em; - - color: #2B81AF; - background-color: #D2E0E6; + color: #366097; + background-color: #E2F0F7; border-bottom: 1px solid #FFF; } +#qunit-testresult a { + color: #2F68DA; +} +#qunit-testresult .clearfix { + height: 0; + clear: both; +} #qunit-testresult .module-name { font-weight: 700; } +#qunit-testresult-display { + padding: 0.5em 1em 0.5em 1em; + width: 85%; + float:left; +} +#qunit-testresult-controls { + padding: 0.5em 1em 0.5em 1em; + width: 10%; + float:left; +} /** Fixture */ diff --git a/public/assets/tests/qunit-2.17.2.js b/public/assets/tests/qunit-2.17.2.js new file mode 100644 index 000000000..9072a0954 --- /dev/null +++ b/public/assets/tests/qunit-2.17.2.js @@ -0,0 +1,7392 @@ +/*! + * QUnit 2.17.2 + * https://qunitjs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + */ +(function () { + 'use strict'; + + // Support IE 9-10, Safari 7, PhantomJS: Partial Map fallback. + // Used by html.js (via fuzzysort.js), and test.js. + // + // FIXME: This check is broken. This file is embedded in the qunit.js closure, + // thus the Map var is hoisted in that scope, and starts undefined (not a function). + var Map = typeof Map === "function" ? Map : function StringMap() { + var store = Object.create( null ); + var hasOwn = Object.prototype.hasOwnProperty; + this.get = function( strKey ) { + return store[ strKey ]; + }; + this.set = function( strKey, val ) { + if ( !hasOwn.call( store, strKey ) ) { + this.size++; + } + store[ strKey ] = val; + return this; + }; + this.delete = function( strKey ) { + if ( hasOwn.call( store, strKey ) ) { + delete store[ strKey ]; + this.size--; + } + }; + this.forEach = function( callback ) { + for ( var strKey in store ) { + callback( store[ strKey ], strKey ); + } + }; + this.clear = function() { + store = Object.create( null ); + this.size = 0; + }; + this.size = 0; + }; + + function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; + + if (_i == null) return; + var _arr = []; + var _n = true; + var _d = false; + + var _s, _e; + + try { + for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _createForOfIteratorHelper(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + + if (!it) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + + var F = function () {}; + + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = it.call(o); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + + /* + https://github.com/ungap/global-this/blob/v0.4.4/esm/index.js + + Copyright (c) 2020, Andrea Giammarchi, @WebReflection + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + + ------- + + Patches for use in QUnit: + + - 2021-02-25: Export as module only, don't change global scope as QUnit must not + affect the host context (e.g. people may test their application intentionally + with different or no polyfills and we must not affect that). + + */ + var foundGlobalThis; + + (function (Object) { + if ((typeof globalThis === "undefined" ? "undefined" : _typeof(globalThis)) === "object") { + foundGlobalThis = globalThis; + } else { + var get = function get() { + foundGlobalThis = this || self; + delete Object.prototype._T_; + }; + + this ? get() : (Object.defineProperty(Object.prototype, "_T_", { + configurable: true, + get: get + }), _T_); + } + })(Object); + + var globalThis$1 = foundGlobalThis; + + var window$1 = globalThis$1.window; + var self$1 = globalThis$1.self; + var console$1 = globalThis$1.console; + var setTimeout$1 = globalThis$1.setTimeout; + var clearTimeout = globalThis$1.clearTimeout; + var document = window$1 && window$1.document; + var navigator = window$1 && window$1.navigator; + var localSessionStorage = function () { + var x = "qunit-test-string"; + + try { + globalThis$1.sessionStorage.setItem(x, x); + globalThis$1.sessionStorage.removeItem(x); + return globalThis$1.sessionStorage; + } catch (e) { + return undefined; + } + }(); + + // Detect if the console object exists and no-op otherwise. + // This allows support for IE 9, which doesn't have a console + // object if the developer tools are not open. + // Support: IE 9 + // Function#bind is supported, but no console.log.bind(). + // Support: SpiderMonkey (mozjs 68+) + // The console object has a log method, but no warn method. + + var Logger = { + warn: console$1 ? Function.prototype.bind.call(console$1.warn || console$1.log, console$1) : function () {} + }; + + var toString = Object.prototype.toString; + var hasOwn$1 = Object.prototype.hasOwnProperty; + var now = Date.now || function () { + return new Date().getTime(); + }; + var nativePerf = getNativePerf(); + + function getNativePerf() { + if (window$1 && typeof window$1.performance !== "undefined" && typeof window$1.performance.mark === "function" && typeof window$1.performance.measure === "function") { + return window$1.performance; + } else { + return undefined; + } + } + + var performance = { + now: nativePerf ? nativePerf.now.bind(nativePerf) : now, + measure: nativePerf ? function (comment, startMark, endMark) { + // `performance.measure` may fail if the mark could not be found. + // reasons a specific mark could not be found include: outside code invoking `performance.clearMarks()` + try { + nativePerf.measure(comment, startMark, endMark); + } catch (ex) { + Logger.warn("performance.measure could not be executed because of ", ex.message); + } + } : function () {}, + mark: nativePerf ? nativePerf.mark.bind(nativePerf) : function () {} + }; // Returns a new Array with the elements that are in a but not in b + + function diff(a, b) { + var result = a.slice(); + + for (var i = 0; i < result.length; i++) { + for (var j = 0; j < b.length; j++) { + if (result[i] === b[j]) { + result.splice(i, 1); + i--; + break; + } + } + } + + return result; + } + /** + * Determines whether an element exists in a given array or not. + * + * @method inArray + * @param {any} elem + * @param {Array} array + * @return {boolean} + */ + + function inArray(elem, array) { + return array.indexOf(elem) !== -1; + } + /** + * Makes a clone of an object using only Array or Object as base, + * and copies over the own enumerable properties. + * + * @param {Object} obj + * @return {Object} New object with only the own properties (recursively). + */ + + function objectValues(obj) { + var vals = is("array", obj) ? [] : {}; + + for (var key in obj) { + if (hasOwn$1.call(obj, key)) { + var val = obj[key]; + vals[key] = val === Object(val) ? objectValues(val) : val; + } + } + + return vals; + } + function extend(a, b, undefOnly) { + for (var prop in b) { + if (hasOwn$1.call(b, prop)) { + if (b[prop] === undefined) { + delete a[prop]; + } else if (!(undefOnly && typeof a[prop] !== "undefined")) { + a[prop] = b[prop]; + } + } + } + + return a; + } + function objectType(obj) { + if (typeof obj === "undefined") { + return "undefined"; + } // Consider: typeof null === object + + + if (obj === null) { + return "null"; + } + + var match = toString.call(obj).match(/^\[object\s(.*)\]$/); + var type = match && match[1]; + + switch (type) { + case "Number": + if (isNaN(obj)) { + return "nan"; + } + + return "number"; + + case "String": + case "Boolean": + case "Array": + case "Set": + case "Map": + case "Date": + case "RegExp": + case "Function": + case "Symbol": + return type.toLowerCase(); + + default: + return _typeof(obj); + } + } // Safe object type checking + + function is(type, obj) { + return objectType(obj) === type; + } // Based on Java's String.hashCode, a simple but not + // rigorously collision resistant hashing function + + function generateHash(module, testName) { + var str = module + "\x1C" + testName; + var hash = 0; + + for (var i = 0; i < str.length; i++) { + hash = (hash << 5) - hash + str.charCodeAt(i); + hash |= 0; + } // Convert the possibly negative integer hash code into an 8 character hex string, which isn't + // strictly necessary but increases user understanding that the id is a SHA-like hash + + + var hex = (0x100000000 + hash).toString(16); + + if (hex.length < 8) { + hex = "0000000" + hex; + } + + return hex.slice(-8); + } + /** + * Converts an error into a simple string for comparisons. + * + * @param {Error|any} error + * @return {string} + */ + + function errorString(error) { + // Use String() instead of toString() to handle non-object values like undefined or null. + var resultErrorString = String(error); // If the error wasn't a subclass of Error but something like + // an object literal with name and message properties... + + if (resultErrorString.slice(0, 7) === "[object") { + // Based on https://es5.github.io/#x15.11.4.4 + return (error.name || "Error") + (error.message ? ": ".concat(error.message) : ""); + } else { + return resultErrorString; + } + } + + // Authors: Philippe Rathé , David Chan + + var equiv = (function () { + // Value pairs queued for comparison. Used for breadth-first processing order, recursion + // detection and avoiding repeated comparison (see below for details). + // Elements are { a: val, b: val }. + var pairs = []; + + var getProto = Object.getPrototypeOf || function (obj) { + return obj.__proto__; + }; + + function useStrictEquality(a, b) { + // This only gets called if a and b are not strict equal, and is used to compare on + // the primitive values inside object wrappers. For example: + // `var i = 1;` + // `var j = new Number(1);` + // Neither a nor b can be null, as a !== b and they have the same type. + if (_typeof(a) === "object") { + a = a.valueOf(); + } + + if (_typeof(b) === "object") { + b = b.valueOf(); + } + + return a === b; + } + + function compareConstructors(a, b) { + var protoA = getProto(a); + var protoB = getProto(b); // Comparing constructors is more strict than using `instanceof` + + if (a.constructor === b.constructor) { + return true; + } // Ref #851 + // If the obj prototype descends from a null constructor, treat it + // as a null prototype. + + + if (protoA && protoA.constructor === null) { + protoA = null; + } + + if (protoB && protoB.constructor === null) { + protoB = null; + } // Allow objects with no prototype to be equivalent to + // objects with Object as their constructor. + + + if (protoA === null && protoB === Object.prototype || protoB === null && protoA === Object.prototype) { + return true; + } + + return false; + } + + function getRegExpFlags(regexp) { + return "flags" in regexp ? regexp.flags : regexp.toString().match(/[gimuy]*$/)[0]; + } + + function isContainer(val) { + return ["object", "array", "map", "set"].indexOf(objectType(val)) !== -1; + } + + function breadthFirstCompareChild(a, b) { + // If a is a container not reference-equal to b, postpone the comparison to the + // end of the pairs queue -- unless (a, b) has been seen before, in which case skip + // over the pair. + if (a === b) { + return true; + } + + if (!isContainer(a)) { + return typeEquiv(a, b); + } + + if (pairs.every(function (pair) { + return pair.a !== a || pair.b !== b; + })) { + // Not yet started comparing this pair + pairs.push({ + a: a, + b: b + }); + } + + return true; + } + + var callbacks = { + "string": useStrictEquality, + "boolean": useStrictEquality, + "number": useStrictEquality, + "null": useStrictEquality, + "undefined": useStrictEquality, + "symbol": useStrictEquality, + "date": useStrictEquality, + "nan": function nan() { + return true; + }, + "regexp": function regexp(a, b) { + return a.source === b.source && // Include flags in the comparison + getRegExpFlags(a) === getRegExpFlags(b); + }, + // abort (identical references / instance methods were skipped earlier) + "function": function _function() { + return false; + }, + "array": function array(a, b) { + var len = a.length; + + if (len !== b.length) { + // Safe and faster + return false; + } + + for (var i = 0; i < len; i++) { + // Compare non-containers; queue non-reference-equal containers + if (!breadthFirstCompareChild(a[i], b[i])) { + return false; + } + } + + return true; + }, + // Define sets a and b to be equivalent if for each element aVal in a, there + // is some element bVal in b such that aVal and bVal are equivalent. Element + // repetitions are not counted, so these are equivalent: + // a = new Set( [ {}, [], [] ] ); + // b = new Set( [ {}, {}, [] ] ); + "set": function set(a, b) { + if (a.size !== b.size) { + // This optimization has certain quirks because of the lack of + // repetition counting. For instance, adding the same + // (reference-identical) element to two equivalent sets can + // make them non-equivalent. + return false; + } + + var outerEq = true; + a.forEach(function (aVal) { + // Short-circuit if the result is already known. (Using for...of + // with a break clause would be cleaner here, but it would cause + // a syntax error on older JavaScript implementations even if + // Set is unused) + if (!outerEq) { + return; + } + + var innerEq = false; + b.forEach(function (bVal) { + // Likewise, short-circuit if the result is already known + if (innerEq) { + return; + } // Swap out the global pairs list, as the nested call to + // innerEquiv will clobber its contents + + + var parentPairs = pairs; + + if (innerEquiv(bVal, aVal)) { + innerEq = true; + } // Replace the global pairs list + + + pairs = parentPairs; + }); + + if (!innerEq) { + outerEq = false; + } + }); + return outerEq; + }, + // Define maps a and b to be equivalent if for each key-value pair (aKey, aVal) + // in a, there is some key-value pair (bKey, bVal) in b such that + // [ aKey, aVal ] and [ bKey, bVal ] are equivalent. Key repetitions are not + // counted, so these are equivalent: + // a = new Map( [ [ {}, 1 ], [ {}, 1 ], [ [], 1 ] ] ); + // b = new Map( [ [ {}, 1 ], [ [], 1 ], [ [], 1 ] ] ); + "map": function map(a, b) { + if (a.size !== b.size) { + // This optimization has certain quirks because of the lack of + // repetition counting. For instance, adding the same + // (reference-identical) key-value pair to two equivalent maps + // can make them non-equivalent. + return false; + } + + var outerEq = true; + a.forEach(function (aVal, aKey) { + // Short-circuit if the result is already known. (Using for...of + // with a break clause would be cleaner here, but it would cause + // a syntax error on older JavaScript implementations even if + // Map is unused) + if (!outerEq) { + return; + } + + var innerEq = false; + b.forEach(function (bVal, bKey) { + // Likewise, short-circuit if the result is already known + if (innerEq) { + return; + } // Swap out the global pairs list, as the nested call to + // innerEquiv will clobber its contents + + + var parentPairs = pairs; + + if (innerEquiv([bVal, bKey], [aVal, aKey])) { + innerEq = true; + } // Replace the global pairs list + + + pairs = parentPairs; + }); + + if (!innerEq) { + outerEq = false; + } + }); + return outerEq; + }, + "object": function object(a, b) { + if (compareConstructors(a, b) === false) { + return false; + } + + var aProperties = []; + var bProperties = []; // Be strict: don't ensure hasOwnProperty and go deep + + for (var i in a) { + // Collect a's properties + aProperties.push(i); // Skip OOP methods that look the same + + if (a.constructor !== Object && typeof a.constructor !== "undefined" && typeof a[i] === "function" && typeof b[i] === "function" && a[i].toString() === b[i].toString()) { + continue; + } // Compare non-containers; queue non-reference-equal containers + + + if (!breadthFirstCompareChild(a[i], b[i])) { + return false; + } + } + + for (var _i in b) { + // Collect b's properties + bProperties.push(_i); + } // Ensures identical properties name + + + return typeEquiv(aProperties.sort(), bProperties.sort()); + } + }; + + function typeEquiv(a, b) { + var type = objectType(a); // Callbacks for containers will append to the pairs queue to achieve breadth-first + // search order. The pairs queue is also used to avoid reprocessing any pair of + // containers that are reference-equal to a previously visited pair (a special case + // this being recursion detection). + // + // Because of this approach, once typeEquiv returns a false value, it should not be + // called again without clearing the pair queue else it may wrongly report a visited + // pair as being equivalent. + + return objectType(b) === type && callbacks[type](a, b); + } + + function innerEquiv(a, b) { + // We're done when there's nothing more to compare + if (arguments.length < 2) { + return true; + } // Clear the global pair queue and add the top-level values being compared + + + pairs = [{ + a: a, + b: b + }]; + + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i]; // Perform type-specific comparison on any pairs that are not strictly + // equal. For container types, that comparison will postpone comparison + // of any sub-container pair to the end of the pair queue. This gives + // breadth-first search order. It also avoids the reprocessing of + // reference-equal siblings, cousins etc, which can have a significant speed + // impact when comparing a container of small objects each of which has a + // reference to the same (singleton) large object. + + if (pair.a !== pair.b && !typeEquiv(pair.a, pair.b)) { + return false; + } + } // ...across all consecutive argument pairs + + + return arguments.length === 2 || innerEquiv.apply(this, [].slice.call(arguments, 1)); + } + + return function () { + var result = innerEquiv.apply(void 0, arguments); // Release any retained objects + + pairs.length = 0; + return result; + }; + })(); + + /** + * Config object: Maintain internal state + * Later exposed as QUnit.config + * `config` initialized at top of scope + */ + + var config = { + // The queue of tests to run + queue: [], + stats: { + all: 0, + bad: 0, + testCount: 0 + }, + // Block until document ready + blocking: true, + // whether or not to fail when there are zero tests + // defaults to `true` + failOnZeroTests: true, + // By default, run previously failed tests first + // very useful in combination with "Hide passed tests" checked + reorder: true, + // By default, modify document.title when suite is done + altertitle: true, + // HTML Reporter: collapse every test except the first failing test + // If false, all failing tests will be expanded + collapse: true, + // By default, scroll to top of the page when suite is done + scrolltop: true, + // Depth up-to which object will be dumped + maxDepth: 5, + // When enabled, all tests must call expect() + requireExpects: false, + // Placeholder for user-configurable form-exposed URL parameters + urlConfig: [], + // Set of all modules. + modules: [], + // The first unnamed module + currentModule: { + name: "", + tests: [], + childModules: [], + testsRun: 0, + testsIgnored: 0, + hooks: { + before: [], + beforeEach: [], + afterEach: [], + after: [] + } + }, + callbacks: {}, + // The storage module to use for reordering tests + storage: localSessionStorage + }; // take a predefined QUnit.config and extend the defaults + + var globalConfig = window$1 && window$1.QUnit && window$1.QUnit.config; // only extend the global config if there is no QUnit overload + + if (window$1 && window$1.QUnit && !window$1.QUnit.version) { + extend(config, globalConfig); + } // Push a loose unnamed module to the modules collection + + + config.modules.push(config.currentModule); + + var dump = (function () { + function quote(str) { + return "\"" + str.toString().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\""; + } + + function literal(o) { + return o + ""; + } + + function join(pre, arr, post) { + var s = dump.separator(); + var inner = dump.indent(1); + + if (arr.join) { + arr = arr.join("," + s + inner); + } + + if (!arr) { + return pre + post; + } + + var base = dump.indent(); + return [pre, inner + arr, base + post].join(s); + } + + function array(arr, stack) { + if (dump.maxDepth && dump.depth > dump.maxDepth) { + return "[object Array]"; + } + + this.up(); + var i = arr.length; + var ret = new Array(i); + + while (i--) { + ret[i] = this.parse(arr[i], undefined, stack); + } + + this.down(); + return join("[", ret, "]"); + } + + function isArray(obj) { + return (//Native Arrays + toString.call(obj) === "[object Array]" || // NodeList objects + typeof obj.length === "number" && obj.item !== undefined && (obj.length ? obj.item(0) === obj[0] : obj.item(0) === null && obj[0] === undefined) + ); + } + + var reName = /^function (\w+)/; + var dump = { + // The objType is used mostly internally, you can fix a (custom) type in advance + parse: function parse(obj, objType, stack) { + stack = stack || []; + var objIndex = stack.indexOf(obj); + + if (objIndex !== -1) { + return "recursion(".concat(objIndex - stack.length, ")"); + } + + objType = objType || this.typeOf(obj); + var parser = this.parsers[objType]; + + var parserType = _typeof(parser); + + if (parserType === "function") { + stack.push(obj); + var res = parser.call(this, obj, stack); + stack.pop(); + return res; + } + + if (parserType === "string") { + return parser; + } + + return "[ERROR: Missing QUnit.dump formatter for type " + objType + "]"; + }, + typeOf: function typeOf(obj) { + var type; + + if (obj === null) { + type = "null"; + } else if (typeof obj === "undefined") { + type = "undefined"; + } else if (is("regexp", obj)) { + type = "regexp"; + } else if (is("date", obj)) { + type = "date"; + } else if (is("function", obj)) { + type = "function"; + } else if (obj.setInterval !== undefined && obj.document !== undefined && obj.nodeType === undefined) { + type = "window"; + } else if (obj.nodeType === 9) { + type = "document"; + } else if (obj.nodeType) { + type = "node"; + } else if (isArray(obj)) { + type = "array"; + } else if (obj.constructor === Error.prototype.constructor) { + type = "error"; + } else { + type = _typeof(obj); + } + + return type; + }, + separator: function separator() { + if (this.multiline) { + return this.HTML ? "
      " : "\n"; + } else { + return this.HTML ? " " : " "; + } + }, + // Extra can be a number, shortcut for increasing-calling-decreasing + indent: function indent(extra) { + if (!this.multiline) { + return ""; + } + + var chr = this.indentChar; + + if (this.HTML) { + chr = chr.replace(/\t/g, " ").replace(/ /g, " "); + } + + return new Array(this.depth + (extra || 0)).join(chr); + }, + up: function up(a) { + this.depth += a || 1; + }, + down: function down(a) { + this.depth -= a || 1; + }, + setParser: function setParser(name, parser) { + this.parsers[name] = parser; + }, + // The next 3 are exposed so you can use them + quote: quote, + literal: literal, + join: join, + depth: 1, + maxDepth: config.maxDepth, + // This is the list of parsers, to modify them, use dump.setParser + parsers: { + window: "[Window]", + document: "[Document]", + error: function error(_error) { + return "Error(\"" + _error.message + "\")"; + }, + // This has been unused since QUnit 1.0.0. + // @todo Deprecate and remove. + unknown: "[Unknown]", + "null": "null", + "undefined": "undefined", + "function": function _function(fn) { + var ret = "function"; // Functions never have name in IE + + var name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1]; + + if (name) { + ret += " " + name; + } + + ret += "("; + ret = [ret, dump.parse(fn, "functionArgs"), "){"].join(""); + return join(ret, dump.parse(fn, "functionCode"), "}"); + }, + array: array, + nodelist: array, + "arguments": array, + object: function object(map, stack) { + var ret = []; + + if (dump.maxDepth && dump.depth > dump.maxDepth) { + return "[object Object]"; + } + + dump.up(); + var keys = []; + + for (var key in map) { + keys.push(key); + } // Some properties are not always enumerable on Error objects. + + + var nonEnumerableProperties = ["message", "name"]; + + for (var i in nonEnumerableProperties) { + var _key = nonEnumerableProperties[i]; + + if (_key in map && !inArray(_key, keys)) { + keys.push(_key); + } + } + + keys.sort(); + + for (var _i = 0; _i < keys.length; _i++) { + var _key2 = keys[_i]; + var val = map[_key2]; + ret.push(dump.parse(_key2, "key") + ": " + dump.parse(val, undefined, stack)); + } + + dump.down(); + return join("{", ret, "}"); + }, + node: function node(_node) { + var open = dump.HTML ? "<" : "<"; + var close = dump.HTML ? ">" : ">"; + + var tag = _node.nodeName.toLowerCase(); + + var ret = open + tag; + var attrs = _node.attributes; + + if (attrs) { + for (var i = 0, len = attrs.length; i < len; i++) { + var val = attrs[i].nodeValue; // IE6 includes all attributes in .attributes, even ones not explicitly + // set. Those have values like undefined, null, 0, false, "" or + // "inherit". + + if (val && val !== "inherit") { + ret += " " + attrs[i].nodeName + "=" + dump.parse(val, "attribute"); + } + } + } + + ret += close; // Show content of TextNode or CDATASection + + if (_node.nodeType === 3 || _node.nodeType === 4) { + ret += _node.nodeValue; + } + + return ret + open + "/" + tag + close; + }, + // Function calls it internally, it's the arguments part of the function + functionArgs: function functionArgs(fn) { + var l = fn.length; + + if (!l) { + return ""; + } + + var args = new Array(l); + + while (l--) { + // 97 is 'a' + args[l] = String.fromCharCode(97 + l); + } + + return " " + args.join(", ") + " "; + }, + // Object calls it internally, the key part of an item in a map + key: quote, + // Function calls it internally, it's the content of the function + functionCode: "[code]", + // Node calls it internally, it's a html attribute value + attribute: quote, + string: quote, + date: quote, + regexp: literal, + number: literal, + "boolean": literal, + symbol: function symbol(sym) { + return sym.toString(); + } + }, + // If true, entities are escaped ( <, >, \t, space and \n ) + HTML: false, + // Indentation unit + indentChar: " ", + // If true, items in a collection, are separated by a \n, else just a space. + multiline: true + }; + return dump; + })(); + + var SuiteReport = /*#__PURE__*/function () { + function SuiteReport(name, parentSuite) { + _classCallCheck(this, SuiteReport); + + this.name = name; + this.fullName = parentSuite ? parentSuite.fullName.concat(name) : []; // When an "error" event is emitted from onUncaughtException(), the + // "runEnd" event should report the status as failed. + // The "runEnd" event data is made by this class (as "globalSuite"). + + this.globalFailureCount = 0; + this.tests = []; + this.childSuites = []; + + if (parentSuite) { + parentSuite.pushChildSuite(this); + } + } + + _createClass(SuiteReport, [{ + key: "start", + value: function start(recordTime) { + if (recordTime) { + this._startTime = performance.now(); + var suiteLevel = this.fullName.length; + performance.mark("qunit_suite_".concat(suiteLevel, "_start")); + } + + return { + name: this.name, + fullName: this.fullName.slice(), + tests: this.tests.map(function (test) { + return test.start(); + }), + childSuites: this.childSuites.map(function (suite) { + return suite.start(); + }), + testCounts: { + total: this.getTestCounts().total + } + }; + } + }, { + key: "end", + value: function end(recordTime) { + if (recordTime) { + this._endTime = performance.now(); + var suiteLevel = this.fullName.length; + var suiteName = this.fullName.join(" – "); + performance.mark("qunit_suite_".concat(suiteLevel, "_end")); + performance.measure(suiteLevel === 0 ? "QUnit Test Run" : "QUnit Test Suite: ".concat(suiteName), "qunit_suite_".concat(suiteLevel, "_start"), "qunit_suite_".concat(suiteLevel, "_end")); + } + + return { + name: this.name, + fullName: this.fullName.slice(), + tests: this.tests.map(function (test) { + return test.end(); + }), + childSuites: this.childSuites.map(function (suite) { + return suite.end(); + }), + testCounts: this.getTestCounts(), + runtime: this.getRuntime(), + status: this.getStatus() + }; + } + }, { + key: "pushChildSuite", + value: function pushChildSuite(suite) { + this.childSuites.push(suite); + } + }, { + key: "pushTest", + value: function pushTest(test) { + this.tests.push(test); + } + }, { + key: "getRuntime", + value: function getRuntime() { + return this._endTime - this._startTime; + } + }, { + key: "getTestCounts", + value: function getTestCounts() { + var counts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { + passed: 0, + failed: 0, + skipped: 0, + todo: 0, + total: 0 + }; + counts.failed += this.globalFailureCount; + counts.total += this.globalFailureCount; + counts = this.tests.reduce(function (counts, test) { + if (test.valid) { + counts[test.getStatus()]++; + counts.total++; + } + + return counts; + }, counts); + return this.childSuites.reduce(function (counts, suite) { + return suite.getTestCounts(counts); + }, counts); + } + }, { + key: "getStatus", + value: function getStatus() { + var _this$getTestCounts = this.getTestCounts(), + total = _this$getTestCounts.total, + failed = _this$getTestCounts.failed, + skipped = _this$getTestCounts.skipped, + todo = _this$getTestCounts.todo; + + if (failed) { + return "failed"; + } else { + if (skipped === total) { + return "skipped"; + } else if (todo === total) { + return "todo"; + } else { + return "passed"; + } + } + } + }]); + + return SuiteReport; + }(); + + var moduleStack = []; + + function isParentModuleInQueue() { + var modulesInQueue = config.modules.filter(function (module) { + return !module.ignored; + }).map(function (module) { + return module.moduleId; + }); + return moduleStack.some(function (module) { + return modulesInQueue.includes(module.moduleId); + }); + } + + function createModule(name, testEnvironment, modifiers) { + var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null; + var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name; + var parentSuite = parentModule ? parentModule.suiteReport : globalSuite; + var skip = parentModule !== null && parentModule.skip || modifiers.skip; + var todo = parentModule !== null && parentModule.todo || modifiers.todo; + var module = { + name: moduleName, + parentModule: parentModule, + tests: [], + moduleId: generateHash(moduleName), + testsRun: 0, + testsIgnored: 0, + childModules: [], + suiteReport: new SuiteReport(name, parentSuite), + // Pass along `skip` and `todo` properties from parent module, in case + // there is one, to childs. And use own otherwise. + // This property will be used to mark own tests and tests of child suites + // as either `skipped` or `todo`. + skip: skip, + todo: skip ? false : todo, + ignored: modifiers.ignored || false + }; + var env = {}; + + if (parentModule) { + parentModule.childModules.push(module); + extend(env, parentModule.testEnvironment); + } + + extend(env, testEnvironment); + module.testEnvironment = env; + config.modules.push(module); + return module; + } + + function processModule(name, options, executeNow) { + var modifiers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + if (objectType(options) === "function") { + executeNow = options; + options = undefined; + } + + var module = createModule(name, options, modifiers); // Move any hooks to a 'hooks' object + + var testEnvironment = module.testEnvironment; + var hooks = module.hooks = {}; + setHookFromEnvironment(hooks, testEnvironment, "before"); + setHookFromEnvironment(hooks, testEnvironment, "beforeEach"); + setHookFromEnvironment(hooks, testEnvironment, "afterEach"); + setHookFromEnvironment(hooks, testEnvironment, "after"); + var moduleFns = { + before: setHookFunction(module, "before"), + beforeEach: setHookFunction(module, "beforeEach"), + afterEach: setHookFunction(module, "afterEach"), + after: setHookFunction(module, "after") + }; + var prevModule = config.currentModule; + config.currentModule = module; + + if (objectType(executeNow) === "function") { + moduleStack.push(module); + + try { + var cbReturnValue = executeNow.call(module.testEnvironment, moduleFns); + + if (cbReturnValue != null && objectType(cbReturnValue.then) === "function") { + Logger.warn("Returning a promise from a module callback is not supported. " + "Instead, use hooks for async behavior. " + "This will become an error in QUnit 3.0."); + } + } finally { + // If the module closure threw an uncaught error during the load phase, + // we let this bubble up to global error handlers. But, not until after + // we teardown internal state to ensure correct module nesting. + // Ref https://github.com/qunitjs/qunit/issues/1478. + moduleStack.pop(); + config.currentModule = module.parentModule || prevModule; + } + } + + function setHookFromEnvironment(hooks, environment, name) { + var potentialHook = environment[name]; + hooks[name] = typeof potentialHook === "function" ? [potentialHook] : []; + delete environment[name]; + } + + function setHookFunction(module, hookName) { + return function setHook(callback) { + if (config.currentModule !== module) { + Logger.warn("The `" + hookName + "` hook was called inside the wrong module (`" + config.currentModule.name + "`). " + "Instead, use hooks provided by the callback to the containing module (`" + module.name + "`). " + "This will become an error in QUnit 3.0."); + } + + module.hooks[hookName].push(callback); + }; + } + } + + var focused$1 = false; // indicates that the "only" filter was used + + function module$1(name, options, executeNow) { + var ignored = focused$1 && !isParentModuleInQueue(); + processModule(name, options, executeNow, { + ignored: ignored + }); + } + + module$1.only = function () { + if (!focused$1) { + // Upon the first module.only() call, + // delete any and all previously registered modules and tests. + config.modules.length = 0; + config.queue.length = 0; // Ignore any tests declared after this block within the same + // module parent. https://github.com/qunitjs/qunit/issues/1645 + + config.currentModule.ignored = true; + } + + focused$1 = true; + processModule.apply(void 0, arguments); + }; + + module$1.skip = function (name, options, executeNow) { + if (focused$1) { + return; + } + + processModule(name, options, executeNow, { + skip: true + }); + }; + + module$1.todo = function (name, options, executeNow) { + if (focused$1) { + return; + } + + processModule(name, options, executeNow, { + todo: true + }); + }; + + var LISTENERS = Object.create(null); + var SUPPORTED_EVENTS = ["error", "runStart", "suiteStart", "testStart", "assertion", "testEnd", "suiteEnd", "runEnd"]; + /** + * Emits an event with the specified data to all currently registered listeners. + * Callbacks will fire in the order in which they are registered (FIFO). This + * function is not exposed publicly; it is used by QUnit internals to emit + * logging events. + * + * @private + * @method emit + * @param {string} eventName + * @param {Object} data + * @return {void} + */ + + function emit(eventName, data) { + if (objectType(eventName) !== "string") { + throw new TypeError("eventName must be a string when emitting an event"); + } // Clone the callbacks in case one of them registers a new callback + + + var originalCallbacks = LISTENERS[eventName]; + var callbacks = originalCallbacks ? _toConsumableArray(originalCallbacks) : []; + + for (var i = 0; i < callbacks.length; i++) { + callbacks[i](data); + } + } + /** + * Registers a callback as a listener to the specified event. + * + * @public + * @method on + * @param {string} eventName + * @param {Function} callback + * @return {void} + */ + + function on(eventName, callback) { + if (objectType(eventName) !== "string") { + throw new TypeError("eventName must be a string when registering a listener"); + } else if (!inArray(eventName, SUPPORTED_EVENTS)) { + var events = SUPPORTED_EVENTS.join(", "); + throw new Error("\"".concat(eventName, "\" is not a valid event; must be one of: ").concat(events, ".")); + } else if (objectType(callback) !== "function") { + throw new TypeError("callback must be a function when registering a listener"); + } + + if (!LISTENERS[eventName]) { + LISTENERS[eventName] = []; + } // Don't register the same callback more than once + + + if (!inArray(callback, LISTENERS[eventName])) { + LISTENERS[eventName].push(callback); + } + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function commonjsRequire (path) { + throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); + } + + var promisePolyfill = {exports: {}}; + + (function () { + /** @suppress {undefinedVars} */ + + var globalNS = function () { + // the only reliable means to get the global object is + // `Function('return this')()` + // However, this causes CSP violations in Chrome apps. + if (typeof globalThis !== 'undefined') { + return globalThis; + } + + if (typeof self !== 'undefined') { + return self; + } + + if (typeof window !== 'undefined') { + return window; + } + + if (typeof commonjsGlobal !== 'undefined') { + return commonjsGlobal; + } + + throw new Error('unable to locate global object'); + }(); // Expose the polyfill if Promise is undefined or set to a + // non-function value. The latter can be due to a named HTMLElement + // being exposed by browsers for legacy reasons. + // https://github.com/taylorhakes/promise-polyfill/issues/114 + + + if (typeof globalNS['Promise'] === 'function') { + promisePolyfill.exports = globalNS['Promise']; + return; + } + /** + * @this {Promise} + */ + + + function finallyConstructor(callback) { + var constructor = this.constructor; + return this.then(function (value) { + // @ts-ignore + return constructor.resolve(callback()).then(function () { + return value; + }); + }, function (reason) { + // @ts-ignore + return constructor.resolve(callback()).then(function () { + // @ts-ignore + return constructor.reject(reason); + }); + }); + } + + function allSettled(arr) { + var P = this; + return new P(function (resolve, reject) { + if (!(arr && typeof arr.length !== 'undefined')) { + return reject(new TypeError(_typeof(arr) + ' ' + arr + ' is not iterable(cannot read property Symbol(Symbol.iterator))')); + } + + var args = Array.prototype.slice.call(arr); + if (args.length === 0) return resolve([]); + var remaining = args.length; + + function res(i, val) { + if (val && (_typeof(val) === 'object' || typeof val === 'function')) { + var then = val.then; + + if (typeof then === 'function') { + then.call(val, function (val) { + res(i, val); + }, function (e) { + args[i] = { + status: 'rejected', + reason: e + }; + + if (--remaining === 0) { + resolve(args); + } + }); + return; + } + } + + args[i] = { + status: 'fulfilled', + value: val + }; + + if (--remaining === 0) { + resolve(args); + } + } + + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); + } // Store setTimeout reference so promise-polyfill will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + + + var setTimeoutFunc = setTimeout; + + function isArray(x) { + return Boolean(x && typeof x.length !== 'undefined'); + } + + function noop() {} // Polyfill for Function.prototype.bind + + + function bind(fn, thisArg) { + return function () { + fn.apply(thisArg, arguments); + }; + } + /** + * @constructor + * @param {Function} fn + */ + + + function Promise(fn) { + if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); + if (typeof fn !== 'function') throw new TypeError('not a function'); + /** @type {!number} */ + + this._state = 0; + /** @type {!boolean} */ + + this._handled = false; + /** @type {Promise|undefined} */ + + this._value = undefined; + /** @type {!Array} */ + + this._deferreds = []; + doResolve(fn, this); + } + + function handle(self, deferred) { + while (self._state === 3) { + self = self._value; + } + + if (self._state === 0) { + self._deferreds.push(deferred); + + return; + } + + self._handled = true; + + Promise._immediateFn(function () { + var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; + + if (cb === null) { + (self._state === 1 ? resolve : reject)(deferred.promise, self._value); + return; + } + + var ret; + + try { + ret = cb(self._value); + } catch (e) { + reject(deferred.promise, e); + return; + } + + resolve(deferred.promise, ret); + }); + } + + function resolve(self, newValue) { + try { + // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure + if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); + + if (newValue && (_typeof(newValue) === 'object' || typeof newValue === 'function')) { + var then = newValue.then; + + if (newValue instanceof Promise) { + self._state = 3; + self._value = newValue; + finale(self); + return; + } else if (typeof then === 'function') { + doResolve(bind(then, newValue), self); + return; + } + } + + self._state = 1; + self._value = newValue; + finale(self); + } catch (e) { + reject(self, e); + } + } + + function reject(self, newValue) { + self._state = 2; + self._value = newValue; + finale(self); + } + + function finale(self) { + if (self._state === 2 && self._deferreds.length === 0) { + Promise._immediateFn(function () { + if (!self._handled) { + Promise._unhandledRejectionFn(self._value); + } + }); + } + + for (var i = 0, len = self._deferreds.length; i < len; i++) { + handle(self, self._deferreds[i]); + } + + self._deferreds = null; + } + /** + * @constructor + */ + + + function Handler(onFulfilled, onRejected, promise) { + this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; + this.onRejected = typeof onRejected === 'function' ? onRejected : null; + this.promise = promise; + } + /** + * Take a potentially misbehaving resolver function and make sure + * onFulfilled and onRejected are only called once. + * + * Makes no guarantees about asynchrony. + */ + + + function doResolve(fn, self) { + var done = false; + + try { + fn(function (value) { + if (done) return; + done = true; + resolve(self, value); + }, function (reason) { + if (done) return; + done = true; + reject(self, reason); + }); + } catch (ex) { + if (done) return; + done = true; + reject(self, ex); + } + } + + Promise.prototype['catch'] = function (onRejected) { + return this.then(null, onRejected); + }; + + Promise.prototype.then = function (onFulfilled, onRejected) { + // @ts-ignore + var prom = new this.constructor(noop); + handle(this, new Handler(onFulfilled, onRejected, prom)); + return prom; + }; + + Promise.prototype['finally'] = finallyConstructor; + + Promise.all = function (arr) { + return new Promise(function (resolve, reject) { + if (!isArray(arr)) { + return reject(new TypeError('Promise.all accepts an array')); + } + + var args = Array.prototype.slice.call(arr); + if (args.length === 0) return resolve([]); + var remaining = args.length; + + function res(i, val) { + try { + if (val && (_typeof(val) === 'object' || typeof val === 'function')) { + var then = val.then; + + if (typeof then === 'function') { + then.call(val, function (val) { + res(i, val); + }, reject); + return; + } + } + + args[i] = val; + + if (--remaining === 0) { + resolve(args); + } + } catch (ex) { + reject(ex); + } + } + + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); + }; + + Promise.allSettled = allSettled; + + Promise.resolve = function (value) { + if (value && _typeof(value) === 'object' && value.constructor === Promise) { + return value; + } + + return new Promise(function (resolve) { + resolve(value); + }); + }; + + Promise.reject = function (value) { + return new Promise(function (resolve, reject) { + reject(value); + }); + }; + + Promise.race = function (arr) { + return new Promise(function (resolve, reject) { + if (!isArray(arr)) { + return reject(new TypeError('Promise.race accepts an array')); + } + + for (var i = 0, len = arr.length; i < len; i++) { + Promise.resolve(arr[i]).then(resolve, reject); + } + }); + }; // Use polyfill for setImmediate for performance gains + + + Promise._immediateFn = // @ts-ignore + typeof setImmediate === 'function' && function (fn) { + // @ts-ignore + setImmediate(fn); + } || function (fn) { + setTimeoutFunc(fn, 0); + }; + + Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { + if (typeof console !== 'undefined' && console) { + console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console + } + }; + + promisePolyfill.exports = Promise; + })(); + + var _Promise = promisePolyfill.exports; + + function registerLoggingCallbacks(obj) { + var callbackNames = ["begin", "done", "log", "testStart", "testDone", "moduleStart", "moduleDone"]; + + function registerLoggingCallback(key) { + var loggingCallback = function loggingCallback(callback) { + if (objectType(callback) !== "function") { + throw new Error("QUnit logging methods require a callback function as their first parameters."); + } + + config.callbacks[key].push(callback); + }; + + return loggingCallback; + } + + for (var i = 0, l = callbackNames.length; i < l; i++) { + var key = callbackNames[i]; // Initialize key collection of logging callback + + if (objectType(config.callbacks[key]) === "undefined") { + config.callbacks[key] = []; + } + + obj[key] = registerLoggingCallback(key); + } + } + function runLoggingCallbacks(key, args) { + var callbacks = config.callbacks[key]; // Handling 'log' callbacks separately. Unlike the other callbacks, + // the log callback is not controlled by the processing queue, + // but rather used by asserts. Hence to promisfy the 'log' callback + // would mean promisfying each step of a test + + if (key === "log") { + callbacks.map(function (callback) { + return callback(args); + }); + return; + } // ensure that each callback is executed serially + + + return callbacks.reduce(function (promiseChain, callback) { + return promiseChain.then(function () { + return _Promise.resolve(callback(args)); + }); + }, _Promise.resolve([])); + } + + // Doesn't support IE9, it will return undefined on these browsers + // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack + var fileName = (sourceFromStacktrace(0) || "").replace(/(:\d+)+\)?/, "").replace(/.+\//, ""); + function extractStacktrace(e, offset) { + offset = offset === undefined ? 4 : offset; + + if (e && e.stack) { + var stack = e.stack.split("\n"); + + if (/^error$/i.test(stack[0])) { + stack.shift(); + } + + if (fileName) { + var include = []; + + for (var i = offset; i < stack.length; i++) { + if (stack[i].indexOf(fileName) !== -1) { + break; + } + + include.push(stack[i]); + } + + if (include.length) { + return include.join("\n"); + } + } + + return stack[offset]; + } + } + function sourceFromStacktrace(offset) { + var error = new Error(); // Support: Safari <=7 only, IE <=10 - 11 only + // Not all browsers generate the `stack` property for `new Error()`, see also #636 + + if (!error.stack) { + try { + throw error; + } catch (err) { + error = err; + } + } + + return extractStacktrace(error, offset); + } + + var priorityCount = 0; + var unitSampler; // This is a queue of functions that are tasks within a single test. + // After tests are dequeued from config.queue they are expanded into + // a set of tasks in this queue. + + var taskQueue = []; + /** + * Advances the taskQueue to the next task. If the taskQueue is empty, + * process the testQueue + */ + + function advance() { + advanceTaskQueue(); + + if (!taskQueue.length && !config.blocking && !config.current) { + advanceTestQueue(); + } + } + /** + * Advances the taskQueue with an increased depth + */ + + + function advanceTaskQueue() { + var start = now(); + config.depth = (config.depth || 0) + 1; + processTaskQueue(start); + config.depth--; + } + /** + * Process the first task on the taskQueue as a promise. + * Each task is a function added by Test#queue() in /src/test.js + */ + + + function processTaskQueue(start) { + if (taskQueue.length && !config.blocking) { + var elapsedTime = now() - start; + + if (!setTimeout$1 || config.updateRate <= 0 || elapsedTime < config.updateRate) { + var task = taskQueue.shift(); + _Promise.resolve(task()).then(function () { + if (!taskQueue.length) { + advance(); + } else { + processTaskQueue(start); + } + }); + } else { + setTimeout$1(advance); + } + } + } + /** + * Advance the testQueue to the next test to process. Call done() if testQueue completes. + */ + + + function advanceTestQueue() { + if (!config.blocking && !config.queue.length && config.depth === 0) { + done(); + return; + } + + var testTasks = config.queue.shift(); + addToTaskQueue(testTasks()); + + if (priorityCount > 0) { + priorityCount--; + } + + advance(); + } + /** + * Enqueue the tasks for a test into the task queue. + * @param {Array} tasksArray + */ + + + function addToTaskQueue(tasksArray) { + taskQueue.push.apply(taskQueue, _toConsumableArray(tasksArray)); + } + /** + * Return the number of tasks remaining in the task queue to be processed. + * @return {number} + */ + + + function taskQueueLength() { + return taskQueue.length; + } + /** + * Adds a test to the TestQueue for execution. + * @param {Function} testTasksFunc + * @param {boolean} prioritize + * @param {string} seed + */ + + + function addToTestQueue(testTasksFunc, prioritize, seed) { + if (prioritize) { + config.queue.splice(priorityCount++, 0, testTasksFunc); + } else if (seed) { + if (!unitSampler) { + unitSampler = unitSamplerGenerator(seed); + } // Insert into a random position after all prioritized items + + + var index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1)); + config.queue.splice(priorityCount + index, 0, testTasksFunc); + } else { + config.queue.push(testTasksFunc); + } + } + /** + * Creates a seeded "sample" generator which is used for randomizing tests. + */ + + + function unitSamplerGenerator(seed) { + // 32-bit xorshift, requires only a nonzero seed + // https://excamera.com/sphinx/article-xorshift.html + var sample = parseInt(generateHash(seed), 16) || -1; + return function () { + sample ^= sample << 13; + sample ^= sample >>> 17; + sample ^= sample << 5; // ECMAScript has no unsigned number type + + if (sample < 0) { + sample += 0x100000000; + } + + return sample / 0x100000000; + }; + } + /** + * This function is called when the ProcessingQueue is done processing all + * items. It handles emitting the final run events. + */ + + + function done() { + // We have reached the end of the processing queue and are about to emit the + // "runEnd" event after which reporters typically stop listening and exit + // the process. First, check if we need to emit one final test. + if (config.stats.testCount === 0 && config.failOnZeroTests === true) { + var error; + + if (config.filter && config.filter.length) { + error = new Error("No tests matched the filter \"".concat(config.filter, "\".")); + } else if (config.module && config.module.length) { + error = new Error("No tests matched the module \"".concat(config.module, "\".")); + } else if (config.moduleId && config.moduleId.length) { + error = new Error("No tests matched the moduleId \"".concat(config.moduleId, "\".")); + } else if (config.testId && config.testId.length) { + error = new Error("No tests matched the testId \"".concat(config.testId, "\".")); + } else { + error = new Error("No tests were run."); + } + + test("global failure", extend(function (assert) { + assert.pushResult({ + result: false, + message: error.message, + source: error.stack + }); + }, { + validTest: true + })); // We do need to call `advance()` in order to resume the processing queue. + // Once this new test is finished processing, we'll reach `done` again, and + // that time the above condition will evaluate to false. + + advance(); + return; + } + + var storage = config.storage; + var runtime = now() - config.started; + var passed = config.stats.all - config.stats.bad; + ProcessingQueue.finished = true; + emit("runEnd", globalSuite.end(true)); + runLoggingCallbacks("done", { + passed: passed, + failed: config.stats.bad, + total: config.stats.all, + runtime: runtime + }).then(function () { + // Clear own storage items if all tests passed + if (storage && config.stats.bad === 0) { + for (var i = storage.length - 1; i >= 0; i--) { + var key = storage.key(i); + + if (key.indexOf("qunit-test-") === 0) { + storage.removeItem(key); + } + } + } + }); + } + + var ProcessingQueue = { + finished: false, + add: addToTestQueue, + advance: advance, + taskCount: taskQueueLength + }; + + var TestReport = /*#__PURE__*/function () { + function TestReport(name, suite, options) { + _classCallCheck(this, TestReport); + + this.name = name; + this.suiteName = suite.name; + this.fullName = suite.fullName.concat(name); + this.runtime = 0; + this.assertions = []; + this.skipped = !!options.skip; + this.todo = !!options.todo; + this.valid = options.valid; + this._startTime = 0; + this._endTime = 0; + suite.pushTest(this); + } + + _createClass(TestReport, [{ + key: "start", + value: function start(recordTime) { + if (recordTime) { + this._startTime = performance.now(); + performance.mark("qunit_test_start"); + } + + return { + name: this.name, + suiteName: this.suiteName, + fullName: this.fullName.slice() + }; + } + }, { + key: "end", + value: function end(recordTime) { + if (recordTime) { + this._endTime = performance.now(); + + if (performance) { + performance.mark("qunit_test_end"); + var testName = this.fullName.join(" – "); + performance.measure("QUnit Test: ".concat(testName), "qunit_test_start", "qunit_test_end"); + } + } + + return extend(this.start(), { + runtime: this.getRuntime(), + status: this.getStatus(), + errors: this.getFailedAssertions(), + assertions: this.getAssertions() + }); + } + }, { + key: "pushAssertion", + value: function pushAssertion(assertion) { + this.assertions.push(assertion); + } + }, { + key: "getRuntime", + value: function getRuntime() { + return this._endTime - this._startTime; + } + }, { + key: "getStatus", + value: function getStatus() { + if (this.skipped) { + return "skipped"; + } + + var testPassed = this.getFailedAssertions().length > 0 ? this.todo : !this.todo; + + if (!testPassed) { + return "failed"; + } else if (this.todo) { + return "todo"; + } else { + return "passed"; + } + } + }, { + key: "getFailedAssertions", + value: function getFailedAssertions() { + return this.assertions.filter(function (assertion) { + return !assertion.passed; + }); + } + }, { + key: "getAssertions", + value: function getAssertions() { + return this.assertions.slice(); + } // Remove actual and expected values from assertions. This is to prevent + // leaking memory throughout a test suite. + + }, { + key: "slimAssertions", + value: function slimAssertions() { + this.assertions = this.assertions.map(function (assertion) { + delete assertion.actual; + delete assertion.expected; + return assertion; + }); + } + }]); + + return TestReport; + }(); + + function Test(settings) { + this.expected = null; + this.assertions = []; + this.module = config.currentModule; + this.steps = []; + this.timeout = undefined; + this.data = undefined; + this.withData = false; + this.pauses = new Map(); + this.nextPauseId = 1; + extend(this, settings); // If a module is skipped, all its tests and the tests of the child suites + // should be treated as skipped even if they are defined as `only` or `todo`. + // As for `todo` module, all its tests will be treated as `todo` except for + // tests defined as `skip` which will be left intact. + // + // So, if a test is defined as `todo` and is inside a skipped module, we should + // then treat that test as if was defined as `skip`. + + if (this.module.skip) { + this.skip = true; + this.todo = false; // Skipped tests should be left intact + } else if (this.module.todo && !this.skip) { + this.todo = true; + } // Queuing a late test after the run has ended is not allowed. + // This was once supported for internal use by QUnit.onError(). + // Ref https://github.com/qunitjs/qunit/issues/1377 + + + if (ProcessingQueue.finished) { + // Using this for anything other than onError(), such as testing in QUnit.done(), + // is unstable and will likely result in the added tests being ignored by CI. + // (Meaning the CI passes irregardless of the added tests). + // + // TODO: Make this an error in QUnit 3.0 + // throw new Error( "Unexpected new test after the run already ended" ); + Logger.warn("Unexpected test after runEnd. This is unstable and will fail in QUnit 3.0."); + return; + } + + if (!this.skip && typeof this.callback !== "function") { + var method = this.todo ? "QUnit.todo" : "QUnit.test"; + throw new TypeError("You must provide a callback to ".concat(method, "(\"").concat(this.testName, "\")")); + } // No validation after this. Beyond this point, failures must be recorded as + // a completed test with errors, instead of early bail out. + // Otherwise, internals may be left in an inconsistent state. + // Ref https://github.com/qunitjs/qunit/issues/1514 + + + ++Test.count; + this.errorForStack = new Error(); + + if (this.callback && this.callback.validTest) { + // Omit the test-level trace for the internal "No tests" test failure, + // There is already an assertion-level trace, and that's noisy enough + // as it is. + this.errorForStack.stack = undefined; + } + + this.testReport = new TestReport(this.testName, this.module.suiteReport, { + todo: this.todo, + skip: this.skip, + valid: this.valid() + }); // Register unique strings + + for (var i = 0, l = this.module.tests; i < l.length; i++) { + if (this.module.tests[i].name === this.testName) { + this.testName += " "; + } + } + + this.testId = generateHash(this.module.name, this.testName); + this.module.tests.push({ + name: this.testName, + testId: this.testId, + skip: !!this.skip + }); + + if (this.skip) { + // Skipped tests will fully ignore any sent callback + this.callback = function () {}; + + this.async = false; + this.expected = 0; + } else { + this.assert = new Assert(this); + } + } + Test.count = 0; + + function getNotStartedModules(startModule) { + var module = startModule; + var modules = []; + + while (module && module.testsRun === 0) { + modules.push(module); + module = module.parentModule; + } // The above push modules from the child to the parent + // return a reversed order with the top being the top most parent module + + + return modules.reverse(); + } + + Test.prototype = { + // generating a stack trace can be expensive, so using a getter defers this until we need it + get stack() { + return extractStacktrace(this.errorForStack, 2); + }, + + before: function before() { + var _this = this; + + var module = this.module; + var notStartedModules = getNotStartedModules(module); // ensure the callbacks are executed serially for each module + + var callbackPromises = notStartedModules.reduce(function (promiseChain, startModule) { + return promiseChain.then(function () { + startModule.stats = { + all: 0, + bad: 0, + started: now() + }; + emit("suiteStart", startModule.suiteReport.start(true)); + return runLoggingCallbacks("moduleStart", { + name: startModule.name, + tests: startModule.tests + }); + }); + }, _Promise.resolve([])); + return callbackPromises.then(function () { + config.current = _this; + _this.testEnvironment = extend({}, module.testEnvironment); + _this.started = now(); + emit("testStart", _this.testReport.start(true)); + return runLoggingCallbacks("testStart", { + name: _this.testName, + module: module.name, + testId: _this.testId, + previousFailure: _this.previousFailure + }).then(function () { + if (!config.pollution) { + saveGlobal(); + } + }); + }); + }, + run: function run() { + config.current = this; + this.callbackStarted = now(); + + if (config.notrycatch) { + runTest(this); + return; + } + + try { + runTest(this); + } catch (e) { + this.pushFailure("Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + (e.message || e), extractStacktrace(e, 0)); // Else next test will carry the responsibility + + saveGlobal(); // Restart the tests if they're blocking + + if (config.blocking) { + internalRecover(this); + } + } + + function runTest(test) { + var promise; + + if (test.withData) { + promise = test.callback.call(test.testEnvironment, test.assert, test.data); + } else { + promise = test.callback.call(test.testEnvironment, test.assert); + } + + test.resolvePromise(promise); // If the test has an async "pause" on it, but the timeout is 0, then we push a + // failure as the test should be synchronous. + + if (test.timeout === 0 && test.pauses.size > 0) { + pushFailure("Test did not finish synchronously even though assert.timeout( 0 ) was used.", sourceFromStacktrace(2)); + } + } + }, + after: function after() { + checkPollution(); + }, + queueHook: function queueHook(hook, hookName, hookOwner) { + var _this2 = this; + + var callHook = function callHook() { + var promise = hook.call(_this2.testEnvironment, _this2.assert); + + _this2.resolvePromise(promise, hookName); + }; + + var runHook = function runHook() { + if (hookName === "before") { + if (hookOwner.testsRun !== 0) { + return; + } + + _this2.preserveEnvironment = true; + } // The 'after' hook should only execute when there are not tests left and + // when the 'after' and 'finish' tasks are the only tasks left to process + + + if (hookName === "after" && !lastTestWithinModuleExecuted(hookOwner) && (config.queue.length > 0 || ProcessingQueue.taskCount() > 2)) { + return; + } + + config.current = _this2; + + if (config.notrycatch) { + callHook(); + return; + } + + try { + callHook(); + } catch (error) { + _this2.pushFailure(hookName + " failed on " + _this2.testName + ": " + (error.message || error), extractStacktrace(error, 0)); + } + }; + + return runHook; + }, + // Currently only used for module level hooks, can be used to add global level ones + hooks: function hooks(handler) { + var hooks = []; + + function processHooks(test, module) { + if (module.parentModule) { + processHooks(test, module.parentModule); + } + + if (module.hooks[handler].length) { + for (var i = 0; i < module.hooks[handler].length; i++) { + hooks.push(test.queueHook(module.hooks[handler][i], handler, module)); + } + } + } // Hooks are ignored on skipped tests + + + if (!this.skip) { + processHooks(this, this.module); + } + + return hooks; + }, + finish: function finish() { + config.current = this; // Release the test callback to ensure that anything referenced has been + // released to be garbage collected. + + this.callback = undefined; + + if (this.steps.length) { + var stepsList = this.steps.join(", "); + this.pushFailure("Expected assert.verifySteps() to be called before end of test " + "after using assert.step(). Unverified steps: ".concat(stepsList), this.stack); + } + + if (config.requireExpects && this.expected === null) { + this.pushFailure("Expected number of assertions to be defined, but expect() was " + "not called.", this.stack); + } else if (this.expected !== null && this.expected !== this.assertions.length) { + this.pushFailure("Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack); + } else if (this.expected === null && !this.assertions.length) { + this.pushFailure("Expected at least one assertion, but none were run - call " + "expect(0) to accept zero assertions.", this.stack); + } + + var module = this.module; + var moduleName = module.name; + var testName = this.testName; + var skipped = !!this.skip; + var todo = !!this.todo; + var bad = 0; + var storage = config.storage; + this.runtime = now() - this.started; + config.stats.all += this.assertions.length; + config.stats.testCount += 1; + module.stats.all += this.assertions.length; + + for (var i = 0; i < this.assertions.length; i++) { + // A failing assertion will counts toward the HTML Reporter's + // "X assertions, Y failed" line even if it was inside a todo. + // Inverting this would be similarly confusing since all but the last + // passing assertion inside a todo test should be considered as good. + // These stats don't decide the outcome of anything, so counting them + // as failing seems the most intuitive. + if (!this.assertions[i].result) { + bad++; + config.stats.bad++; + module.stats.bad++; + } + } + + if (skipped) { + incrementTestsIgnored(module); + } else { + incrementTestsRun(module); + } // Store result when possible. + // Note that this also marks todo tests as bad, thus they get hoisted, + // and always run first on refresh. + + + if (storage) { + if (bad) { + storage.setItem("qunit-test-" + moduleName + "-" + testName, bad); + } else { + storage.removeItem("qunit-test-" + moduleName + "-" + testName); + } + } // After emitting the js-reporters event we cleanup the assertion data to + // avoid leaking it. It is not used by the legacy testDone callbacks. + + + emit("testEnd", this.testReport.end(true)); + this.testReport.slimAssertions(); + var test = this; + return runLoggingCallbacks("testDone", { + name: testName, + module: moduleName, + skipped: skipped, + todo: todo, + failed: bad, + passed: this.assertions.length - bad, + total: this.assertions.length, + runtime: skipped ? 0 : this.runtime, + // HTML Reporter use + assertions: this.assertions, + testId: this.testId, + + // Source of Test + // generating stack trace is expensive, so using a getter will help defer this until we need it + get source() { + return test.stack; + } + + }).then(function () { + if (allTestsExecuted(module)) { + var completedModules = [module]; // Check if the parent modules, iteratively, are done. If that the case, + // we emit the `suiteEnd` event and trigger `moduleDone` callback. + + var parent = module.parentModule; + + while (parent && allTestsExecuted(parent)) { + completedModules.push(parent); + parent = parent.parentModule; + } + + return completedModules.reduce(function (promiseChain, completedModule) { + return promiseChain.then(function () { + return logSuiteEnd(completedModule); + }); + }, _Promise.resolve([])); + } + }).then(function () { + config.current = undefined; + }); + + function logSuiteEnd(module) { + // Reset `module.hooks` to ensure that anything referenced in these hooks + // has been released to be garbage collected. Descendant modules that were + // entirely skipped, e.g. due to filtering, will never have this method + // called for them, but might have hooks with references pinning data in + // memory (even if the hooks weren't actually executed), so we reset the + // hooks on all descendant modules here as well. This is safe because we + // will never call this as long as any descendant modules still have tests + // to run. This also means that in multi-tiered nesting scenarios we might + // reset the hooks multiple times on some modules, but that's harmless. + var modules = [module]; + + while (modules.length) { + var nextModule = modules.shift(); + nextModule.hooks = {}; + modules.push.apply(modules, _toConsumableArray(nextModule.childModules)); + } + + emit("suiteEnd", module.suiteReport.end(true)); + return runLoggingCallbacks("moduleDone", { + name: module.name, + tests: module.tests, + failed: module.stats.bad, + passed: module.stats.all - module.stats.bad, + total: module.stats.all, + runtime: now() - module.stats.started + }); + } + }, + preserveTestEnvironment: function preserveTestEnvironment() { + if (this.preserveEnvironment) { + this.module.testEnvironment = this.testEnvironment; + this.testEnvironment = extend({}, this.module.testEnvironment); + } + }, + queue: function queue() { + var test = this; + + if (!this.valid()) { + incrementTestsIgnored(this.module); + return; + } + + function runTest() { + return [function () { + return test.before(); + }].concat(_toConsumableArray(test.hooks("before")), [function () { + test.preserveTestEnvironment(); + }], _toConsumableArray(test.hooks("beforeEach")), [function () { + test.run(); + }], _toConsumableArray(test.hooks("afterEach").reverse()), _toConsumableArray(test.hooks("after").reverse()), [function () { + test.after(); + }, function () { + return test.finish(); + }]); + } + + var previousFailCount = config.storage && +config.storage.getItem("qunit-test-" + this.module.name + "-" + this.testName); // Prioritize previously failed tests, detected from storage + + var prioritize = config.reorder && !!previousFailCount; + this.previousFailure = !!previousFailCount; + ProcessingQueue.add(runTest, prioritize, config.seed); + }, + pushResult: function pushResult(resultInfo) { + if (this !== config.current) { + var message = resultInfo && resultInfo.message || ""; + var testName = this && this.testName || ""; + var error = "Assertion occurred after test finished.\n" + "> Test: " + testName + "\n" + "> Message: " + message + "\n"; + throw new Error(error); + } // Destructure of resultInfo = { result, actual, expected, message, negative } + + + var details = { + module: this.module.name, + name: this.testName, + result: resultInfo.result, + message: resultInfo.message, + actual: resultInfo.actual, + testId: this.testId, + negative: resultInfo.negative || false, + runtime: now() - this.started, + todo: !!this.todo + }; + + if (hasOwn$1.call(resultInfo, "expected")) { + details.expected = resultInfo.expected; + } + + if (!resultInfo.result) { + var source = resultInfo.source || sourceFromStacktrace(); + + if (source) { + details.source = source; + } + } + + this.logAssertion(details); + this.assertions.push({ + result: !!resultInfo.result, + message: resultInfo.message + }); + }, + pushFailure: function pushFailure(message, source, actual) { + if (!(this instanceof Test)) { + throw new Error("pushFailure() assertion outside test context, was " + sourceFromStacktrace(2)); + } + + this.pushResult({ + result: false, + message: message || "error", + actual: actual || null, + source: source + }); + }, + + /** + * Log assertion details using both the old QUnit.log interface and + * QUnit.on( "assertion" ) interface. + * + * @private + */ + logAssertion: function logAssertion(details) { + runLoggingCallbacks("log", details); + var assertion = { + passed: details.result, + actual: details.actual, + expected: details.expected, + message: details.message, + stack: details.source, + todo: details.todo + }; + this.testReport.pushAssertion(assertion); + emit("assertion", assertion); + }, + resolvePromise: function resolvePromise(promise, phase) { + if (promise != null) { + var _test = this; + + var then = promise.then; + + if (objectType(then) === "function") { + var resume = internalStop(_test); + + var resolve = function resolve() { + resume(); + }; + + if (config.notrycatch) { + then.call(promise, resolve); + } else { + var reject = function reject(error) { + var message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + _test.testName + "\": " + (error && error.message || error); + + _test.pushFailure(message, extractStacktrace(error, 0)); // Else next test will carry the responsibility + + + saveGlobal(); // Unblock + + internalRecover(_test); + }; + + then.call(promise, resolve, reject); + } + } + } + }, + valid: function valid() { + var filter = config.filter; + var regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec(filter); + var module = config.module && config.module.toLowerCase(); + var fullName = this.module.name + ": " + this.testName; + + function moduleChainNameMatch(testModule) { + var testModuleName = testModule.name ? testModule.name.toLowerCase() : null; + + if (testModuleName === module) { + return true; + } else if (testModule.parentModule) { + return moduleChainNameMatch(testModule.parentModule); + } else { + return false; + } + } + + function moduleChainIdMatch(testModule) { + return inArray(testModule.moduleId, config.moduleId) || testModule.parentModule && moduleChainIdMatch(testModule.parentModule); + } // Internally-generated tests are always valid + + + if (this.callback && this.callback.validTest) { + return true; + } + + if (config.moduleId && config.moduleId.length > 0 && !moduleChainIdMatch(this.module)) { + return false; + } + + if (config.testId && config.testId.length > 0 && !inArray(this.testId, config.testId)) { + return false; + } + + if (module && !moduleChainNameMatch(this.module)) { + return false; + } + + if (!filter) { + return true; + } + + return regexFilter ? this.regexFilter(!!regexFilter[1], regexFilter[2], regexFilter[3], fullName) : this.stringFilter(filter, fullName); + }, + regexFilter: function regexFilter(exclude, pattern, flags, fullName) { + var regex = new RegExp(pattern, flags); + var match = regex.test(fullName); + return match !== exclude; + }, + stringFilter: function stringFilter(filter, fullName) { + filter = filter.toLowerCase(); + fullName = fullName.toLowerCase(); + var include = filter.charAt(0) !== "!"; + + if (!include) { + filter = filter.slice(1); + } // If the filter matches, we need to honour include + + + if (fullName.indexOf(filter) !== -1) { + return include; + } // Otherwise, do the opposite + + + return !include; + } + }; + function pushFailure() { + if (!config.current) { + throw new Error("pushFailure() assertion outside test context, in " + sourceFromStacktrace(2)); + } // Gets current test obj + + + var currentTest = config.current; + return currentTest.pushFailure.apply(currentTest, arguments); + } + + function saveGlobal() { + config.pollution = []; + + if (config.noglobals) { + for (var key in globalThis$1) { + if (hasOwn$1.call(globalThis$1, key)) { + // In Opera sometimes DOM element ids show up here, ignore them + if (/^qunit-test-output/.test(key)) { + continue; + } + + config.pollution.push(key); + } + } + } + } + + function checkPollution() { + var old = config.pollution; + saveGlobal(); + var newGlobals = diff(config.pollution, old); + + if (newGlobals.length > 0) { + pushFailure("Introduced global variable(s): " + newGlobals.join(", ")); + } + + var deletedGlobals = diff(old, config.pollution); + + if (deletedGlobals.length > 0) { + pushFailure("Deleted global variable(s): " + deletedGlobals.join(", ")); + } + } + + var focused = false; // indicates that the "only" filter was used + + function addTest(settings) { + if (focused || config.currentModule.ignored) { + return; + } + + var newTest = new Test(settings); + newTest.queue(); + } + + function addOnlyTest(settings) { + if (config.currentModule.ignored) { + return; + } + + if (!focused) { + config.queue.length = 0; + focused = true; + } + + var newTest = new Test(settings); + newTest.queue(); + } // Will be exposed as QUnit.test + + + function test(testName, callback) { + addTest({ + testName: testName, + callback: callback + }); + } + + function makeEachTestName(testName, argument) { + return "".concat(testName, " [").concat(argument, "]"); + } + + function runEach(data, eachFn) { + if (Array.isArray(data)) { + data.forEach(eachFn); + } else if (_typeof(data) === "object" && data !== null) { + var keys = Object.keys(data); + keys.forEach(function (key) { + eachFn(data[key], key); + }); + } else { + throw new Error("test.each() expects an array or object as input, but\nfound ".concat(_typeof(data), " instead.")); + } + } + + extend(test, { + todo: function todo(testName, callback) { + addTest({ + testName: testName, + callback: callback, + todo: true + }); + }, + skip: function skip(testName) { + addTest({ + testName: testName, + skip: true + }); + }, + only: function only(testName, callback) { + addOnlyTest({ + testName: testName, + callback: callback + }); + }, + each: function each(testName, dataset, callback) { + runEach(dataset, function (data, testKey) { + addTest({ + testName: makeEachTestName(testName, testKey), + callback: callback, + withData: true, + data: data + }); + }); + } + }); + + test.todo.each = function (testName, dataset, callback) { + runEach(dataset, function (data, testKey) { + addTest({ + testName: makeEachTestName(testName, testKey), + callback: callback, + todo: true, + withData: true, + data: data + }); + }); + }; + + test.skip.each = function (testName, dataset) { + runEach(dataset, function (_, testKey) { + addTest({ + testName: makeEachTestName(testName, testKey), + skip: true + }); + }); + }; + + test.only.each = function (testName, dataset, callback) { + runEach(dataset, function (data, testKey) { + addOnlyTest({ + testName: makeEachTestName(testName, testKey), + callback: callback, + withData: true, + data: data + }); + }); + }; // Resets config.timeout with a new timeout duration. + + + function resetTestTimeout(timeoutDuration) { + clearTimeout(config.timeout); + config.timeout = setTimeout$1(config.timeoutHandler(timeoutDuration), timeoutDuration); + } // Create a new async pause and return a new function that can release the pause. + // + // This mechanism is internally used by: + // + // * explicit async pauses, created by calling `assert.async()`, + // * implicit async pauses, created when `QUnit.test()` or module hook callbacks + // use async-await or otherwise return a Promise. + // + // Happy scenario: + // + // * Pause is created by calling internalStop(). + // + // Pause is released normally by invoking release() during the same test. + // + // The release() callback lets internal processing resume. + // + // Failure scenarios: + // + // * The test fails due to an uncaught exception. + // + // In this case, Test.run() will call internalRecover() which empties the clears all + // async pauses and sets the cancelled flag, which means we silently ignore any + // late calls to the resume() callback, as we will have moved on to a different + // test by then, and we don't want to cause an extra "release during a different test" + // errors that the developer isn't really responsible for. This can happen when a test + // correctly schedules a call to release(), but also causes an uncaught error. The + // uncaught error means we will no longer wait for the release (as it might not arrive). + // + // * Pause is never released, or called an insufficient number of times. + // + // Our timeout handler will kill the pause and resume test processing, basically + // like internalRecover(), but for one pause instead of any/all. + // + // Here, too, any late calls to resume() will be silently ignored to avoid + // extra errors. We tolerate this since the original test will have already been + // marked as failure. + // + // TODO: QUnit 3 will enable timeouts by default , + // but right now a test will hang indefinitely if async pauses are not released, + // unless QUnit.config.testTimeout or assert.timeout() is used. + // + // * Pause is spontaneously released during a different test, + // or when no test is currently running. + // + // This is close to impossible because this error only happens if the original test + // succesfully finished first (since other failure scenarios kill pauses and ignore + // late calls). It can happen if a test ended exactly as expected, but has some + // external or shared state continuing to hold a reference to the release callback, + // and either the same test scheduled another call to it in the future, or a later test + // causes it to be called through some shared state. + // + // * Pause release() is called too often, during the same test. + // + // This simply throws an error, after which uncaught error handling picks it up + // and processing resumes. + + function internalStop(test) { + var requiredCalls = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + config.blocking = true; + var pauseId = test.nextPauseId++; + var pause = { + cancelled: false, + remaining: requiredCalls + }; + test.pauses.set(pauseId, pause); + + function release() { + if (pause.cancelled) { + return; + } + + if (config.current === undefined) { + throw new Error("Unexpected release of async pause after tests finished.\n" + "> Test: ".concat(test.testName, " [async #").concat(pauseId, "]")); + } + + if (config.current !== test) { + throw new Error("Unexpected release of async pause during a different test.\n" + "> Test: ".concat(test.testName, " [async #").concat(pauseId, "]")); + } + + if (pause.remaining <= 0) { + throw new Error("Tried to release async pause that was already released.\n" + "> Test: ".concat(test.testName, " [async #").concat(pauseId, "]")); + } // The `requiredCalls` parameter exists to support `assert.async(count)` + + + pause.remaining--; + + if (pause.remaining === 0) { + test.pauses.delete(pauseId); + } + + internalStart(test); + } // Set a recovery timeout, if so configured. + + + if (setTimeout$1) { + var timeoutDuration; + + if (typeof test.timeout === "number") { + timeoutDuration = test.timeout; + } else if (typeof config.testTimeout === "number") { + timeoutDuration = config.testTimeout; + } + + if (typeof timeoutDuration === "number" && timeoutDuration > 0) { + config.timeoutHandler = function (timeout) { + return function () { + config.timeout = null; + pause.cancelled = true; + test.pauses.delete(pauseId); + test.pushFailure("Test took longer than ".concat(timeout, "ms; test timed out."), sourceFromStacktrace(2)); + internalStart(test); + }; + }; + + clearTimeout(config.timeout); + config.timeout = setTimeout$1(config.timeoutHandler(timeoutDuration), timeoutDuration); + } + } + + return release; + } // Forcefully release all processing holds. + + function internalRecover(test) { + test.pauses.forEach(function (pause) { + pause.cancelled = true; + }); + test.pauses.clear(); + internalStart(test); + } // Release a processing hold, scheduling a resumption attempt if no holds remain. + + + function internalStart(test) { + // Ignore if other async pauses still exist. + if (test.pauses.size > 0) { + return; + } // Add a slight delay to allow more assertions etc. + + + if (setTimeout$1) { + clearTimeout(config.timeout); + config.timeout = setTimeout$1(function () { + if (test.pauses.size > 0) { + return; + } + + clearTimeout(config.timeout); + config.timeout = null; + begin(); + }); + } else { + begin(); + } + } + + function collectTests(module) { + var tests = [].concat(module.tests); + + var modules = _toConsumableArray(module.childModules); // Do a breadth-first traversal of the child modules + + + while (modules.length) { + var nextModule = modules.shift(); + tests.push.apply(tests, nextModule.tests); + modules.push.apply(modules, _toConsumableArray(nextModule.childModules)); + } + + return tests; + } // This returns true after all executable and skippable tests + // in a module have been proccessed, and informs 'suiteEnd' + // and moduleDone(). + + + function allTestsExecuted(module) { + return module.testsRun + module.testsIgnored === collectTests(module).length; + } // This returns true during the last executable non-skipped test + // within a module, and informs the running of the 'after' hook + // for a given module. This runs only once for a given module, + // but must run during the last non-skipped test. When it runs, + // there may be non-zero skipped tests left. + + + function lastTestWithinModuleExecuted(module) { + return module.testsRun === collectTests(module).filter(function (test) { + return !test.skip; + }).length - 1; + } + + function incrementTestsRun(module) { + module.testsRun++; + + while (module = module.parentModule) { + module.testsRun++; + } + } + + function incrementTestsIgnored(module) { + module.testsIgnored++; + + while (module = module.parentModule) { + module.testsIgnored++; + } + } + + var Assert = /*#__PURE__*/function () { + function Assert(testContext) { + _classCallCheck(this, Assert); + + this.test = testContext; + } // Assert helpers + + + _createClass(Assert, [{ + key: "timeout", + value: function timeout(duration) { + if (typeof duration !== "number") { + throw new Error("You must pass a number as the duration to assert.timeout"); + } + + this.test.timeout = duration; // If a timeout has been set, clear it and reset with the new duration + + if (config.timeout) { + clearTimeout(config.timeout); + config.timeout = null; + + if (config.timeoutHandler && this.test.timeout > 0) { + resetTestTimeout(this.test.timeout); + } + } + } // Documents a "step", which is a string value, in a test as a passing assertion + + }, { + key: "step", + value: function step(message) { + var assertionMessage = message; + var result = !!message; + this.test.steps.push(message); + + if (objectType(message) === "undefined" || message === "") { + assertionMessage = "You must provide a message to assert.step"; + } else if (objectType(message) !== "string") { + assertionMessage = "You must provide a string value to assert.step"; + result = false; + } + + this.pushResult({ + result: result, + message: assertionMessage + }); + } // Verifies the steps in a test match a given array of string values + + }, { + key: "verifySteps", + value: function verifySteps(steps, message) { + // Since the steps array is just string values, we can clone with slice + var actualStepsClone = this.test.steps.slice(); + this.deepEqual(actualStepsClone, steps, message); + this.test.steps.length = 0; + } // Specify the number of expected assertions to guarantee that failed test + // (no assertions are run at all) don't slip through. + + }, { + key: "expect", + value: function expect(asserts) { + if (arguments.length === 1) { + this.test.expected = asserts; + } else { + return this.test.expected; + } + } // Create a new async pause and return a new function that can release the pause. + + }, { + key: "async", + value: function async(count) { + var requiredCalls = count === undefined ? 1 : count; + return internalStop(this.test, requiredCalls); + } // Exports test.push() to the user API + // Alias of pushResult. + + }, { + key: "push", + value: function push(result, actual, expected, message, negative) { + Logger.warn("assert.push is deprecated and will be removed in QUnit 3.0." + " Please use assert.pushResult instead (https://api.qunitjs.com/assert/pushResult)."); + var currentAssert = this instanceof Assert ? this : config.current.assert; + return currentAssert.pushResult({ + result: result, + actual: actual, + expected: expected, + message: message, + negative: negative + }); + } + }, { + key: "pushResult", + value: function pushResult(resultInfo) { + // Destructure of resultInfo = { result, actual, expected, message, negative } + var assert = this; + var currentTest = assert instanceof Assert && assert.test || config.current; // Backwards compatibility fix. + // Allows the direct use of global exported assertions and QUnit.assert.* + // Although, it's use is not recommended as it can leak assertions + // to other tests from async tests, because we only get a reference to the current test, + // not exactly the test where assertion were intended to be called. + + if (!currentTest) { + throw new Error("assertion outside test context, in " + sourceFromStacktrace(2)); + } + + if (!(assert instanceof Assert)) { + assert = currentTest.assert; + } + + return assert.test.pushResult(resultInfo); + } + }, { + key: "ok", + value: function ok(result, message) { + if (!message) { + message = result ? "okay" : "failed, expected argument to be truthy, was: ".concat(dump.parse(result)); + } + + this.pushResult({ + result: !!result, + actual: result, + expected: true, + message: message + }); + } + }, { + key: "notOk", + value: function notOk(result, message) { + if (!message) { + message = !result ? "okay" : "failed, expected argument to be falsy, was: ".concat(dump.parse(result)); + } + + this.pushResult({ + result: !result, + actual: result, + expected: false, + message: message + }); + } + }, { + key: "true", + value: function _true(result, message) { + this.pushResult({ + result: result === true, + actual: result, + expected: true, + message: message + }); + } + }, { + key: "false", + value: function _false(result, message) { + this.pushResult({ + result: result === false, + actual: result, + expected: false, + message: message + }); + } + }, { + key: "equal", + value: function equal(actual, expected, message) { + // eslint-disable-next-line eqeqeq + var result = expected == actual; + this.pushResult({ + result: result, + actual: actual, + expected: expected, + message: message + }); + } + }, { + key: "notEqual", + value: function notEqual(actual, expected, message) { + // eslint-disable-next-line eqeqeq + var result = expected != actual; + this.pushResult({ + result: result, + actual: actual, + expected: expected, + message: message, + negative: true + }); + } + }, { + key: "propEqual", + value: function propEqual(actual, expected, message) { + actual = objectValues(actual); + expected = objectValues(expected); + this.pushResult({ + result: equiv(actual, expected), + actual: actual, + expected: expected, + message: message + }); + } + }, { + key: "notPropEqual", + value: function notPropEqual(actual, expected, message) { + actual = objectValues(actual); + expected = objectValues(expected); + this.pushResult({ + result: !equiv(actual, expected), + actual: actual, + expected: expected, + message: message, + negative: true + }); + } + }, { + key: "deepEqual", + value: function deepEqual(actual, expected, message) { + this.pushResult({ + result: equiv(actual, expected), + actual: actual, + expected: expected, + message: message + }); + } + }, { + key: "notDeepEqual", + value: function notDeepEqual(actual, expected, message) { + this.pushResult({ + result: !equiv(actual, expected), + actual: actual, + expected: expected, + message: message, + negative: true + }); + } + }, { + key: "strictEqual", + value: function strictEqual(actual, expected, message) { + this.pushResult({ + result: expected === actual, + actual: actual, + expected: expected, + message: message + }); + } + }, { + key: "notStrictEqual", + value: function notStrictEqual(actual, expected, message) { + this.pushResult({ + result: expected !== actual, + actual: actual, + expected: expected, + message: message, + negative: true + }); + } + }, { + key: "throws", + value: function throws(block, expected, message) { + var _validateExpectedExce = validateExpectedExceptionArgs(expected, message, "throws"); + + var _validateExpectedExce2 = _slicedToArray(_validateExpectedExce, 2); + + expected = _validateExpectedExce2[0]; + message = _validateExpectedExce2[1]; + var currentTest = this instanceof Assert && this.test || config.current; + + if (objectType(block) !== "function") { + var _message = "The value provided to `assert.throws` in " + "\"" + currentTest.testName + "\" was not a function."; + + currentTest.assert.pushResult({ + result: false, + actual: block, + message: _message + }); + return; + } + + var actual; + var result = false; + currentTest.ignoreGlobalErrors = true; + + try { + block.call(currentTest.testEnvironment); + } catch (e) { + actual = e; + } + + currentTest.ignoreGlobalErrors = false; + + if (actual) { + var _validateException = validateException(actual, expected, message); + + var _validateException2 = _slicedToArray(_validateException, 3); + + result = _validateException2[0]; + expected = _validateException2[1]; + message = _validateException2[2]; + } + + currentTest.assert.pushResult({ + result: result, + // undefined if it didn't throw + actual: actual && errorString(actual), + expected: expected, + message: message + }); + } + }, { + key: "rejects", + value: function rejects(promise, expected, message) { + var _validateExpectedExce3 = validateExpectedExceptionArgs(expected, message, "rejects"); + + var _validateExpectedExce4 = _slicedToArray(_validateExpectedExce3, 2); + + expected = _validateExpectedExce4[0]; + message = _validateExpectedExce4[1]; + var currentTest = this instanceof Assert && this.test || config.current; + var then = promise && promise.then; + + if (objectType(then) !== "function") { + var _message2 = "The value provided to `assert.rejects` in " + "\"" + currentTest.testName + "\" was not a promise."; + + currentTest.assert.pushResult({ + result: false, + message: _message2, + actual: promise + }); + return; + } + + var done = this.async(); + return then.call(promise, function handleFulfillment() { + var message = "The promise returned by the `assert.rejects` callback in " + "\"" + currentTest.testName + "\" did not reject."; + currentTest.assert.pushResult({ + result: false, + message: message, + actual: promise + }); + done(); + }, function handleRejection(actual) { + var result; + + var _validateException3 = validateException(actual, expected, message); + + var _validateException4 = _slicedToArray(_validateException3, 3); + + result = _validateException4[0]; + expected = _validateException4[1]; + message = _validateException4[2]; + currentTest.assert.pushResult({ + result: result, + // leave rejection value of undefined as-is + actual: actual && errorString(actual), + expected: expected, + message: message + }); + done(); + }); + } + }]); + + return Assert; + }(); + + function validateExpectedExceptionArgs(expected, message, assertionMethod) { + var expectedType = objectType(expected); // 'expected' is optional unless doing string comparison + + if (expectedType === "string") { + if (message === undefined) { + message = expected; + expected = undefined; + return [expected, message]; + } else { + throw new Error("assert." + assertionMethod + " does not accept a string value for the expected argument.\n" + "Use a non-string object value (e.g. RegExp or validator function) " + "instead if necessary."); + } + } + + var valid = !expected || // TODO: be more explicit here + expectedType === "regexp" || expectedType === "function" || expectedType === "object"; + + if (!valid) { + var _message3 = "Invalid expected value type (" + expectedType + ") " + "provided to assert." + assertionMethod + "."; + + throw new Error(_message3); + } + + return [expected, message]; + } + + function validateException(actual, expected, message) { + var result = false; + var expectedType = objectType(expected); // These branches should be exhaustive, based on validation done in validateExpectedException + // We don't want to validate + + if (!expected) { + result = true; // Expected is a regexp + } else if (expectedType === "regexp") { + result = expected.test(errorString(actual)); // Log the string form of the regexp + + expected = String(expected); // Expected is a constructor, maybe an Error constructor. + // Note the extra check on its prototype - this is an implicit + // requirement of "instanceof", else it will throw a TypeError. + } else if (expectedType === "function" && expected.prototype !== undefined && actual instanceof expected) { + result = true; // Expected is an Error object + } else if (expectedType === "object") { + result = actual instanceof expected.constructor && actual.name === expected.name && actual.message === expected.message; // Log the string form of the Error object + + expected = errorString(expected); // Expected is a validation function which returns true if validation passed + } else if (expectedType === "function") { + // protect against accidental semantics which could hard error in the test + try { + result = expected.call({}, actual) === true; + expected = null; + } catch (e) { + // assign the "expected" to a nice error string to communicate the local failure to the user + expected = errorString(e); + } + } + + return [result, expected, message]; + } // Provide an alternative to assert.throws(), for environments that consider throws a reserved word + // Known to us are: Closure Compiler, Narwhal + // eslint-disable-next-line dot-notation + + + Assert.prototype.raises = Assert.prototype["throws"]; + + /* global module, exports, define */ + function exportQUnit(QUnit) { + var exportedModule = false; + + if (window$1 && document) { + // QUnit may be defined when it is preconfigured but then only QUnit and QUnit.config may be defined. + if (window$1.QUnit && window$1.QUnit.version) { + throw new Error("QUnit has already been defined."); + } + + window$1.QUnit = QUnit; + exportedModule = true; + } // For Node.js + + + if (typeof module !== "undefined" && module && module.exports) { + module.exports = QUnit; // For consistency with CommonJS environments' exports + + module.exports.QUnit = QUnit; + exportedModule = true; + } // For CommonJS with exports, but without module.exports, like Rhino + + + if (typeof exports !== "undefined" && exports) { + exports.QUnit = QUnit; + exportedModule = true; + } // For AMD + + + if (typeof define === "function" && define.amd) { + define(function () { + return QUnit; + }); + QUnit.config.autostart = false; + exportedModule = true; + } // For Web/Service Workers + + + if (self$1 && self$1.WorkerGlobalScope && self$1 instanceof self$1.WorkerGlobalScope) { + self$1.QUnit = QUnit; + exportedModule = true; + } // For other environments, such as SpiderMonkey (mozjs) and other + // embedded JavaScript engines + + + if (!exportedModule) { + globalThis$1.QUnit = QUnit; + } + } + + var ConsoleReporter = /*#__PURE__*/function () { + function ConsoleReporter(runner) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, ConsoleReporter); + + // Cache references to console methods to ensure we can report failures + // from tests tests that mock the console object itself. + // https://github.com/qunitjs/qunit/issues/1340 + // Support IE 9: Function#bind is supported, but no console.log.bind(). + this.log = options.log || Function.prototype.bind.call(console$1.log, console$1); + runner.on("error", this.onError.bind(this)); + runner.on("runStart", this.onRunStart.bind(this)); + runner.on("testStart", this.onTestStart.bind(this)); + runner.on("testEnd", this.onTestEnd.bind(this)); + runner.on("runEnd", this.onRunEnd.bind(this)); + } + + _createClass(ConsoleReporter, [{ + key: "onError", + value: function onError(error) { + this.log("error", error); + } + }, { + key: "onRunStart", + value: function onRunStart(runStart) { + this.log("runStart", runStart); + } + }, { + key: "onTestStart", + value: function onTestStart(test) { + this.log("testStart", test); + } + }, { + key: "onTestEnd", + value: function onTestEnd(test) { + this.log("testEnd", test); + } + }, { + key: "onRunEnd", + value: function onRunEnd(runEnd) { + this.log("runEnd", runEnd); + } + }], [{ + key: "init", + value: function init(runner, options) { + return new ConsoleReporter(runner, options); + } + }]); + + return ConsoleReporter; + }(); + + var FORCE_COLOR, + NODE_DISABLE_COLORS, + NO_COLOR, + TERM, + isTTY = true; + + if (typeof process !== 'undefined') { + var _process$env = process.env; + FORCE_COLOR = _process$env.FORCE_COLOR; + NODE_DISABLE_COLORS = _process$env.NODE_DISABLE_COLORS; + NO_COLOR = _process$env.NO_COLOR; + TERM = _process$env.TERM; + isTTY = process.stdout && process.stdout.isTTY; + } + + var $ = { + enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (FORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY), + // modifiers + reset: init(0, 0), + bold: init(1, 22), + dim: init(2, 22), + italic: init(3, 23), + underline: init(4, 24), + inverse: init(7, 27), + hidden: init(8, 28), + strikethrough: init(9, 29), + // colors + black: init(30, 39), + red: init(31, 39), + green: init(32, 39), + yellow: init(33, 39), + blue: init(34, 39), + magenta: init(35, 39), + cyan: init(36, 39), + white: init(37, 39), + gray: init(90, 39), + grey: init(90, 39), + // background colors + bgBlack: init(40, 49), + bgRed: init(41, 49), + bgGreen: init(42, 49), + bgYellow: init(43, 49), + bgBlue: init(44, 49), + bgMagenta: init(45, 49), + bgCyan: init(46, 49), + bgWhite: init(47, 49) + }; + + function run(arr, str) { + var i = 0, + tmp, + beg = '', + end = ''; + + for (; i < arr.length; i++) { + tmp = arr[i]; + beg += tmp.open; + end += tmp.close; + + if (!!~str.indexOf(tmp.close)) { + str = str.replace(tmp.rgx, tmp.close + tmp.open); + } + } + + return beg + str + end; + } + + function chain(has, keys) { + var ctx = { + has: has, + keys: keys + }; + ctx.reset = $.reset.bind(ctx); + ctx.bold = $.bold.bind(ctx); + ctx.dim = $.dim.bind(ctx); + ctx.italic = $.italic.bind(ctx); + ctx.underline = $.underline.bind(ctx); + ctx.inverse = $.inverse.bind(ctx); + ctx.hidden = $.hidden.bind(ctx); + ctx.strikethrough = $.strikethrough.bind(ctx); + ctx.black = $.black.bind(ctx); + ctx.red = $.red.bind(ctx); + ctx.green = $.green.bind(ctx); + ctx.yellow = $.yellow.bind(ctx); + ctx.blue = $.blue.bind(ctx); + ctx.magenta = $.magenta.bind(ctx); + ctx.cyan = $.cyan.bind(ctx); + ctx.white = $.white.bind(ctx); + ctx.gray = $.gray.bind(ctx); + ctx.grey = $.grey.bind(ctx); + ctx.bgBlack = $.bgBlack.bind(ctx); + ctx.bgRed = $.bgRed.bind(ctx); + ctx.bgGreen = $.bgGreen.bind(ctx); + ctx.bgYellow = $.bgYellow.bind(ctx); + ctx.bgBlue = $.bgBlue.bind(ctx); + ctx.bgMagenta = $.bgMagenta.bind(ctx); + ctx.bgCyan = $.bgCyan.bind(ctx); + ctx.bgWhite = $.bgWhite.bind(ctx); + return ctx; + } + + function init(open, close) { + var blk = { + open: "\x1B[".concat(open, "m"), + close: "\x1B[".concat(close, "m"), + rgx: new RegExp("\\x1b\\[".concat(close, "m"), 'g') + }; + return function (txt) { + if (this !== void 0 && this.has !== void 0) { + !!~this.has.indexOf(open) || (this.has.push(open), this.keys.push(blk)); + return txt === void 0 ? this : $.enabled ? run(this.keys, txt + '') : txt + ''; + } + + return txt === void 0 ? chain([open], [blk]) : $.enabled ? run([blk], txt + '') : txt + ''; + }; + } + + var hasOwn = Object.prototype.hasOwnProperty; + /** + * Format a given value into YAML. + * + * YAML is a superset of JSON that supports all the same data + * types and syntax, and more. As such, it is always possible + * to fallback to JSON.stringfify, but we generally avoid + * that to make output easier to read for humans. + * + * Supported data types: + * + * - null + * - boolean + * - number + * - string + * - array + * - object + * + * Anything else (including NaN, Infinity, and undefined) + * must be described in strings, for display purposes. + * + * Note that quotes are optional in YAML strings if the + * strings are "simple", and as such we generally prefer + * that for improved readability. We output strings in + * one of three ways: + * + * - bare unquoted text, for simple one-line strings. + * - JSON (quoted text), for complex one-line strings. + * - YAML Block, for complex multi-line strings. + * + * Objects with cyclical references will be stringifed as + * "[Circular]" as they cannot otherwise be represented. + */ + + function prettyYamlValue(value) { + var indent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4; + + if (value === undefined) { + // Not supported in JSON/YAML, turn into string + // and let the below output it as bare string. + value = String(value); + } // Support IE 9-11: Use isFinite instead of ES6 Number.isFinite + + + if (typeof value === "number" && !isFinite(value)) { + // Turn NaN and Infinity into simple strings. + // Paranoia: Don't return directly just in case there's + // a way to add special characters here. + value = String(value); + } + + if (typeof value === "number") { + // Simple numbers + return JSON.stringify(value); + } + + if (typeof value === "string") { + // If any of these match, then we can't output it + // as bare unquoted text, because that would either + // cause data loss or invalid YAML syntax. + // + // - Quotes, escapes, line breaks, or JSON-like stuff. + var rSpecialJson = /['"\\/[{}\]\r\n]/; // - Characters that are special at the start of a YAML value + + var rSpecialYaml = /[-?:,[\]{}#&*!|=>'"%@`]/; // - Leading or trailing whitespace. + + var rUntrimmed = /(^\s|\s$)/; // - Ambiguous as YAML number, e.g. '2', '-1.2', '.2', or '2_000' + + var rNumerical = /^[\d._-]+$/; // - Ambiguous as YAML bool. + // Use case-insensitive match, although technically only + // fully-lower, fully-upper, or uppercase-first would be ambiguous. + // e.g. true/True/TRUE, but not tRUe. + + var rBool = /^(true|false|y|n|yes|no|on|off)$/i; // Is this a complex string? + + if (value === "" || rSpecialJson.test(value) || rSpecialYaml.test(value[0]) || rUntrimmed.test(value) || rNumerical.test(value) || rBool.test(value)) { + if (!/\n/.test(value)) { + // Complex one-line string, use JSON (quoted string) + return JSON.stringify(value); + } // See also + // Support IE 9-11: Avoid ES6 String#repeat + + + var prefix = new Array(indent + 1).join(" "); + var trailingLinebreakMatch = value.match(/\n+$/); + var trailingLinebreaks = trailingLinebreakMatch ? trailingLinebreakMatch[0].length : 0; + + if (trailingLinebreaks === 1) { + // Use the most straight-forward "Block" string in YAML + // without any "Chomping" indicators. + var lines = value // Ignore the last new line, since we'll get that one for free + // with the straight-forward Block syntax. + .replace(/\n$/, "").split("\n").map(function (line) { + return prefix + line; + }); + return "|\n" + lines.join("\n"); + } else { + // This has either no trailing new lines, or more than 1. + // Use |+ so that YAML parsers will preserve it exactly. + var _lines = value.split("\n").map(function (line) { + return prefix + line; + }); + + return "|+\n" + _lines.join("\n"); + } + } else { + // Simple string, use bare unquoted text + return value; + } + } // Handle null, boolean, array, and object + + + return JSON.stringify(decycledShallowClone(value), null, 2); + } + /** + * Creates a shallow clone of an object where cycles have + * been replaced with "[Circular]". + */ + + + function decycledShallowClone(object) { + var ancestors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + + if (ancestors.indexOf(object) !== -1) { + return "[Circular]"; + } + + var clone; + var type = Object.prototype.toString.call(object).replace(/^\[.+\s(.+?)]$/, "$1").toLowerCase(); + + switch (type) { + case "array": + ancestors.push(object); + clone = object.map(function (element) { + return decycledShallowClone(element, ancestors); + }); + ancestors.pop(); + break; + + case "object": + ancestors.push(object); + clone = {}; + Object.keys(object).forEach(function (key) { + clone[key] = decycledShallowClone(object[key], ancestors); + }); + ancestors.pop(); + break; + + default: + clone = object; + } + + return clone; + } + + var TapReporter = /*#__PURE__*/function () { + function TapReporter(runner) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, TapReporter); + + // Cache references to console methods to ensure we can report failures + // from tests tests that mock the console object itself. + // https://github.com/qunitjs/qunit/issues/1340 + // Support IE 9: Function#bind is supported, but no console.log.bind(). + this.log = options.log || Function.prototype.bind.call(console$1.log, console$1); + this.testCount = 0; + this.ended = false; + this.bailed = false; + runner.on("error", this.onError.bind(this)); + runner.on("runStart", this.onRunStart.bind(this)); + runner.on("testEnd", this.onTestEnd.bind(this)); + runner.on("runEnd", this.onRunEnd.bind(this)); + } + + _createClass(TapReporter, [{ + key: "onRunStart", + value: function onRunStart(_globalSuite) { + this.log("TAP version 13"); + } + }, { + key: "onError", + value: function onError(error) { + if (this.bailed) { + return; + } + + this.bailed = true; // Imitate onTestEnd + // Skip this if we're past "runEnd" as it would look odd + + if (!this.ended) { + this.testCount = this.testCount + 1; + this.log($.red("not ok ".concat(this.testCount, " global failure"))); + this.logError(error); + } + + this.log("Bail out! " + errorString(error).split("\n")[0]); + + if (this.ended) { + this.logError(error); + } + } + }, { + key: "onTestEnd", + value: function onTestEnd(test) { + var _this = this; + + this.testCount = this.testCount + 1; + + if (test.status === "passed") { + this.log("ok ".concat(this.testCount, " ").concat(test.fullName.join(" > "))); + } else if (test.status === "skipped") { + this.log($.yellow("ok ".concat(this.testCount, " # SKIP ").concat(test.fullName.join(" > ")))); + } else if (test.status === "todo") { + this.log($.cyan("not ok ".concat(this.testCount, " # TODO ").concat(test.fullName.join(" > ")))); + test.errors.forEach(function (error) { + return _this.logAssertion(error, "todo"); + }); + } else { + this.log($.red("not ok ".concat(this.testCount, " ").concat(test.fullName.join(" > ")))); + test.errors.forEach(function (error) { + return _this.logAssertion(error); + }); + } + } + }, { + key: "onRunEnd", + value: function onRunEnd(globalSuite) { + this.ended = true; + this.log("1..".concat(globalSuite.testCounts.total)); + this.log("# pass ".concat(globalSuite.testCounts.passed)); + this.log($.yellow("# skip ".concat(globalSuite.testCounts.skipped))); + this.log($.cyan("# todo ".concat(globalSuite.testCounts.todo))); + this.log($.red("# fail ".concat(globalSuite.testCounts.failed))); + } + }, { + key: "logAssertion", + value: function logAssertion(error, severity) { + var out = " ---"; + out += "\n message: ".concat(prettyYamlValue(error.message || "failed")); + out += "\n severity: ".concat(prettyYamlValue(severity || "failed")); + + if (hasOwn.call(error, "actual")) { + out += "\n actual : ".concat(prettyYamlValue(error.actual)); + } + + if (hasOwn.call(error, "expected")) { + out += "\n expected: ".concat(prettyYamlValue(error.expected)); + } + + if (error.stack) { + // Since stacks aren't user generated, take a bit of liberty by + // adding a trailing new line to allow a straight-forward YAML Blocks. + out += "\n stack: ".concat(prettyYamlValue(error.stack + "\n")); + } + + out += "\n ..."; + this.log(out); + } + }, { + key: "logError", + value: function logError(error) { + var out = " ---"; + out += "\n message: ".concat(prettyYamlValue(errorString(error))); + out += "\n severity: ".concat(prettyYamlValue("failed")); + + if (error && error.stack) { + out += "\n stack: ".concat(prettyYamlValue(error.stack + "\n")); + } + + out += "\n ..."; + this.log(out); + } + }], [{ + key: "init", + value: function init(runner, options) { + return new TapReporter(runner, options); + } + }]); + + return TapReporter; + }(); + + var reporters = { + console: ConsoleReporter, + tap: TapReporter + }; + + /** + * Handle a global error that should result in a failed test run. + * + * Summary: + * + * - If we're strictly inside a test (or one if its module hooks), the exception + * becomes a failed assertion. + * + * This has the important side-effect that uncaught exceptions (such as + * calling an undefined function) during a "todo" test do NOT result in + * a failed test run. + * + * - If we're anywhere outside a test (be it in early event callbacks, or + * internally between tests, or somewhere after "runEnd" if the process is + * still alive for some reason), then send an "error" event to the reporters. + * + * @since 2.17.0 + * @param {Error|any} error + */ + + function onUncaughtException(error) { + if (config.current) { + config.current.assert.pushResult({ + result: false, + message: "global failure: ".concat(errorString(error)), + // We could let callers specify an offset to subtract a number of frames via + // sourceFromStacktrace, in case they are a wrapper further away from the error + // handler, and thus reduce some noise in the stack trace. However, we're not + // doing this right now because it would almost never be used in practice given + // the vast majority of error values will be Error objects, and thus have their + // own stack trace already. + source: error && error.stack || sourceFromStacktrace(2) + }); + } else { + // The "error" event was added in QUnit 2.17. + // Increase "bad assertion" stats despite no longer pushing an assertion in this case. + // This ensures "runEnd" and "QUnit.done()" handlers behave as expected, since the "bad" + // count is typically how reporters decide on the boolean outcome of the test run. + globalSuite.globalFailureCount++; + config.stats.bad++; + config.stats.all++; + emit("error", error); + } + } + + /** + * Handle a window.onerror error. + * + * If there is a current test that sets the internal `ignoreGlobalErrors` field + * (such as during `assert.throws()`), then the error is ignored and native + * error reporting is suppressed as well. This is because in browsers, an error + * can sometimes end up in `window.onerror` instead of in the local try/catch. + * This ignoring of errors does not apply to our general onUncaughtException + * method, nor to our `unhandledRejection` handlers, as those are not meant + * to receive an "expected" error during `assert.throws()`. + * + * @see + * @deprecated since 2.17.0 Use QUnit.onUncaughtException instead. + * @param {Object} details + * @param {string} details.message + * @param {string} details.fileName + * @param {number} details.lineNumber + * @param {string|undefined} [details.stacktrace] + * @return {bool} True if native error reporting should be suppressed. + */ + + function onWindowError(details) { + Logger.warn("QUnit.onError is deprecated and will be removed in QUnit 3.0." + " Please use QUnit.onUncaughtException instead."); + + if (config.current && config.current.ignoreGlobalErrors) { + return true; + } + + var err = new Error(details.message); + err.stack = details.stacktrace || details.fileName + ":" + details.lineNumber; + onUncaughtException(err); + return false; + } + + var QUnit = {}; + var globalSuite = new SuiteReport(); // The initial "currentModule" represents the global (or top-level) module that + // is not explicitly defined by the user, therefore we add the "globalSuite" to + // it since each module has a suiteReport associated with it. + + config.currentModule.suiteReport = globalSuite; + var globalStartCalled = false; + var runStarted = false; // Figure out if we're running the tests from a server or not + + QUnit.isLocal = window$1 && window$1.location && window$1.location.protocol === "file:"; // Expose the current QUnit version + + QUnit.version = "2.17.2"; + + extend(QUnit, { + config: config, + dump: dump, + equiv: equiv, + reporters: reporters, + is: is, + objectType: objectType, + on: on, + onError: onWindowError, + onUncaughtException: onUncaughtException, + pushFailure: pushFailure, + assert: Assert.prototype, + module: module$1, + test: test, + // alias other test flavors for easy access + todo: test.todo, + skip: test.skip, + only: test.only, + start: function start(count) { + if (config.current) { + throw new Error("QUnit.start cannot be called inside a test context."); + } + + var globalStartAlreadyCalled = globalStartCalled; + globalStartCalled = true; + + if (runStarted) { + throw new Error("Called start() while test already started running"); + } + + if (globalStartAlreadyCalled || count > 1) { + throw new Error("Called start() outside of a test context too many times"); + } + + if (config.autostart) { + throw new Error("Called start() outside of a test context when " + "QUnit.config.autostart was true"); + } + + if (!config.pageLoaded) { + // The page isn't completely loaded yet, so we set autostart and then + // load if we're in Node or wait for the browser's load event. + config.autostart = true; // Starts from Node even if .load was not previously called. We still return + // early otherwise we'll wind up "beginning" twice. + + if (!document) { + QUnit.load(); + } + + return; + } + + scheduleBegin(); + }, + onUnhandledRejection: function onUnhandledRejection(reason) { + Logger.warn("QUnit.onUnhandledRejection is deprecated and will be removed in QUnit 3.0." + " Please use QUnit.onUncaughtException instead."); + onUncaughtException(reason); + }, + extend: function extend$1() { + Logger.warn("QUnit.extend is deprecated and will be removed in QUnit 3.0." + " Please use Object.assign instead."); // delegate to utility implementation, which does not warn and can be used elsewhere internally + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return extend.apply(this, args); + }, + load: function load() { + config.pageLoaded = true; // Initialize the configuration options + + extend(config, { + started: 0, + updateRate: 1000, + autostart: true, + filter: "" + }, true); + + if (!runStarted) { + config.blocking = false; + + if (config.autostart) { + scheduleBegin(); + } + } + }, + stack: function stack(offset) { + offset = (offset || 0) + 2; + return sourceFromStacktrace(offset); + } + }); + + registerLoggingCallbacks(QUnit); + + function scheduleBegin() { + runStarted = true; // Add a slight delay to allow definition of more modules and tests. + + if (setTimeout$1) { + setTimeout$1(function () { + begin(); + }); + } else { + begin(); + } + } + + function unblockAndAdvanceQueue() { + config.blocking = false; + ProcessingQueue.advance(); + } + + function begin() { + if (config.started) { + unblockAndAdvanceQueue(); + return; + } // The test run hasn't officially begun yet + // Record the time of the test run's beginning + + + config.started = now(); // Delete the loose unnamed module if unused. + + if (config.modules[0].name === "" && config.modules[0].tests.length === 0) { + config.modules.shift(); + } // Avoid unnecessary information by not logging modules' test environments + + + var l = config.modules.length; + var modulesLog = []; + + for (var i = 0; i < l; i++) { + modulesLog.push({ + name: config.modules[i].name, + tests: config.modules[i].tests + }); + } // The test run is officially beginning now + + + emit("runStart", globalSuite.start(true)); + runLoggingCallbacks("begin", { + totalTests: Test.count, + modules: modulesLog + }).then(unblockAndAdvanceQueue); + } + exportQUnit(QUnit); + + (function () { + if (!window$1 || !document) { + return; + } + + var config = QUnit.config, + hasOwn = Object.prototype.hasOwnProperty; // Stores fixture HTML for resetting later + + function storeFixture() { + // Avoid overwriting user-defined values + if (hasOwn.call(config, "fixture")) { + return; + } + + var fixture = document.getElementById("qunit-fixture"); + + if (fixture) { + config.fixture = fixture.cloneNode(true); + } + } + + QUnit.begin(storeFixture); // Resets the fixture DOM element if available. + + function resetFixture() { + if (config.fixture == null) { + return; + } + + var fixture = document.getElementById("qunit-fixture"); + + var resetFixtureType = _typeof(config.fixture); + + if (resetFixtureType === "string") { + // support user defined values for `config.fixture` + var newFixture = document.createElement("div"); + newFixture.setAttribute("id", "qunit-fixture"); + newFixture.innerHTML = config.fixture; + fixture.parentNode.replaceChild(newFixture, fixture); + } else { + var clonedFixture = config.fixture.cloneNode(true); + fixture.parentNode.replaceChild(clonedFixture, fixture); + } + } + + QUnit.testStart(resetFixture); + })(); + + (function () { + // Only interact with URLs via window.location + var location = typeof window$1 !== "undefined" && window$1.location; + + if (!location) { + return; + } + + var urlParams = getUrlParams(); + QUnit.urlParams = urlParams; // Match module/test by inclusion in an array + + QUnit.config.moduleId = [].concat(urlParams.moduleId || []); + QUnit.config.testId = [].concat(urlParams.testId || []); // Exact case-insensitive match of the module name + + QUnit.config.module = urlParams.module; // Regular expression or case-insenstive substring match against "moduleName: testName" + + QUnit.config.filter = urlParams.filter; // Test order randomization + + if (urlParams.seed === true) { + // Generate a random seed if the option is specified without a value + QUnit.config.seed = Math.random().toString(36).slice(2); + } else if (urlParams.seed) { + QUnit.config.seed = urlParams.seed; + } // Add URL-parameter-mapped config values with UI form rendering data + + + QUnit.config.urlConfig.push({ + id: "hidepassed", + label: "Hide passed tests", + tooltip: "Only show tests and assertions that fail. Stored as query-strings." + }, { + id: "noglobals", + label: "Check for Globals", + tooltip: "Enabling this will test if any test introduces new properties on the " + "global object (`window` in Browsers). Stored as query-strings." + }, { + id: "notrycatch", + label: "No try-catch", + tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " + "exceptions in IE reasonable. Stored as query-strings." + }); + QUnit.begin(function () { + var i, + option, + urlConfig = QUnit.config.urlConfig; + + for (i = 0; i < urlConfig.length; i++) { + // Options can be either strings or objects with nonempty "id" properties + option = QUnit.config.urlConfig[i]; + + if (typeof option !== "string") { + option = option.id; + } + + if (QUnit.config[option] === undefined) { + QUnit.config[option] = urlParams[option]; + } + } + }); + + function getUrlParams() { + var i, param, name, value; + var urlParams = Object.create(null); + var params = location.search.slice(1).split("&"); + var length = params.length; + + for (i = 0; i < length; i++) { + if (params[i]) { + param = params[i].split("="); + name = decodeQueryParam(param[0]); // Allow just a key to turn on a flag, e.g., test.html?noglobals + + value = param.length === 1 || decodeQueryParam(param.slice(1).join("=")); + + if (name in urlParams) { + urlParams[name] = [].concat(urlParams[name], value); + } else { + urlParams[name] = value; + } + } + } + + return urlParams; + } + + function decodeQueryParam(param) { + return decodeURIComponent(param.replace(/\+/g, "%20")); + } + })(); + + var fuzzysort$1 = {exports: {}}; + + (function (module) { + + (function (root, UMD) { + if (module.exports) module.exports = UMD();else root.fuzzysort = UMD(); + })(commonjsGlobal, function UMD() { + function fuzzysortNew(instanceOptions) { + var fuzzysort = { + single: function single(search, target, options) { + if (!search) return null; + if (!isObj(search)) search = fuzzysort.getPreparedSearch(search); + if (!target) return null; + if (!isObj(target)) target = fuzzysort.getPrepared(target); + var allowTypo = options && options.allowTypo !== undefined ? options.allowTypo : instanceOptions && instanceOptions.allowTypo !== undefined ? instanceOptions.allowTypo : true; + var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo; + return algorithm(search, target, search[0]); // var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991 + // var result = algorithm(search, target, search[0]) + // if(result === null) return null + // if(result.score < threshold) return null + // return result + }, + go: function go(search, targets, options) { + if (!search) return noResults; + search = fuzzysort.prepareSearch(search); + var searchLowerCode = search[0]; + var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991; + var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991; + var allowTypo = options && options.allowTypo !== undefined ? options.allowTypo : instanceOptions && instanceOptions.allowTypo !== undefined ? instanceOptions.allowTypo : true; + var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo; + var resultsLen = 0; + var limitedCount = 0; + var targetsLen = targets.length; // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys] + // options.keys + + if (options && options.keys) { + var scoreFn = options.scoreFn || defaultScoreFn; + var keys = options.keys; + var keysLen = keys.length; + + for (var i = targetsLen - 1; i >= 0; --i) { + var obj = targets[i]; + var objResults = new Array(keysLen); + + for (var keyI = keysLen - 1; keyI >= 0; --keyI) { + var key = keys[keyI]; + var target = getValue(obj, key); + + if (!target) { + objResults[keyI] = null; + continue; + } + + if (!isObj(target)) target = fuzzysort.getPrepared(target); + objResults[keyI] = algorithm(search, target, searchLowerCode); + } + + objResults.obj = obj; // before scoreFn so scoreFn can use it + + var score = scoreFn(objResults); + if (score === null) continue; + if (score < threshold) continue; + objResults.score = score; + + if (resultsLen < limit) { + q.add(objResults); + ++resultsLen; + } else { + ++limitedCount; + if (score > q.peek().score) q.replaceTop(objResults); + } + } // options.key + + } else if (options && options.key) { + var key = options.key; + + for (var i = targetsLen - 1; i >= 0; --i) { + var obj = targets[i]; + var target = getValue(obj, key); + if (!target) continue; + if (!isObj(target)) target = fuzzysort.getPrepared(target); + var result = algorithm(search, target, searchLowerCode); + if (result === null) continue; + if (result.score < threshold) continue; // have to clone result so duplicate targets from different obj can each reference the correct obj + + result = { + target: result.target, + _targetLowerCodes: null, + _nextBeginningIndexes: null, + score: result.score, + indexes: result.indexes, + obj: obj + }; // hidden + + if (resultsLen < limit) { + q.add(result); + ++resultsLen; + } else { + ++limitedCount; + if (result.score > q.peek().score) q.replaceTop(result); + } + } // no keys + + } else { + for (var i = targetsLen - 1; i >= 0; --i) { + var target = targets[i]; + if (!target) continue; + if (!isObj(target)) target = fuzzysort.getPrepared(target); + var result = algorithm(search, target, searchLowerCode); + if (result === null) continue; + if (result.score < threshold) continue; + + if (resultsLen < limit) { + q.add(result); + ++resultsLen; + } else { + ++limitedCount; + if (result.score > q.peek().score) q.replaceTop(result); + } + } + } + + if (resultsLen === 0) return noResults; + var results = new Array(resultsLen); + + for (var i = resultsLen - 1; i >= 0; --i) { + results[i] = q.poll(); + } + + results.total = resultsLen + limitedCount; + return results; + }, + goAsync: function goAsync(search, targets, options) { + var canceled = false; + var p = new Promise(function (resolve, reject) { + if (!search) return resolve(noResults); + search = fuzzysort.prepareSearch(search); + var searchLowerCode = search[0]; + var q = fastpriorityqueue(); + var iCurrent = targets.length - 1; + var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991; + var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991; + var allowTypo = options && options.allowTypo !== undefined ? options.allowTypo : instanceOptions && instanceOptions.allowTypo !== undefined ? instanceOptions.allowTypo : true; + var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo; + var resultsLen = 0; + var limitedCount = 0; + + function step() { + if (canceled) return reject('canceled'); + var startMs = Date.now(); // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys] + // options.keys + + if (options && options.keys) { + var scoreFn = options.scoreFn || defaultScoreFn; + var keys = options.keys; + var keysLen = keys.length; + + for (; iCurrent >= 0; --iCurrent) { + var obj = targets[iCurrent]; + var objResults = new Array(keysLen); + + for (var keyI = keysLen - 1; keyI >= 0; --keyI) { + var key = keys[keyI]; + var target = getValue(obj, key); + + if (!target) { + objResults[keyI] = null; + continue; + } + + if (!isObj(target)) target = fuzzysort.getPrepared(target); + objResults[keyI] = algorithm(search, target, searchLowerCode); + } + + objResults.obj = obj; // before scoreFn so scoreFn can use it + + var score = scoreFn(objResults); + if (score === null) continue; + if (score < threshold) continue; + objResults.score = score; + + if (resultsLen < limit) { + q.add(objResults); + ++resultsLen; + } else { + ++limitedCount; + if (score > q.peek().score) q.replaceTop(objResults); + } + + if (iCurrent % 1000 + /*itemsPerCheck*/ + === 0) { + if (Date.now() - startMs >= 10 + /*asyncInterval*/ + ) { + isNode ? setImmediate(step) : setTimeout(step); + return; + } + } + } // options.key + + } else if (options && options.key) { + var key = options.key; + + for (; iCurrent >= 0; --iCurrent) { + var obj = targets[iCurrent]; + var target = getValue(obj, key); + if (!target) continue; + if (!isObj(target)) target = fuzzysort.getPrepared(target); + var result = algorithm(search, target, searchLowerCode); + if (result === null) continue; + if (result.score < threshold) continue; // have to clone result so duplicate targets from different obj can each reference the correct obj + + result = { + target: result.target, + _targetLowerCodes: null, + _nextBeginningIndexes: null, + score: result.score, + indexes: result.indexes, + obj: obj + }; // hidden + + if (resultsLen < limit) { + q.add(result); + ++resultsLen; + } else { + ++limitedCount; + if (result.score > q.peek().score) q.replaceTop(result); + } + + if (iCurrent % 1000 + /*itemsPerCheck*/ + === 0) { + if (Date.now() - startMs >= 10 + /*asyncInterval*/ + ) { + isNode ? setImmediate(step) : setTimeout(step); + return; + } + } + } // no keys + + } else { + for (; iCurrent >= 0; --iCurrent) { + var target = targets[iCurrent]; + if (!target) continue; + if (!isObj(target)) target = fuzzysort.getPrepared(target); + var result = algorithm(search, target, searchLowerCode); + if (result === null) continue; + if (result.score < threshold) continue; + + if (resultsLen < limit) { + q.add(result); + ++resultsLen; + } else { + ++limitedCount; + if (result.score > q.peek().score) q.replaceTop(result); + } + + if (iCurrent % 1000 + /*itemsPerCheck*/ + === 0) { + if (Date.now() - startMs >= 10 + /*asyncInterval*/ + ) { + isNode ? setImmediate(step) : setTimeout(step); + return; + } + } + } + } + + if (resultsLen === 0) return resolve(noResults); + var results = new Array(resultsLen); + + for (var i = resultsLen - 1; i >= 0; --i) { + results[i] = q.poll(); + } + + results.total = resultsLen + limitedCount; + resolve(results); + } + + isNode ? setImmediate(step) : step(); + }); + + p.cancel = function () { + canceled = true; + }; + + return p; + }, + highlight: function highlight(result, hOpen, hClose) { + if (result === null) return null; + if (hOpen === undefined) hOpen = ''; + if (hClose === undefined) hClose = ''; + var highlighted = ''; + var matchesIndex = 0; + var opened = false; + var target = result.target; + var targetLen = target.length; + var matchesBest = result.indexes; + + for (var i = 0; i < targetLen; ++i) { + var char = target[i]; + + if (matchesBest[matchesIndex] === i) { + ++matchesIndex; + + if (!opened) { + opened = true; + highlighted += hOpen; + } + + if (matchesIndex === matchesBest.length) { + highlighted += char + hClose + target.substr(i + 1); + break; + } + } else { + if (opened) { + opened = false; + highlighted += hClose; + } + } + + highlighted += char; + } + + return highlighted; + }, + prepare: function prepare(target) { + if (!target) return; + return { + target: target, + _targetLowerCodes: fuzzysort.prepareLowerCodes(target), + _nextBeginningIndexes: null, + score: null, + indexes: null, + obj: null + }; // hidden + }, + prepareSlow: function prepareSlow(target) { + if (!target) return; + return { + target: target, + _targetLowerCodes: fuzzysort.prepareLowerCodes(target), + _nextBeginningIndexes: fuzzysort.prepareNextBeginningIndexes(target), + score: null, + indexes: null, + obj: null + }; // hidden + }, + prepareSearch: function prepareSearch(search) { + if (!search) return; + return fuzzysort.prepareLowerCodes(search); + }, + // Below this point is only internal code + // Below this point is only internal code + // Below this point is only internal code + // Below this point is only internal code + getPrepared: function getPrepared(target) { + if (target.length > 999) return fuzzysort.prepare(target); // don't cache huge targets + + var targetPrepared = preparedCache.get(target); + if (targetPrepared !== undefined) return targetPrepared; + targetPrepared = fuzzysort.prepare(target); + preparedCache.set(target, targetPrepared); + return targetPrepared; + }, + getPreparedSearch: function getPreparedSearch(search) { + if (search.length > 999) return fuzzysort.prepareSearch(search); // don't cache huge searches + + var searchPrepared = preparedSearchCache.get(search); + if (searchPrepared !== undefined) return searchPrepared; + searchPrepared = fuzzysort.prepareSearch(search); + preparedSearchCache.set(search, searchPrepared); + return searchPrepared; + }, + algorithm: function algorithm(searchLowerCodes, prepared, searchLowerCode) { + var targetLowerCodes = prepared._targetLowerCodes; + var searchLen = searchLowerCodes.length; + var targetLen = targetLowerCodes.length; + var searchI = 0; // where we at + + var targetI = 0; // where you at + + var typoSimpleI = 0; + var matchesSimpleLen = 0; // very basic fuzzy match; to remove non-matching targets ASAP! + // walk through target. find sequential matches. + // if all chars aren't found then exit + + for (;;) { + var isMatch = searchLowerCode === targetLowerCodes[targetI]; + + if (isMatch) { + matchesSimple[matchesSimpleLen++] = targetI; + ++searchI; + if (searchI === searchLen) break; + searchLowerCode = searchLowerCodes[typoSimpleI === 0 ? searchI : typoSimpleI === searchI ? searchI + 1 : typoSimpleI === searchI - 1 ? searchI - 1 : searchI]; + } + + ++targetI; + + if (targetI >= targetLen) { + // Failed to find searchI + // Check for typo or exit + // we go as far as possible before trying to transpose + // then we transpose backwards until we reach the beginning + for (;;) { + if (searchI <= 1) return null; // not allowed to transpose first char + + if (typoSimpleI === 0) { + // we haven't tried to transpose yet + --searchI; + var searchLowerCodeNew = searchLowerCodes[searchI]; + if (searchLowerCode === searchLowerCodeNew) continue; // doesn't make sense to transpose a repeat char + + typoSimpleI = searchI; + } else { + if (typoSimpleI === 1) return null; // reached the end of the line for transposing + + --typoSimpleI; + searchI = typoSimpleI; + searchLowerCode = searchLowerCodes[searchI + 1]; + var searchLowerCodeNew = searchLowerCodes[searchI]; + if (searchLowerCode === searchLowerCodeNew) continue; // doesn't make sense to transpose a repeat char + } + + matchesSimpleLen = searchI; + targetI = matchesSimple[matchesSimpleLen - 1] + 1; + break; + } + } + } + + var searchI = 0; + var typoStrictI = 0; + var successStrict = false; + var matchesStrictLen = 0; + var nextBeginningIndexes = prepared._nextBeginningIndexes; + if (nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target); + var firstPossibleI = targetI = matchesSimple[0] === 0 ? 0 : nextBeginningIndexes[matchesSimple[0] - 1]; // Our target string successfully matched all characters in sequence! + // Let's try a more advanced and strict test to improve the score + // only count it as a match if it's consecutive or a beginning character! + + if (targetI !== targetLen) for (;;) { + if (targetI >= targetLen) { + // We failed to find a good spot for this search char, go back to the previous search char and force it forward + if (searchI <= 0) { + // We failed to push chars forward for a better match + // transpose, starting from the beginning + ++typoStrictI; + if (typoStrictI > searchLen - 2) break; + if (searchLowerCodes[typoStrictI] === searchLowerCodes[typoStrictI + 1]) continue; // doesn't make sense to transpose a repeat char + + targetI = firstPossibleI; + continue; + } + + --searchI; + var lastMatch = matchesStrict[--matchesStrictLen]; + targetI = nextBeginningIndexes[lastMatch]; + } else { + var isMatch = searchLowerCodes[typoStrictI === 0 ? searchI : typoStrictI === searchI ? searchI + 1 : typoStrictI === searchI - 1 ? searchI - 1 : searchI] === targetLowerCodes[targetI]; + + if (isMatch) { + matchesStrict[matchesStrictLen++] = targetI; + ++searchI; + + if (searchI === searchLen) { + successStrict = true; + break; + } + + ++targetI; + } else { + targetI = nextBeginningIndexes[targetI]; + } + } + } + { + // tally up the score & keep track of matches for highlighting later + if (successStrict) { + var matchesBest = matchesStrict; + var matchesBestLen = matchesStrictLen; + } else { + var matchesBest = matchesSimple; + var matchesBestLen = matchesSimpleLen; + } + + var score = 0; + var lastTargetI = -1; + + for (var i = 0; i < searchLen; ++i) { + var targetI = matchesBest[i]; // score only goes down if they're not consecutive + + if (lastTargetI !== targetI - 1) score -= targetI; + lastTargetI = targetI; + } + + if (!successStrict) { + score *= 1000; + if (typoSimpleI !== 0) score += -20; + /*typoPenalty*/ + } else { + if (typoStrictI !== 0) score += -20; + /*typoPenalty*/ + } + + score -= targetLen - searchLen; + prepared.score = score; + prepared.indexes = new Array(matchesBestLen); + + for (var i = matchesBestLen - 1; i >= 0; --i) { + prepared.indexes[i] = matchesBest[i]; + } + + return prepared; + } + }, + algorithmNoTypo: function algorithmNoTypo(searchLowerCodes, prepared, searchLowerCode) { + var targetLowerCodes = prepared._targetLowerCodes; + var searchLen = searchLowerCodes.length; + var targetLen = targetLowerCodes.length; + var searchI = 0; // where we at + + var targetI = 0; // where you at + + var matchesSimpleLen = 0; // very basic fuzzy match; to remove non-matching targets ASAP! + // walk through target. find sequential matches. + // if all chars aren't found then exit + + for (;;) { + var isMatch = searchLowerCode === targetLowerCodes[targetI]; + + if (isMatch) { + matchesSimple[matchesSimpleLen++] = targetI; + ++searchI; + if (searchI === searchLen) break; + searchLowerCode = searchLowerCodes[searchI]; + } + + ++targetI; + if (targetI >= targetLen) return null; // Failed to find searchI + } + + var searchI = 0; + var successStrict = false; + var matchesStrictLen = 0; + var nextBeginningIndexes = prepared._nextBeginningIndexes; + if (nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target); + targetI = matchesSimple[0] === 0 ? 0 : nextBeginningIndexes[matchesSimple[0] - 1]; // Our target string successfully matched all characters in sequence! + // Let's try a more advanced and strict test to improve the score + // only count it as a match if it's consecutive or a beginning character! + + if (targetI !== targetLen) for (;;) { + if (targetI >= targetLen) { + // We failed to find a good spot for this search char, go back to the previous search char and force it forward + if (searchI <= 0) break; // We failed to push chars forward for a better match + + --searchI; + var lastMatch = matchesStrict[--matchesStrictLen]; + targetI = nextBeginningIndexes[lastMatch]; + } else { + var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI]; + + if (isMatch) { + matchesStrict[matchesStrictLen++] = targetI; + ++searchI; + + if (searchI === searchLen) { + successStrict = true; + break; + } + + ++targetI; + } else { + targetI = nextBeginningIndexes[targetI]; + } + } + } + { + // tally up the score & keep track of matches for highlighting later + if (successStrict) { + var matchesBest = matchesStrict; + var matchesBestLen = matchesStrictLen; + } else { + var matchesBest = matchesSimple; + var matchesBestLen = matchesSimpleLen; + } + + var score = 0; + var lastTargetI = -1; + + for (var i = 0; i < searchLen; ++i) { + var targetI = matchesBest[i]; // score only goes down if they're not consecutive + + if (lastTargetI !== targetI - 1) score -= targetI; + lastTargetI = targetI; + } + + if (!successStrict) score *= 1000; + score -= targetLen - searchLen; + prepared.score = score; + prepared.indexes = new Array(matchesBestLen); + + for (var i = matchesBestLen - 1; i >= 0; --i) { + prepared.indexes[i] = matchesBest[i]; + } + + return prepared; + } + }, + prepareLowerCodes: function prepareLowerCodes(str) { + var strLen = str.length; + var lowerCodes = []; // new Array(strLen) sparse array is too slow + + var lower = str.toLowerCase(); + + for (var i = 0; i < strLen; ++i) { + lowerCodes[i] = lower.charCodeAt(i); + } + + return lowerCodes; + }, + prepareBeginningIndexes: function prepareBeginningIndexes(target) { + var targetLen = target.length; + var beginningIndexes = []; + var beginningIndexesLen = 0; + var wasUpper = false; + var wasAlphanum = false; + + for (var i = 0; i < targetLen; ++i) { + var targetCode = target.charCodeAt(i); + var isUpper = targetCode >= 65 && targetCode <= 90; + var isAlphanum = isUpper || targetCode >= 97 && targetCode <= 122 || targetCode >= 48 && targetCode <= 57; + var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum; + wasUpper = isUpper; + wasAlphanum = isAlphanum; + if (isBeginning) beginningIndexes[beginningIndexesLen++] = i; + } + + return beginningIndexes; + }, + prepareNextBeginningIndexes: function prepareNextBeginningIndexes(target) { + var targetLen = target.length; + var beginningIndexes = fuzzysort.prepareBeginningIndexes(target); + var nextBeginningIndexes = []; // new Array(targetLen) sparse array is too slow + + var lastIsBeginning = beginningIndexes[0]; + var lastIsBeginningI = 0; + + for (var i = 0; i < targetLen; ++i) { + if (lastIsBeginning > i) { + nextBeginningIndexes[i] = lastIsBeginning; + } else { + lastIsBeginning = beginningIndexes[++lastIsBeginningI]; + nextBeginningIndexes[i] = lastIsBeginning === undefined ? targetLen : lastIsBeginning; + } + } + + return nextBeginningIndexes; + }, + cleanup: cleanup, + new: fuzzysortNew + }; + return fuzzysort; + } // fuzzysortNew + // This stuff is outside fuzzysortNew, because it's shared with instances of fuzzysort.new() + + + var isNode = typeof commonjsRequire !== 'undefined' && typeof window === 'undefined'; // var MAX_INT = Number.MAX_SAFE_INTEGER + // var MIN_INT = Number.MIN_VALUE + + var preparedCache = new Map(); + var preparedSearchCache = new Map(); + var noResults = []; + noResults.total = 0; + var matchesSimple = []; + var matchesStrict = []; + + function cleanup() { + preparedCache.clear(); + preparedSearchCache.clear(); + matchesSimple = []; + matchesStrict = []; + } + + function defaultScoreFn(a) { + var max = -9007199254740991; + + for (var i = a.length - 1; i >= 0; --i) { + var result = a[i]; + if (result === null) continue; + var score = result.score; + if (score > max) max = score; + } + + if (max === -9007199254740991) return null; + return max; + } // prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop] + // prop = 'key1.key2' 10ms + // prop = ['key1', 'key2'] 27ms + + + function getValue(obj, prop) { + var tmp = obj[prop]; + if (tmp !== undefined) return tmp; + var segs = prop; + if (!Array.isArray(prop)) segs = prop.split('.'); + var len = segs.length; + var i = -1; + + while (obj && ++i < len) { + obj = obj[segs[i]]; + } + + return obj; + } + + function isObj(x) { + return _typeof(x) === 'object'; + } // faster as a function + // Hacked version of https://github.com/lemire/FastPriorityQueue.js + + + var fastpriorityqueue = function fastpriorityqueue() { + var r = [], + o = 0, + e = {}; + + function n() { + for (var e = 0, n = r[e], c = 1; c < o;) { + var f = c + 1; + e = c, f < o && r[f].score < r[c].score && (e = f), r[e - 1 >> 1] = r[e], c = 1 + (e << 1); + } + + for (var a = e - 1 >> 1; e > 0 && n.score < r[a].score; a = (e = a) - 1 >> 1) { + r[e] = r[a]; + } + + r[e] = n; + } + + return e.add = function (e) { + var n = o; + r[o++] = e; + + for (var c = n - 1 >> 1; n > 0 && e.score < r[c].score; c = (n = c) - 1 >> 1) { + r[n] = r[c]; + } + + r[n] = e; + }, e.poll = function () { + if (0 !== o) { + var e = r[0]; + return r[0] = r[--o], n(), e; + } + }, e.peek = function (e) { + if (0 !== o) return r[0]; + }, e.replaceTop = function (o) { + r[0] = o, n(); + }, e; + }; + + var q = fastpriorityqueue(); // reuse this, except for async, it needs to make its own + + return fuzzysortNew(); + }); // UMD + // TODO: (performance) wasm version!? + // TODO: (performance) layout memory in an optimal way to go fast by avoiding cache misses + // TODO: (performance) preparedCache is a memory leak + // TODO: (like sublime) backslash === forwardslash + // TODO: (performance) i have no idea how well optizmied the allowing typos algorithm is + + })(fuzzysort$1); + + var fuzzysort = fuzzysort$1.exports; + + var stats = { + failedTests: [], + defined: 0, + completed: 0 + }; // Escape text for attribute or text content. + + function escapeText(s) { + if (!s) { + return ""; + } + + s = s + ""; // Both single quotes and double quotes (for attributes) + + return s.replace(/['"<>&]/g, function (s) { + switch (s) { + case "'": + return "'"; + + case "\"": + return """; + + case "<": + return "<"; + + case ">": + return ">"; + + case "&": + return "&"; + } + }); + } + + (function () { + // Don't load the HTML Reporter on non-browser environments + if (!window$1 || !document) { + return; + } + + var config = QUnit.config, + hiddenTests = [], + collapseNext = false, + hasOwn = Object.prototype.hasOwnProperty, + unfilteredUrl = setUrl({ + filter: undefined, + module: undefined, + moduleId: undefined, + testId: undefined + }); + + function trim(string) { + if (typeof string.trim === "function") { + return string.trim(); + } else { + return string.replace(/^\s+|\s+$/g, ""); + } + } + + function addEvent(elem, type, fn) { + elem.addEventListener(type, fn, false); + } + + function removeEvent(elem, type, fn) { + elem.removeEventListener(type, fn, false); + } + + function addEvents(elems, type, fn) { + var i = elems.length; + + while (i--) { + addEvent(elems[i], type, fn); + } + } + + function hasClass(elem, name) { + return (" " + elem.className + " ").indexOf(" " + name + " ") >= 0; + } + + function addClass(elem, name) { + if (!hasClass(elem, name)) { + elem.className += (elem.className ? " " : "") + name; + } + } + + function toggleClass(elem, name, force) { + if (force || typeof force === "undefined" && !hasClass(elem, name)) { + addClass(elem, name); + } else { + removeClass(elem, name); + } + } + + function removeClass(elem, name) { + var set = " " + elem.className + " "; // Class name may appear multiple times + + while (set.indexOf(" " + name + " ") >= 0) { + set = set.replace(" " + name + " ", " "); + } // Trim for prettiness + + + elem.className = trim(set); + } + + function id(name) { + return document.getElementById && document.getElementById(name); + } + + function abortTests() { + var abortButton = id("qunit-abort-tests-button"); + + if (abortButton) { + abortButton.disabled = true; + abortButton.innerHTML = "Aborting..."; + } + + QUnit.config.queue.length = 0; + return false; + } + + function interceptNavigation(ev) { + // Trim potential accidental whitespace so that QUnit doesn't throw an error about no tests matching the filter. + var filterInputElem = id("qunit-filter-input"); + filterInputElem.value = trim(filterInputElem.value); + applyUrlParams(); + + if (ev && ev.preventDefault) { + ev.preventDefault(); + } + + return false; + } + + function getUrlConfigHtml() { + var i, + j, + val, + escaped, + escapedTooltip, + selection = false, + urlConfig = config.urlConfig, + urlConfigHtml = ""; + + for (i = 0; i < urlConfig.length; i++) { + // Options can be either strings or objects with nonempty "id" properties + val = config.urlConfig[i]; + + if (typeof val === "string") { + val = { + id: val, + label: val + }; + } + + escaped = escapeText(val.id); + escapedTooltip = escapeText(val.tooltip); + + if (!val.value || typeof val.value === "string") { + urlConfigHtml += ""; + } else { + urlConfigHtml += ""; + } + } + + return urlConfigHtml; + } // Handle "click" events on toolbar checkboxes and "change" for select menus. + // Updates the URL with the new state of `config.urlConfig` values. + + + function toolbarChanged() { + var updatedUrl, + value, + tests, + field = this, + params = {}; // Detect if field is a select menu or a checkbox + + if ("selectedIndex" in field) { + value = field.options[field.selectedIndex].value || undefined; + } else { + value = field.checked ? field.defaultValue || true : undefined; + } + + params[field.name] = value; + updatedUrl = setUrl(params); // Check if we can apply the change without a page refresh + + if ("hidepassed" === field.name && "replaceState" in window$1.history) { + QUnit.urlParams[field.name] = value; + config[field.name] = value || false; + tests = id("qunit-tests"); + + if (tests) { + var length = tests.children.length; + var children = tests.children; + + if (field.checked) { + for (var i = 0; i < length; i++) { + var test = children[i]; + var className = test ? test.className : ""; + var classNameHasPass = className.indexOf("pass") > -1; + var classNameHasSkipped = className.indexOf("skipped") > -1; + + if (classNameHasPass || classNameHasSkipped) { + hiddenTests.push(test); + } + } + + var _iterator = _createForOfIteratorHelper(hiddenTests), + _step; + + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var hiddenTest = _step.value; + tests.removeChild(hiddenTest); + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + } else { + while ((test = hiddenTests.pop()) != null) { + tests.appendChild(test); + } + } + } + + window$1.history.replaceState(null, "", updatedUrl); + } else { + window$1.location = updatedUrl; + } + } + + function setUrl(params) { + var key, + arrValue, + i, + querystring = "?", + location = window$1.location; + params = extend(extend({}, QUnit.urlParams), params); + + for (key in params) { + // Skip inherited or undefined properties + if (hasOwn.call(params, key) && params[key] !== undefined) { + // Output a parameter for each value of this key + // (but usually just one) + arrValue = [].concat(params[key]); + + for (i = 0; i < arrValue.length; i++) { + querystring += encodeURIComponent(key); + + if (arrValue[i] !== true) { + querystring += "=" + encodeURIComponent(arrValue[i]); + } + + querystring += "&"; + } + } + } + + return location.protocol + "//" + location.host + location.pathname + querystring.slice(0, -1); + } + + function applyUrlParams() { + var i, + selectedModules = [], + modulesList = id("qunit-modulefilter-dropdown-list").getElementsByTagName("input"), + filter = id("qunit-filter-input").value; + + for (i = 0; i < modulesList.length; i++) { + if (modulesList[i].checked) { + selectedModules.push(modulesList[i].value); + } + } + + window$1.location = setUrl({ + filter: filter === "" ? undefined : filter, + moduleId: selectedModules.length === 0 ? undefined : selectedModules, + // Remove module and testId filter + module: undefined, + testId: undefined + }); + } + + function toolbarUrlConfigContainer() { + var urlConfigContainer = document.createElement("span"); + urlConfigContainer.innerHTML = getUrlConfigHtml(); + addClass(urlConfigContainer, "qunit-url-config"); + addEvents(urlConfigContainer.getElementsByTagName("input"), "change", toolbarChanged); + addEvents(urlConfigContainer.getElementsByTagName("select"), "change", toolbarChanged); + return urlConfigContainer; + } + + function abortTestsButton() { + var button = document.createElement("button"); + button.id = "qunit-abort-tests-button"; + button.innerHTML = "Abort"; + addEvent(button, "click", abortTests); + return button; + } + + function toolbarLooseFilter() { + var filter = document.createElement("form"), + label = document.createElement("label"), + input = document.createElement("input"), + button = document.createElement("button"); + addClass(filter, "qunit-filter"); + label.innerHTML = "Filter: "; + input.type = "text"; + input.value = config.filter || ""; + input.name = "filter"; + input.id = "qunit-filter-input"; + button.innerHTML = "Go"; + label.appendChild(input); + filter.appendChild(label); + filter.appendChild(document.createTextNode(" ")); + filter.appendChild(button); + addEvent(filter, "submit", interceptNavigation); + return filter; + } + + function moduleListHtml(modules) { + var i, + checked, + html = ""; + + for (i = 0; i < modules.length; i++) { + if (modules[i].name !== "") { + checked = config.moduleId.indexOf(modules[i].moduleId) > -1; + html += "
    1. "; + } + } + + return html; + } + + function toolbarModuleFilter() { + var commit, + reset, + moduleFilter = document.createElement("form"), + label = document.createElement("label"), + moduleSearch = document.createElement("input"), + dropDown = document.createElement("div"), + actions = document.createElement("span"), + applyButton = document.createElement("button"), + resetButton = document.createElement("button"), + allModulesLabel = document.createElement("label"), + allCheckbox = document.createElement("input"), + dropDownList = document.createElement("ul"), + dirty = false; + moduleSearch.id = "qunit-modulefilter-search"; + moduleSearch.autocomplete = "off"; + addEvent(moduleSearch, "input", searchInput); + addEvent(moduleSearch, "input", searchFocus); + addEvent(moduleSearch, "focus", searchFocus); + addEvent(moduleSearch, "click", searchFocus); + config.modules.forEach(function (module) { + return module.namePrepared = fuzzysort.prepare(module.name); + }); + label.id = "qunit-modulefilter-search-container"; + label.innerHTML = "Module: "; + label.appendChild(moduleSearch); + applyButton.textContent = "Apply"; + applyButton.style.display = "none"; + resetButton.textContent = "Reset"; + resetButton.type = "reset"; + resetButton.style.display = "none"; + allCheckbox.type = "checkbox"; + allCheckbox.checked = config.moduleId.length === 0; + allModulesLabel.className = "clickable"; + + if (config.moduleId.length) { + allModulesLabel.className = "checked"; + } + + allModulesLabel.appendChild(allCheckbox); + allModulesLabel.appendChild(document.createTextNode("All modules")); + actions.id = "qunit-modulefilter-actions"; + actions.appendChild(applyButton); + actions.appendChild(resetButton); + actions.appendChild(allModulesLabel); + commit = actions.firstChild; + reset = commit.nextSibling; + addEvent(commit, "click", applyUrlParams); + dropDownList.id = "qunit-modulefilter-dropdown-list"; + dropDownList.innerHTML = moduleListHtml(config.modules); + dropDown.id = "qunit-modulefilter-dropdown"; + dropDown.style.display = "none"; + dropDown.appendChild(actions); + dropDown.appendChild(dropDownList); + addEvent(dropDown, "change", selectionChange); + selectionChange(); + moduleFilter.id = "qunit-modulefilter"; + moduleFilter.appendChild(label); + moduleFilter.appendChild(dropDown); + addEvent(moduleFilter, "submit", interceptNavigation); + addEvent(moduleFilter, "reset", function () { + // Let the reset happen, then update styles + window$1.setTimeout(selectionChange); + }); // Enables show/hide for the dropdown + + function searchFocus() { + if (dropDown.style.display !== "none") { + return; + } + + dropDown.style.display = "block"; + addEvent(document, "click", hideHandler); + addEvent(document, "keydown", hideHandler); // Hide on Escape keydown or outside-container click + + function hideHandler(e) { + var inContainer = moduleFilter.contains(e.target); + + if (e.keyCode === 27 || !inContainer) { + if (e.keyCode === 27 && inContainer) { + moduleSearch.focus(); + } + + dropDown.style.display = "none"; + removeEvent(document, "click", hideHandler); + removeEvent(document, "keydown", hideHandler); + moduleSearch.value = ""; + searchInput(); + } + } + } + + function filterModules(searchText) { + if (searchText === "") { + return config.modules; + } + + return fuzzysort.go(searchText, config.modules, { + key: "namePrepared", + threshold: -10000 + }).map(function (module) { + return module.obj; + }); + } // Processes module search box input + + + var searchInputTimeout; + + function searchInput() { + window$1.clearTimeout(searchInputTimeout); + searchInputTimeout = window$1.setTimeout(function () { + var searchText = moduleSearch.value.toLowerCase(), + filteredModules = filterModules(searchText); + dropDownList.innerHTML = moduleListHtml(filteredModules); + }, 200); + } // Processes selection changes + + + function selectionChange(evt) { + var i, + item, + checkbox = evt && evt.target || allCheckbox, + modulesList = dropDownList.getElementsByTagName("input"), + selectedNames = []; + toggleClass(checkbox.parentNode, "checked", checkbox.checked); + dirty = false; + + if (checkbox.checked && checkbox !== allCheckbox) { + allCheckbox.checked = false; + removeClass(allCheckbox.parentNode, "checked"); + } + + for (i = 0; i < modulesList.length; i++) { + item = modulesList[i]; + + if (!evt) { + toggleClass(item.parentNode, "checked", item.checked); + } else if (checkbox === allCheckbox && checkbox.checked) { + item.checked = false; + removeClass(item.parentNode, "checked"); + } + + dirty = dirty || item.checked !== item.defaultChecked; + + if (item.checked) { + selectedNames.push(item.parentNode.textContent); + } + } + + commit.style.display = reset.style.display = dirty ? "" : "none"; + moduleSearch.placeholder = selectedNames.join(", ") || allCheckbox.parentNode.textContent; + moduleSearch.title = "Type to filter list. Current selection:\n" + (selectedNames.join("\n") || allCheckbox.parentNode.textContent); + } + + return moduleFilter; + } + + function toolbarFilters() { + var toolbarFilters = document.createElement("span"); + toolbarFilters.id = "qunit-toolbar-filters"; + toolbarFilters.appendChild(toolbarLooseFilter()); + toolbarFilters.appendChild(toolbarModuleFilter()); + return toolbarFilters; + } + + function appendToolbar() { + var toolbar = id("qunit-testrunner-toolbar"); + + if (toolbar) { + toolbar.appendChild(toolbarUrlConfigContainer()); + toolbar.appendChild(toolbarFilters()); + toolbar.appendChild(document.createElement("div")).className = "clearfix"; + } + } + + function appendHeader() { + var header = id("qunit-header"); + + if (header) { + header.innerHTML = "" + header.innerHTML + " "; + } + } + + function appendBanner() { + var banner = id("qunit-banner"); + + if (banner) { + banner.className = ""; + } + } + + function appendTestResults() { + var tests = id("qunit-tests"), + result = id("qunit-testresult"), + controls; + + if (result) { + result.parentNode.removeChild(result); + } + + if (tests) { + tests.innerHTML = ""; + result = document.createElement("p"); + result.id = "qunit-testresult"; + result.className = "result"; + tests.parentNode.insertBefore(result, tests); + result.innerHTML = "
      Running...
       
      " + "
      " + "
      "; + controls = id("qunit-testresult-controls"); + } + + if (controls) { + controls.appendChild(abortTestsButton()); + } + } + + function appendFilteredTest() { + var testId = QUnit.config.testId; + + if (!testId || testId.length <= 0) { + return ""; + } + + return "
      Rerunning selected tests: " + escapeText(testId.join(", ")) + " Run all tests
      "; + } + + function appendUserAgent() { + var userAgent = id("qunit-userAgent"); + + if (userAgent) { + userAgent.innerHTML = ""; + userAgent.appendChild(document.createTextNode("QUnit " + QUnit.version + "; " + navigator.userAgent)); + } + } + + function appendInterface() { + var qunit = id("qunit"); // For compat with QUnit 1.2, and to support fully custom theme HTML, + // we will use any existing elements if no id="qunit" element exists. + // + // Note that we don't fail or fallback to creating it ourselves, + // because not having id="qunit" (and not having the below elements) + // simply means QUnit acts headless, allowing users to use their own + // reporters, or for a test runner to listen for events directly without + // having the HTML reporter actively render anything. + + if (qunit) { + qunit.setAttribute("role", "main"); // Since QUnit 1.3, these are created automatically if the page + // contains id="qunit". + + qunit.innerHTML = "

      " + escapeText(document.title) + "

      " + "

      " + "" + appendFilteredTest() + "

      " + "
        "; + } + + appendHeader(); + appendBanner(); + appendTestResults(); + appendUserAgent(); + appendToolbar(); + } + + function appendTest(name, testId, moduleName) { + var title, + rerunTrigger, + testBlock, + assertList, + tests = id("qunit-tests"); + + if (!tests) { + return; + } + + title = document.createElement("strong"); + title.innerHTML = getNameHtml(name, moduleName); + testBlock = document.createElement("li"); + testBlock.appendChild(title); // No ID or rerun link for "global failure" blocks + + if (testId !== undefined) { + rerunTrigger = document.createElement("a"); + rerunTrigger.innerHTML = "Rerun"; + rerunTrigger.href = setUrl({ + testId: testId + }); + testBlock.id = "qunit-test-output-" + testId; + testBlock.appendChild(rerunTrigger); + } + + assertList = document.createElement("ol"); + assertList.className = "qunit-assert-list"; + testBlock.appendChild(assertList); + tests.appendChild(testBlock); + return testBlock; + } // HTML Reporter initialization and load + + + QUnit.on("runStart", function (runStart) { + stats.defined = runStart.testCounts.total; + }); + QUnit.begin(function () { + // Initialize QUnit elements + // This is done from begin() instead of runStart, because + // urlparams.js uses begin(), which we need to wait for. + // urlparams.js in turn uses begin() to allow plugins to + // add entries to QUnit.config.urlConfig, which may be done + // asynchronously. + // + appendInterface(); + }); + + function getRerunFailedHtml(failedTests) { + if (failedTests.length === 0) { + return ""; + } + + var href = setUrl({ + testId: failedTests + }); + return ["
        ", failedTests.length === 1 ? "Rerun 1 failed test" : "Rerun " + failedTests.length + " failed tests", ""].join(""); + } + + QUnit.on("runEnd", function (runEnd) { + var banner = id("qunit-banner"), + tests = id("qunit-tests"), + abortButton = id("qunit-abort-tests-button"), + assertPassed = config.stats.all - config.stats.bad, + html = [runEnd.testCounts.total, " tests completed in ", runEnd.runtime, " milliseconds, with ", runEnd.testCounts.failed, " failed, ", runEnd.testCounts.skipped, " skipped, and ", runEnd.testCounts.todo, " todo.
        ", "", assertPassed, " assertions of ", config.stats.all, " passed, ", config.stats.bad, " failed.", getRerunFailedHtml(stats.failedTests)].join(""), + test, + assertLi, + assertList; // Update remaining tests to aborted + + if (abortButton && abortButton.disabled) { + html = "Tests aborted after " + runEnd.runtime + " milliseconds."; + + for (var i = 0; i < tests.children.length; i++) { + test = tests.children[i]; + + if (test.className === "" || test.className === "running") { + test.className = "aborted"; + assertList = test.getElementsByTagName("ol")[0]; + assertLi = document.createElement("li"); + assertLi.className = "fail"; + assertLi.innerHTML = "Test aborted."; + assertList.appendChild(assertLi); + } + } + } + + if (banner && (!abortButton || abortButton.disabled === false)) { + banner.className = runEnd.status === "failed" ? "qunit-fail" : "qunit-pass"; + } + + if (abortButton) { + abortButton.parentNode.removeChild(abortButton); + } + + if (tests) { + id("qunit-testresult-display").innerHTML = html; + } + + if (config.altertitle && document.title) { + // Show ✖ for good, ✔ for bad suite result in title + // use escape sequences in case file gets loaded with non-utf-8 + // charset + document.title = [runEnd.status === "failed" ? "\u2716" : "\u2714", document.title.replace(/^[\u2714\u2716] /i, "")].join(" "); + } // Scroll back to top to show results + + + if (config.scrolltop && window$1.scrollTo) { + window$1.scrollTo(0, 0); + } + }); + + function getNameHtml(name, module) { + var nameHtml = ""; + + if (module) { + nameHtml = "" + escapeText(module) + ": "; + } + + nameHtml += "" + escapeText(name) + ""; + return nameHtml; + } + + function getProgressHtml(stats) { + return [stats.completed, " / ", stats.defined, " tests completed.
        "].join(""); + } + + QUnit.testStart(function (details) { + var running, bad; + appendTest(details.name, details.testId, details.module); + running = id("qunit-testresult-display"); + + if (running) { + addClass(running, "running"); + bad = QUnit.config.reorder && details.previousFailure; + running.innerHTML = [getProgressHtml(stats), bad ? "Rerunning previously failed test:
        " : "Running: ", getNameHtml(details.name, details.module), getRerunFailedHtml(stats.failedTests)].join(""); + } + }); + + function stripHtml(string) { + // Strip tags, html entity and whitespaces + return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/"/g, "").replace(/\s+/g, ""); + } + + QUnit.log(function (details) { + var assertList, + assertLi, + message, + expected, + actual, + diff, + showDiff = false, + testItem = id("qunit-test-output-" + details.testId); + + if (!testItem) { + return; + } + + message = escapeText(details.message) || (details.result ? "okay" : "failed"); + message = "" + message + ""; + message += "@ " + details.runtime + " ms"; // The pushFailure doesn't provide details.expected + // when it calls, it's implicit to also not show expected and diff stuff + // Also, we need to check details.expected existence, as it can exist and be undefined + + if (!details.result && hasOwn.call(details, "expected")) { + if (details.negative) { + expected = "NOT " + QUnit.dump.parse(details.expected); + } else { + expected = QUnit.dump.parse(details.expected); + } + + actual = QUnit.dump.parse(details.actual); + message += ""; + + if (actual !== expected) { + message += ""; + + if (typeof details.actual === "number" && typeof details.expected === "number") { + if (!isNaN(details.actual) && !isNaN(details.expected)) { + showDiff = true; + diff = details.actual - details.expected; + diff = (diff > 0 ? "+" : "") + diff; + } + } else if (typeof details.actual !== "boolean" && typeof details.expected !== "boolean") { + diff = QUnit.diff(expected, actual); // don't show diff if there is zero overlap + + showDiff = stripHtml(diff).length !== stripHtml(expected).length + stripHtml(actual).length; + } + + if (showDiff) { + message += ""; + } + } else if (expected.indexOf("[object Array]") !== -1 || expected.indexOf("[object Object]") !== -1) { + message += ""; + } else { + message += ""; + } + + if (details.source) { + message += ""; + } + + message += "
        Expected:
        " + escapeText(expected) + "
        Result:
        " + escapeText(actual) + "
        Diff:
        " + diff + "
        Message: " + "Diff suppressed as the depth of object is more than current max depth (" + QUnit.config.maxDepth + ").

        Hint: Use QUnit.dump.maxDepth to " + " run with a higher max depth or " + "Rerun without max depth.

        Message: " + "Diff suppressed as the expected and actual results have an equivalent" + " serialization
        Source:
        " + escapeText(details.source) + "
        "; // This occurs when pushFailure is set and we have an extracted stack trace + } else if (!details.result && details.source) { + message += "" + "" + "
        Source:
        " + escapeText(details.source) + "
        "; + } + + assertList = testItem.getElementsByTagName("ol")[0]; + assertLi = document.createElement("li"); + assertLi.className = details.result ? "pass" : "fail"; + assertLi.innerHTML = message; + assertList.appendChild(assertLi); + }); + QUnit.testDone(function (details) { + var testTitle, + time, + assertList, + status, + good, + bad, + testCounts, + skipped, + sourceName, + tests = id("qunit-tests"), + testItem = id("qunit-test-output-" + details.testId); + + if (!tests || !testItem) { + return; + } + + removeClass(testItem, "running"); + + if (details.failed > 0) { + status = "failed"; + } else if (details.todo) { + status = "todo"; + } else { + status = details.skipped ? "skipped" : "passed"; + } + + assertList = testItem.getElementsByTagName("ol")[0]; + good = details.passed; + bad = details.failed; // This test passed if it has no unexpected failed assertions + + var testPassed = details.failed > 0 ? details.todo : !details.todo; + + if (testPassed) { + // Collapse the passing tests + addClass(assertList, "qunit-collapsed"); + } else { + stats.failedTests.push(details.testId); + + if (config.collapse) { + if (!collapseNext) { + // Skip collapsing the first failing test + collapseNext = true; + } else { + // Collapse remaining tests + addClass(assertList, "qunit-collapsed"); + } + } + } // The testItem.firstChild is the test name + + + testTitle = testItem.firstChild; + testCounts = bad ? "" + bad + ", " + "" + good + ", " : ""; + testTitle.innerHTML += " (" + testCounts + details.assertions.length + ")"; + stats.completed++; + + if (details.skipped) { + testItem.className = "skipped"; + skipped = document.createElement("em"); + skipped.className = "qunit-skipped-label"; + skipped.innerHTML = "skipped"; + testItem.insertBefore(skipped, testTitle); + } else { + addEvent(testTitle, "click", function () { + toggleClass(assertList, "qunit-collapsed"); + }); + testItem.className = testPassed ? "pass" : "fail"; + + if (details.todo) { + var todoLabel = document.createElement("em"); + todoLabel.className = "qunit-todo-label"; + todoLabel.innerHTML = "todo"; + testItem.className += " todo"; + testItem.insertBefore(todoLabel, testTitle); + } + + time = document.createElement("span"); + time.className = "runtime"; + time.innerHTML = details.runtime + " ms"; + testItem.insertBefore(time, assertList); + } // Show the source of the test when showing assertions + + + if (details.source) { + sourceName = document.createElement("p"); + sourceName.innerHTML = "Source: " + escapeText(details.source); + addClass(sourceName, "qunit-source"); + + if (testPassed) { + addClass(sourceName, "qunit-collapsed"); + } + + addEvent(testTitle, "click", function () { + toggleClass(sourceName, "qunit-collapsed"); + }); + testItem.appendChild(sourceName); + } + + if (config.hidepassed && (status === "passed" || details.skipped)) { + // use removeChild instead of remove because of support + hiddenTests.push(testItem); + tests.removeChild(testItem); + } + }); + QUnit.on("error", function (error) { + var testItem = appendTest("global failure"); + + if (!testItem) { + // HTML Reporter is probably disabled or not yet initialized. + return; + } // Render similar to a failed assertion (see above QUnit.log callback) + + + var message = escapeText(errorString(error)); + message = "" + message + ""; + + if (error && error.stack) { + message += "" + "" + "
        Source:
        " + escapeText(error.stack) + "
        "; + } + + var assertList = testItem.getElementsByTagName("ol")[0]; + var assertLi = document.createElement("li"); + assertLi.className = "fail"; + assertLi.innerHTML = message; + assertList.appendChild(assertLi); // Make it visible + + testItem.className = "fail"; + }); // Avoid readyState issue with phantomjs + // Ref: #818 + + var usingPhantom = function (p) { + return p && p.version && p.version.major > 0; + }(window$1.phantom); + + if (usingPhantom) { + console$1.warn("Support for PhantomJS is deprecated and will be removed in QUnit 3.0."); + } + + if (!usingPhantom && document.readyState === "complete") { + QUnit.load(); + } else { + addEvent(window$1, "load", QUnit.load); + } // Wrap window.onerror. We will call the original window.onerror to see if + // the existing handler fully handles the error; if not, we will call the + // QUnit.onError function. + + + var originalWindowOnError = window$1.onerror; // Cover uncaught exceptions + // Returning true will suppress the default browser handler, + // returning false will let it run. + + window$1.onerror = function (message, fileName, lineNumber, columnNumber, errorObj) { + var ret = false; + + if (originalWindowOnError) { + for (var _len = arguments.length, args = new Array(_len > 5 ? _len - 5 : 0), _key = 5; _key < _len; _key++) { + args[_key - 5] = arguments[_key]; + } + + ret = originalWindowOnError.call.apply(originalWindowOnError, [this, message, fileName, lineNumber, columnNumber, errorObj].concat(args)); + } // Treat return value as window.onerror itself does, + // Only do our handling if not suppressed. + + + if (ret !== true) { + // If there is a current test that sets the internal `ignoreGlobalErrors` field + // (such as during `assert.throws()`), then the error is ignored and native + // error reporting is suppressed as well. This is because in browsers, an error + // can sometimes end up in `window.onerror` instead of in the local try/catch. + // This ignoring of errors does not apply to our general onUncaughtException + // method, nor to our `unhandledRejection` handlers, as those are not meant + // to receive an "expected" error during `assert.throws()`. + if (config.current && config.current.ignoreGlobalErrors) { + return true; + } // According to + // https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror, + // most modern browsers support an errorObj argument; use that to + // get a full stack trace if it's available. + + + var error = errorObj || new Error(message); + + if (!error.stack && fileName && lineNumber) { + error.stack = "".concat(fileName, ":").concat(lineNumber); + } + + QUnit.onUncaughtException(error); + } + + return ret; + }; + + window$1.addEventListener("unhandledrejection", function (event) { + QUnit.onUncaughtException(event.reason); + }); + })(); + + /* + * This file is a modified version of google-diff-match-patch's JavaScript implementation + * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js), + * modifications are licensed as more fully set forth in LICENSE.txt. + * + * The original source of google-diff-match-patch is attributable and licensed as follows: + * + * Copyright 2006 Google Inc. + * https://code.google.com/p/google-diff-match-patch/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * More Info: + * https://code.google.com/p/google-diff-match-patch/ + * + * Usage: QUnit.diff(expected, actual) + * + */ + + QUnit.diff = function () { + function DiffMatchPatch() {} // DIFF FUNCTIONS + + /** + * The data structure representing a diff is an array of tuples: + * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] + * which means: delete 'Hello', add 'Goodbye' and keep ' world.' + */ + + + var DIFF_DELETE = -1, + DIFF_INSERT = 1, + DIFF_EQUAL = 0, + hasOwn = Object.prototype.hasOwnProperty; + /** + * Find the differences between two texts. Simplifies the problem by stripping + * any common prefix or suffix off the texts before diffing. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @param {boolean=} optChecklines Optional speedup flag. If present and false, + * then don't run a line-level diff first to identify the changed areas. + * Defaults to true, which does a faster, slightly less optimal diff. + * @return {!Array.} Array of diff tuples. + */ + + DiffMatchPatch.prototype.DiffMain = function (text1, text2, optChecklines) { + var deadline, checklines, commonlength, commonprefix, commonsuffix, diffs; // The diff must be complete in up to 1 second. + + deadline = new Date().getTime() + 1000; // Check for null inputs. + + if (text1 === null || text2 === null) { + throw new Error("Null input. (DiffMain)"); + } // Check for equality (speedup). + + + if (text1 === text2) { + if (text1) { + return [[DIFF_EQUAL, text1]]; + } + + return []; + } + + if (typeof optChecklines === "undefined") { + optChecklines = true; + } + + checklines = optChecklines; // Trim off common prefix (speedup). + + commonlength = this.diffCommonPrefix(text1, text2); + commonprefix = text1.substring(0, commonlength); + text1 = text1.substring(commonlength); + text2 = text2.substring(commonlength); // Trim off common suffix (speedup). + + commonlength = this.diffCommonSuffix(text1, text2); + commonsuffix = text1.substring(text1.length - commonlength); + text1 = text1.substring(0, text1.length - commonlength); + text2 = text2.substring(0, text2.length - commonlength); // Compute the diff on the middle block. + + diffs = this.diffCompute(text1, text2, checklines, deadline); // Restore the prefix and suffix. + + if (commonprefix) { + diffs.unshift([DIFF_EQUAL, commonprefix]); + } + + if (commonsuffix) { + diffs.push([DIFF_EQUAL, commonsuffix]); + } + + this.diffCleanupMerge(diffs); + return diffs; + }; + /** + * Reduce the number of edits by eliminating operationally trivial equalities. + * @param {!Array.} diffs Array of diff tuples. + */ + + + DiffMatchPatch.prototype.diffCleanupEfficiency = function (diffs) { + var changes, equalities, equalitiesLength, lastequality, pointer, preIns, preDel, postIns, postDel; + changes = false; + equalities = []; // Stack of indices where equalities are found. + + equalitiesLength = 0; // Keeping our own length var is faster in JS. + + /** @type {?string} */ + + lastequality = null; // Always equal to diffs[equalities[equalitiesLength - 1]][1] + + pointer = 0; // Index of current position. + // Is there an insertion operation before the last equality. + + preIns = false; // Is there a deletion operation before the last equality. + + preDel = false; // Is there an insertion operation after the last equality. + + postIns = false; // Is there a deletion operation after the last equality. + + postDel = false; + + while (pointer < diffs.length) { + // Equality found. + if (diffs[pointer][0] === DIFF_EQUAL) { + if (diffs[pointer][1].length < 4 && (postIns || postDel)) { + // Candidate found. + equalities[equalitiesLength++] = pointer; + preIns = postIns; + preDel = postDel; + lastequality = diffs[pointer][1]; + } else { + // Not a candidate, and can never become one. + equalitiesLength = 0; + lastequality = null; + } + + postIns = postDel = false; // An insertion or deletion. + } else { + if (diffs[pointer][0] === DIFF_DELETE) { + postDel = true; + } else { + postIns = true; + } + /* + * Five types to be split: + * ABXYCD + * AXCD + * ABXC + * AXCD + * ABXC + */ + + + if (lastequality && (preIns && preDel && postIns && postDel || lastequality.length < 2 && preIns + preDel + postIns + postDel === 3)) { + // Duplicate record. + diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]); // Change second copy to insert. + + diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; + equalitiesLength--; // Throw away the equality we just deleted; + + lastequality = null; + + if (preIns && preDel) { + // No changes made which could affect previous entry, keep going. + postIns = postDel = true; + equalitiesLength = 0; + } else { + equalitiesLength--; // Throw away the previous equality. + + pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; + postIns = postDel = false; + } + + changes = true; + } + } + + pointer++; + } + + if (changes) { + this.diffCleanupMerge(diffs); + } + }; + /** + * Convert a diff array into a pretty HTML report. + * @param {!Array.} diffs Array of diff tuples. + * @param {integer} string to be beautified. + * @return {string} HTML representation. + */ + + + DiffMatchPatch.prototype.diffPrettyHtml = function (diffs) { + var op, + data, + x, + html = []; + + for (x = 0; x < diffs.length; x++) { + op = diffs[x][0]; // Operation (insert, delete, equal) + + data = diffs[x][1]; // Text of change. + + switch (op) { + case DIFF_INSERT: + html[x] = "" + escapeText(data) + ""; + break; + + case DIFF_DELETE: + html[x] = "" + escapeText(data) + ""; + break; + + case DIFF_EQUAL: + html[x] = "" + escapeText(data) + ""; + break; + } + } + + return html.join(""); + }; + /** + * Determine the common prefix of two strings. + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {number} The number of characters common to the start of each + * string. + */ + + + DiffMatchPatch.prototype.diffCommonPrefix = function (text1, text2) { + var pointermid, pointermax, pointermin, pointerstart; // Quick check for common null cases. + + if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) { + return 0; + } // Binary search. + // Performance analysis: https://neil.fraser.name/news/2007/10/09/ + + + pointermin = 0; + pointermax = Math.min(text1.length, text2.length); + pointermid = pointermax; + pointerstart = 0; + + while (pointermin < pointermid) { + if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) { + pointermin = pointermid; + pointerstart = pointermin; + } else { + pointermax = pointermid; + } + + pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); + } + + return pointermid; + }; + /** + * Determine the common suffix of two strings. + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {number} The number of characters common to the end of each string. + */ + + + DiffMatchPatch.prototype.diffCommonSuffix = function (text1, text2) { + var pointermid, pointermax, pointermin, pointerend; // Quick check for common null cases. + + if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) { + return 0; + } // Binary search. + // Performance analysis: https://neil.fraser.name/news/2007/10/09/ + + + pointermin = 0; + pointermax = Math.min(text1.length, text2.length); + pointermid = pointermax; + pointerend = 0; + + while (pointermin < pointermid) { + if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) { + pointermin = pointermid; + pointerend = pointermin; + } else { + pointermax = pointermid; + } + + pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); + } + + return pointermid; + }; + /** + * Find the differences between two texts. Assumes that the texts do not + * have any common prefix or suffix. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @param {boolean} checklines Speedup flag. If false, then don't run a + * line-level diff first to identify the changed areas. + * If true, then run a faster, slightly less optimal diff. + * @param {number} deadline Time when the diff should be complete by. + * @return {!Array.} Array of diff tuples. + * @private + */ + + + DiffMatchPatch.prototype.diffCompute = function (text1, text2, checklines, deadline) { + var diffs, longtext, shorttext, i, hm, text1A, text2A, text1B, text2B, midCommon, diffsA, diffsB; + + if (!text1) { + // Just add some text (speedup). + return [[DIFF_INSERT, text2]]; + } + + if (!text2) { + // Just delete some text (speedup). + return [[DIFF_DELETE, text1]]; + } + + longtext = text1.length > text2.length ? text1 : text2; + shorttext = text1.length > text2.length ? text2 : text1; + i = longtext.indexOf(shorttext); + + if (i !== -1) { + // Shorter text is inside the longer text (speedup). + diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]]; // Swap insertions for deletions if diff is reversed. + + if (text1.length > text2.length) { + diffs[0][0] = diffs[2][0] = DIFF_DELETE; + } + + return diffs; + } + + if (shorttext.length === 1) { + // Single character string. + // After the previous speedup, the character can't be an equality. + return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; + } // Check to see if the problem can be split in two. + + + hm = this.diffHalfMatch(text1, text2); + + if (hm) { + // A half-match was found, sort out the return data. + text1A = hm[0]; + text1B = hm[1]; + text2A = hm[2]; + text2B = hm[3]; + midCommon = hm[4]; // Send both pairs off for separate processing. + + diffsA = this.DiffMain(text1A, text2A, checklines, deadline); + diffsB = this.DiffMain(text1B, text2B, checklines, deadline); // Merge the results. + + return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB); + } + + if (checklines && text1.length > 100 && text2.length > 100) { + return this.diffLineMode(text1, text2, deadline); + } + + return this.diffBisect(text1, text2, deadline); + }; + /** + * Do the two texts share a substring which is at least half the length of the + * longer text? + * This speedup can produce non-minimal diffs. + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {Array.} Five element Array, containing the prefix of + * text1, the suffix of text1, the prefix of text2, the suffix of + * text2 and the common middle. Or null if there was no match. + * @private + */ + + + DiffMatchPatch.prototype.diffHalfMatch = function (text1, text2) { + var longtext, shorttext, dmp, text1A, text2B, text2A, text1B, midCommon, hm1, hm2, hm; + longtext = text1.length > text2.length ? text1 : text2; + shorttext = text1.length > text2.length ? text2 : text1; + + if (longtext.length < 4 || shorttext.length * 2 < longtext.length) { + return null; // Pointless. + } + + dmp = this; // 'this' becomes 'window' in a closure. + + /** + * Does a substring of shorttext exist within longtext such that the substring + * is at least half the length of longtext? + * Closure, but does not reference any external variables. + * @param {string} longtext Longer string. + * @param {string} shorttext Shorter string. + * @param {number} i Start index of quarter length substring within longtext. + * @return {Array.} Five element Array, containing the prefix of + * longtext, the suffix of longtext, the prefix of shorttext, the suffix + * of shorttext and the common middle. Or null if there was no match. + * @private + */ + + function diffHalfMatchI(longtext, shorttext, i) { + var seed, j, bestCommon, prefixLength, suffixLength, bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB; // Start with a 1/4 length substring at position i as a seed. + + seed = longtext.substring(i, i + Math.floor(longtext.length / 4)); + j = -1; + bestCommon = ""; + + while ((j = shorttext.indexOf(seed, j + 1)) !== -1) { + prefixLength = dmp.diffCommonPrefix(longtext.substring(i), shorttext.substring(j)); + suffixLength = dmp.diffCommonSuffix(longtext.substring(0, i), shorttext.substring(0, j)); + + if (bestCommon.length < suffixLength + prefixLength) { + bestCommon = shorttext.substring(j - suffixLength, j) + shorttext.substring(j, j + prefixLength); + bestLongtextA = longtext.substring(0, i - suffixLength); + bestLongtextB = longtext.substring(i + prefixLength); + bestShorttextA = shorttext.substring(0, j - suffixLength); + bestShorttextB = shorttext.substring(j + prefixLength); + } + } + + if (bestCommon.length * 2 >= longtext.length) { + return [bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB, bestCommon]; + } else { + return null; + } + } // First check if the second quarter is the seed for a half-match. + + + hm1 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 4)); // Check again based on the third quarter. + + hm2 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 2)); + + if (!hm1 && !hm2) { + return null; + } else if (!hm2) { + hm = hm1; + } else if (!hm1) { + hm = hm2; + } else { + // Both matched. Select the longest. + hm = hm1[4].length > hm2[4].length ? hm1 : hm2; + } // A half-match was found, sort out the return data. + + + if (text1.length > text2.length) { + text1A = hm[0]; + text1B = hm[1]; + text2A = hm[2]; + text2B = hm[3]; + } else { + text2A = hm[0]; + text2B = hm[1]; + text1A = hm[2]; + text1B = hm[3]; + } + + midCommon = hm[4]; + return [text1A, text1B, text2A, text2B, midCommon]; + }; + /** + * Do a quick line-level diff on both strings, then rediff the parts for + * greater accuracy. + * This speedup can produce non-minimal diffs. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @param {number} deadline Time when the diff should be complete by. + * @return {!Array.} Array of diff tuples. + * @private + */ + + + DiffMatchPatch.prototype.diffLineMode = function (text1, text2, deadline) { + var a, diffs, linearray, pointer, countInsert, countDelete, textInsert, textDelete, j; // Scan the text on a line-by-line basis first. + + a = this.diffLinesToChars(text1, text2); + text1 = a.chars1; + text2 = a.chars2; + linearray = a.lineArray; + diffs = this.DiffMain(text1, text2, false, deadline); // Convert the diff back to original text. + + this.diffCharsToLines(diffs, linearray); // Eliminate freak matches (e.g. blank lines) + + this.diffCleanupSemantic(diffs); // Rediff any replacement blocks, this time character-by-character. + // Add a dummy entry at the end. + + diffs.push([DIFF_EQUAL, ""]); + pointer = 0; + countDelete = 0; + countInsert = 0; + textDelete = ""; + textInsert = ""; + + while (pointer < diffs.length) { + switch (diffs[pointer][0]) { + case DIFF_INSERT: + countInsert++; + textInsert += diffs[pointer][1]; + break; + + case DIFF_DELETE: + countDelete++; + textDelete += diffs[pointer][1]; + break; + + case DIFF_EQUAL: + // Upon reaching an equality, check for prior redundancies. + if (countDelete >= 1 && countInsert >= 1) { + // Delete the offending records and add the merged ones. + diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert); + pointer = pointer - countDelete - countInsert; + a = this.DiffMain(textDelete, textInsert, false, deadline); + + for (j = a.length - 1; j >= 0; j--) { + diffs.splice(pointer, 0, a[j]); + } + + pointer = pointer + a.length; + } + + countInsert = 0; + countDelete = 0; + textDelete = ""; + textInsert = ""; + break; + } + + pointer++; + } + + diffs.pop(); // Remove the dummy entry at the end. + + return diffs; + }; + /** + * Find the 'middle snake' of a diff, split the problem in two + * and return the recursively constructed diff. + * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @param {number} deadline Time at which to bail if not yet complete. + * @return {!Array.} Array of diff tuples. + * @private + */ + + + DiffMatchPatch.prototype.diffBisect = function (text1, text2, deadline) { + var text1Length, text2Length, maxD, vOffset, vLength, v1, v2, x, delta, front, k1start, k1end, k2start, k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2; // Cache the text lengths to prevent multiple calls. + + text1Length = text1.length; + text2Length = text2.length; + maxD = Math.ceil((text1Length + text2Length) / 2); + vOffset = maxD; + vLength = 2 * maxD; + v1 = new Array(vLength); + v2 = new Array(vLength); // Setting all elements to -1 is faster in Chrome & Firefox than mixing + // integers and undefined. + + for (x = 0; x < vLength; x++) { + v1[x] = -1; + v2[x] = -1; + } + + v1[vOffset + 1] = 0; + v2[vOffset + 1] = 0; + delta = text1Length - text2Length; // If the total number of characters is odd, then the front path will collide + // with the reverse path. + + front = delta % 2 !== 0; // Offsets for start and end of k loop. + // Prevents mapping of space beyond the grid. + + k1start = 0; + k1end = 0; + k2start = 0; + k2end = 0; + + for (d = 0; d < maxD; d++) { + // Bail out if deadline is reached. + if (new Date().getTime() > deadline) { + break; + } // Walk the front path one step. + + + for (k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { + k1Offset = vOffset + k1; + + if (k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1]) { + x1 = v1[k1Offset + 1]; + } else { + x1 = v1[k1Offset - 1] + 1; + } + + y1 = x1 - k1; + + while (x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1)) { + x1++; + y1++; + } + + v1[k1Offset] = x1; + + if (x1 > text1Length) { + // Ran off the right of the graph. + k1end += 2; + } else if (y1 > text2Length) { + // Ran off the bottom of the graph. + k1start += 2; + } else if (front) { + k2Offset = vOffset + delta - k1; + + if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) { + // Mirror x2 onto top-left coordinate system. + x2 = text1Length - v2[k2Offset]; + + if (x1 >= x2) { + // Overlap detected. + return this.diffBisectSplit(text1, text2, x1, y1, deadline); + } + } + } + } // Walk the reverse path one step. + + + for (k2 = -d + k2start; k2 <= d - k2end; k2 += 2) { + k2Offset = vOffset + k2; + + if (k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1]) { + x2 = v2[k2Offset + 1]; + } else { + x2 = v2[k2Offset - 1] + 1; + } + + y2 = x2 - k2; + + while (x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1)) { + x2++; + y2++; + } + + v2[k2Offset] = x2; + + if (x2 > text1Length) { + // Ran off the left of the graph. + k2end += 2; + } else if (y2 > text2Length) { + // Ran off the top of the graph. + k2start += 2; + } else if (!front) { + k1Offset = vOffset + delta - k2; + + if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) { + x1 = v1[k1Offset]; + y1 = vOffset + x1 - k1Offset; // Mirror x2 onto top-left coordinate system. + + x2 = text1Length - x2; + + if (x1 >= x2) { + // Overlap detected. + return this.diffBisectSplit(text1, text2, x1, y1, deadline); + } + } + } + } + } // Diff took too long and hit the deadline or + // number of diffs equals number of characters, no commonality at all. + + + return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; + }; + /** + * Given the location of the 'middle snake', split the diff in two parts + * and recurse. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @param {number} x Index of split point in text1. + * @param {number} y Index of split point in text2. + * @param {number} deadline Time at which to bail if not yet complete. + * @return {!Array.} Array of diff tuples. + * @private + */ + + + DiffMatchPatch.prototype.diffBisectSplit = function (text1, text2, x, y, deadline) { + var text1a, text1b, text2a, text2b, diffs, diffsb; + text1a = text1.substring(0, x); + text2a = text2.substring(0, y); + text1b = text1.substring(x); + text2b = text2.substring(y); // Compute both diffs serially. + + diffs = this.DiffMain(text1a, text2a, false, deadline); + diffsb = this.DiffMain(text1b, text2b, false, deadline); + return diffs.concat(diffsb); + }; + /** + * Reduce the number of edits by eliminating semantically trivial equalities. + * @param {!Array.} diffs Array of diff tuples. + */ + + + DiffMatchPatch.prototype.diffCleanupSemantic = function (diffs) { + var changes, equalities, equalitiesLength, lastequality, pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1, lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2; + changes = false; + equalities = []; // Stack of indices where equalities are found. + + equalitiesLength = 0; // Keeping our own length var is faster in JS. + + /** @type {?string} */ + + lastequality = null; // Always equal to diffs[equalities[equalitiesLength - 1]][1] + + pointer = 0; // Index of current position. + // Number of characters that changed prior to the equality. + + lengthInsertions1 = 0; + lengthDeletions1 = 0; // Number of characters that changed after the equality. + + lengthInsertions2 = 0; + lengthDeletions2 = 0; + + while (pointer < diffs.length) { + if (diffs[pointer][0] === DIFF_EQUAL) { + // Equality found. + equalities[equalitiesLength++] = pointer; + lengthInsertions1 = lengthInsertions2; + lengthDeletions1 = lengthDeletions2; + lengthInsertions2 = 0; + lengthDeletions2 = 0; + lastequality = diffs[pointer][1]; + } else { + // An insertion or deletion. + if (diffs[pointer][0] === DIFF_INSERT) { + lengthInsertions2 += diffs[pointer][1].length; + } else { + lengthDeletions2 += diffs[pointer][1].length; + } // Eliminate an equality that is smaller or equal to the edits on both + // sides of it. + + + if (lastequality && lastequality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastequality.length <= Math.max(lengthInsertions2, lengthDeletions2)) { + // Duplicate record. + diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]); // Change second copy to insert. + + diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; // Throw away the equality we just deleted. + + equalitiesLength--; // Throw away the previous equality (it needs to be reevaluated). + + equalitiesLength--; + pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; // Reset the counters. + + lengthInsertions1 = 0; + lengthDeletions1 = 0; + lengthInsertions2 = 0; + lengthDeletions2 = 0; + lastequality = null; + changes = true; + } + } + + pointer++; + } // Normalize the diff. + + + if (changes) { + this.diffCleanupMerge(diffs); + } // Find any overlaps between deletions and insertions. + // e.g: abcxxxxxxdef + // -> abcxxxdef + // e.g: xxxabcdefxxx + // -> defxxxabc + // Only extract an overlap if it is as big as the edit ahead or behind it. + + + pointer = 1; + + while (pointer < diffs.length) { + if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) { + deletion = diffs[pointer - 1][1]; + insertion = diffs[pointer][1]; + overlapLength1 = this.diffCommonOverlap(deletion, insertion); + overlapLength2 = this.diffCommonOverlap(insertion, deletion); + + if (overlapLength1 >= overlapLength2) { + if (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) { + // Overlap found. Insert an equality and trim the surrounding edits. + diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]); + diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1); + diffs[pointer + 1][1] = insertion.substring(overlapLength1); + pointer++; + } + } else { + if (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) { + // Reverse overlap found. + // Insert an equality and swap and trim the surrounding edits. + diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]); + diffs[pointer - 1][0] = DIFF_INSERT; + diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2); + diffs[pointer + 1][0] = DIFF_DELETE; + diffs[pointer + 1][1] = deletion.substring(overlapLength2); + pointer++; + } + } + + pointer++; + } + + pointer++; + } + }; + /** + * Determine if the suffix of one string is the prefix of another. + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {number} The number of characters common to the end of the first + * string and the start of the second string. + * @private + */ + + + DiffMatchPatch.prototype.diffCommonOverlap = function (text1, text2) { + var text1Length, text2Length, textLength, best, length, pattern, found; // Cache the text lengths to prevent multiple calls. + + text1Length = text1.length; + text2Length = text2.length; // Eliminate the null case. + + if (text1Length === 0 || text2Length === 0) { + return 0; + } // Truncate the longer string. + + + if (text1Length > text2Length) { + text1 = text1.substring(text1Length - text2Length); + } else if (text1Length < text2Length) { + text2 = text2.substring(0, text1Length); + } + + textLength = Math.min(text1Length, text2Length); // Quick check for the worst case. + + if (text1 === text2) { + return textLength; + } // Start by looking for a single character match + // and increase length until no match is found. + // Performance analysis: https://neil.fraser.name/news/2010/11/04/ + + + best = 0; + length = 1; + + while (true) { + pattern = text1.substring(textLength - length); + found = text2.indexOf(pattern); + + if (found === -1) { + return best; + } + + length += found; + + if (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) { + best = length; + length++; + } + } + }; + /** + * Split two texts into an array of strings. Reduce the texts to a string of + * hashes where each Unicode character represents one line. + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {{chars1: string, chars2: string, lineArray: !Array.}} + * An object containing the encoded text1, the encoded text2 and + * the array of unique strings. + * The zeroth element of the array of unique strings is intentionally blank. + * @private + */ + + + DiffMatchPatch.prototype.diffLinesToChars = function (text1, text2) { + var lineArray, lineHash, chars1, chars2; + lineArray = []; // E.g. lineArray[4] === 'Hello\n' + + lineHash = {}; // E.g. lineHash['Hello\n'] === 4 + // '\x00' is a valid character, but various debuggers don't like it. + // So we'll insert a junk entry to avoid generating a null character. + + lineArray[0] = ""; + /** + * Split a text into an array of strings. Reduce the texts to a string of + * hashes where each Unicode character represents one line. + * Modifies linearray and linehash through being a closure. + * @param {string} text String to encode. + * @return {string} Encoded string. + * @private + */ + + function diffLinesToCharsMunge(text) { + var chars, lineStart, lineEnd, lineArrayLength, line; + chars = ""; // Walk the text, pulling out a substring for each line. + // text.split('\n') would would temporarily double our memory footprint. + // Modifying text would create many large strings to garbage collect. + + lineStart = 0; + lineEnd = -1; // Keeping our own length variable is faster than looking it up. + + lineArrayLength = lineArray.length; + + while (lineEnd < text.length - 1) { + lineEnd = text.indexOf("\n", lineStart); + + if (lineEnd === -1) { + lineEnd = text.length - 1; + } + + line = text.substring(lineStart, lineEnd + 1); + lineStart = lineEnd + 1; + + if (hasOwn.call(lineHash, line)) { + chars += String.fromCharCode(lineHash[line]); + } else { + chars += String.fromCharCode(lineArrayLength); + lineHash[line] = lineArrayLength; + lineArray[lineArrayLength++] = line; + } + } + + return chars; + } + + chars1 = diffLinesToCharsMunge(text1); + chars2 = diffLinesToCharsMunge(text2); + return { + chars1: chars1, + chars2: chars2, + lineArray: lineArray + }; + }; + /** + * Rehydrate the text in a diff from a string of line hashes to real lines of + * text. + * @param {!Array.} diffs Array of diff tuples. + * @param {!Array.} lineArray Array of unique strings. + * @private + */ + + + DiffMatchPatch.prototype.diffCharsToLines = function (diffs, lineArray) { + var x, chars, text, y; + + for (x = 0; x < diffs.length; x++) { + chars = diffs[x][1]; + text = []; + + for (y = 0; y < chars.length; y++) { + text[y] = lineArray[chars.charCodeAt(y)]; + } + + diffs[x][1] = text.join(""); + } + }; + /** + * Reorder and merge like edit sections. Merge equalities. + * Any edit section can move as long as it doesn't cross an equality. + * @param {!Array.} diffs Array of diff tuples. + */ + + + DiffMatchPatch.prototype.diffCleanupMerge = function (diffs) { + var pointer, countDelete, countInsert, textInsert, textDelete, commonlength, changes, diffPointer, position; + diffs.push([DIFF_EQUAL, ""]); // Add a dummy entry at the end. + + pointer = 0; + countDelete = 0; + countInsert = 0; + textDelete = ""; + textInsert = ""; + + while (pointer < diffs.length) { + switch (diffs[pointer][0]) { + case DIFF_INSERT: + countInsert++; + textInsert += diffs[pointer][1]; + pointer++; + break; + + case DIFF_DELETE: + countDelete++; + textDelete += diffs[pointer][1]; + pointer++; + break; + + case DIFF_EQUAL: + // Upon reaching an equality, check for prior redundancies. + if (countDelete + countInsert > 1) { + if (countDelete !== 0 && countInsert !== 0) { + // Factor out any common prefixes. + commonlength = this.diffCommonPrefix(textInsert, textDelete); + + if (commonlength !== 0) { + if (pointer - countDelete - countInsert > 0 && diffs[pointer - countDelete - countInsert - 1][0] === DIFF_EQUAL) { + diffs[pointer - countDelete - countInsert - 1][1] += textInsert.substring(0, commonlength); + } else { + diffs.splice(0, 0, [DIFF_EQUAL, textInsert.substring(0, commonlength)]); + pointer++; + } + + textInsert = textInsert.substring(commonlength); + textDelete = textDelete.substring(commonlength); + } // Factor out any common suffixies. + + + commonlength = this.diffCommonSuffix(textInsert, textDelete); + + if (commonlength !== 0) { + diffs[pointer][1] = textInsert.substring(textInsert.length - commonlength) + diffs[pointer][1]; + textInsert = textInsert.substring(0, textInsert.length - commonlength); + textDelete = textDelete.substring(0, textDelete.length - commonlength); + } + } // Delete the offending records and add the merged ones. + + + if (countDelete === 0) { + diffs.splice(pointer - countInsert, countDelete + countInsert, [DIFF_INSERT, textInsert]); + } else if (countInsert === 0) { + diffs.splice(pointer - countDelete, countDelete + countInsert, [DIFF_DELETE, textDelete]); + } else { + diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert, [DIFF_DELETE, textDelete], [DIFF_INSERT, textInsert]); + } + + pointer = pointer - countDelete - countInsert + (countDelete ? 1 : 0) + (countInsert ? 1 : 0) + 1; + } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) { + // Merge this equality with the previous one. + diffs[pointer - 1][1] += diffs[pointer][1]; + diffs.splice(pointer, 1); + } else { + pointer++; + } + + countInsert = 0; + countDelete = 0; + textDelete = ""; + textInsert = ""; + break; + } + } + + if (diffs[diffs.length - 1][1] === "") { + diffs.pop(); // Remove the dummy entry at the end. + } // Second pass: look for single edits surrounded on both sides by equalities + // which can be shifted sideways to eliminate an equality. + // e.g: ABAC -> ABAC + + + changes = false; + pointer = 1; // Intentionally ignore the first and last element (don't need checking). + + while (pointer < diffs.length - 1) { + if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) { + diffPointer = diffs[pointer][1]; + position = diffPointer.substring(diffPointer.length - diffs[pointer - 1][1].length); // This is a single edit surrounded by equalities. + + if (position === diffs[pointer - 1][1]) { + // Shift the edit over the previous equality. + diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length); + diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; + diffs.splice(pointer - 1, 1); + changes = true; + } else if (diffPointer.substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) { + // Shift the edit over the next equality. + diffs[pointer - 1][1] += diffs[pointer + 1][1]; + diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1]; + diffs.splice(pointer + 1, 1); + changes = true; + } + } + + pointer++; + } // If shifts were made, the diff needs reordering and another shift sweep. + + + if (changes) { + this.diffCleanupMerge(diffs); + } + }; + + return function (o, n) { + var diff, output, text; + diff = new DiffMatchPatch(); + output = diff.DiffMain(o, n); + diff.diffCleanupEfficiency(output); + text = diff.diffPrettyHtml(output); + return text; + }; + }(); + +}()); diff --git a/public/assets/tests/qunit/color_object.js b/public/assets/tests/qunit/color_object.js new file mode 100644 index 000000000..8c1af8d97 --- /dev/null +++ b/public/assets/tests/qunit/color_object.js @@ -0,0 +1,21 @@ +QUnit.test('test color object', assert => { + let hex = new App.ColorObject('#09f609') + let hsl = new App.ColorObject([0.5, 0.2, 0.3]) + + assert.deepEqual(hex.asHslArray(), [1/3, 0.9294117647058824, 0.5], 'HEX converted to HSL components') + assert.deepEqual(hsl.asHslArray(), [0.5, 0.2, 0.3], 'HSL components returned as original input') + assert.equal(hex.asString(), '#09f609', 'HEX represented as original input') + assert.equal(hsl.asString(), 'hsl(180,20%,30%)', 'HSL components represented as HSL string') + + hex.updateWithString('#fff') + assert.equal(hex.asString(), '#fff', 'color updated') + + hsl.updateWithHslComponent(0.25, 1) + assert.deepEqual(hsl.asHslArray(), [0.5, 0.25, 0.3], 'given HSL component updated') + + assert.deepEqual(Array.from(App.ColorObject.anyToRgb('#ff0000')), [255, 0, 0, 255], 'any to RGB') + assert.deepEqual(App.ColorObject.anyToHslArray('#ff0000'), [0,1,0.5], 'any to HSL components') + assert.equal(App.ColorObject.anyToHslString('#ff0000'), 'hsl(0,100%,50%)', 'any to HSL string') + assert.deepEqual(App.ColorObject.rgbToHslArray([255, 0, 0]), [0,1,0.5], 'RGB to HSL components') + assert.equal(App.ColorObject.hslArrayToHslString([0.5, 0.25, 0.3]), 'hsl(180,25%,30%)', 'HSL components to HSL string') +}) diff --git a/public/assets/tests/core.js b/public/assets/tests/qunit/core.js similarity index 66% rename from public/assets/tests/core.js rename to public/assets/tests/qunit/core.js index 765594dfe..dad19c095 100644 --- a/public/assets/tests/core.js +++ b/public/assets/tests/qunit/core.js @@ -1,4 +1,5 @@ -test( "ajax get 200", function(assert) { +QUnit.test( "ajax get 200", assert => { + App.Config.set('api_path', '/api/v1') var done = assert.async(1) new Promise( (resolve, reject) => { @@ -9,16 +10,16 @@ test( "ajax get 200", function(assert) { error: reject }); }).then( function(data) { - ok( true, "File found!") - equal(data.success, true, "content parsable and ok!") - equal(data.success2, undefined, "content parsable and ok!") + assert.ok( true, "File found!") + assert.equal(data.success, true, "content parsable and assert.ok!") + assert.equal(data.success2, undefined, "content parsable and assert.ok!") }, function(data) { - ok( false, "Failed!") + assert.ok( false, "Failed!") }) .finally(done) }); -test( "ajax - queue - ajax get 200 1/2", function(assert) { +QUnit.test( "ajax - queue - ajax get 200 1/2", assert => { var done = assert.async(1) new Promise( (resolve, reject) => { @@ -30,17 +31,17 @@ test( "ajax - queue - ajax get 200 1/2", function(assert) { error: reject }); }).then( function(data) { - ok( !window.testAjax, 'ajax - queue - check queue') + assert.ok( !window.testAjax, 'ajax - queue - check queue') window.testAjax = true; - equal(data.success, true, "ajax - queue - content parsable and ok!") - equal(data.success2, undefined, "ajax - queue - content parsable and ok!") + assert.equal(data.success, true, "ajax - queue - content parsable and assert.ok!") + assert.equal(data.success2, undefined, "ajax - queue - content parsable and assert.ok!") }, function(data) { - ok( false, "Failed!") + assert.ok( false, "Failed!") }) .finally(done) }); -test( "ajax - queue - ajax get 200 2/2", function(assert) { +QUnit.test( "ajax - queue - ajax get 200 2/2", assert => { var done = assert.async(1) new Promise( (resolve, reject) => { @@ -54,19 +55,19 @@ test( "ajax - queue - ajax get 200 2/2", function(assert) { }).then( function(data) { // check queue - ok( window.testAjax, 'ajax - queue - check queue') + assert.ok( window.testAjax, 'ajax - queue - check queue') window.testAjax = undefined; - equal(data.success, true, "content parsable and ok!") - equal(data.success2, undefined, "content parsable and ok!") + assert.equal(data.success, true, "content parsable and assert.ok!") + assert.equal(data.success2, undefined, "content parsable and assert.ok!") }, function(data) { - ok( false, "Failed!") + assert.ok( false, "Failed!") }) .finally(done) }); -test( "ajax - parallel - ajax get 200", function(assert) { - var done = assert.async(1) +QUnit.test( "ajax - parallel - ajax get 200", assert => { + var done = assert.async(2) new Promise( (resolve, reject) => { App.Ajax.request({ @@ -86,28 +87,29 @@ test( "ajax - parallel - ajax get 200", function(assert) { }).then( function(data) { // check queue - ok( !window.testAjaxQ, 'ajax - parallel - check queue') + assert.ok( !window.testAjaxQ, 'ajax - parallel - check queue') window.testAjaxQ = true; - equal(data.success, true, "content parsable and ok!") - equal(data.success2, undefined, "content parsable and ok!") + assert.equal(data.success, true, "content parsable and assert.ok!") + assert.equal(data.success2, undefined, "content parsable and assert.ok!") }, function(data) { - ok( false, "Failed!") + assert.ok( false, "Failed!") }) .finally(done) }).then( function(data) { // check queue - ok( window.testAjaxQ, 'ajax - parallel - check queue') + assert.ok( window.testAjaxQ, 'ajax - parallel - check queue') window.testAjaxQ = undefined; - equal(data.success, true, "ajax - parallel - content parsable and ok!") - equal(data.success2, undefined, "ajax - parallel - content parsable and ok!") + assert.equal(data.success, true, "ajax - parallel - content parsable and assert.ok!") + assert.equal(data.success2, undefined, "ajax - parallel - content parsable and assert.ok!") + done() }, function(data) { - ok( false, "Failed!") + assert.ok( false, "Failed!") }) }); -test('delay - test', function(assert) { +QUnit.test('delay - test', assert => { var done = assert.async(1) window.testDelay1 = false @@ -117,24 +119,24 @@ test('delay - test', function(assert) { new Promise( (resolve, reject) => { App.Delay.set(resolve, 2000, 'delay-test1', 'level'); }).then( function() { - ok(!window.testDelay1, 'delay - 1/2') + assert.ok(!window.testDelay1, 'delay - 1/2') window.testDelay1 = 1; }) new Promise( (resolve, reject) => { App.Delay.set(resolve, 3000, 'delay-test1-verify', 'level'); }).then( function() { - ok(window.testDelay1, 'delay - 2/2') + assert.ok(window.testDelay1, 'delay - 2/2') window.testDelay1 = false; }) .finally(done) }).then( function() { - ok(false, 'delay - 1/2 - FAILED - should not be executed, will be reset by next set()') + assert.ok(false, 'delay - 1/2 - FAILED - should not be executed, will be reset by next set()') window.testDelay1 = true; }) }); -test('delay - test 2', function(assert) { +QUnit.test('delay - test 2', assert => { var done = assert.async(1) new Promise( (resolve, reject) => { @@ -143,48 +145,48 @@ test('delay - test 2', function(assert) { new Promise( (resolve, reject) => { App.Delay.set(resolve, 1000); }).then( function() { - ok(!window.testDelay2, 'delay - test 2 - 1/3') + assert.ok(!window.testDelay2, 'delay - test 2 - 1/3') }) new Promise( (resolve, reject) => { App.Delay.set(resolve, 3000); }).then( function() { - ok(window.testDelay2, 'delay - test 2 - 3/3') + assert.ok(window.testDelay2, 'delay - test 2 - 3/3') }) .finally(done) }).then( function() { - ok(!window.testDelay2, 'delay - test 2 - 2/3') + assert.ok(!window.testDelay2, 'delay - test 2 - 2/3') window.testDelay2 = 1; }) }); -test('delay - test 3', function(assert) { +QUnit.test('delay - test 3', assert => { var done = assert.async(1) new Promise( (resolve, reject) => { App.Delay.set(resolve, 1000, 'delay3'); App.Delay.clear('delay3') - ok(true, 'delay - test 3 - 1/1') + assert.ok(true, 'delay - test 3 - 1/1') done() }).then( function() { - ok(false, 'delay - test 3 - 1/1 - FAILED') + assert.ok(false, 'delay - test 3 - 1/1 - FAILED') }) }); -test('delay - test 4', function(assert) { +QUnit.test('delay - test 4', assert => { var done = assert.async(1) new Promise( (resolve, reject) => { App.Delay.set(resolve, 1000, undefined, 'Page'); App.Delay.clearLevel('Page') - ok(true, 'delay - test 4 - 1/1') + assert.ok(true, 'delay - test 4 - 1/1') done() }).then( function() { - ok(false, 'delay - test 4 - 1/1 - FAILED') + assert.ok(false, 'delay - test 4 - 1/1 - FAILED') }) }); -test('interval - test 1', function(assert) { +QUnit.test('interval - test 1', assert => { var done = assert.async(1) window.testInterval1 = 1 @@ -201,17 +203,17 @@ test('interval - test 1', function(assert) { new Promise( (resolve, reject) => { App.Delay.set(resolve, 2000); }).then( function() { - equal(window.testInterval1, window.testInterval1Backup, 'interval - did not change after clear interval') + assert.equal(window.testInterval1, window.testInterval1Backup, 'interval - did not change after clear interval') }) .finally(done) }).then( function() { - notEqual(window.testInterval1, 1, 'interval - interval moved up') + assert.notEqual(window.testInterval1, 1, 'interval - interval moved up') App.Interval.clear('interval-test1') window.testInterval1Backup = window.testInterval1; }) }) -test('interval - test 2', function(assert) { +QUnit.test('interval - test 2', assert => { var done = assert.async(1) window.testInterval1 = 1 @@ -229,58 +231,58 @@ test('interval - test 2', function(assert) { new Promise( (resolve, reject) => { App.Delay.set(resolve, 2000); }).then( function() { - equal(window.testInterval1, window.testInterval1Backup, 'interval - did not change after clear interval') + assert.equal(window.testInterval1, window.testInterval1Backup, 'interval - did not change after clear interval') }) .finally(done) }).then( function() { - notEqual(window.testInterval1, 1, 'interval - interval moved up') + assert.notEqual(window.testInterval1, 1, 'interval - interval moved up') App.Interval.clearLevel('someLevel') window.testInterval1Backup = window.testInterval1; }) }) // events -test('events simple', function() { +QUnit.test('events simple', assert => { // single bind App.Event.bind('test1', function(data) { - ok(true, 'event received - single bind') - equal(data.success, true, 'event received - data ok - single bind') + assert.ok(true, 'event received - single bind') + assert.equal(data.success, true, 'event received - data assert.ok - single bind') }); App.Event.bind('test2', function(data) { - ok(false, 'should not be triggered - single bind') + assert.ok(false, 'should not be triggered - single bind') }); App.Event.trigger('test1', { success: true }) App.Event.unbind('test1') App.Event.bind('test1', function(data) { - ok(false, 'should not be triggered - single bind') + assert.ok(false, 'should not be triggered - single bind') }); App.Event.unbind('test1') App.Event.trigger('test1', { success: true }) // multi bind App.Event.bind('test1-1 test1-2', function(data) { - ok(true, 'event received - multi bind') - equal(data.success, true, 'event received - data ok - multi bind') + assert.ok(true, 'event received - multi bind') + assert.equal(data.success, true, 'event received - data assert.ok - multi bind') }); App.Event.bind('test1-3', function(data) { - ok(false, 'should not be triggered - multi bind') + assert.ok(false, 'should not be triggered - multi bind') }); App.Event.trigger('test1-2', { success: true }) App.Event.unbind('test1-1') App.Event.bind('test1-1', function(data) { - ok(false, 'should not be triggered - multi bind') + assert.ok(false, 'should not be triggered - multi bind') }); App.Event.trigger('test1-2', { success: true }) }); -test('events level', function() { +QUnit.test('events level', assert => { // bind with level App.Event.bind('test3', function(data) { - ok(false, 'should not be triggered!') + assert.ok(false, 'should not be triggered!') }, 'test-level') // unbind with level @@ -288,15 +290,15 @@ test('events level', function() { // bind with level App.Event.bind('test3', function(data) { - ok(true, 'event received') - equal(data.success, true, 'event received - data ok - level bind') + assert.ok(true, 'event received') + assert.equal(data.success, true, 'event received - data assert.ok - level bind') }, 'test-level') App.Event.trigger('test3', { success: true}) }); // session store -test('session store', function() { +QUnit.test('session store', assert => { var tests = [ 'some 123äöüßadajsdaiosjdiaoidj', @@ -309,14 +311,14 @@ test('session store', function() { _.each(tests, function(test) { App.SessionStorage.set('test1', test) var item = App.SessionStorage.get('test1') - deepEqual(test, item, 'write/get - compare stored and actual data') + assert.deepEqual(test, item, 'write/get - compare stored and actual data') }); // undefined/get App.SessionStorage.clear() _.each(tests, function(test) { var item = App.SessionStorage.get('test1') - deepEqual(undefined, item, 'undefined/get - compare not existing data and actual data') + assert.deepEqual(undefined, item, 'undefined/get - compare not existing data and actual data') }); // write/get/delete @@ -333,16 +335,16 @@ test('session store', function() { _.each(tests, function(test) { var item = App.SessionStorage.get(test.key) - deepEqual(test.value, item, 'write/get/delete - compare stored and actual data') + assert.deepEqual(test.value, item, 'write/get/delete - compare stored and actual data') App.SessionStorage.delete( test.key) item = App.SessionStorage.get(test.key) - deepEqual(undefined, item, 'write/get/delete - compare deleted data') + assert.deepEqual(undefined, item, 'write/get/delete - compare deleted data') }); }); // config -test('config', function() { +QUnit.test('config', assert => { // simple var tests = [ @@ -357,7 +359,7 @@ test('config', function() { _.each(tests, function(test) { var item = App.Config.get(test.key ) - deepEqual(item, test.value, 'set/get tests') + assert.deepEqual(item, test.value, 'set/get tests') }); // group @@ -374,18 +376,18 @@ test('config', function() { // verify whole group var item = App.Config.get('group1') - deepEqual(item, group, 'group - verify group hash') + assert.deepEqual(item, group, 'group - verify group hash') // verify each setting _.each(test_groups, function(test) { var item = App.Config.get(test.key, 'group1') - deepEqual(item, test.value, 'group set/get tests') + assert.deepEqual(item, test.value, 'group set/get tests') }); }); // clone -test('clone', function() { +QUnit.test('clone', assert => { // simple var tests = [ @@ -436,7 +438,7 @@ test('clone', function() { _.each(tests, function(test) { var item = clone( test ) - deepEqual(item, test, 'clone') + assert.deepEqual(item, test, 'clone') }); // complex test @@ -455,7 +457,7 @@ test('clone', function() { // modify source later, should not have any result source[0].name = 'some new name' - deepEqual(result, reference, 'clone') + assert.deepEqual(result, reference, 'clone') // full test var source = [ @@ -474,19 +476,19 @@ test('clone', function() { source[0].name = 'some new name' source[2].fn = 'some new name' - deepEqual(result[0], reference[0], 'clone full') - deepEqual(result[1], reference[1], 'clone full') + assert.deepEqual(result[0], reference[0], 'clone full') + assert.deepEqual(result[1], reference[1], 'clone full') - equal(typeof reference[2].fn, 'function') - equal(typeof result[2].fn, 'function') + assert.equal(typeof reference[2].fn, 'function') + assert.equal(typeof result[2].fn, 'function') - equal(reference[2].fn(), 'test') - equal(result[2].fn(), 'test') + assert.equal(reference[2].fn(), 'test') + assert.equal(result[2].fn(), 'test') }); // diff -test('difference', function() { +QUnit.test('difference', assert => { // simple var object1 = { @@ -501,7 +503,7 @@ test('difference', function() { key2: 1235 } var item = difference(object1, object2) - deepEqual(item, result) + assert.deepEqual(item, result) object1 = { key1: 123, @@ -513,7 +515,7 @@ test('difference', function() { } result = {} item = difference(object1, object2) - deepEqual(item, result) + assert.deepEqual(item, result) object1 = { key1: 123, @@ -527,7 +529,7 @@ test('difference', function() { key2: 123 } item = difference(object1, object2) - deepEqual(item, result) + assert.deepEqual(item, result) object1 = { key1: 123, @@ -538,7 +540,7 @@ test('difference', function() { } result = {} item = difference(object1, object2) - deepEqual(item, result) + assert.deepEqual(item, result) object1 = { key1: 123, @@ -549,7 +551,7 @@ test('difference', function() { } result = {} item = difference(object1, object2) - deepEqual(item, result) + assert.deepEqual(item, result) object1 = { customer_id: 1, @@ -563,7 +565,7 @@ test('difference', function() { organization_id: null, } item = difference(object1, object2) - deepEqual(item, result) + assert.deepEqual(item, result) object1 = { customer_id: 1, @@ -577,11 +579,11 @@ test('difference', function() { organization_id: 2, } item = difference(object1, object2) - deepEqual(item, result) + assert.deepEqual(item, result) }); -test('auth - not existing user', function(assert) { +QUnit.test('auth - not existing user', assert => { var done = assert.async(1) new Promise( (resolve, reject) => { @@ -594,14 +596,15 @@ test('auth - not existing user', function(assert) { error: reject }); }).then( function(data) { - ok(false, 'ok') + assert.ok(false, 'ok') }, function() { - ok(true, 'ok') + assert.ok(true, 'ok') }) .finally(done) }) -test('auth - existing user', function(assert) { +QUnit.test('auth - existing user', assert => { + App.Config.set('api_path', '/api/v1') var done = assert.async(1) new Promise( (resolve, reject) => { @@ -614,11 +617,11 @@ test('auth - existing user', function(assert) { error: reject }); }).then( function(data) { - ok(true, 'authenticated') + assert.ok(true, 'authenticated') var user = App.Session.get('login') - equal('admin@example.com', user, 'session login') + assert.equal('admin@example.com', user, 'session login') }, function() { - ok(false, 'failed') + assert.ok(false, 'failed') }) .finally(done) }) diff --git a/public/assets/tests/form.js b/public/assets/tests/qunit/form.js similarity index 69% rename from public/assets/tests/form.js rename to public/assets/tests/qunit/form.js index 3eb0468d9..cd7edc261 100644 --- a/public/assets/tests/form.js +++ b/public/assets/tests/qunit/form.js @@ -1,16 +1,16 @@ // form -test("form without @el", function() { +QUnit.test("form without @el", assert => { var form = new App.ControllerForm() - equal($(form.html()).is('div'), true) - equal($(form.html()).hasClass('alert'), true) - equal($(form.html()).hasClass('hide'), true) + assert.equal($(form.html()).is('div'), true) + assert.equal($(form.html()).hasClass('alert'), true) + assert.equal($(form.html()).hasClass('hide'), true) }) -test("form elements check", function() { -// deepEqual(item, test.value, 'group set/get tests' ); - $('#forms').append('

        form elements check

        ') +QUnit.test("form elements check", assert => { +// assert.deepEqual(item, test.value, 'group set/get tests' ); + $('#qunit').append('

        form elements check

        ') var el = $('#form1') var defaults = { input2: '123abc', @@ -58,70 +58,70 @@ test("form elements check", function() { }, autofocus: true }); - equal(el.find('[name="input1"]').val(), '', 'check input1 value') - equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') -// equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') + assert.equal(el.find('[name="input1"]').val(), '', 'check input1 value') + assert.equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') +// assert.equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') - equal(el.find('[name="input2"]').val(), '123abc', 'check input2 value') - equal(el.find('[name="input2"]').prop('required'), true, 'check input2 required') - equal(el.find('[name="input2"]').is(":focus"), false, 'check input2 focus') + assert.equal(el.find('[name="input2"]').val(), '123abc', 'check input2 value') + assert.equal(el.find('[name="input2"]').prop('required'), true, 'check input2 required') + assert.equal(el.find('[name="input2"]').is(":focus"), false, 'check input2 focus') - equal(el.find('[name="password1"]').val(), '', 'check password1 value') - equal(el.find('[name="password1_confirm"]').val(), '', 'check password1 value') - equal(el.find('[name="password1"]').prop('required'), false, 'check password1 required') - equal(el.find('[name="password1"]').is(":focus"), false, 'check password1 focus') + assert.equal(el.find('[name="password1"]').val(), '', 'check password1 value') + assert.equal(el.find('[name="password1_confirm"]').val(), '', 'check password1 value') + assert.equal(el.find('[name="password1"]').prop('required'), false, 'check password1 required') + assert.equal(el.find('[name="password1"]').is(":focus"), false, 'check password1 focus') - equal(el.find('[name="password2"]').val(), 'pw1234', 'check password2 value') - equal(el.find('[name="password2_confirm"]').val(), 'pw1234', 'check password2 value') - equal(el.find('[name="password2"]').prop('required'), true, 'check password2 required') - equal(el.find('[name="password2"]').is(":focus"), false, 'check password2 focus') + assert.equal(el.find('[name="password2"]').val(), 'pw1234', 'check password2 value') + assert.equal(el.find('[name="password2_confirm"]').val(), 'pw1234', 'check password2 value') + assert.equal(el.find('[name="password2"]').prop('required'), true, 'check password2 required') + assert.equal(el.find('[name="password2"]').is(":focus"), false, 'check password2 focus') - equal(el.find('[name="textarea1"]').val(), '', 'check textarea1 value') - equal(el.find('[name="textarea1"]').prop('required'), false, 'check textarea1 required') - equal(el.find('[name="textarea1"]').is(":focus"), false, 'check textarea1 focus') + assert.equal(el.find('[name="textarea1"]').val(), '', 'check textarea1 value') + assert.equal(el.find('[name="textarea1"]').prop('required'), false, 'check textarea1 required') + assert.equal(el.find('[name="textarea1"]').is(":focus"), false, 'check textarea1 focus') - equal(el.find('[name="textarea2"]').val(), 'lalu lalu', 'check textarea2 value') - equal(el.find('[name="textarea2"]').prop('required'), true, 'check textarea2 required') - equal(el.find('[name="textarea2"]').is(":focus"), false, 'check textarea2 focus') + assert.equal(el.find('[name="textarea2"]').val(), 'lalu lalu', 'check textarea2 value') + assert.equal(el.find('[name="textarea2"]').prop('required'), true, 'check textarea2 required') + assert.equal(el.find('[name="textarea2"]').is(":focus"), false, 'check textarea2 focus') - equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') - equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') - equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') + assert.equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') + assert.equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') + assert.equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') - equal(el.find('[name="select2"]').val(), 'true', 'check select2 value') - equal(el.find('[name="select2"]').prop('required'), true, 'check select2 required') - equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') + assert.equal(el.find('[name="select2"]').val(), 'true', 'check select2 value') + assert.equal(el.find('[name="select2"]').prop('required'), true, 'check select2 required') + assert.equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') - equal(el.find('[name="selectmulti1"]').val(), 'false', 'check selectmulti1 value') - equal(el.find('[name="selectmulti1"]').prop('required'), false, 'check selectmulti1 required') - equal(el.find('[name="selectmulti1"]').is(":focus"), false, 'check selectmulti1 focus') + assert.equal(el.find('[name="selectmulti1"]').val(), 'false', 'check selectmulti1 value') + assert.equal(el.find('[name="selectmulti1"]').prop('required'), false, 'check selectmulti1 required') + assert.equal(el.find('[name="selectmulti1"]').is(":focus"), false, 'check selectmulti1 focus') - equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') - equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') + assert.equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') + assert.equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') //equal(el.find('[name="richtext1"]').val(), '', 'check textarea1 value') //equal(el.find('[name="richtext1"]').prop('required'), false, 'check textarea1 required') - equal(el.find('[name="richtext1"]').is(":focus"), false, 'check textarea1 focus') + assert.equal(el.find('[name="richtext1"]').is(":focus"), false, 'check textarea1 focus') //equal(el.find('[name="richtext2"]').val(), 'lalu lalu', 'check textarea2 value') //equal(el.find('[name="richtext2"]').prop('required'), true, 'check textarea2 required') - equal(el.find('[name="richtext2"]').is(":focus"), false, 'check textarea2 focus') + assert.equal(el.find('[name="richtext2"]').is(":focus"), false, 'check textarea2 focus') - equal(el.find('[name="checkbox1"]').first().is(":checked"), false) - equal(el.find('[name="checkbox1"]').last().is(":checked"), false) - equal(el.find('[name="checkbox2"]').is(":checked"), true) + assert.equal(el.find('[name="checkbox1"]').first().is(":checked"), false) + assert.equal(el.find('[name="checkbox1"]').last().is(":checked"), false) + assert.equal(el.find('[name="checkbox2"]').is(":checked"), true) - equal(el.find('[name="boolean1"]').val(), 'true') - equal(el.find('[name="boolean1"]').val(), 'true') - equal(el.find('[name="boolean2"]').val(), 'false') + assert.equal(el.find('[name="boolean1"]').val(), 'true') + assert.equal(el.find('[name="boolean1"]').val(), 'true') + assert.equal(el.find('[name="boolean2"]').val(), 'false') }); -test("form params check", function() { -// deepEqual(item, test.value, 'group set/get tests' ); +QUnit.test("form params check", assert => { +// assert.deepEqual(item, test.value, 'group set/get tests' ); - $('#forms').append('

        form params check

        ') + $('#qunit').append('

        form params check

        ') var el = $('#form2') var defaults = { input2: '123abc', @@ -231,70 +231,70 @@ test("form params check", function() { params: defaults, autofocus: true }); - equal(el.find('[name="input1"]').val(), '', 'check input1 value') - equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') -// equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') + assert.equal(el.find('[name="input1"]').val(), '', 'check input1 value') + assert.equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') +// assert.equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') - equal(el.find('[name="input2"]').val(), '123abc', 'check input2 value') - equal(el.find('[name="input2"]').prop('required'), true, 'check input2 required') - equal(el.find('[name="input2"]').is(":focus"), false, 'check input2 focus') + assert.equal(el.find('[name="input2"]').val(), '123abc', 'check input2 value') + assert.equal(el.find('[name="input2"]').prop('required'), true, 'check input2 required') + assert.equal(el.find('[name="input2"]').is(":focus"), false, 'check input2 focus') - equal(el.find('[name="input3"]').prop("disabled"), true, 'check input3 disabled') + assert.equal(el.find('[name="input3"]').prop("disabled"), true, 'check input3 disabled') - equal(el.find('[name="password1"]').val(), '', 'check password1 value') - equal(el.find('[name="password1_confirm"]').val(), '', 'check password1 value') - equal(el.find('[name="password1"]').prop('required'), false, 'check password1 required') - equal(el.find('[name="password1"]').is(":focus"), false, 'check password1 focus') + assert.equal(el.find('[name="password1"]').val(), '', 'check password1 value') + assert.equal(el.find('[name="password1_confirm"]').val(), '', 'check password1 value') + assert.equal(el.find('[name="password1"]').prop('required'), false, 'check password1 required') + assert.equal(el.find('[name="password1"]').is(":focus"), false, 'check password1 focus') - equal(el.find('[name="password2"]').val(), 'pw1234', 'check password2 value') - equal(el.find('[name="password2_confirm"]').val(), 'pw1234', 'check password2 value') - equal(el.find('[name="password2"]').prop('required'), true, 'check password2 required') - equal(el.find('[name="password2"]').is(":focus"), false, 'check password2 focus') + assert.equal(el.find('[name="password2"]').val(), 'pw1234', 'check password2 value') + assert.equal(el.find('[name="password2_confirm"]').val(), 'pw1234', 'check password2 value') + assert.equal(el.find('[name="password2"]').prop('required'), true, 'check password2 required') + assert.equal(el.find('[name="password2"]').is(":focus"), false, 'check password2 focus') - equal(el.find('[name="textarea1"]').val(), '', 'check textarea1 value') - equal(el.find('[name="textarea1"]').prop('required'), false, 'check textarea1 required') - equal(el.find('[name="textarea1"]').is(":focus"), false, 'check textarea1 focus') + assert.equal(el.find('[name="textarea1"]').val(), '', 'check textarea1 value') + assert.equal(el.find('[name="textarea1"]').prop('required'), false, 'check textarea1 required') + assert.equal(el.find('[name="textarea1"]').is(":focus"), false, 'check textarea1 focus') - equal(el.find('[name="textarea2"]').val(), 'lalu lalu', 'check textarea2 value') - equal(el.find('[name="textarea2"]').prop('required'), true, 'check textarea2 required') - equal(el.find('[name="textarea2"]').is(":focus"), false, 'check textarea2 focus') + assert.equal(el.find('[name="textarea2"]').val(), 'lalu lalu', 'check textarea2 value') + assert.equal(el.find('[name="textarea2"]').prop('required'), true, 'check textarea2 required') + assert.equal(el.find('[name="textarea2"]').is(":focus"), false, 'check textarea2 focus') - equal(el.find('[name="textarea3"]').prop("disabled"), true, 'check textarea3 disabled') + assert.equal(el.find('[name="textarea3"]').prop("disabled"), true, 'check textarea3 disabled') - equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') - equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') - equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') + assert.equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') + assert.equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') + assert.equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') - equal(el.find('[name="select2"]').val(), 'true', 'check select2 value') - equal(el.find('[name="select2"]').prop('required'), true, 'check select2 required') - equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') + assert.equal(el.find('[name="select2"]').val(), 'true', 'check select2 value') + assert.equal(el.find('[name="select2"]').prop('required'), true, 'check select2 required') + assert.equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') - equal(el.find('[name="select3"]').val(), '', 'check select3 value') - equal(el.find('[name="select3"]').prop('required'), true, 'check select3 required') - equal(el.find('[name="select3"]').is(":focus"), false, 'check select3 focus') + assert.equal(el.find('[name="select3"]').val(), '', 'check select3 value') + assert.equal(el.find('[name="select3"]').prop('required'), true, 'check select3 required') + assert.equal(el.find('[name="select3"]').is(":focus"), false, 'check select3 focus') - equal(el.find('[name="select4"]').val(), '', 'check select4 value') - equal(el.find('[name="select4"]').prop('required'), true, 'check select4 required') - equal(el.find('[name="select4"]').is(":focus"), false, 'check select4 focus') + assert.equal(el.find('[name="select4"]').val(), '', 'check select4 value') + assert.equal(el.find('[name="select4"]').prop('required'), true, 'check select4 required') + assert.equal(el.find('[name="select4"]').is(":focus"), false, 'check select4 focus') - equal(el.find('[name="select5"]').prop("disabled"), true, 'check select5 disabled') + assert.equal(el.find('[name="select5"]').prop("disabled"), true, 'check select5 disabled') - equal(el.find('[name="selectmulti1"]').val(), 'false', 'check selectmulti1 value') - equal(el.find('[name="selectmulti1"]').prop('required'), false, 'check selectmulti1 required') - equal(el.find('[name="selectmulti1"]').is(":focus"), false, 'check selectmulti1 focus') + assert.equal(el.find('[name="selectmulti1"]').val(), 'false', 'check selectmulti1 value') + assert.equal(el.find('[name="selectmulti1"]').prop('required'), false, 'check selectmulti1 required') + assert.equal(el.find('[name="selectmulti1"]').is(":focus"), false, 'check selectmulti1 focus') - equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') - equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') + assert.equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') + assert.equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') - equal(el.find('[name="selectmulti3"]').prop("disabled"), true, 'check selectmulti3 disabled') - equal(el.find('[name="selectmultioption3"]').prop("disabled"), true, 'check selectmultioption3 disabled') + assert.equal(el.find('[name="selectmulti3"]').prop("disabled"), true, 'check selectmulti3 disabled') + assert.equal(el.find('[name="selectmultioption3"]').prop("disabled"), true, 'check selectmultioption3 disabled') - equal(el.find('[name="boolean4"]').prop("disabled"), true, 'check boolean4 disabled') - equal(el.find('[data-name="richtext9"]').prop("contenteditable"), "false", 'check richtext9 disabled') - equal(el.find('[name="checkbox5"]').prop("disabled"), true, 'check checkbox5 disabled') - equal(el.find('[name="radiobox3"]').prop("disabled"), true, 'check radiobox3 disabled') + assert.equal(el.find('[name="boolean4"]').prop("disabled"), true, 'check boolean4 disabled') + assert.equal(el.find('[data-name="richtext9"]').prop("contenteditable"), "false", 'check richtext9 disabled') + assert.equal(el.find('[name="checkbox5"]').prop("disabled"), true, 'check checkbox5 disabled') + assert.equal(el.find('[name="radiobox3"]').prop("disabled"), true, 'check radiobox3 disabled') params = App.ControllerForm.params(el) test_params = { @@ -359,12 +359,12 @@ test("form params check", function() { boolean3: true, boolean4: false, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("form defaults + params check", function() { -// deepEqual(item, test.value, 'group set/get tests' ); +QUnit.test("form defaults + params check", assert => { +// assert.deepEqual(item, test.value, 'group set/get tests' ); // mix default and params -> check it -> add note // test auto completion @@ -373,7 +373,7 @@ test("form defaults + params check", function() { // form params check // add signature only if form_state is empty - $('#forms').append('

        form defaults + params check

        ') + $('#qunit').append('

        form defaults + params check

        ') var el = $('#form3') var defaults = { input1: '', @@ -402,47 +402,47 @@ test("form defaults + params check", function() { params: defaults, autofocus: true }); - equal(el.find('[name="input1"]').val(), '', 'check input1 value') - equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') -// equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') - equal(el.find('[name="input2"]').val(), 'some used default', 'check input2 value') - equal(el.find('[name="input2"]').prop('required'), false, 'check input2 required') + assert.equal(el.find('[name="input1"]').val(), '', 'check input1 value') + assert.equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') +// assert.equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') + assert.equal(el.find('[name="input2"]').val(), 'some used default', 'check input2 value') + assert.equal(el.find('[name="input2"]').prop('required'), false, 'check input2 required') - equal(el.find('[name="password1"]').val(), 'some used pass', 'check password1 value') - equal(el.find('[name="password1_confirm"]').val(), 'some used pass', 'check password1 value') - equal(el.find('[name="password1"]').prop('required'), true, 'check password1 required') - equal(el.find('[name="password1"]').is(":focus"), false, 'check password1 focus') + assert.equal(el.find('[name="password1"]').val(), 'some used pass', 'check password1 value') + assert.equal(el.find('[name="password1_confirm"]').val(), 'some used pass', 'check password1 value') + assert.equal(el.find('[name="password1"]').prop('required'), true, 'check password1 required') + assert.equal(el.find('[name="password1"]').is(":focus"), false, 'check password1 focus') - equal(el.find('[name="password2"]').val(), 'pw1234', 'check password2 value') - equal(el.find('[name="password2_confirm"]').val(), 'pw1234', 'check password2 value') - equal(el.find('[name="password2"]').prop('required'), true, 'check password2 required') - equal(el.find('[name="password2"]').is(":focus"), false, 'check password2 focus') + assert.equal(el.find('[name="password2"]').val(), 'pw1234', 'check password2 value') + assert.equal(el.find('[name="password2_confirm"]').val(), 'pw1234', 'check password2 value') + assert.equal(el.find('[name="password2"]').prop('required'), true, 'check password2 required') + assert.equal(el.find('[name="password2"]').is(":focus"), false, 'check password2 focus') - equal(el.find('[name="textarea1"]').val(), 'some used text', 'check textarea1 value') - equal(el.find('[name="textarea1"]').prop('required'), true, 'check textarea1 required') - equal(el.find('[name="textarea1"]').is(":focus"), false, 'check textarea1 focus') + assert.equal(el.find('[name="textarea1"]').val(), 'some used text', 'check textarea1 value') + assert.equal(el.find('[name="textarea1"]').prop('required'), true, 'check textarea1 required') + assert.equal(el.find('[name="textarea1"]').is(":focus"), false, 'check textarea1 focus') - equal(el.find('[name="textarea2"]').val(), 'lalu lalu', 'check textarea2 value') - equal(el.find('[name="textarea2"]').prop('required'), true, 'check textarea2 required') - equal(el.find('[name="textarea2"]').is(":focus"), false, 'check textarea2 focus') + assert.equal(el.find('[name="textarea2"]').val(), 'lalu lalu', 'check textarea2 value') + assert.equal(el.find('[name="textarea2"]').prop('required'), true, 'check textarea2 required') + assert.equal(el.find('[name="textarea2"]').is(":focus"), false, 'check textarea2 focus') - equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') - equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') - equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') + assert.equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') + assert.equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') + assert.equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') - equal(el.find('[name="select2"]').val(), 'false', 'check select2 value') - equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') - equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') + assert.equal(el.find('[name="select2"]').val(), 'false', 'check select2 value') + assert.equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') + assert.equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') - equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') - equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') + assert.equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') + assert.equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') }); -test("form dependend fields check", function() { -// deepEqual(item, test.value, 'group set/get tests' ); +QUnit.test("form dependend fields check", assert => { +// assert.deepEqual(item, test.value, 'group set/get tests' ); // mix default and params -> check it -> add note // test auto completion @@ -451,7 +451,7 @@ test("form dependend fields check", function() { // form params check // add signature only if form_state is empty - $('#forms').append('

        form dependend fields check

        ') + $('#qunit').append('

        form dependend fields check

        ') var el = $('#form4') var defaults = { input1: '', @@ -549,27 +549,27 @@ test("form dependend fields check", function() { ], autofocus: true }); - equal(el.find('[name="input1"]').val(), '', 'check input1 value') - equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') -// equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') - equal(el.find('[name="input2"]').val(), 'some used default', 'check input2 value') - equal(el.find('[name="input2"]').prop('required'), false, 'check input2 required') + assert.equal(el.find('[name="input1"]').val(), '', 'check input1 value') + assert.equal(el.find('[name="input1"]').prop('required'), false, 'check input1 required') +// assert.equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') + assert.equal(el.find('[name="input2"]').val(), 'some used default', 'check input2 value') + assert.equal(el.find('[name="input2"]').prop('required'), false, 'check input2 required') - equal(el.find('[name="input3"]').val(), 'some used default', 'check input3 value') - equal(el.find('[name="input3"]').prop('required'), false, 'check input3 required') + assert.equal(el.find('[name="input3"]').val(), 'some used default', 'check input3 value') + assert.equal(el.find('[name="input3"]').prop('required'), false, 'check input3 required') - equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') - equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') - equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') + assert.equal(el.find('[name="select1"]').val(), 'false', 'check select1 value') + assert.equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') + assert.equal(el.find('[name="select1"]').is(":focus"), false, 'check select1 focus') - equal(el.find('[name="select2"]').val(), 'false', 'check select2 value') - equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') - equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') + assert.equal(el.find('[name="select2"]').val(), 'false', 'check select2 value') + assert.equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') + assert.equal(el.find('[name="select2"]').is(":focus"), false, 'check select2 focus') - equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') - equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') - equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') + assert.equal(el.find('[name="selectmulti2"]').val()[0], 'true', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').val()[1], 'false', 'check selectmulti2 value') + assert.equal(el.find('[name="selectmulti2"]').prop('required'), true, 'check selectmulti2 required') + assert.equal(el.find('[name="selectmulti2"]').is(":focus"), false, 'check selectmulti2 focus') var params = App.ControllerForm.params(el) var test_params = { @@ -589,14 +589,14 @@ test("form dependend fields check", function() { date3: '2015-01-11', date4: null, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') errors = form.validate(params) test_errors = { datetime4: "is required", date4: "is required", } - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) el.find('[name="select1"]').val('true') @@ -619,11 +619,11 @@ test("form dependend fields check", function() { date3: '2015-01-11', date4: null, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("form handler check with and without fieldset", function() { -// deepEqual(item, test.value, 'group set/get tests' ); +QUnit.test("form handler check with and without fieldset", assert => { +// assert.deepEqual(item, test.value, 'group set/get tests' ); // mix default and params -> check it -> add note // test auto completion @@ -632,7 +632,7 @@ test("form handler check with and without fieldset", function() { // form params check // add signature only if form_state is empty - $('#forms').append('

        form handler check with and without fieldset

        ') + $('#qunit').append('

        form handler check with and without fieldset

        ') var el = $('#form5') var defaults = { select1: 'a', @@ -683,18 +683,18 @@ test("form handler check with and without fieldset", function() { ], //noFieldset: true, }); - equal(el.find('[name="select1"]').val(), 'a', 'check select1 value') - equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') + assert.equal(el.find('[name="select1"]').val(), 'a', 'check select1 value') + assert.equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') - equal(el.find('[name="select2"]').val(), '1', 'check select2 value') - equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') + assert.equal(el.find('[name="select2"]').val(), '1', 'check select2 value') + assert.equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') var params = App.ControllerForm.params(el) var test_params = { select1: 'a', select2: '1', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name="select1"]').val('b') el.find('[name="select1"]').trigger('change') params = App.ControllerForm.params(el) @@ -702,7 +702,7 @@ test("form handler check with and without fieldset", function() { select1: 'b', select2: '3', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name="select1"]').val('a') el.find('[name="select1"]').trigger('change') params = App.ControllerForm.params(el) @@ -710,7 +710,7 @@ test("form handler check with and without fieldset", function() { select1: 'a', select2: '1', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // test with noFieldset el.empty() @@ -728,18 +728,18 @@ test("form handler check with and without fieldset", function() { ], noFieldset: true, }); - equal(el.find('[name="select1"]').val(), 'a', 'check select1 value') - equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') + assert.equal(el.find('[name="select1"]').val(), 'a', 'check select1 value') + assert.equal(el.find('[name="select1"]').prop('required'), false, 'check select1 required') - equal(el.find('[name="select2"]').val(), '1', 'check select2 value') - equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') + assert.equal(el.find('[name="select2"]').val(), '1', 'check select2 value') + assert.equal(el.find('[name="select2"]').prop('required'), false, 'check select2 required') var params = App.ControllerForm.params(el) var test_params = { select1: 'a', select2: '1', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name="select1"]').val('b') el.find('[name="select1"]').trigger('change') params = App.ControllerForm.params(el) @@ -747,7 +747,7 @@ test("form handler check with and without fieldset", function() { select1: 'b', select2: '3', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name="select1"]').val('a') el.find('[name="select1"]').trigger('change') params = App.ControllerForm.params(el) @@ -755,11 +755,11 @@ test("form handler check with and without fieldset", function() { select1: 'a', select2: '1', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("form postmaster filter", function() { +QUnit.test("form postmaster filter", assert => { App.TicketPriority.refresh([ { @@ -782,7 +782,7 @@ test("form postmaster filter", function() { }, ] ) - $('#forms').append('

        form postmaster filter

        ') + $('#qunit').append('

        form postmaster filter

        ') var el = $('#form6') var defaults = { input2: 'some name', @@ -864,7 +864,7 @@ test("form postmaster filter", function() { } }, }; - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name="set::x-zammad-ticket-priority_id::value"]').closest('.js-filterElement').find('.js-remove').click() el.find('[name="set::x-zammad-ticket-customer_id::value"]').closest('.js-filterElement').find('.js-remove').click() @@ -897,7 +897,7 @@ test("form postmaster filter", function() { }, }, }; - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('.postmaster_set .js-filterElement').last().find('.filter-controls .js-add').click() @@ -932,10 +932,10 @@ test("form postmaster filter", function() { }, }, }; - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') App.Delay.set(function() { - test("form postmaster filter - needed to do delayed because of tag ui", function() { + QUnit.test("form postmaster filter - needed to do delayed because of tag ui", assert => { el.find('[name="set::x-zammad-ticket-tags::value"]').closest('.js-filterElement').find('.token .close').last().click() params = App.ControllerForm.params(el) test_params = { @@ -968,13 +968,13 @@ test("form postmaster filter", function() { }, }, }; - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }) }, 500); }); -test("form selector", function() { - $('#forms').append('

        form selector

        ') +QUnit.test("form selector", assert => { + $('#qunit').append('

        form selector

        ') var el = $('#form7') var defaults = { input2: 'some name66', @@ -994,19 +994,19 @@ test("form selector", function() { input2: 'some name66', }; params = App.ControllerForm.params(el) - deepEqual(params, test_params, 'form param check via $("#form")') + assert.deepEqual(params, test_params, 'form param check via $("#form")') params = App.ControllerForm.params(el.find('input')) - deepEqual(params, test_params, 'form param check via $("#form").find("input")') + assert.deepEqual(params, test_params, 'form param check via $("#form").find("input")') params = App.ControllerForm.params(el.parent()) - deepEqual(params, test_params, 'form param check via $("#form").parent()') + assert.deepEqual(params, test_params, 'form param check via $("#form").parent()') }); -test("form params check", function() { +QUnit.test("form params check", assert => { - $('#forms').append('

        form params check

        ') + $('#qunit').append('

        form params check

        ') var el = $('#form9') var defaults = { select1: false, @@ -1038,13 +1038,13 @@ test("form params check", function() { } //console.log('params', params) //console.log('test_params', test_params) - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("form params check direct", function() { +QUnit.test("form params check direct", assert => { - $('#forms').append('

        form params check direct

        ') + $('#qunit').append('

        form params check direct

        ') var el = $('#form10') params = App.ControllerForm.params(el) @@ -1065,12 +1065,12 @@ test("form params check direct", function() { } //console.log('params', params) //console.log('test_params', test_params) - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("object manager form 1", function() { +QUnit.test("object manager form 1", assert => { - $('#forms').append('

        object manager 1

        ') + $('#qunit').append('

        object manager 1

        ') var el = $('#form11') var defaults = {} @@ -1118,7 +1118,7 @@ test("object manager form 1", function() { } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name=data_type]').val('datetime').trigger('change') @@ -1153,13 +1153,13 @@ test("object manager form 1", function() { } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("object manager form 2", function() { +QUnit.test("object manager form 2", assert => { - $('#forms').append('

        object manager 2

        ') + $('#qunit').append('

        object manager 2

        ') var el = $('#form12') var defaults = { @@ -1230,13 +1230,13 @@ test("object manager form 2", function() { } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("object manager form 3", function() { +QUnit.test("object manager form 3", assert => { - $('#forms').append('

        object manager 3

        ') + $('#qunit').append('

        object manager 3

        ') var el = $('#form13') var defaults = {} @@ -1284,7 +1284,7 @@ test("object manager form 3", function() { } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name="screens::create_middle::ticket.customer::shown"]').click() el.find('[name="screens::edit::ticket.customer::shown"]').click() @@ -1321,13 +1321,13 @@ test("object manager form 3", function() { } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test("check if select value is not existing but is shown", function() { +QUnit.test("check if select value is not existing but is shown", assert => { - $('#forms').append('

        check if select value is not existing but is shown

        ') + $('#qunit').append('

        check if select value is not existing but is shown

        ') var el = $('#form17') var defaults = { select1: 'NOT EXISTING', @@ -1346,20 +1346,20 @@ test("check if select value is not existing but is shown", function() { test_params = { select1: 'NOT EXISTING', } - deepEqual(params, test_params) + assert.deepEqual(params, test_params) - equal('AA', el.find('[name=select1] option')[0].text) - equal('äöü', el.find('[name=select1] option')[1].text) - equal('b', el.find('[name=select1] option')[2].text) - equal('B', el.find('[name=select1] option')[3].text) - equal('NOT EXISTING', el.find('[name=select1] option')[4].text) - equal('XX', el.find('[name=select1] option')[5].text) + assert.equal('AA', el.find('[name=select1] option')[0].text) + assert.equal('äöü', el.find('[name=select1] option')[1].text) + assert.equal('b', el.find('[name=select1] option')[2].text) + assert.equal('B', el.find('[name=select1] option')[3].text) + assert.equal('NOT EXISTING', el.find('[name=select1] option')[4].text) + assert.equal('XX', el.find('[name=select1] option')[5].text) }); -test("check if select value is not existing and is not shown", function() { +QUnit.test("check if select value is not existing and is not shown", assert => { - $('#forms').append('

        check if select value is not existing and is not shown

        ') + $('#qunit').append('

        check if select value is not existing and is not shown

        ') var el = $('#form18') var defaults = { select1: 'NOT EXISTING', @@ -1379,19 +1379,19 @@ test("check if select value is not existing and is not shown", function() { test_params = { select1: 'XY', } - deepEqual(params, test_params) + assert.deepEqual(params, test_params) - equal('AA', el.find('[name=select1] option')[0].text) - equal('äöü', el.find('[name=select1] option')[1].text) - equal('b', el.find('[name=select1] option')[2].text) - equal('B', el.find('[name=select1] option')[3].text) - equal('XX', el.find('[name=select1] option')[4].text) + assert.equal('AA', el.find('[name=select1] option')[0].text) + assert.equal('äöü', el.find('[name=select1] option')[1].text) + assert.equal('b', el.find('[name=select1] option')[2].text) + assert.equal('B', el.find('[name=select1] option')[3].text) + assert.equal('XX', el.find('[name=select1] option')[4].text) }); -test("time range form 1", function() { +QUnit.test("time range form 1", assert => { - $('#forms').append('

        time range form 1

        ') + $('#qunit').append('

        time range form 1

        ') var el = $('#form14') var defaults = {} @@ -1414,7 +1414,7 @@ test("time range form 1", function() { } } - deepEqual(params, test_params, 'base form param range check') + assert.deepEqual(params, test_params, 'base form param range check') el.find('.js-range').val('minute').trigger('change') el.find('.js-valueRangeSelector .js-value').val('120').trigger('change') @@ -1426,7 +1426,7 @@ test("time range form 1", function() { "value": "120" } } - deepEqual(params, test_params, 'form param minute range check') + assert.deepEqual(params, test_params, 'form param minute range check') el.find('.js-range').val('hour').trigger('change') el.find('.js-valueRangeSelector .js-value').val('48').trigger('change') @@ -1438,7 +1438,7 @@ test("time range form 1", function() { "value": "48" } } - deepEqual(params, test_params, 'form param hour range check') + assert.deepEqual(params, test_params, 'form param hour range check') el.find('.js-range').val('day').trigger('change') el.find('.js-valueRangeSelector .js-value').val('31').trigger('change') @@ -1450,7 +1450,7 @@ test("time range form 1", function() { "value": "31" } } - deepEqual(params, test_params, 'form param day range check') + assert.deepEqual(params, test_params, 'form param day range check') el.find('.js-range').val('month').trigger('change') el.find('.js-valueRangeSelector .js-value').val('12').trigger('change') @@ -1462,7 +1462,7 @@ test("time range form 1", function() { "value": "12" } } - deepEqual(params, test_params, 'form param month range check') + assert.deepEqual(params, test_params, 'form param month range check') el.find('.js-range').val('year').trigger('change') el.find('.js-valueRangeSelector .js-value').val('20').trigger('change') @@ -1474,12 +1474,12 @@ test("time range form 1", function() { "value": "20" } } - deepEqual(params, test_params, 'form param year range check') + assert.deepEqual(params, test_params, 'form param year range check') }); -test("form select with empty option list", function() { +QUnit.test("form select with empty option list", assert => { - $('#forms').append('

        form select with empty option list

        ') + $('#qunit').append('

        form select with empty option list

        ') var el = $('#form15') var defaults = {} new App.ControllerForm({ @@ -1506,12 +1506,12 @@ test("form select with empty option list", function() { select5: 'A', select6: 'B', } - deepEqual(params, test_params) + assert.deepEqual(params, test_params) }); -test("form elements with sort check", function() { +QUnit.test("form elements with sort check", assert => { - $('#forms').append('

        form elements with sort check

        ') + $('#qunit').append('

        form elements with sort check

        ') var el = $('#form16') var defaults = {} new App.ControllerForm({ @@ -1533,30 +1533,30 @@ test("form elements with sort check", function() { checkbox1: 'A', radio1: 'A', } - deepEqual(params, test_params) + assert.deepEqual(params, test_params) - equal('AA', el.find('[name=select1] option')[0].text) - equal('äöü', el.find('[name=select1] option')[1].text) - equal('b', el.find('[name=select1] option')[2].text) - equal('B', el.find('[name=select1] option')[3].text) - equal('XX', el.find('[name=select1] option')[4].text) + assert.equal('AA', el.find('[name=select1] option')[0].text) + assert.equal('äöü', el.find('[name=select1] option')[1].text) + assert.equal('b', el.find('[name=select1] option')[2].text) + assert.equal('B', el.find('[name=select1] option')[3].text) + assert.equal('XX', el.find('[name=select1] option')[4].text) - equal('XX', el.find('[name=checkbox1]')[0].value) - equal('', el.find('[name=checkbox1]')[1].value) - equal('XY', el.find('[name=checkbox1]')[2].value) - equal('B', el.find('[name=checkbox1]')[3].value) - equal('A', el.find('[name=checkbox1]')[4].value) + assert.equal('XX', el.find('[name=checkbox1]')[0].value) + assert.equal('', el.find('[name=checkbox1]')[1].value) + assert.equal('XY', el.find('[name=checkbox1]')[2].value) + assert.equal('B', el.find('[name=checkbox1]')[3].value) + assert.equal('A', el.find('[name=checkbox1]')[4].value) - equal('XX', el.find('[name=radio1]')[0].value) - equal('', el.find('[name=radio1]')[1].value) - equal('XY', el.find('[name=radio1]')[2].value) - equal('B', el.find('[name=radio1]')[3].value) - equal('A', el.find('[name=radio1]')[4].value) + assert.equal('XX', el.find('[name=radio1]')[0].value) + assert.equal('', el.find('[name=radio1]')[1].value) + assert.equal('XY', el.find('[name=radio1]')[2].value) + assert.equal('B', el.find('[name=radio1]')[3].value) + assert.equal('A', el.find('[name=radio1]')[4].value) }); -test("form deep nesting", function() { - $('#forms').append('

        form selector

        ') +QUnit.test("form deep nesting", assert => { + $('#qunit').append('

        form selector

        ') var el = $('#form19') var defaults = { a: { @@ -1580,11 +1580,11 @@ test("form deep nesting", function() { }); params = App.ControllerForm.params(el) - deepEqual(params, defaults, 'nested params') + assert.deepEqual(params, defaults, 'nested params') }); -test("form with external links", function() { - $('#forms').append('

        form with external links

        ') +QUnit.test("form with external links", assert => { + $('#qunit').append('

        form with external links

        ') var el = $('#form20') var defaults = { a: '133', @@ -1603,7 +1603,7 @@ test("form with external links", function() { }); params = App.ControllerForm.params(el) - deepEqual(params, defaults) - equal('https://example.com/?q=133', el.find('input[name="a"]').parents('.controls').find('a[href]').attr('href')) - equal('https://example.com/?q=abc%20d', el.find('select[name="b"]').parents('.controls').find('a[href]').attr('href')) + assert.deepEqual(params, defaults) + assert.equal('https://example.com/?q=133', el.find('input[name="a"]').parents('.controls').find('a[href]').attr('href')) + assert.equal('https://example.com/?q=abc%20d', el.find('select[name="b"]').parents('.controls').find('a[href]').attr('href')) }); diff --git a/public/assets/tests/form_autocompletion_ajax.js b/public/assets/tests/qunit/form_autocompletion_ajax.js similarity index 73% rename from public/assets/tests/form_autocompletion_ajax.js rename to public/assets/tests/qunit/form_autocompletion_ajax.js index 36cff5209..bd6ab1694 100644 --- a/public/assets/tests/form_autocompletion_ajax.js +++ b/public/assets/tests/qunit/form_autocompletion_ajax.js @@ -1,4 +1,4 @@ -function check_ajax_field(field, value, count, callback, waitTotal = 30000, wait = 0) { +function check_ajax_field(field, value, count, callback, assert, waitTotal = 30000, wait = 0) { $elementInput = $('[name="' + field + '"].js-shadow + .js-input') if ($elementInput.val() != value) { $elementInput.focus().val(value).trigger('input') @@ -9,22 +9,22 @@ function check_ajax_field(field, value, count, callback, waitTotal = 30000, wait var match = entries == count if (match || wait >= waitTotal) { - equal(entries, count, 'search result found for email address ' + value) + assert.equal(entries, count, 'search result found for email address ' + value) callback() return } wait += 100 if (wait % 3000 == 0) { - ok(true, 'check_ajax_field for ' + field + ' waiting ' + wait) + assert.ok(true, 'check_ajax_field for ' + field + ' waiting ' + wait) } setTimeout(function() { - check_ajax_field(field, value, count, callback, waitTotal, wait) + check_ajax_field(field, value, count, callback, assert, waitTotal, wait) }, 100) } -test( "autocompletion_ajax check", function(assert) { +QUnit.test( "autocompletion_ajax check", assert => { var done = assert.async(1) $('#forms').append('

        autocompletion_ajax check

        ') @@ -57,14 +57,14 @@ test( "autocompletion_ajax check", function(assert) { }) .then( function() { return new Promise( (resolve, reject) => { - notEqual(App.Session.get(), undefined, 'User is logged in so the api requests will work') + assert.notEqual(App.Session.get(), undefined, 'User is logged in so the api requests will work') - check_ajax_field('autocompletion_ajax1', 'admin@example.com', 1, resolve) + check_ajax_field('autocompletion_ajax1', 'admin@example.com', 1, resolve, assert) }) }) .then( function() { return new Promise( (resolve, reject) => { - check_ajax_field('autocompletion_ajax1', 'xxx@example.com', 0, resolve) + check_ajax_field('autocompletion_ajax1', 'xxx@example.com', 0, resolve, assert) }) }) .finally(done) diff --git a/public/assets/tests/form_color.js b/public/assets/tests/qunit/form_color.js similarity index 70% rename from public/assets/tests/form_color.js rename to public/assets/tests/qunit/form_color.js index 690fcd3c6..678d982d7 100644 --- a/public/assets/tests/form_color.js +++ b/public/assets/tests/qunit/form_color.js @@ -1,4 +1,4 @@ -test("form elements check", function(assert) { +QUnit.test("form elements check", assert => { var done = assert.async(1) $('#forms').append('

        form elements check

        ') @@ -21,7 +21,7 @@ test("form elements check", function(assert) { color: '#fff' } - deepEqual(params, test_params, 'default param check') + assert.deepEqual(params, test_params, 'default param check') var inputEl = el.find('.js-input')[0] @@ -37,7 +37,7 @@ test("form elements check", function(assert) { color: '' } - deepEqual(params, test_params, 'UI allows color field to be empty') + assert.deepEqual(params, test_params, 'UI allows color field to be empty') }) .then( function() { previousSwatchColor = getSwatchColor() @@ -51,8 +51,8 @@ test("form elements check", function(assert) { color: 'rgb(0,100,100)' } - deepEqual(params, test_params, 'UI allows to type in RGB colors') - notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') + assert.deepEqual(params, test_params, 'UI allows to type in RGB colors') + assert.notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') }) .then( function() { var circle = el.find('.js-colorpicker-circle')[0] @@ -68,15 +68,15 @@ test("form elements check", function(assert) { color: 'hsl(169,100%,20%)' } - deepEqual(params, test_params, 'Color is transformed to HSL after moving the circle') - notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') + assert.deepEqual(params, test_params, 'Color is transformed to HSL after moving the circle') + assert.notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') }) .then( function() { var slider = el.find('.js-colorpicker-slider')[0] previousSwatchColor = getSwatchColor() return new Promise( (resolve,reject) => { - syn.drag(slider, { to: '-0x-10'}, resolve) + syn.drag(slider, { to: '-0x-11'}, resolve) }) }) .then( function() { @@ -85,8 +85,8 @@ test("form elements check", function(assert) { color: 'hsl(169,100%,27%)' } - deepEqual(params, test_params, 'Color code is changed after draging slider') - notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') + assert.deepEqual(params, test_params, 'Color code is changed after draging slider') + assert.notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') }) .then( function() { let circle = el.find('.js-colorpicker-circle').position() @@ -101,10 +101,10 @@ test("form elements check", function(assert) { let new_circle = el.find('.js-colorpicker-circle').position() let new_slider = el.find('.js-colorpicker-slider').position() - notDeepEqual(circle, new_circle, 'Color picker is updated after typing in color') - notDeepEqual(slider, new_slider, 'Color picker is updated after typing in color') + assert.notDeepEqual(circle, new_circle, 'Color picker is updated after typing in color') + assert.notDeepEqual(slider, new_slider, 'Color picker is updated after typing in color') - notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') + assert.notEqual(previousSwatchColor, getSwatchColor(), 'color in swatch was updated') }) }) .finally(done) diff --git a/public/assets/tests/form_column_select.js b/public/assets/tests/qunit/form_column_select.js similarity index 89% rename from public/assets/tests/form_column_select.js rename to public/assets/tests/qunit/form_column_select.js index a81645e3e..2a3a84c2d 100644 --- a/public/assets/tests/form_column_select.js +++ b/public/assets/tests/qunit/form_column_select.js @@ -1,6 +1,6 @@ // column_select -test( "column_select check", function(assert) { +QUnit.test( "column_select check", assert => { $('#forms').append('

        column_select check

        ') var el = $('#form1') var defaults = { @@ -32,7 +32,7 @@ test( "column_select check", function(assert) { column_select2: ['aaa', 'bbb'], column_select3: ['1', '2'], } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // add and remove selections $('[data-name="column_select1"] .js-pool .js-option[data-value="bbb"]').click() @@ -43,7 +43,7 @@ test( "column_select check", function(assert) { column_select2: ['aaa', 'bbb'], column_select3: ['1', '2'], } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') var done = assert.async(); setTimeout(function() { @@ -58,7 +58,7 @@ test( "column_select check", function(assert) { column_select2: ['1', 'bbb'], column_select3: ['1', '2', 'aaa'], } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') done(); }, 400); diff --git a/public/assets/tests/form_core_workflow.js b/public/assets/tests/qunit/form_core_workflow.js similarity index 52% rename from public/assets/tests/form_core_workflow.js rename to public/assets/tests/qunit/form_core_workflow.js index acffeac13..32dc05615 100644 --- a/public/assets/tests/form_core_workflow.js +++ b/public/assets/tests/qunit/form_core_workflow.js @@ -1,4 +1,4 @@ -test("core_workflow_condition", function(assert) { +QUnit.test("core_workflow_condition", assert => { var form = $('#forms') var el = $('
        ').attr('id', 'form1') @@ -14,20 +14,20 @@ test("core_workflow_condition", function(assert) { autofocus: true }); - equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button') + assert.equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button') el.find('.js-add').click() - equal(el.find('.js-remove.is-disabled').length, 0, 'find no disabled button after add') + assert.equal(el.find('.js-remove.is-disabled').length, 0, 'find no disabled button after add') el.find('.js-remove').click() - equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button after remove') - equal(typeof(App.ControllerForm.params(el).condition_selected), 'object', 'empty element results in a hash') - equal(_.isEmpty(App.ControllerForm.params(el).condition_selected), true, 'empty element results are empty') + assert.equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button after remove') + assert.equal(typeof(App.ControllerForm.params(el).condition_selected), 'object', 'empty element results in a hash') + assert.equal(_.isEmpty(App.ControllerForm.params(el).condition_selected), true, 'empty element results are empty') el.find('.js-add').click() el.find("option[value='ticket.owner_id']").prop('selected', true) - equal(el.find('.js-preCondition').length, 0, 'pre condition not available') + assert.equal(el.find('.js-preCondition').length, 0, 'pre condition not available') }); -test("core_workflow_perform", function(assert) { +QUnit.test("core_workflow_perform", assert => { var form = $('#forms') var el = $('
        ').attr('id', 'form1') @@ -43,17 +43,17 @@ test("core_workflow_perform", function(assert) { autofocus: true }); - equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button') + assert.equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button') el.find('.js-add').click() - equal(el.find('.js-remove.is-disabled').length, 0, 'find no disabled button after add') + assert.equal(el.find('.js-remove.is-disabled').length, 0, 'find no disabled button after add') el.find('.js-remove').click() - equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button after remove') - equal(typeof(App.ControllerForm.params(el).perform), 'object', 'empty element results in a hash') - equal(_.isEmpty(App.ControllerForm.params(el).perform), true, 'empty element results are empty') + assert.equal(el.find('.js-remove.is-disabled').length, 1, 'find disabled button after remove') + assert.equal(typeof(App.ControllerForm.params(el).perform), 'object', 'empty element results in a hash') + assert.equal(_.isEmpty(App.ControllerForm.params(el).perform), true, 'empty element results are empty') el.find('.js-add').click() el.find("option[value='ticket.owner_id']").prop('selected', true) - equal(el.find('.js-preCondition').length, 0, 'pre condition not available') + assert.equal(el.find('.js-preCondition').length, 0, 'pre condition not available') el.find('.js-add:last').click() el.find("option[value='ticket.group_id']:last").prop('selected', true) @@ -67,5 +67,5 @@ test("core_workflow_perform", function(assert) { attribute_count[$(this).val()] ||= 0 attribute_count[$(this).val()] += 1 }) - equal(attribute_count['ticket.group_id'], 3, 'hasDuplicateSelector - its possible to select an attribute multiple times') + assert.equal(attribute_count['ticket.group_id'], 3, 'hasDuplicateSelector - its possible to select an attribute multiple times') }); diff --git a/public/assets/tests/form_datetime.js b/public/assets/tests/qunit/form_datetime.js similarity index 51% rename from public/assets/tests/form_datetime.js rename to public/assets/tests/qunit/form_datetime.js index a0767cbea..701427fd3 100644 --- a/public/assets/tests/form_datetime.js +++ b/public/assets/tests/qunit/form_datetime.js @@ -1,4 +1,4 @@ -test("DateTime timepicker focuses hours", function(assert) { +QUnit.test("DateTime timepicker focuses hours", assert => { var form = $('#forms') var el = $('
        ').attr('id', 'form1') @@ -16,9 +16,9 @@ test("DateTime timepicker focuses hours", function(assert) { autofocus: true }); - equal(el.find('[data-name=datetime1] [data-item=date]')[0].disabled, false) - equal(el.find('[data-name=datetime1] [data-item=time]')[0].disabled, false) - equal(el.find('[data-name=datetime2] [data-item=date]')[0].disabled, true) - equal(el.find('[data-name=datetime2] [data-item=time]')[0].disabled, true) - equal(el.find('[data-name=date3] [data-item=date]')[0].disabled, true) + assert.equal(el.find('[data-name=datetime1] [data-item=date]')[0].disabled, false) + assert.equal(el.find('[data-name=datetime1] [data-item=time]')[0].disabled, false) + assert.equal(el.find('[data-name=datetime2] [data-item=date]')[0].disabled, true) + assert.equal(el.find('[data-name=datetime2] [data-item=time]')[0].disabled, true) + assert.equal(el.find('[data-name=date3] [data-item=date]')[0].disabled, true) }); diff --git a/public/assets/tests/form_extended.js b/public/assets/tests/qunit/form_extended.js similarity index 88% rename from public/assets/tests/form_extended.js rename to public/assets/tests/qunit/form_extended.js index b4ce7be80..1424c6b36 100644 --- a/public/assets/tests/form_extended.js +++ b/public/assets/tests/qunit/form_extended.js @@ -1,6 +1,6 @@ // form -test('form checks', function() { +QUnit.test('form checks', assert => { // use unsorted order to check if the frontend is sorting correctly App.TicketPriority.refresh([ @@ -222,42 +222,42 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // check possible options - equal(el.find('[name="priority1_id"] option').length, 3) - equal(el.find('[name="priority2_id"] option').length, 4) - equal(el.find('[name="priority3_id"] option').length, 4) - equal(el.find('[name="priority4_id"] option').length, 4) - equal(el.find('[name="priority5_id"] option').length, 3) + assert.equal(el.find('[name="priority1_id"] option').length, 3) + assert.equal(el.find('[name="priority2_id"] option').length, 4) + assert.equal(el.find('[name="priority3_id"] option').length, 4) + assert.equal(el.find('[name="priority4_id"] option').length, 4) + assert.equal(el.find('[name="priority5_id"] option').length, 3) // check priority1_id selection order - equal(el.find('[name="priority1_id"] option:nth-child(1)').text(), '1 low') - equal(el.find('[name="priority1_id"] option:nth-child(2)').text(), '3 high') - equal(el.find('[name="priority1_id"] option:nth-child(3)').text(), '4 very high') + assert.equal(el.find('[name="priority1_id"] option:nth-child(1)').text(), '1 low') + assert.equal(el.find('[name="priority1_id"] option:nth-child(2)').text(), '3 high') + assert.equal(el.find('[name="priority1_id"] option:nth-child(3)').text(), '4 very high') // check priority2_id selection order - equal(el.find('[name="priority2_id"] option:nth-child(1)').text(), '1 low') - equal(el.find('[name="priority2_id"] option:nth-child(2)').text(), '2 normal') - equal(el.find('[name="priority2_id"] option:nth-child(3)').text(), '3 high') - equal(el.find('[name="priority2_id"] option:nth-child(4)').text(), '4 very high') + assert.equal(el.find('[name="priority2_id"] option:nth-child(1)').text(), '1 low') + assert.equal(el.find('[name="priority2_id"] option:nth-child(2)').text(), '2 normal') + assert.equal(el.find('[name="priority2_id"] option:nth-child(3)').text(), '3 high') + assert.equal(el.find('[name="priority2_id"] option:nth-child(4)').text(), '4 very high') // check priority3_id selection order - equal(el.find('[name="priority3_id"] option:nth-child(1)').text(), '1 low') - equal(el.find('[name="priority3_id"] option:nth-child(2)').text(), '2 normal') - equal(el.find('[name="priority3_id"] option:nth-child(3)').text(), '3 high') - equal(el.find('[name="priority3_id"] option:nth-child(4)').text(), '4 very high') + assert.equal(el.find('[name="priority3_id"] option:nth-child(1)').text(), '1 low') + assert.equal(el.find('[name="priority3_id"] option:nth-child(2)').text(), '2 normal') + assert.equal(el.find('[name="priority3_id"] option:nth-child(3)').text(), '3 high') + assert.equal(el.find('[name="priority3_id"] option:nth-child(4)').text(), '4 very high') // check priority4_id selection order - equal(el.find('[name="priority4_id"] option:nth-child(1)').text(), '1 low') - equal(el.find('[name="priority4_id"] option:nth-child(2)').text(), '2 normal') - equal(el.find('[name="priority4_id"] option:nth-child(3)').text(), '3 high') - equal(el.find('[name="priority4_id"] option:nth-child(4)').text(), '4 very high') + assert.equal(el.find('[name="priority4_id"] option:nth-child(1)').text(), '1 low') + assert.equal(el.find('[name="priority4_id"] option:nth-child(2)').text(), '2 normal') + assert.equal(el.find('[name="priority4_id"] option:nth-child(3)').text(), '3 high') + assert.equal(el.find('[name="priority4_id"] option:nth-child(4)').text(), '4 very high') // check priority5_id selection order - equal(el.find('[name="priority5_id"] option:nth-child(1)').text(), '1 low') - equal(el.find('[name="priority5_id"] option:nth-child(2)').text(), '3 high') - equal(el.find('[name="priority5_id"] option:nth-child(3)').text(), '4 very high') + assert.equal(el.find('[name="priority5_id"] option:nth-child(1)').text(), '1 low') + assert.equal(el.find('[name="priority5_id"] option:nth-child(2)').text(), '3 high') + assert.equal(el.find('[name="priority5_id"] option:nth-child(3)').text(), '4 very high') // change sla times el.find('[name="first_response_time_in_text"]').val('0:30').trigger('blur') @@ -325,7 +325,7 @@ test('form checks', function() { update_time_enabled: undefined, update_time_in_text: '', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') /* empty params or defaults */ $('#forms').append('

        form condition check

        ') @@ -354,7 +354,7 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form param check'); + assert.deepEqual(params, test_params, 'form param check'); /* with params or defaults */ $('#forms').append('

        form 3

        ') @@ -492,7 +492,7 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // change selector el.find('[name="condition::ticket.priority_id::value"]').closest('.js-filterElement').find('.js-remove').click() @@ -554,7 +554,7 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // change selector el.find('[name="executions::notification.email::subject"]').closest('.js-filterElement').find('.js-remove').click() @@ -608,7 +608,7 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // change selector el.find('.js-attributeSelector').last().find('select').val('notification.email').trigger('change') @@ -668,7 +668,7 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') /* with params or defaults */ $('#forms').append('

        form 4

        ') @@ -720,7 +720,7 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('#forms').append('

        form 5

        ') var el = $('#form5') @@ -770,5 +770,5 @@ test('form checks', function() { }, }, } - deepEqual(params, test_params, 'form article body param check') + assert.deepEqual(params, test_params, 'form article body param check') }); diff --git a/public/assets/tests/qunit/form_find.js b/public/assets/tests/qunit/form_find.js new file mode 100644 index 000000000..2bad13f1f --- /dev/null +++ b/public/assets/tests/qunit/form_find.js @@ -0,0 +1,59 @@ + +// form +QUnit.test( "find form check", assert => { + + $('#forms').append('

        find form check

        ') + var form1 = App.ControllerForm.findForm($('#form1')) + assert.equal(form1.is('form'), true) + + $('#forms').append('

        find form check

        ') + var form2 = App.ControllerForm.findForm($('#form2 .js-input')) + assert.equal(form2.is('form'), true) + + $('#forms').append('

        find form check

        ') + var form3 = App.ControllerForm.findForm($('#form3 .js-button')) + assert.equal(form3.is('form'), true) + App.ControllerForm.disable($('#form3 .js-button')) + assert.equal($('#form3 .js-button').prop('readonly'), true) + assert.equal($('#form3 .js-button').prop('disabled'), true) + assert.equal($('#form3 .js-input').prop('readonly'), true) + assert.equal($('#form3 .js-input').prop('disabled'), false) + + App.ControllerForm.enable($('#form3 .js-button')) + assert.equal($('#form3 .js-button').prop('readonly'), false) + assert.equal($('#form3 .js-button').prop('disabled'), false) + assert.equal($('#form3 .js-input').prop('readonly'), false) + assert.equal($('#form3 .js-input').prop('disabled'), false) + + $('#forms').append('

        find form check by only disable button

        ') + var form31 = App.ControllerForm.findForm($('#form31 .js-button')) + + App.ControllerForm.disable($('#form31 .js-button'), 'button') + + assert.equal($('#form31 .js-button').prop('readonly'), true) + assert.equal($('#form31 .js-button').prop('disabled'), true) + assert.equal($('#form31 .js-input').prop('readonly'), false) + assert.equal($('#form31 .js-input').prop('disabled'), false) + + App.ControllerForm.enable($('#form31 .js-button')) + assert.equal($('#form31 .js-button').prop('readonly'), false) + assert.equal($('#form31 .js-button').prop('disabled'), false) + assert.equal($('#form31 .js-input').prop('readonly'), false) + assert.equal($('#form31 .js-input').prop('disabled'), false) + + $('#forms').append('

        find form check

        ') + var form4 = App.ControllerForm.findForm($('#form4 .js-button')) + assert.equal(form4.is('form'), false) + App.ControllerForm.disable($('#form4 .js-button')) + assert.equal($('#form4 .js-button').prop('readonly'), true) + assert.equal($('#form4 .js-button').prop('disabled'), true) + assert.equal($('#form4 .js-input').prop('readonly'), false) + assert.equal($('#form4 .js-input').prop('disabled'), false) + + App.ControllerForm.enable($('#form4 .js-button')) + assert.equal($('#form4 .js-button').prop('readonly'), false) + assert.equal($('#form4 .js-button').prop('disabled'), false) + assert.equal($('#form4 .js-input').prop('readonly'), false) + assert.equal($('#form4 .js-input').prop('disabled'), false) + +}); diff --git a/public/assets/tests/form_searchable_select.js b/public/assets/tests/qunit/form_searchable_select.js similarity index 84% rename from public/assets/tests/form_searchable_select.js rename to public/assets/tests/qunit/form_searchable_select.js index 826928503..a29ce8e20 100644 --- a/public/assets/tests/form_searchable_select.js +++ b/public/assets/tests/qunit/form_searchable_select.js @@ -1,5 +1,5 @@ // searchable_select -test( "searchable_select check", function() { +QUnit.test( "searchable_select check", assert => { $('#forms').append('

        searchable_select check

        ') var el = $('#form1') @@ -70,16 +70,16 @@ test( "searchable_select check", function() { searchable_select3: '', searchable_select4: 'ccc', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // change selection $('[name="searchable_select1"].js-shadow + .js-input').focus().val('').trigger('input') var $element = $('[name="searchable_select1"]').closest('.searchableSelect').find('.js-optionsList') var entries = $element.find('li:not(.is-hidden)').length - equal(entries, 3, 'dropdown count') + assert.equal(entries, 3, 'dropdown count') $('[name="searchable_select1"].js-shadow + .js-input').focus().val('ccc display').trigger('input') var entries = $element.find('li:not(.is-hidden)').length - equal(entries, 1, 'dropdown count') + assert.equal(entries, 1, 'dropdown count') $element.find('li:not(.is-hidden)').first().click() params = App.ControllerForm.params(el) test_params = { @@ -88,15 +88,15 @@ test( "searchable_select check", function() { searchable_select3: '', searchable_select4: 'ccc', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('[name="searchable_select2"].js-shadow + .js-input').focus().val('').trigger('input') var $element = $('[name="searchable_select2"]').closest('.searchableSelect').find('.js-optionsList') var entries = $element.find('li:not(.is-hidden)').length - equal(entries, 3, 'dropdown count') + assert.equal(entries, 3, 'dropdown count') $('[name="searchable_select2"].js-shadow + .js-input').focus().val('ccc display').trigger('input') var entries = $element.find('li:not(.is-hidden)').length - equal(entries, 1, 'dropdown count') + assert.equal(entries, 1, 'dropdown count') $element.find('li:not(.is-hidden)').first().click() params = App.ControllerForm.params(el) @@ -106,20 +106,20 @@ test( "searchable_select check", function() { searchable_select3: '', searchable_select4: 'ccc', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('[name="searchable_select3"].js-shadow + .js-input').focus().val('').trigger('input') var $element = $('[name="searchable_select3"]').closest('.searchableSelect').find('.js-optionsList') var entries = $element.find('li:not(.is-hidden)').length - equal(entries, 3, 'dropdown count') + assert.equal(entries, 3, 'dropdown count') $('[name="searchable_select3"].js-shadow + .js-input').focus().val('ccc display').trigger('input') var entries = $element.find('li:not(.is-hidden)').length - equal(entries, 1, 'dropdown count') + assert.equal(entries, 1, 'dropdown count') $('[name="searchable_select3"].js-shadow + .js-input').focus().val('unknown value').trigger('input') var entries = $element.find('li:not(.is-hidden)').length - equal(entries, 3, 'dropdown count') + assert.equal(entries, 3, 'dropdown count') var entries = $element.find('li.is-active').length - equal(entries, 0, 'active count') + assert.equal(entries, 0, 'active count') var e = $.Event('keydown') e.which = 13 //enter @@ -133,7 +133,7 @@ test( "searchable_select check", function() { searchable_select3: 'unknown value', searchable_select4: 'ccc', } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('#forms').append('

        searchable_select check for .js-input field values

        ') var el = $('#form2') @@ -179,14 +179,14 @@ test( "searchable_select check", function() { searchable_select1: 'ccc::aaa', searchable_select2: 'ccc::ccc', } - deepEqual(params, test_params, 'form param check') - equal(el.find('[name="searchable_select1"].js-shadow + .js-input').val(), 'aaa display L2', 'verify shown input') - equal(el.find('[name="searchable_select2"].js-shadow + .js-input').val(), 'ccc display L2', 'verify shown input') + assert.deepEqual(params, test_params, 'form param check') + assert.equal(el.find('[name="searchable_select1"].js-shadow + .js-input').val(), 'aaa display L2', 'verify shown input') + assert.equal(el.find('[name="searchable_select2"].js-shadow + .js-input').val(), 'ccc display L2', 'verify shown input') }); -asyncTest("searchable_select submenu and option list check", function() { - expect(3); +QUnit.test("searchable_select submenu and option list check", assert => { + var done = assert.async() $('#forms').append('

        searchable_select check for special charaters values

        ') var el = $('#form3') @@ -232,10 +232,10 @@ asyncTest("searchable_select submenu and option list check", function() { var optionsList = el.find(".searchableSelect .js-optionsList") setTimeout( () => { - deepEqual(params, test_params, 'form param check') - equal(optionsSubmenu.is('[hidden]'), false, 'options submenu menu not hidden') - equal(optionsList.is('[hidden]'), true, 'options list is hidden') - start(); + assert.deepEqual(params, test_params, 'form param check') + assert.equal(optionsSubmenu.is('[hidden]'), false, 'options submenu menu not hidden') + assert.equal(optionsList.is('[hidden]'), true, 'options list is hidden') + done() }, 300) }); diff --git a/public/assets/tests/form_skip_rendering.js b/public/assets/tests/qunit/form_skip_rendering.js similarity index 62% rename from public/assets/tests/form_skip_rendering.js rename to public/assets/tests/qunit/form_skip_rendering.js index 0339c9923..85964afef 100644 --- a/public/assets/tests/form_skip_rendering.js +++ b/public/assets/tests/qunit/form_skip_rendering.js @@ -1,4 +1,4 @@ -test("form elements not rendered", function(assert) { +QUnit.test("form elements not rendered", assert => { $('#forms').append('

        form elements check

        ') var el = $('#form1') @@ -14,6 +14,6 @@ test("form elements not rendered", function(assert) { autofocus: true }); - ok(el.find('input[name=shown]').get(0), 'control element is visible') - notOk(el.find('input[name=hidden]').get(0), 'element with skipRendering is not shown') + assert.ok(el.find('input[name=shown]').get(0), 'control element is visible') + assert.notOk(el.find('input[name=hidden]').get(0), 'element with skipRendering is not shown') }); diff --git a/public/assets/tests/form_sla_times.js b/public/assets/tests/qunit/form_sla_times.js similarity index 62% rename from public/assets/tests/form_sla_times.js rename to public/assets/tests/qunit/form_sla_times.js index 0c1518ed0..65a4fd905 100644 --- a/public/assets/tests/form_sla_times.js +++ b/public/assets/tests/qunit/form_sla_times.js @@ -1,4 +1,4 @@ -test("form SLA times highlights first row and sets 2:00 by default for new item", function(assert) { +QUnit.test("form SLA times highlights first row and sets 2:00 by default for new item", function(assert) { $('#forms').append('

        SLA with defaults

        ') var el = $('#form1') @@ -13,8 +13,8 @@ test("form SLA times highlights first row and sets 2:00 by default for new item" var row = el.find('.sla_times tbody > tr:first') - ok(row.hasClass('is-active')) - equal(row.find('input[data-name=first_response_time]').val(), '02:00') + assert.ok(row.hasClass('is-active')) + assert.equal(row.find('input[data-name=first_response_time]').val(), '02:00') $('#forms').append('

        SLA with empty times

        ') @@ -31,11 +31,11 @@ test("form SLA times highlights first row and sets 2:00 by default for new item" var row = el.find('.sla_times tbody > tr:first') - notOk(row.hasClass('is-active')) - equal(row.find('input[data-name=first_response_time]').val(), '') + assert.notOk(row.hasClass('is-active')) + assert.equal(row.find('input[data-name=first_response_time]').val(), '') }); -test("form SLA times highlights and shows settings accordingly", function(assert) { +QUnit.test("form SLA times highlights and shows settings accordingly", function(assert) { $('#forms').append('

        SLA with non-first time set

        ') var el = $('#form3') @@ -53,13 +53,13 @@ test("form SLA times highlights and shows settings accordingly", function(assert var firstRow = el.find('.sla_times tbody > tr:first') var secondRow = el.find('.sla_times tbody > tr:nth-child(2)') - notOk(firstRow.hasClass('is-active')) - equal(firstRow.find('input[data-name=first_response_time]').val(), '') - ok(secondRow.hasClass('is-active')) - equal(secondRow.find('input[data-name=update_time]').val(), '04:00') + assert.notOk(firstRow.hasClass('is-active')) + assert.equal(firstRow.find('input[data-name=first_response_time]').val(), '') + assert.ok(secondRow.hasClass('is-active')) + assert.equal(secondRow.find('input[data-name=update_time]').val(), '04:00') }) -test("form SLA times clears field instead of 00:00", function(assert) { +QUnit.test("form SLA times clears field instead of 00:00", function(assert) { $('#forms').append('

        SLA placeholder instead of 00:00

        ') var el = $('#form5') @@ -77,5 +77,5 @@ test("form SLA times clears field instead of 00:00", function(assert) { input.val('asd').blur() - equal(input.val(), '', 'shows placeholder') + assert.equal(input.val(), '', 'shows placeholder') }); diff --git a/public/assets/tests/form_ticket_perform_action.js b/public/assets/tests/qunit/form_ticket_perform_action.js similarity index 88% rename from public/assets/tests/form_ticket_perform_action.js rename to public/assets/tests/qunit/form_ticket_perform_action.js index 685a39e80..737e31387 100644 --- a/public/assets/tests/form_ticket_perform_action.js +++ b/public/assets/tests/qunit/form_ticket_perform_action.js @@ -1,5 +1,5 @@ // ticket_perform_action -test( "ticket_perform_action check", function(assert) { +QUnit.test( "ticket_perform_action check", assert => { App.TicketPriority.refresh([ { @@ -120,7 +120,7 @@ test( "ticket_perform_action check", function(assert) { } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // add email notification $('[data-attribute-name="ticket_perform_action3"] .js-add').click() @@ -164,7 +164,7 @@ test( "ticket_perform_action check", function(assert) { } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // remove recipient $('[data-attribute-name="ticket_perform_action2"] .js-setNotification .js-recipient .js-remove.js-option[data-value="ticket_owner"]').click() @@ -204,7 +204,7 @@ test( "ticket_perform_action check", function(assert) { } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // set notification to internal $('[data-attribute-name="ticket_perform_action2"] .js-internal select').val('true').trigger('change') @@ -244,7 +244,7 @@ test( "ticket_perform_action check", function(assert) { } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') // add pending time $('[data-attribute-name="ticket_perform_action3"] .js-add').last().click() @@ -302,7 +302,7 @@ test( "ticket_perform_action check", function(assert) { setTimeout(function(){ params = App.ControllerForm.params(el) - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') done() }, 0); @@ -352,11 +352,11 @@ test( "ticket_perform_action check", function(assert) { } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); // Test for backwards compatibility after issue is fixed https://github.com/zammad/zammad/issues/2782 -test( "ticket_perform_action backwards check after issue #2782", function() { +QUnit.test( "ticket_perform_action backwards check after issue #2782", assert => { $('#forms').append('

        ticket_perform_action check

        ') var el = $('#form2') @@ -401,10 +401,10 @@ test( "ticket_perform_action backwards check after issue #2782", function() { } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test( "ticket_perform_action rows manipulation", function() { +QUnit.test( "ticket_perform_action rows manipulation", assert => { App.TicketPriority.refresh([ { id: 2, @@ -461,29 +461,29 @@ test( "ticket_perform_action rows manipulation", function() { autofocus: true }) - equal(true, true) + assert.equal(true, true) var selector = '[data-attribute-name="ticket_perform_action99"] ' $(selector + '.js-remove').click() - equal($(selector + '.js-filterElement').length, 1, 'prevents removing single initial row') + assert.equal($(selector + '.js-filterElement').length, 1, 'prevents removing single initial row') $(selector + '.js-add').click() - equal($(selector + '.js-filterElement').length, 2, 'adds 2nd row') + assert.equal($(selector + '.js-filterElement').length, 2, 'adds 2nd row') $(selector + ' .js-remove:last').click() - equal($(selector + '.js-filterElement').length, 1, 'removes 2nd row') + assert.equal($(selector + '.js-filterElement').length, 1, 'removes 2nd row') $(selector + '.js-remove:last').click() - equal($(selector + ' .js-filterElement').length, 1, 'prevents removing last row') + assert.equal($(selector + ' .js-filterElement').length, 1, 'prevents removing last row') }); // Test for backwards compatibility after PR https://github.com/zammad/zammad/pull/2862 -test( "ticket_perform_action backwards check after PR#2862", function() { +QUnit.test( "ticket_perform_action backwards check after PR#2862", assert => { $('#forms').append('

        ticket_perform_action check

        ') var el = $('#form3') @@ -522,10 +522,10 @@ test( "ticket_perform_action backwards check after PR#2862", function() { } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test( "ticket_perform_action orphan time fields", function() { +QUnit.test( "ticket_perform_action orphan time fields", assert => { $('#forms').append('

        ticket_perform_action orphan time fields

        ') var el = $('#form4') @@ -558,10 +558,10 @@ test( "ticket_perform_action orphan time fields", function() { // change to another attribute el.find('select:first').val('ticket.tags').trigger('change') - equal(el.find('.js-valueRangeSelector').length, 0) + assert.equal(el.find('.js-valueRangeSelector').length, 0) }); -test( "ticket_perform_action check possible owner selection", function() { +QUnit.test( "ticket_perform_action check possible owner selection", assert => { $('#forms').append('

        ticket_perform_action check possible owner selection

        ') var el = $('#form5') @@ -601,7 +601,7 @@ test( "ticket_perform_action check possible owner selection", function() { } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') el.find('[name="ticket_perform_action5::ticket.owner_id::pre_condition"]').val('specific').trigger('change') @@ -616,11 +616,11 @@ test( "ticket_perform_action check possible owner selection", function() { } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -test( "ticket_perform_action check when there's no available webhook", function() { +QUnit.test( "ticket_perform_action check when there's no available webhook", assert => { $('#forms').append('

        ticket_perform_action check when there\'s no available webhook

        ') var el = $('#form6') @@ -649,14 +649,14 @@ test( "ticket_perform_action check when there's no available webhook", function( }) var params = App.ControllerForm.params(el) - deepEqual(params, {}, 'form param check') + assert.deepEqual(params, {}, 'form param check') var testNoticeMessage = 'No available webhook, please create a new one or activate an existing one at "Manage > Webhook"' var noticeMessage = el.find('.controls.js-webhooks div').text() - equal(noticeMessage, testNoticeMessage, 'form shows message when webhook is not available') + assert.equal(noticeMessage, testNoticeMessage, 'form shows message when webhook is not available') }); -test( "ticket_perform_action check when there's an available webhook", function() { +QUnit.test( "ticket_perform_action check when there's an available webhook", assert => { $('#forms').append('

        ticket_perform_action check when there\'s an available webhook

        ') var el = $('#form7') @@ -702,12 +702,12 @@ test( "ticket_perform_action check when there's an available webhook", function( } } } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') var testNoticeMessage = 'No available webhook, please create a new one or activate an existing one at "Manage > Webhook"' var noticeMessage = el.find('.controls.js-webhooks').text() - notEqual(noticeMessage, testNoticeMessage, 'form does not show notice message when webhook is available') + assert.notEqual(noticeMessage, testNoticeMessage, 'form does not show notice message when webhook is available') var noticeMessage = el.find('.controls.js-webhooks select option').eq(1).text() - equal(noticeMessage, 'Webhook test (https://target.example.com/webhook)', 'form shows available webhook when webhook is available') + assert.equal(noticeMessage, 'Webhook test (https://target.example.com/webhook)', 'form shows available webhook when webhook is available') }); diff --git a/public/assets/tests/form_timer.js b/public/assets/tests/qunit/form_timer.js similarity index 87% rename from public/assets/tests/form_timer.js rename to public/assets/tests/qunit/form_timer.js index e799ea041..acc2801d1 100644 --- a/public/assets/tests/form_timer.js +++ b/public/assets/tests/qunit/form_timer.js @@ -1,5 +1,4 @@ - -test("form elements check", function() { +QUnit.test("form elements check", assert => { $('#forms').append('

        form elements check

        ') var el = $('#form1') @@ -16,7 +15,7 @@ test("form elements check", function() { autofocus: true }); - equal('Run every Monday at 00:00 in UTC time', el.find('.js-timerResult').text()) + assert.equal('Run every Monday at 00:00 in UTC time', el.find('.js-timerResult').text()) var params = App.ControllerForm.params(el) var test_params = { @@ -67,7 +66,7 @@ test("form elements check", function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('#forms').append('

        form elements check

        ') var el = $('#form2') @@ -101,7 +100,7 @@ test("form elements check", function() { autofocus: true }); - equal('Run every Monday and Friday at 00:00, 00:10, 00:50, 10:00, 10:10, 10:50, 16:00, 16:10 and 16:50 in UTC time', el.find('.js-timerResult').text()) + assert.equal('Run every Monday and Friday at 00:00, 00:10, 00:50, 10:00, 10:10, 10:50, 16:00, 16:10 and 16:50 in UTC time', el.find('.js-timerResult').text()) var params = App.ControllerForm.params(el) var test_params = { @@ -152,13 +151,13 @@ test("form elements check", function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('#form2 .js-day [data-value="Sat"]').click() $('#form2 .js-hour [data-value="16"]').click() $('#form2 .js-minute [data-value="10"]').click() - equal('Run every Monday, Friday and Saturday at 00:00, 00:50, 10:00 and 10:50 in UTC time', el.find('.js-timerResult').text()) + assert.equal('Run every Monday, Friday and Saturday at 00:00, 00:50, 10:00 and 10:50 in UTC time', el.find('.js-timerResult').text()) var params = App.ControllerForm.params(el) var test_params = { @@ -209,6 +208,6 @@ test("form elements check", function() { }, }, } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); diff --git a/public/assets/tests/form_tree_select.js b/public/assets/tests/qunit/form_tree_select.js similarity index 87% rename from public/assets/tests/form_tree_select.js rename to public/assets/tests/qunit/form_tree_select.js index a19f2de47..51110e74d 100644 --- a/public/assets/tests/form_tree_select.js +++ b/public/assets/tests/qunit/form_tree_select.js @@ -1,4 +1,4 @@ -test("form elements check", function() { +QUnit.test("form elements check", assert => { $('#forms').append('

        form elements check

        ') var el = $('#form1') new App.ControllerForm({ @@ -54,13 +54,13 @@ test("form elements check", function() { }, autofocus: true }); - equal(el.find('[name="tree_select"]').val(), '', 'check tree_select value'); - equal(el.find('[name="tree_select"]').closest('.searchableSelect').find('.js-input').val(), '', 'check tree_select .js-input value'); + assert.equal(el.find('[name="tree_select"]').val(), '', 'check tree_select value'); + assert.equal(el.find('[name="tree_select"]').closest('.searchableSelect').find('.js-input').val(), '', 'check tree_select .js-input value'); var params = App.ControllerForm.params(el) var test_params = { tree_select: '' } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('#forms').append('

        form elements check

        ') var el = $('#form2') @@ -119,13 +119,13 @@ test("form elements check", function() { autofocus: true }); - equal(el.find('[name="tree_select"]').val(), 'aa', 'check tree_select value'); - equal(el.find('[name="tree_select"]').closest('.searchableSelect').find('.js-input').val(), 'yes', 'check tree_select .js-input value'); + assert.equal(el.find('[name="tree_select"]').val(), 'aa', 'check tree_select value'); + assert.equal(el.find('[name="tree_select"]').closest('.searchableSelect').find('.js-input').val(), 'yes', 'check tree_select .js-input value'); var params = App.ControllerForm.params(el) var test_params = { tree_select: 'aa' } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('#forms').append('

        form elements check

        ') var el = $('#form3') @@ -183,13 +183,13 @@ test("form elements check", function() { }, autofocus: true }); - equal(el.find('[name="tree_select"]').val(), 'aa::aab', 'check tree_select value'); - equal(el.find('[name="tree_select"]').closest('.searchableSelect').find('.js-input').val(), 'yes2', 'check tree_select .js-input value'); + assert.equal(el.find('[name="tree_select"]').val(), 'aa::aab', 'check tree_select value'); + assert.equal(el.find('[name="tree_select"]').closest('.searchableSelect').find('.js-input').val(), 'yes2', 'check tree_select .js-input value'); var params = App.ControllerForm.params(el) var test_params = { tree_select: 'aa::aab' } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') $('#forms').append('

        form elements check

        ') var el = $('#form4') @@ -265,13 +265,12 @@ test("form elements check", function() { var test_params = { tree_select_search: ['aa::aab', 'aa::aac::33', 'bb'], } - deepEqual(params, test_params, 'form param check') + assert.deepEqual(params, test_params, 'form param check') }); -asyncTest("searchable_select submenu and option list check", function() { - expect(3); - +QUnit.test("searchable_select submenu and option list check", assert => { + var done = assert.async() $('#forms').append('

        form elements check

        ') var el = $('#form5') @@ -344,10 +343,11 @@ asyncTest("searchable_select submenu and option list check", function() { var optionsList = el.find(".searchableSelect .js-optionsList") setTimeout( () => { - deepEqual(params, test_params, 'form param check') - equal(optionsSubmenu.is('[hidden]'), false, 'options submenu menu not hidden') - equal(optionsList.is('[hidden]'), true, 'options list is hidden') - start(); + assert.deepEqual(params, test_params, 'form param check') + assert.equal(optionsSubmenu.is('[hidden]'), false, 'options submenu menu not hidden') + assert.equal(optionsList.is('[hidden]'), true, 'options list is hidden') + + done() }, 300) }); diff --git a/public/assets/tests/form_trim.js b/public/assets/tests/qunit/form_trim.js similarity index 81% rename from public/assets/tests/form_trim.js rename to public/assets/tests/qunit/form_trim.js index d2ee3875e..98a3f1b38 100644 --- a/public/assets/tests/form_trim.js +++ b/public/assets/tests/qunit/form_trim.js @@ -1,5 +1,5 @@ -test( 'form trim checks', function() { +QUnit.test( 'form trim checks', assert => { var el = $('#form1') var test_params = { @@ -28,6 +28,6 @@ test( 'form trim checks', function() { var params = App.ControllerForm.params( el ) - deepEqual( params, test_params, 'form param check' ) + assert.deepEqual( params, test_params, 'form param check' ) }) diff --git a/public/assets/tests/form_validation.js b/public/assets/tests/qunit/form_validation.js similarity index 57% rename from public/assets/tests/form_validation.js rename to public/assets/tests/qunit/form_validation.js index 870e92180..9484346c0 100644 --- a/public/assets/tests/form_validation.js +++ b/public/assets/tests/qunit/form_validation.js @@ -1,4 +1,4 @@ -test('form validation check', function() { +QUnit.test('form validation check', assert => { $('#forms').append('

        form params check

        ') @@ -22,27 +22,27 @@ test('form validation check', function() { }, params: defaults, }); - equal(el.find('[name="input1"]').val(), '', 'check input1 value') - equal(el.find('[name="input1"]').prop('required'), true, 'check input1 required') -// equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') + assert.equal(el.find('[name="input1"]').val(), '', 'check input1 value') + assert.equal(el.find('[name="input1"]').prop('required'), true, 'check input1 required') +// assert.equal(el.find('[name="input1"]').is(":focus"), true, 'check input1 focus') - equal(el.find('[name="password1"]').val(), '', 'check password1 value') - equal(el.find('[name="password1_confirm"]').val(), '', 'check password1 value') - equal(el.find('[name="password1"]').prop('required'), true, 'check password1 required') + assert.equal(el.find('[name="password1"]').val(), '', 'check password1 value') + assert.equal(el.find('[name="password1_confirm"]').val(), '', 'check password1 value') + assert.equal(el.find('[name="password1"]').prop('required'), true, 'check password1 required') - equal(el.find('[name="textarea1"]').val(), '', 'check textarea1 value') - equal(el.find('[name="textarea1"]').prop('required'), true, 'check textarea1 required') + assert.equal(el.find('[name="textarea1"]').val(), '', 'check textarea1 value') + assert.equal(el.find('[name="textarea1"]').prop('required'), true, 'check textarea1 required') - equal(el.find('[name="select1"]').val(), '', 'check select1 value') - equal(el.find('[name="select1"]').prop('required'), true, 'check select1 required') + assert.equal(el.find('[name="select1"]').val(), '', 'check select1 value') + assert.equal(el.find('[name="select1"]').prop('required'), true, 'check select1 required') - equal(el.find('[name="selectmulti1"]').val(), '', 'check selectmulti1 value') - equal(el.find('[name="selectmulti1"]').prop('required'), true, 'check selectmulti1 required') + assert.equal(el.find('[name="selectmulti1"]').val(), '', 'check selectmulti1 value') + assert.equal(el.find('[name="selectmulti1"]').prop('required'), true, 'check selectmulti1 required') - equal(el.find('[name="autocompletion1"]').val(), '', 'check autocompletion1 value') - equal(el.find('[name="autocompletion1"]').prop('required'), true, 'check autocompletion1 required') + assert.equal(el.find('[name="autocompletion1"]').val(), '', 'check autocompletion1 value') + assert.equal(el.find('[name="autocompletion1"]').prop('required'), true, 'check autocompletion1 required') - equal(el.find('[data-name="richtext1"]').val(), '', 'check richtext1 value') + assert.equal(el.find('[data-name="richtext1"]').val(), '', 'check richtext1 value') //equal(el.find('[data-name="richtext1"]').prop('required'), true, 'check richtext1 required') params = App.ControllerForm.params(el) @@ -59,40 +59,40 @@ test('form validation check', function() { datetime1: 'is required', date1: 'is required', } - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) - equal(el.find('[name="input1"]').closest('.form-group').hasClass('has-error'), true, 'check input1 has-error') - equal(el.find('[name="input1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check input1 error message') + assert.equal(el.find('[name="input1"]').closest('.form-group').hasClass('has-error'), true, 'check input1 has-error') + assert.equal(el.find('[name="input1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check input1 error message') - equal(el.find('[name="password1"]').closest('.form-group').hasClass('has-error'), true, 'check password1 has-error') - equal(el.find('[name="password1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check password1 error message') + assert.equal(el.find('[name="password1"]').closest('.form-group').hasClass('has-error'), true, 'check password1 has-error') + assert.equal(el.find('[name="password1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check password1 error message') - equal(el.find('[name="textarea1"]').closest('.form-group').hasClass('has-error'), true, 'check textarea1 has-error') - equal(el.find('[name="textarea1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check textarea1 error message') + assert.equal(el.find('[name="textarea1"]').closest('.form-group').hasClass('has-error'), true, 'check textarea1 has-error') + assert.equal(el.find('[name="textarea1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check textarea1 error message') - equal(el.find('[name="select1"]').closest('.form-group').hasClass('has-error'), true, 'check select1 has-error') - equal(el.find('[name="select1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check select1 error message') + assert.equal(el.find('[name="select1"]').closest('.form-group').hasClass('has-error'), true, 'check select1 has-error') + assert.equal(el.find('[name="select1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check select1 error message') - equal(el.find('[name="selectmulti1"]').closest('.form-group').hasClass('has-error'), true, 'check selectmulti1 has-error') - equal(el.find('[name="selectmulti1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check selectmulti1 error message') + assert.equal(el.find('[name="selectmulti1"]').closest('.form-group').hasClass('has-error'), true, 'check selectmulti1 has-error') + assert.equal(el.find('[name="selectmulti1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check selectmulti1 error message') - equal(el.find('[name="autocompletion1"]').closest('.form-group').hasClass('has-error'), true, 'check autocompletion1 has-error') - equal(el.find('[name="autocompletion1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check autocompletion1 error message') + assert.equal(el.find('[name="autocompletion1"]').closest('.form-group').hasClass('has-error'), true, 'check autocompletion1 has-error') + assert.equal(el.find('[name="autocompletion1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check autocompletion1 error message') - equal(el.find('[data-name="richtext1"]').closest('.form-group').hasClass('has-error'), true, 'check richtext1 has-error') - equal(el.find('[data-name="richtext1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check richtext1 error message') + assert.equal(el.find('[data-name="richtext1"]').closest('.form-group').hasClass('has-error'), true, 'check richtext1 has-error') + assert.equal(el.find('[data-name="richtext1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check richtext1 error message') - equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true, 'check datetime1 has-error') - equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check datetime1 error message') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true, 'check datetime1 has-error') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check datetime1 error message') - equal(el.find('[data-name="date1"]').closest('.form-group').hasClass('has-error'), true, 'check date1 has-error') - equal(el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date1 error message') + assert.equal(el.find('[data-name="date1"]').closest('.form-group').hasClass('has-error'), true, 'check date1 has-error') + assert.equal(el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date1 error message') }); -test('datetime validation check', function() { +QUnit.test('datetime validation check', assert => { $('#forms').append('

        datetime validation check

        ') @@ -113,17 +113,17 @@ test('datetime validation check', function() { test_params = { datetime1: null, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') errors = form.validate(params) test_errors = { datetime1: 'is required', } - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) - equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true, 'check datetime1 has-error') - equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check datetime1 error message') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true, 'check datetime1 has-error') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check datetime1 error message') //equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message') // set new values @@ -139,38 +139,38 @@ test('datetime validation check', function() { test_params = { datetime1: timeStamp.toISOString(), } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') // check errors errors = form.validate(params) test_errors = undefined - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) - equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), false, 'check datetime1 has-error') - equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), false, 'check datetime1 has-error') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message') el.find('[data-name="datetime1"] [data-item="date"]').val('').trigger('blur') el.find('[data-name="datetime1"] [data-item="date"]').datepicker('setDate') el.find('[data-name="datetime1"] [data-item="time"]').val('12:42').trigger('blur') el.find('[data-name="datetime1"] [data-item="time"]').trigger('change') - equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true ) + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true ) params = App.ControllerForm.params(el) errors = form.validate(params) test_errors = { datetime1: 'is required', } - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) - equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true, 'check datetime1 no has-error') - equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check datetime1 error message') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true, 'check datetime1 no has-error') + assert.equal(el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check datetime1 error message') }); -test('date validation check', function() { +QUnit.test('date validation check', assert => { $('#forms').append('

        date validation check

        ') @@ -193,17 +193,17 @@ test('date validation check', function() { test_params = { date2: null, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') errors = form.validate(params) test_errors = { date2: 'is required', } - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) - equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error') - equal(el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date2 error message') + assert.equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error') + assert.equal(el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date2 error message') // set new values el.find('[data-name="date2"] [data-item="date"]').val('01/01/2015').trigger('blur') @@ -215,42 +215,42 @@ test('date validation check', function() { test_params = { date2: '2015-01-01', } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') // check errors errors = form.validate(params) test_errors = undefined - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) - equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), false, 'check date1 has-error') - equal(el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), '', 'check date1 error message') + assert.equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), false, 'check date1 has-error') + assert.equal(el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), '', 'check date1 error message') // set invalid values el.find('[data-name="date2"] [data-item="date"]').val('').trigger('blur') el.find('[data-name="date2"] [data-item="date"]').datepicker('setDate') el.find('[data-name="date2"] [data-item="date"]').trigger('change') - equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error') + assert.equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error') // check params params = App.ControllerForm.params(el) test_params = { date2: null, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') // check errors errors = form.validate(params) test_errors = { date2: 'is required', } - deepEqual(errors, test_errors, 'validation errors check') + assert.deepEqual(errors, test_errors, 'validation errors check') App.ControllerForm.validate({ errors: errors, form: el }) - equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error') - equal(el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date2 error message') + assert.equal(el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error') + assert.equal(el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date2 error message') }); -test( "datetime selector check", function() { +QUnit.test( "datetime selector check", assert => { $('#forms').append('

        datetime selector check

        ') @@ -273,7 +273,7 @@ test( "datetime selector check", function() { datetime1: null, datetime2: null, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') var timeStamp1 = new Date() timeStamp1.setMinutes(0) @@ -290,7 +290,7 @@ test( "datetime selector check", function() { datetime1: timeStamp1.toISOString(), datetime2: null, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') el.find('[data-name="datetime1"] .js-timepicker[data-item="time"]').val('9:00') el.find('[data-name="datetime1"] .js-timepicker[data-item="time"]').trigger('blur') @@ -303,7 +303,7 @@ test( "datetime selector check", function() { datetime1: timeStamp1.toISOString(), datetime2: null, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') var timeStamp2 = new Date() timeStamp2.setMinutes(0) @@ -322,7 +322,7 @@ test( "datetime selector check", function() { datetime1: timeStamp1.toISOString(), datetime2: timeStamp2.toISOString(), } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') // Regression test for issue #2173 - Invalid date causes errors el.find('[data-name="datetime1"] .js-datepicker').datepicker('setDate', '01/01/99999') @@ -330,7 +330,7 @@ test( "datetime selector check", function() { el.find('[data-name="datetime1"] .js-datepicker').datepicker('setDate', '01/01/1äöüß') }); -test( "date selector check", function() { +QUnit.test( "date selector check", assert => { $('#forms').append('

        date selector check

        ') @@ -351,7 +351,7 @@ test( "date selector check", function() { test_params = { date3: null, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') timeStamp = new Date() @@ -371,6 +371,6 @@ test( "date selector check", function() { test_params = { date3: currentTime, } - deepEqual(params, test_params, 'params check') + assert.deepEqual(params, test_params, 'params check') -}); \ No newline at end of file +}); diff --git a/public/assets/tests/html_utils.js b/public/assets/tests/qunit/html_utils.js similarity index 88% rename from public/assets/tests/html_utils.js rename to public/assets/tests/qunit/html_utils.js index 1835a895f..ee77d5112 100644 --- a/public/assets/tests/html_utils.js +++ b/public/assets/tests/qunit/html_utils.js @@ -1,1055 +1,1055 @@ window.onload = function() { // textCleanup -test("textCleanup", function() { +QUnit.test("textCleanup", assert => { var source = "Some\nValue\n\n\nTest" var should = "Some\nValue\n\nTest" var result = App.Utils.textCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\nValue\n\n \n\n\nTest" should = "Some\nValue\n\nTest" result = App.Utils.textCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\n\rValue\n\r\n\r\n\rTest" should = "Some\nValue\n\nTest" result = App.Utils.textCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\n\rValue\n\r\n\r\n\rTest\r" should = "Some\nValue\n\nTest" result = App.Utils.textCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\r\nValue\r\n\r\n\r\nTest\r\n" should = "Some\nValue\n\nTest" result = App.Utils.textCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\r\nValue\r\n\r\n\r\n\r\n\r\n\r\nTest\r\n" should = "Some\nValue\n\nTest" result = App.Utils.textCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "> Welcome!\n> \n> Thank you for installing Zammad.\n> \n> You will find ..." should = "> Welcome!\n>\n> Thank you for installing Zammad.\n>\n> You will find ..." result = App.Utils.textCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) }); // text2html -test("text2html", function() { +QUnit.test("text2html", assert => { var source = "Some\nValue\n\n\nTest" var should = "
        Some
        Value

        Test
        " var result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\nValue\n" should = "
        Some
        Value
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\nValue\n" should = "
        Some
        <b>Value</b>
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "> Welcome!\n> \n> Thank you for installing Zammad.\n> \n> You will find ..." should = "
        > Welcome!
        >
        > Thank you for installing Zammad.
        >
        > You will find ...
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\nValue\n" should = "
        Some
        Value
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\rValue\r" should = "
        Some
        Value
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\n\rValue\n\r" should = "
        Some
        Value
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\r\nValue\r\n" should = "
        Some
        Value
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some Value 123" should = "
        Some   Value 123
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Some\n Value\n 123" should = "
        Some
          Value
           123
        " result = App.Utils.text2html(source) - equal(result, should, source) + assert.equal(result, should, source) }); // htmlStrip -test("htmlStrip", function() { +QUnit.test("htmlStrip", assert => { var source = $('

        lala
        ') var should = '
        lala
        ' App.Utils.htmlStrip(source) - equal(source.get(0).outerHTML, should) + assert.equal(source.get(0).outerHTML, should) source = $('



        lala
        ') should = '
        lala
        ' App.Utils.htmlStrip(source) - equal(source.get(0).outerHTML, should) + assert.equal(source.get(0).outerHTML, should) source = $('



        lala

        ') should = '
        lala
        ' App.Utils.htmlStrip(source) - equal(source.get(0).outerHTML, should) + assert.equal(source.get(0).outerHTML, should) source = $('



        lala

        ') should = '

        lala
        ' App.Utils.htmlStrip(source) - equal(source.get(0).outerHTML, should) + assert.equal(source.get(0).outerHTML, should) }); // lastLineEmpty -test("htmlLastLineEmpty", function() { +QUnit.test("htmlLastLineEmpty", assert => { var source = $('

        lala
        ') - equal(App.Utils.htmlLastLineEmpty(source), false) + assert.equal(App.Utils.htmlLastLineEmpty(source), false) source = $('

        lala
        ') - equal(App.Utils.htmlLastLineEmpty(source), true) + assert.equal(App.Utils.htmlLastLineEmpty(source), true) }); // html2text -test("html2text", function() { +QUnit.test("html2text", assert => { var source = "
        Some
        Value

        Test
        " var should = "Some\nValue\n\nTest" var result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        Some
        Value
        " should = "Some\nValue" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        Some
        Value
        " should = "Some\nValue" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        Some & <Value>
        " should = "Some & " result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        Some
        <b>Value</b>
        " should = "Some\nValue" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        > Welcome!
        >
        > Thank you for installing Zammad.
        >
        > You will find ...
        " should = "> Welcome!\n>\n> Thank you for installing Zammad.\n>\n> You will find ..." result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        test 123










        --
        Bob Smith
        " should = "test 123 \n\n--\nBob Smith" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "test 123










        --
        Bob Smith" should = "test 123 \n\n--\nBob Smith" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        1









        Von: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        \n
        Gesendet: Donnerstag, 2. April 2015 11:32
        " should = "1\n\nVon: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]\nGesendet: Donnerstag, 2. April 2015 11:32" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "
        test 123
        lalala

        --

        some test
        " should = "test 123\nlalala\n--\nsome test" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) source = "

        Was\nsoll verbessert werden:

        " should = "Was soll verbessert werden:" result = App.Utils.html2text(source) - equal(result, should, source) + assert.equal(result, should, source) // in raw format, without cleanup source = "
        Some
        1234
        " should = "Some\n1234\n" result = App.Utils.html2text(source, true) - equal(result, should, source) + assert.equal(result, should, source) source = "
        Some
        1234
        " should = "Some\n 1234\n" result = App.Utils.html2text(source, true) - equal(result, should, source) + assert.equal(result, should, source) source = "\n\n
        Some
        \n
        1234
        " should = "Some\n 1234\n" result = App.Utils.html2text(source, true) - equal(result, should, source) + assert.equal(result, should, source) source = "
        Some
        1234
        " should = "Some\n 1234\n" result = App.Utils.html2text(source, true) - equal(result, should, source) + assert.equal(result, should, source) source = "
        Some
        \n\n
        1234
        \n" should = "Some\n 1234\n" result = App.Utils.html2text(source, true) - equal(result, should, source) + assert.equal(result, should, source) source = "
        test
        new line
        " should = "test\nnew line\n\n" result = App.Utils.html2text(source, true) - equal(result, should, source) + assert.equal(result, should, source) source = "

        Was\nsoll verbessert werden:

        " should = "Was soll verbessert werden:\n" result = App.Utils.html2text(source, true) - equal(result, should, source) + assert.equal(result, should, source) }); // phoneify -test("phoneify", function() { +QUnit.test("phoneify", assert => { var source = "+1 123 123 123-123" var should = 'tel:+1123123123123' var result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "+1 123 123 A 123-123<>" should = 'tel:+1123123123123' result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "+1 (123) 123 123-123" should = 'tel:+1123123123123' result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "+1 (123) 123 1#23-123" should = 'tel:+11231231#23123' result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "+1 (123) 12*3 1#23-123" should = 'tel:+112312*31#23123' result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "+1 (123) 12+3" should = 'tel:+1123123' result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "+1 (123) 123 " should = 'tel:+1123123' result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) source = " +1 (123) 123 " should = 'tel:+1123123' result = App.Utils.phoneify(source) - equal(result, should, source) + assert.equal(result, should, source) }) // linkify -test("linkify", function() { +QUnit.test("linkify", assert => { var source = "http://example.com" var should = 'http://example.com' var result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "http://example.com?some_param=lalala" should = 'http://example.com?some_param=lalala' result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "example.com" should = 'example.com' result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "some text example.com" should = 'some text example.com' result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "example.com some text" should = 'example.com some text' result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "test@example.com some text" should = 'test@example.com some text' result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) source = "abc test@example.com some text" should = 'abc test@example.com some text' result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) /* source = "example.com" should = 'http://example.com' result = App.Utils.linkify(source) - equal(result, should, source) + assert.equal(result, should, source) */ }); // htmlEscape -test("htmlEscape", function() { +QUnit.test("htmlEscape", assert => { var source = "<" var should = "<" var result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = ">" should = ">" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = "&" should = "&" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = "&" should = "&amp;" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = "& ;" should = "&amp ;" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = "& amp;" should = "& amp;" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = "'test'" should = "'test'" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = '"test"' should = ""test"" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = "<>" should = "<>" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) source = "<<>" should = "<&lt;>" result = App.Utils.htmlEscape(source) - equal(result, should, source) + assert.equal(result, should, source) }); // htmlRemoveTags -test("htmlRemoveTags", function() { +QUnit.test("htmlRemoveTags", assert => { var source = "
        test
        " //var should = "
        test
        " var should = "test" var result = App.Utils.htmlRemoveTags($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test
        " //should = "
        test
        " should = "test" result = App.Utils.htmlRemoveTags($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "some link to somewhere" should = "some link to somewhere" result = App.Utils.htmlRemoveTags($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "" //should = "
        some link to somewhere
        " should = "some link to somewhere" result = App.Utils.htmlRemoveTags($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "" //should = "
        some link to somewhere
        " should = "some link to somewhere" result = App.Utils.htmlRemoveTags($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "" //should = "
        some link to somewhere 123
        " should = "some link to somewhere 123 " result = App.Utils.htmlRemoveTags($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) }); // htmlRemoveRichtext -test("htmlRemoveRichtext", function() { +QUnit.test("htmlRemoveRichtext", assert => { source = "
        test 123
        " //should = "
        test 123
        " should = "test 123" result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        " //should = "
        test 123
        " should = "test 123" result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        test 123

        " should = "

        test 123

        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        This is some text!
        " should = "This is some text!" result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) should = "This is some text!" result = App.Utils.htmlRemoveRichtext(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) var source = "" //var should = "
        test
        " var should = "test" var result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        1.1.1     Description
        " //should = "
        1.1.1     Description
        " should = "1.1.1     Description" //should = '1.1.1 Description' result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "some link to somewhere" should = "some link to somewhere" result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test
        " //should = "
        test
        " should = " test " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test
        " //should = "
        test
        " should = " test " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test
        " //should = "
        test
        " should = "
        test
        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test
        " //should = "
        test
        " should = "
        test
        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test
        123
        " //should = "
        test
        123
        " should = "
        test
        123" //should = '
        test
        123' result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test
        " //should = "
        test
        " should = "
        test
        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        " //should = "
        test
        " should = " test " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        " //should = "

        " should = "
        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        " //should = "

        " should = "

        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test 123
        " //should = "
        test 123
        " should = "test 123" result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        \n" //should = "
        test 123
        " should = '
        Gruppe *
        Besitzer
        Status *
        ' result = App.Utils.htmlRemoveRichtext(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        This is some text!
        " should = "This is some text!" result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) should = "This is some text!" result = App.Utils.htmlRemoveRichtext(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) var source = "" var should = "
        test
        " var result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.get(0).outerHTML, should, source) + assert.equal(result.get(0).outerHTML, should, source) source = "
        some link to somewhere" should = "
        some link to somewhere
        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.get(0).outerHTML, should, source) + assert.equal(result.get(0).outerHTML, should, source) source = "

        " should = "

        " result = App.Utils.htmlRemoveRichtext($(source)) - equal(result.get(0).outerHTML, should, source) + assert.equal(result.get(0).outerHTML, should, source) source = "
        111aaa
        keyvalue
        " should = "
        111aaakeyvalue
        " result = App.Utils.htmlRemoveRichtext(source, true) - equal(result.get(0).outerHTML, should, source) + assert.equal(result.get(0).outerHTML, should, source) }); // htmlCleanup -test("htmlCleanup", function() { +QUnit.test("htmlCleanup", assert => { var source = "" //var should = "
        test
        " var should = "test" var result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "" should = "test" result = App.Utils.htmlCleanup(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "some link to somewhere" should = "some link to somewhere" result = App.Utils.htmlCleanup(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
      1. a
      2. b
      3. " should = "
      4. a
      5. b
      6. " result = App.Utils.htmlCleanup(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "some link to somewhere" should = "some link to somewhere" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        some link to somewhere

        " should = "some link to somewhere" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        some link to somewhere

        " should = "

        some link to somewhere

        " result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        some link to somewhere

        " should = "

        some link to somewhere

        " result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        some link to somewhere" //should = "
        some link to somewhere
        " should = "some link to somewhere" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        " //should = "
        some link to somewhere
        " should = "some link to somewhere" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        some h1 for somewhere


        " should = "

        some h1 for somewhere


        " result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        " //should = "

        " should = "
        " result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        " //should = "

        " should = "

        " result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test 123
        " //should = "
        test 123
        " should = "test 123" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test 123
        some other value
        " //should = "
        test 123 some other value
        " should = "test 123 some other value" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        test 123
        some other value
        " //should = "
        test 123 some other value
        " should = "test 123 some other value" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        This is some text!
        " //should = "
        This is some text!
        " should = "This is some text!" result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "

        some link to somewhere from wordabc

        " //should = "

        some link to somewhere from wordabc

        " should = '

        some link to somewhere from wordabc

        ' result = App.Utils.htmlCleanup($(source)) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        \n" //should = "
        test 123
        " should = '
        Gruppe *
        Besitzer
        Status *
        ' result = App.Utils.htmlCleanup(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n

        ·            \nTest 1

        \n\n

        ·            \nTest 2

        \n\n

        ·            \nTest 3

        \n\n

        ·            \nTest 4

        \n\n

        ·            \nTest5

        \n\n\n\n\n" should = "
        • Test 1
        • Test 2
        • Test 3
        • Test 4
        • Test5
        " result = App.Utils.htmlCleanup(source) - equal(result.html().trim(), should, source) + assert.equal(result.html().trim(), should, source) source = "\n\n\n \n \n \n \n\n\n

        1.\nGehe auf https://www.pferdiathek.ge

        \n


        \n\n

        \n

        2.\nMelde Dich mit folgende Zugangsdaten an:

        \n

        Benutzer:\nme@xxx.net

        \n

        Passwort:\nxxx.

        \n\n" should = "\n\n\n \n \n \n \n\n\n

        1.\nGehe auf https://www.pferdiathek.ge

        \n


        \n\n

        \n

        2.\nMelde Dich mit folgende Zugangsdaten an:

        \n

        Benutzer:\nme@xxx.net

        \n

        Passwort:\nxxx.

        \n\n" result = App.Utils.htmlCleanup(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        aaa
        value
        " should = "
        aaa
        value
        " result = App.Utils.htmlCleanup(source) - equal(result.get(0).outerHTML, should, source) + assert.equal(result.get(0).outerHTML, should, source) // strip out browser-inserted (broken) link (see https://github.com/zammad/zammad/issues/2019) source = "" should = "test" result = App.Utils.htmlCleanup(source) - equal(result.html(), should, source) + assert.equal(result.html(), should, source) source = "
        aaa
        value
        " should = "
        aaa
        value
        " result = App.Utils.htmlCleanup(source) result.get(0).outerHTML //equal(result.get(0).outerHTML, should, source) / string order is different on browsers - equal(result.first().attr('bgcolor'), 'green') - equal(result.first().attr('style'), 'color:red;') - equal(result.first().attr('aaa'), undefined) - equal(result.find('tr').first().attr('style'), 'margin-top:10px;') - equal(result.find('th').first().attr('colspan'), '2') - equal(result.find('th').first().attr('abc'), undefined) - equal(result.find('th').first().attr('style'), 'margin-top:12px;') + assert.equal(result.first().attr('bgcolor'), 'green') + assert.equal(result.first().attr('style'), 'color:red;') + assert.equal(result.first().attr('aaa'), undefined) + assert.equal(result.find('tr').first().attr('style'), 'margin-top:10px;') + assert.equal(result.find('th').first().attr('colspan'), '2') + assert.equal(result.find('th').first().attr('abc'), undefined) + assert.equal(result.find('th').first().attr('style'), 'margin-top:12px;') source = "
        aaa
        value
        " should = "
        aaa
        value
        " result = App.Utils.htmlCleanup(source) //equal(result.get(0).outerHTML, should, source) / string order is different on browsers - equal(result.first().attr('bgcolor'), 'green') - equal(result.first().attr('style'), 'color:red;') - equal(result.first().attr('aaa'), undefined) - equal(result.find('tr').first().attr('style'), undefined) - equal(result.find('th').first().attr('colspan'), '2') - equal(result.find('th').first().attr('abc'), undefined) - equal(result.find('th').first().attr('style'), undefined) + assert.equal(result.first().attr('bgcolor'), 'green') + assert.equal(result.first().attr('style'), 'color:red;') + assert.equal(result.first().attr('aaa'), undefined) + assert.equal(result.find('tr').first().attr('style'), undefined) + assert.equal(result.find('th').first().attr('colspan'), '2') + assert.equal(result.find('th').first().attr('abc'), undefined) + assert.equal(result.find('th').first().attr('style'), undefined) }); // wrap -test("wrap", function() { +QUnit.test("wrap", assert => { var source = "some text" var should = 'some text' var result = App.Utils.wrap(source) - equal(result, should, source) + assert.equal(result, should, source) source = "some text\nsome other text\n" should = "some text\nsome other text\n" result = App.Utils.wrap(source) - equal(result, should, source) + assert.equal(result, should, source) source = "some text with some line to wrap" should = "some text with\nsome line to\nwrap" result = App.Utils.wrap(source, 14) - equal(result, should, source) + assert.equal(result, should, source) source = "some text\nsome other text\n" should = "some text\nsome other text\n" result = App.Utils.wrap(source) - equal(result, should, source) + assert.equal(result, should, source) source = "1234567890 1234567890 1234567890 1234567890" should = "1234567890 1234567890 1234567890 1234567890" result = App.Utils.wrap(source) - equal(result, should, source) + assert.equal(result, should, source) source = "123456789012 123456789012 123456789012" should = "123456789012\n123456789012\n123456789012" result = App.Utils.wrap(source, 14) - equal(result, should, source) + assert.equal(result, should, source) }); // remove empty lines -test("remove empty lines", function() { +QUnit.test("remove empty lines", assert => { var source = "\ntest 123\n" var should = "test 123\n" var result = App.Utils.removeEmptyLines(source) - equal(result, should, source) + assert.equal(result, should, source) source = "\ntest\n\n123\n" should = "test\n123\n" result = App.Utils.removeEmptyLines(source) - equal(result, should, source) + assert.equal(result, should, source) }); // quote -test("quote", function() { +QUnit.test("quote", assert => { var source = "some text" var should = '> some text' var result = App.Utils.quote(source) - equal(result, should, source) + assert.equal(result, should, source) source = "some text\nsome other text\n" should = "> some text\n> some other text" result = App.Utils.quote(source) - equal(result, should, source) + assert.equal(result, should, source) source = "\n\nsome text\nsome other text\n \n" should = "> some text\n> some other text" result = App.Utils.quote(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Welcome!\n\nThank you for installing Zammad.\n\nYou will find ..." should = "> Welcome!\n>\n> Thank you for installing Zammad.\n>\n> You will find ..." result = App.Utils.quote(source) - equal(result, should, source) + assert.equal(result, should, source) source = "Welcome! Thank you for installing Zammad. You will find ..." should = "> Welcome! Thank you\n> for installing\n> Zammad. You will\n> find ..." result = App.Utils.quote(source, 20) - equal(result, should, source) + assert.equal(result, should, source) }); // check signature -test("check signature", function() { +QUnit.test("check signature", assert => { var message = "
        test 123
        " var signature = '
        --
        Some Signature
        some department
        ' var result = App.Utils.signatureCheck(message, signature) - equal(result, true) + assert.equal(result, true) message = "
        test 123
        --
        Some Signature
        some department\n
        " signature = '
        --
        Some Signature
        some department
        ' result = App.Utils.signatureCheck(message, signature) - equal(result, false) + assert.equal(result, false) message = "
        test 123
        --
        Some Signature\n
        some department\n
        " signature = '
        --
        Some Signature
        some department
        ' result = App.Utils.signatureCheck(message, signature) - equal(result, false) + assert.equal(result, false) message = "
        test 123
        --

        Some Signature

        \n

        some department
        \n

        \n
        " signature = '
        --
        Some Signature
        some department
        ' result = App.Utils.signatureCheck(message, signature) - equal(result, false) + assert.equal(result, false) message = "" signature = '
        --
        Some Signature
        some department
        ' result = App.Utils.signatureCheck(message, signature) - equal(result, true) + assert.equal(result, true) message = "" signature = "--\nSome Signature\nsome department" result = App.Utils.signatureCheck(message, signature) - equal(result, true) + assert.equal(result, true) }); // identify signature -test("identify signature by plaintext", function() { +QUnit.test("identify signature by plaintext", assert => { var message = "
        test 123
        " var should = '
        test 123
        ' var result = App.Utils.signatureIdentifyByPlaintext(message) - equal(result, should) + assert.equal(result, should) message = "
        test 123
        --
        Bob Smith
        " should = '
        test 123
        --
        Bob Smith
        ' result = App.Utils.signatureIdentifyByPlaintext(message) - equal(result, should) + assert.equal(result, should) message = "
        test 123
        1
        2
        3
        4
        5
        6
        7
        8
        9

        --
        Bob Smith
        " should = '
        test 123
        1
        2
        3
        4
        5
        6
        7
        8
        9

        --
        Bob Smith
        ' result = App.Utils.signatureIdentifyByPlaintext(message) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --no not match--
        --
        Bob Smith
        " should = '
        test 123

        --no not match--
        --
        Bob Smith
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --no not match--
        --
        Bob Smith
        " should = '
        test 123

        --no not match--
        --
        Bob Smith
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --
        Bob Smith




        --
        Bob Smith
        " should = '
        test 123

        --
        Bob Smith




        --
        Bob Smith
        ' //should = '
        test 123










        --
        Bob Smith




        --
        Bob Smith
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123
        test 123
        --
        Bob Smith
        " should = "
        test 123
        test 123
        --
        Bob Smith
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "

        test 123

        test 123

        --

        Bob Smith

        " should = "

        test 123

        test 123

        --

        Bob Smith

        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "Test reply to zammad

        Am 24.10.2016 18:55 schrieb "Android Support" <android-support@example.com>:

        >
        > Sehr geehrte Damen" should = "Test reply to zammad

        Am 24.10.2016 18:55 schrieb "Android Support" <android-support@example.com>:

        >
        > Sehr geehrte Damen" result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        < On 20 Oct 2016, at 12:23, Martin Edenhofer via Zammad Helpdesk wrote:
        " should = "
        < On 20 Oct 2016, at 12:23, Martin Edenhofer via Zammad Helpdesk wrote:
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // apple // en message = "
        test 123

        --no not match--

        Bob Smith
        On 01/04/15 10:55, Bob Smith wrote:
        lalala

        --

        some test
        " should = '
        test 123

        --no not match--

        Bob Smith
        On 01/04/15 10:55, Bob Smith wrote:
        lalala

        --

        some test
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // de message = "
        test 123

        --no not match--

        Bob Smith
        Am 03.04.2015 um 20:58 schrieb Bob Smith <bob@example.com>:
        lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        Am 03.04.2015 um 20:58 schrieb Bob Smith <bob@example.com>:
        lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // ms // en message = "
        test 123

        --no not match--

        Bob Smith
        From: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Sent: Donnerstag, 2. April 2015 10:00
        lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        From: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Sent: Donnerstag, 2. April 2015 10:00
        lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --no not match--

        Bob Smith
        From: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Sent: Donnerstag, 2. April 2015 10:00
        Subject: lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        From: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Sent: Donnerstag, 2. April 2015 10:00
        Subject: lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --no not match--

        Bob Smith
        From: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Sent: Donnerstag, 2. April 2015 10:00
        1
        2
        3
        4
        4
        Subject: lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        From: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Sent: Donnerstag, 2. April 2015 10:00
        1
        2
        3
        4
        4
        Subject: lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // de message = "
        test 123

        --no not match--

        Bob Smith
        Von: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Gesendet: Donnerstag, 2. April 2015 10:00
        Betreff: lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        Von: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Gesendet: Donnerstag, 2. April 2015 10:00
        Betreff: lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        1

        Von: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        \n
        Gesendet: Donnerstag, 2. April 2015 11:32
        " should = "
        1

        Von: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        \n
        Gesendet: Donnerstag, 2. April 2015 11:32
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        1

        Von: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        \n
        Gesendet: Donnerstag, 2. April 2015 11:32
        Betreff: lalala
        " should = "
        1

        Von: Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        \n
        Gesendet: Donnerstag, 2. April 2015 11:32
        Betreff: lalala
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        1

        Von: Martin Edenhofer via Znuny Support <mailto:support@znuny.inc>
        \n
        An: somebody
        Datum: Donnerstag, 2. April 2015 11:32
        Betreff: lalala
        " should = "
        1

        Von: Martin Edenhofer via Znuny Support <mailto:support@znuny.inc>
        \n
        An: somebody
        Datum: Donnerstag, 2. April 2015 11:32
        Betreff: lalala
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        Von: "Johannes Nickel via Znuny Projects" <projects@znuny.inc>
        An: \"Lisa Smith\" <lisa.smith@example.com>
        Gesendet: Donnerstag, 2. April 2015 10:11:12
        Betreff: Angebot Redundanz / Paket mit Silver Subscription [Ticket#424242]

        Hallo Frau Smith,
        " should = "
        Von: "Johannes Nickel via Znuny Projects" <projects@znuny.inc>
        An: \"Lisa Smith\" <lisa.smith@example.com>
        Gesendet: Donnerstag, 2. April 2015 10:11:12
        Betreff: Angebot Redundanz / Paket mit Silver Subscription [Ticket#424242]

        Hallo Frau Smith,
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) - message = "
        Hi Johannes,

        das Angebot für den halben Tag bitte an uns.
        Der Termin hat sich jetzt auf 10-12 Uhr verschoben, hab ich dir weitergeleitet.

        Viele Grüße
        Max

        > On 07 Oct 2015, at 11:55, Johannes Smith <smith@example.com <mailto:smith@example.com>> wrote:
        >
        > Hi,
        >
        > OK. Wer kriegt das Angebot? Ist das wirklich nur ein halber Tag?
        " - should = "
        Hi Johannes,

        das Angebot für den halben Tag bitte an uns.
        Der Termin hat sich jetzt auf 10-12 Uhr verschoben, hab ich dir weitergeleitet.

        Viele Grüße
        Max

        > On 07 Oct 2015, at 11:55, Johannes Smith <smith@example.com <mailto:smith@example.com>> wrote:
        >
        > Hi,
        >
        > OK. Wer kriegt das Angebot? Ist das wirklich nur ein halber Tag?
        " + message = "
        Hi Johannes,

        das Angebot für den halben Tag bitte an uns.
        Der Termin hat sich jetzt auf 10-12 Uhr verschoben, hab ich dir weitergeleitet.

        Viele Grüße
        Max

        > On 07 Oct 2015, at 11:55, Johannes Smith <smith@example.com <mailto:smith@example.com>> wrote:
        >
        > Hi,
        >
        > assert.OK. Wer kriegt das Angebot? Ist das wirklich nur ein halber Tag?
        " + should = "
        Hi Johannes,

        das Angebot für den halben Tag bitte an uns.
        Der Termin hat sich jetzt auf 10-12 Uhr verschoben, hab ich dir weitergeleitet.

        Viele Grüße
        Max

        > On 07 Oct 2015, at 11:55, Johannes Smith <smith@example.com <mailto:smith@example.com>> wrote:
        >
        > Hi,
        >
        > assert.OK. Wer kriegt das Angebot? Ist das wirklich nur ein halber Tag?
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "Dear Mr. Smith,

        it seems to be, dass Sie den AutoIncrement Nummerngenerator für Ihre ITSMChangeManagement Installation verwenden. Seit ABC 3.2 wird führend vor der sich in der Datei <ABC_CONFIG_Home>/war/log/ITSMChangeCounter.log  befindenden Zahl die SystemID (SysConfig) geschrieben. Dies ist ein Standardverhalten, dass auch bei der Ticketnummer verwendet wird.

        Please ask me if you have questions.

        Viele Grüße,
          Thorsten Smith\n
        \n
        --\n
        Enterprise Services for ABC\n
        \n
        Znuny GmbH // Marienstraße 11 // 10117 Berlin // Germany\n
        \n
        P: +49 (0) 30 111 111 111-0\n
        F: +49 (0) 30 111 111 111-8\n
        W: http://znuny.com \n
        \n
        Location: Berlin - HRB 12345678 B Amtsgericht Berlin-Charlottenburg\n
        Managing Director: Martin Edenhofer\n
        " should = "Dear Mr. Smith,

        it seems to be, dass Sie den AutoIncrement Nummerngenerator für Ihre ITSMChangeManagement Installation verwenden. Seit ABC 3.2 wird führend vor der sich in der Datei <ABC_CONFIG_Home>/war/log/ITSMChangeCounter.log  befindenden Zahl die SystemID (SysConfig) geschrieben. Dies ist ein Standardverhalten, dass auch bei der Ticketnummer verwendet wird.

        Please ask me if you have questions.

        Viele Grüße,
          Thorsten Smith\n
        \n
        --\n
        Enterprise Services for ABC\n
        \n
        Znuny GmbH // Marienstraße 11 // 10117 Berlin // Germany\n
        \n
        P: +49 (0) 30 111 111 111-0\n
        F: +49 (0) 30 111 111 111-8\n
        W: http://znuny.com \n
        \n
        Location: Berlin - HRB 12345678 B Amtsgericht Berlin-Charlottenburg\n
        Managing Director: Martin Edenhofer\n
        " result = App.Utils.signatureIdentifyByPlaintext(message, true, true) - equal(result, should) + assert.equal(result, should) message = "Dear Mr. Smith, nice to read you,
          Thorsten Smith\n
        \n
        --\n
        " should = "Dear Mr. Smith, nice to read you,
          Thorsten Smith\n
        \n
        --\n
        " result = App.Utils.signatureIdentifyByPlaintext(message, true, true) - equal(result, should) + assert.equal(result, should) message = "Dear Mr. Smith, nice to read you,
          Thorsten Smith\n
        \n
        --\n
        " should = "Dear Mr. Smith, nice to read you,
          Thorsten Smith\n
        \n
        --\n
        " result = App.Utils.signatureIdentifyByPlaintext(message, false, true) - equal(result, should) + assert.equal(result, should) // fr message = "
        test 123

        --no not match--

        Bob Smith
        De : Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Envoyé : mercredi 29 avril 2015 17:31
        Objet : lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        De : Martin Edenhofer via Znuny Support [mailto:support@znuny.inc]
        Envoyé : mercredi 29 avril 2015 17:31
        Objet : lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // thunderbird // de message = "

        Viele Grüße,
        Christian

        Am 04.03.2015 um 12:47 schrieb Martin Edenhofer via Znuny Sales:
        > Hallo Christian,
        " should = "

        Viele Grüße,
        Christian

        Am 04.03.2015 um 12:47 schrieb Martin Edenhofer via Znuny Sales:
        > Hallo Christian,
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // en - Thunderbird default - http://kb.mozillazine.org/Reply_header_settings message = "

        Viele Grüße,
        Christian

        On 01-01-2007 11:00 AM, Alf Aardvark wrote:
        > Hallo Christian,
        " should = "

        Viele Grüße,
        Christian

        On 01-01-2007 11:00 AM, Alf Aardvark wrote:
        > Hallo Christian,
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // en - http://kb.mozillazine.org/Reply_header_settings message = "

        Viele Grüße,
        Christian

        Alf Aardvark wrote, on 01-01-2007 11:00 AM:
        > Hallo Christian,
        " should = "

        Viele Grüße,
        Christian

        Alf Aardvark wrote, on 01-01-2007 11:00 AM:
        > Hallo Christian,
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // otrs // en message = "
        test 123

        --no not match--

        Bob Smith
        01/04/15 10:55 - Bob Smith wrote:
        lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        01/04/15 10:55 - Bob Smith wrote:
        lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // de message = "
        test 123

        --no not match--

        Bob Smith
        01/04/15 10:55 - Bob Smith schrieb:
        lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        01/04/15 10:55 - Bob Smith schrieb:
        lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        24.02.2015 14:20 - Roy Kaldung via Znuny Sales schrieb:  
        " should = "
        test 123

        24.02.2015 14:20 - Roy Kaldung via Znuny Sales schrieb:  
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // zammad message = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " should = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " should = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // gmail message = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " should = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " should = "
        test 123

        --no not match--

        Bob Smith
        lalala
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) message = "
        test 123

        --no not match--

        Bob Smith
        Am 24. Dezember 2015 um 07:45 schrieb kathrine <kathrine@example.com>:
        lalala
        " should = "
        test 123

        --no not match--

        Bob Smith
        Am 24. Dezember 2015 um 07:45 schrieb kathrine <kathrine@example.com>:
        lalala
        " result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // word 14 // en message = "
        test 123

        --no not match--

        Bob Smith
        Bob Smith wrote:
        lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        Bob Smith wrote:
        lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) // de message = "
        test 123

        --no not match--

        Bob Smith
        Bob Smith schrieb:
        lalala
        " should = '
        test 123

        --no not match--

        Bob Smith
        Bob Smith schrieb:
        lalala
        ' result = App.Utils.signatureIdentifyByPlaintext(message, true) - equal(result, should) + assert.equal(result, should) }); -test("identify signature by HTML", function() { +QUnit.test("identify signature by HTML", assert => { var message = "
        test 123
        " var should = message var result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // test if, according to jQuery, invalid HTML does not cause a a crash @@ -1057,43 +1057,43 @@ test("identify signature by HTML", function() { message = "
        test 123
        " should = message result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // simple case 1 message = '
        actual content
        quoted content
        ' should = '
        actual content
        quoted content
        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // simple case 2 message = '
        actual content
        quoted content



        ' should = '
        actual content
        quoted content



        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // simple case 3 message = '
        actual content
        quoted content

        actual content 2
        ' should = message result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // simple case 4 message = ' content 0
        content 1
        content 2
        quoted content



        ' should = ' content 0
        content 1
        content 2
        quoted content



        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Invalid html signature detection for exchange warning boxes #3571 message = '
        CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

        actual content

        actual content 2

         

        actual quote

        actual quote

         

         

        ' should = '
        CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

        actual content

        actual content 2

         

        actual quote

        actual quote

         

         

        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Invalid html signature detection for exchange warning boxes #3571 message = '
        CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

        actual content

        actual content 2

         

        actual quote

        actual quote

         

         

        ' should = '
        CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

        actual content

        actual content 2

         

        actual quote

        actual quote

         

         

        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Gmail via Safari on MacOS 10.12 message = '
        Reply with gmail via Safari on MacOS 10.12

        \ @@ -1113,13 +1113,13 @@ test("identify signature by HTML", function() { \ ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Yahoo Mail via Safari on MacOS 10.12 message = '
        Reply with Yahoo Mail via Safari on MacOS 10.12


        Billy Zhou <bz@zammad.com> schrieb am 9:08 Mittwoch, 5.September 2018:


        test email content



        ' should = '
        Reply with Yahoo Mail via Safari on MacOS 10.12


        Billy Zhou <bz@zammad.com> schrieb am 9:08 Mittwoch, 5.September 2018:


        test email content



        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Thunderbird 52 on MacOS 10.12 message = 'Reply with Thunderbird 52 on MacOS 10.12
        \ @@ -1146,13 +1146,13 @@ test("identify signature by HTML", function() { \
        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Apple Mail on MacOS 10 message = '
        Reply by Apple Mail on MacOS 10.


        On 4. Sep 2018, at 15:32, Billy Zhou <bz@zammad.com> wrote:

        test email content


        ' should = '
        Reply by Apple Mail on MacOS 10.


        On 4. Sep 2018, at 15:32, Billy Zhou <bz@zammad.com> wrote:

        test email content


        ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Office 365 (10325.20118) on Windows 10 Build 1803 // With German marker: -----Ursprüngliche Nachricht----- @@ -1198,7 +1198,7 @@ test("identify signature by HTML", function() {

        \ ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Office 365 (10325.20118) on Windows 10 Build 1803 // With English marker: -----Original Message----- @@ -1244,7 +1244,7 @@ test("identify signature by HTML", function() {

        \ ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) // Office 365 (10325.20118) on Windows 10 Build 1803 // With German marker: -----Ursprüngliche Nachricht----- @@ -1291,64 +1291,64 @@ test("identify signature by HTML", function() {

        \ ' result = App.Utils.signatureIdentifyByHtml(message) - equal(result, should) + assert.equal(result, should) }); // check attachment references -test("check check attachment reference", function() { +QUnit.test("check check attachment reference", assert => { var message = 'some not existing' var result = false var verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = 'some attachment for you' result = 'Attachment' verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = 'your attachment.' result = 'Attachment' verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = 'some otherattachment for you' result = false verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = 'some attachmentother for you' result = false verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = 'someattachment' result = false verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = 'As enclosed you will find.' result = 'Enclosed' verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = '
        Hi Test,
        On Monday, 22 July 2019, 14:07:54, Test User wrote:

        Test attachment
        ' result = false verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = '
        Hi Test,
        cite attachment
        ' result = false verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) message = '
        Hi Test,
        ecxgmail_quote attachment
        ' result = false verify = App.Utils.checkAttachmentReference(message) - equal(verify, result) + assert.equal(verify, result) }); // replace tags -test("check replace tags", function() { +QUnit.test("check replace tags", assert => { var formatNumber = function(num, digits) { while (num.toString().length < digits) { num = '0' + num @@ -1374,7 +1374,7 @@ test("check replace tags", function() { }, } var verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.lastname}
        " result = '
        Bob Smith
        ' @@ -1385,7 +1385,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.lastname}
        " result = '
        Bob -
        ' @@ -1395,7 +1395,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.lastname}
        " result = '
        Bob 0
        ' @@ -1406,7 +1406,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.lastname}
        " result = '
        Bob -
        ' @@ -1417,7 +1417,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.not.existing.test}
        " result = '
        Bob -
        ' @@ -1427,7 +1427,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{not.existing.test}
        " result = '
        Bob -
        ' @@ -1437,7 +1437,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{not.existing.test}
        " result = '
        Bob -
        ' @@ -1448,7 +1448,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{not.existing.test}
        " result = '
        Bob -
        ' @@ -1459,7 +1459,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.lastname}
        " result = '
        Bob Smith
        ' @@ -1470,7 +1470,7 @@ test("check replace tags", function() { }, } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) user = new App.User({ firstname: 'Bob', @@ -1483,7 +1483,7 @@ test("check replace tags", function() { user: user } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.created_at.date}
        " result = '
        Bob -
        ' @@ -1491,7 +1491,7 @@ test("check replace tags", function() { user: user } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "
        #{user.firstname} #{user.created.date}
        " result = '
        Bob -
        ' @@ -1499,7 +1499,7 @@ test("check replace tags", function() { user: user } verify = App.Utils.replaceTags(message, data) - equal(verify, result) + assert.equal(verify, result) message = "some text" result = 'some text' @@ -1507,76 +1507,76 @@ test("check replace tags", function() { user: user } verify = App.Utils.replaceTags(message, data, true) - equal(verify, result) + assert.equal(verify, result) }); // check attibute validation -test("check attibute validation", function() { +QUnit.test("check attibute validation", assert => { var string = '123' var result = '123' var verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '123!' result = '123' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '12 3!' result = '123' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '12-3!' result = '12-3' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '12_3!' result = '12_3' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '^12_3!' result = '12_3' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '^1\n 2_3!' result = '12_3' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = 'abc?' result = 'abc' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = 'abc."' result = 'abc' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '#abc!^' result = 'abc' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = 'abc()=$' result = 'abc' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = "abc()=$\n123\rß" result = 'abc123' verify = App.Utils.htmlAttributeCleanup(string) - equal(verify, result, string) + assert.equal(verify, result, string) }); // check form diff -test("check form diff", function() { +QUnit.test("check form diff", assert => { var dataNow = { owner_id: 1, @@ -1588,7 +1588,7 @@ test("check form diff", function() { } var diff = {} var result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1601,7 +1601,7 @@ test("check form diff", function() { } diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1613,7 +1613,7 @@ test("check form diff", function() { } diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1626,7 +1626,7 @@ test("check form diff", function() { diff = { } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1638,7 +1638,7 @@ test("check form diff", function() { state_ids: ['1','5','6','7'], } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1651,7 +1651,7 @@ test("check form diff", function() { } diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1665,7 +1665,7 @@ test("check form diff", function() { state_ids: ['6'], } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1678,7 +1678,7 @@ test("check form diff", function() { } diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1693,7 +1693,7 @@ test("check form diff", function() { owner_id: '' } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1709,7 +1709,7 @@ test("check form diff", function() { pending_time: '2015-01-28T11:34:00Z' } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1720,7 +1720,7 @@ test("check form diff", function() { } diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1735,7 +1735,7 @@ test("check form diff", function() { } diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1752,7 +1752,7 @@ test("check form diff", function() { } diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1763,7 +1763,7 @@ test("check form diff", function() { test: '123', } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1776,7 +1776,7 @@ test("check form diff", function() { test: '123', } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1792,7 +1792,7 @@ test("check form diff", function() { test: '123', } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1805,7 +1805,7 @@ test("check form diff", function() { test: ['1','2','3','4'] } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { @@ -1824,7 +1824,7 @@ test("check form diff", function() { } } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') // regression test for issue #2042 - incorrect notification when closing a tab after setting up an object @@ -1835,7 +1835,7 @@ test("check form diff", function() { dataLast = {} diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff for a newly created attribute that is blank') + assert.deepEqual(result, diff, 'check form diff for a newly created attribute that is blank') dataNow = { @@ -1848,7 +1848,7 @@ test("check form diff", function() { test: '', } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff for setting a previously valid value to blank') + assert.deepEqual(result, diff, 'check form diff for setting a previously valid value to blank') dataNow = { @@ -1866,7 +1866,7 @@ test("check form diff", function() { test: '123', } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = undefined @@ -1874,14 +1874,14 @@ test("check form diff", function() { diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = {} dataLast = {"number":"10012","title":"some subject 123äöü","group_id":1,"owner_id":1,"customer_id":2,"state_id":3,"priority_id":2,"article":{"from":"Test Admin Agent","to":"","cc":"","body":"dasdad","content_type":"text/html","ticket_id":12,"type_id":9,"sender_id":1,"internal":false,"form_id":"523405147"},"updated_at":"2015-01-29T09:22:23.000Z","pending_time":"2015-01-28T22:22:00.000Z","id":12} diff = {} result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') // do not compare content of data instances/objects no = function test_object() { @@ -1908,7 +1908,7 @@ test("check form diff", function() { number:'10013', } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') dataNow = { number:'10013', @@ -1924,96 +1924,96 @@ test("check form diff", function() { Article: ['2'], } result = App.Utils.formDiff(dataNow, dataLast) - deepEqual(result, diff, 'check form diff') + assert.deepEqual(result, diff, 'check form diff') }); // check decimal format -test("check decimal format", function() { +QUnit.test("check decimal format", assert => { var string = '123' var result = '123.00' var verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '0.6' result = '0.60' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '6' result = '6.00' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = 6.5 result = '6.50' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '111111.6' result = '111111.60' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '111111.622' result = '111111.62' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = 'abc.6' result = 'abc.6' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = '' result = '' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = undefined result = '' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) string = null result = '' verify = App.Utils.decimal(string) - equal(verify, result, string) + assert.equal(verify, result, string) }); // check formatTime format -test("check formatTime format", function() { +QUnit.test("check formatTime format", assert => { var string = '123' var result = '123' var verify = App.Utils.formatTime(string, 0) - equal(verify, result, string) + assert.equal(verify, result, string) string = '6' result = '06' verify = App.Utils.formatTime(string, 2) - equal(verify, result, string) + assert.equal(verify, result, string) string = '' result = '00' verify = App.Utils.formatTime(string, 2) - equal(verify, result, string) + assert.equal(verify, result, string) string = undefined result = '' verify = App.Utils.formatTime(string, 2) - equal(verify, result, string) + assert.equal(verify, result, string) string = null result = '' verify = App.Utils.formatTime(string, 2) - equal(verify, result, string) + assert.equal(verify, result, string) }); // check diffPosition -test("check diffPosition format", function() { +QUnit.test("check diffPosition format", assert => { var a = [1,2,3,4] var b = [1,2,3,4,5] @@ -2024,7 +2024,7 @@ test("check diffPosition format", function() { }, ] var verify = App.Utils.diffPositionAdd(a, b) - deepEqual(verify, result) + assert.deepEqual(verify, result) a = [2,3,4] b = [1,2,3,4] @@ -2035,7 +2035,7 @@ test("check diffPosition format", function() { }, ] verify = App.Utils.diffPositionAdd(a, b) - deepEqual(verify, result) + assert.deepEqual(verify, result) a = [2,3,4] b = [1,2,3,4,5] @@ -2050,7 +2050,7 @@ test("check diffPosition format", function() { }, ] verify = App.Utils.diffPositionAdd(a, b) - deepEqual(verify, result) + assert.deepEqual(verify, result) a = [2,3,4] b = [1,99,12,2,3,4,5] @@ -2073,13 +2073,13 @@ test("check diffPosition format", function() { }, ] verify = App.Utils.diffPositionAdd(a, b) - deepEqual(verify, result) + assert.deepEqual(verify, result) a = [4,3,1] b = [1,2,3,4,5] result = false verify = App.Utils.diffPositionAdd(a, b) - deepEqual(verify, result) + assert.deepEqual(verify, result) a = ['Ticket-347', 'TicketCreateScreen-2217'] b = ['Ticket-347', 'TicketCreateScreen-2217', 'TicketCreateScreen-71517'] @@ -2090,57 +2090,57 @@ test("check diffPosition format", function() { }, ] verify = App.Utils.diffPositionAdd(a, b) - deepEqual(verify, result) + assert.deepEqual(verify, result) }); // check textLengthWithUrl format -test("check textLengthWithUrl format", function() { +QUnit.test("check textLengthWithUrl format", assert => { var string = '123' var result = 3 var verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) string = '123 http is not here' result = 20 verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) string = '123 http://host is not here' result = 39 verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) string = '123 http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX is not here' result = 39 verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) string = 'http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' result = 23 verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) string = 'http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, some other text' result = 23 + 17 verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) string = 'some other text,http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' result = 23 + 16 verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) string = 'some other text, http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX?abc=123;aaa=ab+c usw' result = 23 + 21 verify = App.Utils.textLengthWithUrl(string) - equal(verify, result) + assert.equal(verify, result) }); // check getRecipientArticle format -test('check getRecipientArticle format', function() { +QUnit.test('check getRecipientArticle format', assert => { var customer = { login: 'login', @@ -2175,7 +2175,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id1', } var verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2209,7 +2209,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id2', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2243,7 +2243,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id3', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2279,7 +2279,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id4', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2313,7 +2313,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id5', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2348,7 +2348,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id6', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2384,7 +2384,7 @@ test('check getRecipientArticle format', function() { } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) console.log(verify) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2420,7 +2420,7 @@ test('check getRecipientArticle format', function() { } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) console.log(verify) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2456,7 +2456,7 @@ test('check getRecipientArticle format', function() { } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) console.log(verify) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2492,7 +2492,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id8', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2528,7 +2528,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id9', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2565,7 +2565,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id10', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2602,7 +2602,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id11', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, [], true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2639,7 +2639,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id12', } verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, [], true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2684,7 +2684,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2729,7 +2729,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2768,7 +2768,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2807,7 +2807,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2846,7 +2846,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2891,7 +2891,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -2936,7 +2936,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false) - deepEqual(verify, result) + assert.deepEqual(verify, result) agent = { login: 'login', @@ -2975,7 +2975,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false) - deepEqual(verify, result) + assert.deepEqual(verify, result) agent = { login: 'login', @@ -3014,7 +3014,7 @@ test('check getRecipientArticle format', function() { } ] verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false) - deepEqual(verify, result) + assert.deepEqual(verify, result) customer = { login: 'login', @@ -3050,7 +3050,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id21', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) // Regression test for issue #2184 // Case 1 @@ -3098,7 +3098,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id22', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) // Regression test for issue #2184 // Case 2 @@ -3146,7 +3146,7 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id23', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type) - deepEqual(verify, result) + assert.deepEqual(verify, result) // https://github.com/zammad/zammad/issues/2551 // If "From:" is local address and "Reply-To:" is available, use it @@ -3192,121 +3192,121 @@ test('check getRecipientArticle format', function() { in_reply_to: 'message_id22', } verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, email_addresses) - deepEqual(verify, result) + assert.deepEqual(verify, result) }); -test("contentTypeCleanup", function() { +QUnit.test("contentTypeCleanup", assert => { var source = "image/png" var should = "image/png" var result = App.Utils.contentTypeCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "image/png; some.file" should = "image/png" result = App.Utils.contentTypeCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "image/png;some.file" should = "image/png" result = App.Utils.contentTypeCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "image/jpeg;some.file" should = "image/jpeg" result = App.Utils.contentTypeCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "image/jpg;some.file" should = "image/jpg" result = App.Utils.contentTypeCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "image/gif;some.file" should = "image/gif" result = App.Utils.contentTypeCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) source = "image/gif\n;some.file" should = "image/gif" result = App.Utils.contentTypeCleanup(source) - equal(result, should, source) + assert.equal(result, should, source) }); // htmlImage2DataUrl -test("htmlImage2DataUrl", function() { +QUnit.test("htmlImage2DataUrl", assert => { var source = '
        test 13
        ' var should = '
        test 13
        ' var result = App.Utils.htmlImage2DataUrl(source) - equal(result, should, source) + assert.equal(result, should, source) source = 'some test' should = 'some test' result = App.Utils.htmlImage2DataUrl(source) - equal(result, should, source) + assert.equal(result, should, source) source = 'some test' should = 'some test' result = App.Utils.htmlImage2DataUrl(source) - equal(result, should, source) + assert.equal(result, should, source) source = 'some test' should = 'some test' result = App.Utils.htmlImage2DataUrl(source) - equal(result, should, source) + assert.equal(result, should, source) source = 'some test' should = 'some test' result = App.Utils.htmlImage2DataUrl(source) - equal(result, should, source) + assert.equal(result, should, source) // GitHub issue #2305 source = 'some test' should = 'some test' result = App.Utils.htmlImage2DataUrl(source) - equal(result, should, source) + assert.equal(result, should, source) // GitHub issue #2701 source = 'foosome test' should = 'foosome test' result = App.Utils.htmlImage2DataUrl(source) - equal(result, should, source) + assert.equal(result, should, source) }); -test('App.Utils.icon()', function() { +QUnit.test('App.Utils.icon()', assert => { // When given no arguments, // expect @icon() to return null - equal(App.Utils.icon(), null, 'with no arguments') + assert.equal(App.Utils.icon(), null, 'with no arguments') // On a modern browser and when given a single argument, // expect @icon(name) to return an tag window.svgPolyfill = false svgTag = '' - equal(App.Utils.icon('foo'), svgTag, 'with one arg / no SVG polyfill') + assert.equal(App.Utils.icon('foo'), svgTag, 'with one arg / no SVG polyfill') // On a modern browser and when given two arguments, // expect @icon(name) to return an tag // with second arg as add'l class name window.svgPolyfill = false svgTag = '' - equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / no SVG polyfill') + assert.equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / no SVG polyfill') // On a browser requiring SVG polyfill and when given a single argument, // expect @icon(name, class) to return an tag // with pathless xlink:href attr window.svgPolyfill = true svgTag = '' - equal(App.Utils.icon('foo'), svgTag, 'with one arg / SVG polyfill') + assert.equal(App.Utils.icon('foo'), svgTag, 'with one arg / SVG polyfill') // On a browser requiring SVG polyfill and when given two arguments, // expect @icon(name, class) to return an tag // with pathless xlink:href attr and second arg as add'l class name window.svgPolyfill = true svgTag = '' - equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / SVG polyfill') + assert.equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / SVG polyfill') // For a left-to-right browser language and when given an argument containing '{start}' or '{end}', // expect @icon(name) to return an tag @@ -3314,9 +3314,9 @@ test('App.Utils.icon()', function() { window.svgPolyfill = false App.i18n.dir = function() { return 'ltr' } svgTag = '' - equal(App.Utils.icon('arrow-{start}'), svgTag, 'for ltr locale / name includes "{start}"') + assert.equal(App.Utils.icon('arrow-{start}'), svgTag, 'for ltr locale / name includes "{start}"') svgTag = '' - equal(App.Utils.icon('arrow-{end}'), svgTag, 'for ltr locale / name includes "{end}"') + assert.equal(App.Utils.icon('arrow-{end}'), svgTag, 'for ltr locale / name includes "{end}"') // For a right-to-left browser language and when given an argument containing '{start}' or '{end}', // expect @icon(name) to return an tag @@ -3324,19 +3324,19 @@ test('App.Utils.icon()', function() { window.svgPolyFill = false App.i18n.dir = function() { return 'rtl' } svgTag = '' - equal(App.Utils.icon('arrow-{start}'), svgTag, 'for rtl locale / name includes "{start}"') + assert.equal(App.Utils.icon('arrow-{start}'), svgTag, 'for rtl locale / name includes "{start}"') svgTag = '' - equal(App.Utils.icon('arrow-{end}'), svgTag, 'for rtl locale / name includes "{end}"') + assert.equal(App.Utils.icon('arrow-{end}'), svgTag, 'for rtl locale / name includes "{end}"') }); var source1 = 'some test' $('#image2data1').html(source1) var htmlImage2DataUrlTest1 = function() { - test("htmlImage2DataUrl1 async", function() { + QUnit.test("htmlImage2DataUrl1 async", assert => { var result1 = App.Utils.htmlImage2DataUrl(source1) - ok(result1.match(/some test/), source1) - ok(!result1.match(/avatar-bg.png/), source1) - ok(result1.match(/^\ { + assert.ok(!$(element).html().match(/chat-demo-avatar/), source2) + assert.ok($(element).get(0).outerHTML.match(/^\ { + assert.ok(false, 'fail callback is exectuted!') }); } @@ -3364,10 +3364,10 @@ var htmlImage2DataUrlTest2Fail = function() { var jpegImageSource = 'test.jpegjpeg image' $('#jpegImage').html(jpegImageSource) var htmlImage2DataUrlTest3 = function() { - test("htmlImage2DataUrl3 async", function() { + QUnit.test("htmlImage2DataUrl3 async", assert => { var result = App.Utils.htmlImage2DataUrl(jpegImageSource) - ok(result.match(/jpeg image/), jpegImageSource) - ok(result.match(/^\ { var result = App.Utils.htmlImage2DataUrl(pngImageSource) - ok(result.match(/png image/), pngImageSource) - ok(result.match(/^\ { var result = App.Utils.htmlImage2DataUrl(jpegImageSourceWithoutAlt) - ok(result.match(/jpeg image/), jpegImageSourceWithoutAlt) - ok(result.match(/^\ { configGetBackup = App.Config.get // When FQDN is undefined or null, // expect @baseUrl() to return window.location.origin App.Config.get = function(key) { return undefined } - equal(App.Utils.baseUrl(), window.location.origin, 'with undefined FQDN') + assert.equal(App.Utils.baseUrl(), window.location.origin, 'with undefined FQDN') App.Config.get = function(key) { return null } - equal(App.Utils.baseUrl(), window.location.origin, 'with null FQDN') + assert.equal(App.Utils.baseUrl(), window.location.origin, 'with null FQDN') // When FQDN is zammad.example.com, // expect @baseUrl() to return window.location.origin @@ -3415,7 +3415,7 @@ test('App.Utils.baseUrl()', function() { return 'zammad.example.com' } } - equal(App.Utils.baseUrl(), window.location.origin, 'with FQDN zammad.example.com') + assert.equal(App.Utils.baseUrl(), window.location.origin, 'with FQDN zammad.example.com') // Otherwise, // expect @baseUrl() to return FQDN with current HTTP(S) scheme @@ -3426,7 +3426,7 @@ test('App.Utils.baseUrl()', function() { return 'https' } } - equal(App.Utils.baseUrl(), 'https://foo.zammad.com', 'with any other FQDN (and https scheme)') + assert.equal(App.Utils.baseUrl(), 'https://foo.zammad.com', 'with any other FQDN (and https scheme)') App.Config.get = function(key) { if (key === 'fqdn') { @@ -3435,73 +3435,73 @@ test('App.Utils.baseUrl()', function() { return 'http' } } - equal(App.Utils.baseUrl(), 'http://bar.zammad.com', 'with any other FQDN (and http scheme)') + assert.equal(App.Utils.baseUrl(), 'http://bar.zammad.com', 'with any other FQDN (and http scheme)') App.Config.get = configGetBackup }); -test('App.Utils.joinUrlComponents()', function() { +QUnit.test('App.Utils.joinUrlComponents()', assert => { // When given a list of strings, // expect @joinUrlComponents() to join them with slashes - equal(App.Utils.joinUrlComponents('foo', 'bar', 'baz'), 'foo/bar/baz', 'with a destructured list of strings') + assert.equal(App.Utils.joinUrlComponents('foo', 'bar', 'baz'), 'foo/bar/baz', 'with a destructured list of strings') // When given an array of strings, // expect @joinUrlComponents() to join them with slashes - equal(App.Utils.joinUrlComponents(['foo', 'bar', 'baz']), 'foo/bar/baz', 'with an array of strings') + assert.equal(App.Utils.joinUrlComponents(['foo', 'bar', 'baz']), 'foo/bar/baz', 'with an array of strings') // When given a list of many types, // expect @joinUrlComponents() to join their string representations with slashes - equal(App.Utils.joinUrlComponents(0, 1, 'two', true, false, { foo: 'bar' }), '0/1/two/true/false/[object Object]', 'with a list of many types') + assert.equal(App.Utils.joinUrlComponents(0, 1, 'two', true, false, { foo: 'bar' }), '0/1/two/true/false/[object Object]', 'with a list of many types') // When given a list including null or undefined, // expect @joinUrlComponents() to filter them out of the results before joining the rest with slashes - equal(App.Utils.joinUrlComponents('foo', undefined, 'bar', null, 'baz'), 'foo/bar/baz', 'with a list including null or undefined') + assert.equal(App.Utils.joinUrlComponents('foo', undefined, 'bar', null, 'baz'), 'foo/bar/baz', 'with a list including null or undefined') }); -test('App.Utils.clipboardHtmlIsWithText()', function() { +QUnit.test('App.Utils.clipboardHtmlIsWithText()', assert => { // no content with text - equal(App.Utils.clipboardHtmlIsWithText('
        '), false) - equal(App.Utils.clipboardHtmlIsWithText('
        '), false) - equal(App.Utils.clipboardHtmlIsWithText('
        '), false) - equal(App.Utils.clipboardHtmlIsWithText('
        '), false) - equal(App.Utils.clipboardHtmlIsWithText('
        '), false) - equal(App.Utils.clipboardHtmlIsWithText("
        \n
        "), false) + assert.equal(App.Utils.clipboardHtmlIsWithText('
        '), false) + assert.equal(App.Utils.clipboardHtmlIsWithText('
        '), false) + assert.equal(App.Utils.clipboardHtmlIsWithText('
        '), false) + assert.equal(App.Utils.clipboardHtmlIsWithText('
        '), false) + assert.equal(App.Utils.clipboardHtmlIsWithText('
        '), false) + assert.equal(App.Utils.clipboardHtmlIsWithText("
        \n
        "), false) // content with text - equal(App.Utils.clipboardHtmlIsWithText('test'), true) - equal(App.Utils.clipboardHtmlIsWithText('
        test
        '), true) - equal(App.Utils.clipboardHtmlIsWithText('sometext'), true) + assert.equal(App.Utils.clipboardHtmlIsWithText('test'), true) + assert.equal(App.Utils.clipboardHtmlIsWithText('
        test
        '), true) + assert.equal(App.Utils.clipboardHtmlIsWithText('sometext'), true) }); -test('App.Utils.clipboardHtmlInsertPreperation()', function() { - equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), '') - equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), ' ') - equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), '') - equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), '') - equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), ' ') - equal(App.Utils.clipboardHtmlInsertPreperation("
        \n
        ", {}), " \n ") - equal(App.Utils.clipboardHtmlInsertPreperation('test', {}), 'test') - equal(App.Utils.clipboardHtmlInsertPreperation('
        test
        ', {}), 'test') - equal(App.Utils.clipboardHtmlInsertPreperation('sometext', {}), '
        sometext
        ') - equal(App.Utils.clipboardHtmlInsertPreperation('
        test 123
        ', { mode: 'textonly' }), 'test 123') - equal(App.Utils.clipboardHtmlInsertPreperation('
        test
        123
        ', { mode: 'textonly' }), 'test 123') - equal(App.Utils.clipboardHtmlInsertPreperation('
        test
        123
        ', { mode: 'textonly', multiline: true }), 'test
        123') +QUnit.test('App.Utils.clipboardHtmlInsertPreperation()', assert => { + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), '') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), ' ') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), '') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), '') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        ', {}), ' ') + assert.equal(App.Utils.clipboardHtmlInsertPreperation("
        \n
        ", {}), " \n ") + assert.equal(App.Utils.clipboardHtmlInsertPreperation('test', {}), 'test') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        test
        ', {}), 'test') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('sometext', {}), '
        sometext
        ') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        test 123
        ', { mode: 'textonly' }), 'test 123') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        test
        123
        ', { mode: 'textonly' }), 'test 123') + assert.equal(App.Utils.clipboardHtmlInsertPreperation('
        test
        123
        ', { mode: 'textonly', multiline: true }), 'test
        123') }); -test('App.Utils.signatureIdentifyByHtmlHelper()', function() { +QUnit.test('App.Utils.signatureIdentifyByHtmlHelper()', assert => { result = App.Utils.signatureIdentifyByHtmlHelper("<script>alert('fish2');</script>
        ") - equal(result, "<script>alert('fish2');</script>
        ", 'signatureIdentifyByHtmlHelper does not reactivate alert') + assert.equal(result, "<script>alert('fish2');</script>
        ", 'signatureIdentifyByHtmlHelper does not reactivate alert') }); -test("#safeParseHtml", function() { +QUnit.test("#safeParseHtml", assert => { var unwrap = input => $('
        ').html(input)[0].innerHTML var html = "
        test 123
        " var result = App.Utils.safeParseHtml(html) var should = html - equal(unwrap(result), html) + assert.equal(unwrap(result), html) // test if, according to jQuery, invalid HTML does not cause a a crash @@ -3509,5 +3509,5 @@ test("#safeParseHtml", function() { html = "
        test 123
        " should = "
        test 123
        " result = App.Utils.safeParseHtml(html) - equal(unwrap(result), should) + assert.equal(unwrap(result), should) }) diff --git a/public/assets/tests/qunit/i18n.js b/public/assets/tests/qunit/i18n.js new file mode 100644 index 000000000..bec133e44 --- /dev/null +++ b/public/assets/tests/qunit/i18n.js @@ -0,0 +1,230 @@ +QUnit.test('i18n .detectBrowserLocale', assert => { + var original_userLanguage = window.navigator.userLanguage + var original_language = window.navigator.language + var original_languages = window.navigator.languages + + var reset = function(){ + window.navigator.userLanguage = original_userLanguage + window.navigator.language = original_language + window.navigator.languages = original_languages + } + + var mock = function(languages, language, userLanguage){ + Object.defineProperty(window.navigator, 'language', {value: language, configurable: true }); + Object.defineProperty(window.navigator, 'languages', {value: languages, configurable: true }); + Object.defineProperty(window.navigator, 'userLanguage', {value: userLanguage, configurable: true }); + } + + mock(undefined, undefined, undefined) + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(undefined, undefined, 'non-existant'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(undefined, undefined, 'en'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(undefined, undefined, 'lt'); + assert.equal(App.i18n.detectBrowserLocale(), 'lt') + + mock(undefined, 'lt', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'lt') + + mock(undefined, 'en', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(['en'], 'lt', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(['en-us'], 'lt', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(['en-US'], 'lt', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(['lt', 'en-US'], 'lt', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'lt') + + mock(['en-GB', 'en-US'], 'lt', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-gb') + + mock(['en-XYZ'], 'lt', 'lv'); + assert.equal(App.i18n.detectBrowserLocale(), 'en-us') + + mock(['xyz', 'lt'], 'lv', undefined); + assert.equal(App.i18n.detectBrowserLocale(), 'lt') + + reset() +}) + + // i18n +QUnit.test('i18n', assert => { + + // de + App.i18n.set('de-de') + var translated = App.i18n.translateContent('yes') + assert.equal(translated, 'ja', 'de-de - yes / ja translated correctly') + + translated = App.i18n.translatePlain('yes') + assert.equal(translated, 'ja', 'de-de - yes / ja translated correctly') + + translated = App.i18n.translateInline('yes') + assert.equal(translated, 'ja', 'de-de - yes / ja translated correctly') + + translated = App.i18n.translateContent('%s ago', 123); + assert.equal(translated, 'vor 123', 'de-de - %s') + + translated = App.i18n.translateContent('%s ago', 'quote') + assert.equal(translated, 'vor <b>quote</b>', 'de-de - %s - quote') + + translated = App.i18n.translateContent('%s %s test', 123, 'xxx |B|') + assert.equal(translated, '123 xxx |B| test', 'de-de - %s %s') + + translated = App.i18n.translateContent('|%s| %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'de-de - *%s* %s') + + translated = App.i18n.translateContent('||%s|| %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'de-de - *%s* %s') + + translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'de-de - _%s_ %s') + + translated = App.i18n.translateContent('§%s§ %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'de-de - §%s§ %s') + + translated = App.i18n.translateContent('//%s// %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'de-de - //%s// %s') + + translated = App.i18n.translateContent('\'%s\' %s test', 123, 'xxx') + assert.equal(translated, ''123' xxx test', 'de-de - \'%s\' %s') + + translated = App.i18n.translateContent('//*äöüß') + assert.equal(translated, '<test&now>//*äöüß', 'de - //*äöüß') + + translated = App.i18n.translateContent('some link [to what ever](http://lalala)') + assert.equal(translated, 'some link to what ever', 'de-de - link') + + translated = App.i18n.translateContent('some link [to what ever](%s)', 'http://lalala') + assert.equal(translated, 'some link to what ever', 'de-de - link') + + translated = App.i18n.translateContent('Enables user authentication via %s. Register your app first at [%s](%s).', 'XXX', 'YYY', 'http://lalala') + assert.equal(translated, 'Aktivieren der Benutzeranmeldung über XXX. Registriere Deine Anwendung zuerst über YYY.', 'en-us - link') + + var time_local = new Date(); + var offset = time_local.getTimezoneOffset(); + var timestamp = App.i18n.translateTimestamp('2012-11-06T21:07:24Z', offset); + assert.equal(timestamp, '06.11.2012 21:07', 'de-de - timestamp translated correctly') + + var timestamp = App.i18n.translateTimestamp('2021-02-08 09:13:20 UTC', offset); + assert.equal(timestamp, '08.02.2021 09:13', 'de-de - timestamp translated correctly with UTC format') + + timestamp = App.i18n.translateTimestamp('', offset); + assert.equal(timestamp, '', 'de-de - timestamp translated correctly') + + timestamp = App.i18n.translateTimestamp(null, offset); + assert.equal(timestamp, null, 'de-de - timestamp translated correctly') + + timestamp = App.i18n.translateTimestamp(undefined, offset); + assert.equal(timestamp, undefined, 'de-de - timestamp translated correctly') + + var date = App.i18n.translateDate('2012-11-06', 0) + assert.equal(date, '06.11.2012', 'de-de - date translated correctly') + + date = App.i18n.translateDate('', 0) + assert.equal(date, '', 'de-de - date translated correctly') + + date = App.i18n.translateDate(null, 0) + assert.equal(date, null, 'de-de - date translated correctly') + + date = App.i18n.translateDate(undefined, 0) + assert.equal(date, undefined, 'de-de - date translated correctly') + + // en + App.i18n.set('en-us') + translated = App.i18n.translateContent('yes') + assert.equal(translated, 'yes', 'en-us - yes translated correctly') + + translated = App.i18n.translatePlain('yes') + assert.equal(translated, 'yes', 'en-us - yes translated correctly') + + translated = App.i18n.translateInline('yes') + assert.equal(translated, 'yes', 'en-us - yes translated correctly') + + translated = App.i18n.translateContent('%s ago', 123); + assert.equal(translated, '123 ago', 'en-us - %s') + + translated = App.i18n.translateContent('%s ago', 'quote') + assert.equal(translated, '<b>quote</b> ago', 'en-us - %s - qupte') + + translated = App.i18n.translateContent('%s %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'en-us - %s %s') + + translated = App.i18n.translateContent('|%s| %s test', 123, 'xxx |B|') + assert.equal(translated, '123 xxx |B| test', 'en-us - *%s* %s') + + translated = App.i18n.translateContent('||%s|| %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'en-us - *%s* %s') + + translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'en-us - _%s_ %s') + + translated = App.i18n.translateContent('§%s§ %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'en-us - §%s§ %s') + + translated = App.i18n.translateContent('Here you can search for tickets, customers and organizations. Use the wildcard §*§ to find everything. E. g. §smi*§ or §rosent*l§. You also can use ||double quotes|| for searching phrases §"some phrase"§.') + assert.equal(translated, 'Here you can search for tickets, customers and organizations. Use the wildcard * to find everything. E. g. smi* or rosent*l. You also can use double quotes for searching phrases "some phrase".', 'en-us - §§ §§ §§ || §§') + + translated = App.i18n.translateContent('//%s// %s test', 123, 'xxx') + assert.equal(translated, '123 xxx test', 'en-us - //%s// %s') + + translated = App.i18n.translateContent('\'%s\' %s test', 123, 'xxx') + assert.equal(translated, ''123' xxx test', 'en-us - \'%s\' %s') + + translated = App.i18n.translateContent('') + assert.equal(translated, '<test&now>', 'en-us - ') + + translated = App.i18n.translateContent('some link [to what ever](http://lalala)') + assert.equal(translated, 'some link to what ever', 'en-us - link') + + translated = App.i18n.translateContent('some link [to what ever](%s)', 'http://lalala') + assert.equal(translated, 'some link to what ever', 'en-us - link') + + translated = App.i18n.translateContent('Enables user authentication via %s. Register your app first at [%s](%s).', 'XXX', 'YYY', 'http://lalala') + assert.equal(translated, 'Enables user authentication via XXX. Register your app first at YYY.', 'en-us - link') + + timestamp = App.i18n.translateTimestamp('2012-11-06T21:07:24Z', offset) + assert.equal(timestamp, '11/06/2012 21:07', 'en - timestamp translated correctly') + + timestamp = App.i18n.translateTimestamp('', offset); + assert.equal(timestamp, '', 'en - timestamp translated correctly') + + timestamp = App.i18n.translateTimestamp(null, offset); + assert.equal(timestamp, null, 'en - timestamp translated correctly') + + timestamp = App.i18n.translateTimestamp(undefined, offset); + assert.equal(timestamp, undefined, 'en - timestamp translated correctly') + + date = App.i18n.translateDate('2012-11-06', 0) + assert.equal(date, '11/06/2012', 'en - date translated correctly') + + date = App.i18n.translateDate('', 0) + assert.equal(date, '', 'en - date translated correctly') + + date = App.i18n.translateDate(null, 0) + assert.equal(date, null, 'en - date translated correctly') + + date = App.i18n.translateDate(undefined, 0) + assert.equal(date, undefined, 'en - date translated correctly') + + // locale alias test + // de + App.i18n.set('de') + var translated = App.i18n.translateContent('yes') + assert.equal(translated, 'ja', 'de - yes / ja translated correctly') + + // locale detection test + // de-ch + App.i18n.set('de-ch') + var translated = App.i18n.translateContent('yes') + assert.equal(translated, 'ja', 'de - yes / ja translated correctly') +}); diff --git a/public/assets/tests/image_service.js b/public/assets/tests/qunit/image_service.js similarity index 92% rename from public/assets/tests/image_service.js rename to public/assets/tests/qunit/image_service.js index 83df8bfff..eecd71652 100644 --- a/public/assets/tests/image_service.js +++ b/public/assets/tests/qunit/image_service.js @@ -1,11 +1,11 @@ // image service -test('test image resizing with defined height', function(assert) { - var async_done = assert.async(1) +QUnit.test('test image resizing with defined height', assert => { + var done = assert.async() App.ImageService.resize(image_40x30, 'auto', 15, 1, 'image/png', 0.7, function(image, width, height) { - equal(width, 20) + assert.equal(width, 20) - async_done() + done() }) }); diff --git a/public/assets/tests/kb_video_embeding.js b/public/assets/tests/qunit/kb_video_embeding.js similarity index 52% rename from public/assets/tests/kb_video_embeding.js rename to public/assets/tests/qunit/kb_video_embeding.js index 12138b0f3..96d02c070 100644 --- a/public/assets/tests/kb_video_embeding.js +++ b/public/assets/tests/qunit/kb_video_embeding.js @@ -1,38 +1,38 @@ -test('kb video url parsing and converting to embeding url', function() { +QUnit.test('kb video url parsing and converting to embeding url', assert => { var klass = App.UiElement.richtext.additions.RichTextToolPopupVideo; var parsed = klass.detectProviderAndId('https://www.youtube.com/watch?v=vTTzwJsHpU8') - equal(parsed[0], 'youtube') - equal(parsed[1], 'vTTzwJsHpU8') + assert.equal(parsed[0], 'youtube') + assert.equal(parsed[1], 'vTTzwJsHpU8') var parsed = klass.detectProviderAndId('https://www.youtube.com/watch?v=vTTzwJsHpU8&other=true') - equal(parsed[0], 'youtube') - equal(parsed[1], 'vTTzwJsHpU8') + assert.equal(parsed[0], 'youtube') + assert.equal(parsed[1], 'vTTzwJsHpU8') var parsed = klass.detectProviderAndId('https://www.youtube.com/watch?v=vTTzwJsHpU8#hashtag') - equal(parsed[0], 'youtube') - equal(parsed[1], 'vTTzwJsHpU8') + assert.equal(parsed[0], 'youtube') + assert.equal(parsed[1], 'vTTzwJsHpU8') var parsed = klass.detectProviderAndId('https://www.youtube.com/watch?v=_EYF1-2uiIg') - equal(parsed[0], 'youtube') - equal(parsed[1], '_EYF1-2uiIg') + assert.equal(parsed[0], 'youtube') + assert.equal(parsed[1], '_EYF1-2uiIg') var parsed = klass.detectProviderAndId('https://www.youtu.be/vTTzwJsHpU8') - equal(parsed[0], 'youtube') - equal(parsed[1], 'vTTzwJsHpU8') + assert.equal(parsed[0], 'youtube') + assert.equal(parsed[1], 'vTTzwJsHpU8') var parsed = klass.detectProviderAndId('https://www.youtube.com/embed/vTTzwJsHpU8') - equal(parsed[0], 'youtube') - equal(parsed[1], 'vTTzwJsHpU8') + assert.equal(parsed[0], 'youtube') + assert.equal(parsed[1], 'vTTzwJsHpU8') var parsed = klass.detectProviderAndId('https://www.vimeo.com/358296442') - equal(parsed[0], 'vimeo') - equal(parsed[1], '358296442') + assert.equal(parsed[0], 'vimeo') + assert.equal(parsed[1], '358296442') }) diff --git a/public/assets/tests/qunit/local_storage.js b/public/assets/tests/qunit/local_storage.js new file mode 100644 index 000000000..5a4ab2bb0 --- /dev/null +++ b/public/assets/tests/qunit/local_storage.js @@ -0,0 +1,65 @@ +window.onload = function() { + +QUnit.test('Test item removal from local storage', assert => { + var key = 'test_key_1' + var value = 'test_value_1' + + App.LocalStorage.set(key, value) + + assert.equal(App.LocalStorage.get(key), value) + + App.LocalStorage.delete(key) + + assert.equal(App.LocalStorage.get(key), undefined) +}); + +QUnit.test('Test user-specific item removal from local storage', assert => { + var key = 'test_key_2' + var value = 'test_value_2' + var user_id = 2 + + App.LocalStorage.set(key, value, user_id) + + assert.equal(App.LocalStorage.get(key, user_id), value) + + App.LocalStorage.delete(key, user_id) + + assert.equal(App.LocalStorage.get(key, user_id), undefined) +}); + +QUnit.test('Test key lookup', assert => { + App.LocalStorage.clear() + + var key = 'test_key_3' + var value = 'test_value_3' + var user_id = 2 + var alt_key = 'test_alt_key_3' + + // verify no keys initially + assert.equal(App.LocalStorage.keys().length, 0) + + App.LocalStorage.set(key, value, user_id) + + // has 1 key in total + assert.equal(App.LocalStorage.keys().length, 1) + + // doesn't return anything with wrong prefix + assert.equal(App.LocalStorage.keys('a').length, 0) + + // doesn't return anything since user id not given + assert.equal(App.LocalStorage.keys('test').length, 0) + + // correct + assert.equal(App.LocalStorage.keys('test', user_id).length, 1) + + // verify value + assert.equal(App.LocalStorage.keys('test', user_id)[0].match(key + '$'), key) + + App.LocalStorage.set(alt_key, value) + + // returns 1 key without user id + assert.equal(App.LocalStorage.keys('test').length, 1) + assert.equal(App.LocalStorage.keys('test')[0], alt_key) +}); + +} diff --git a/public/assets/tests/model.js b/public/assets/tests/qunit/model.js similarity index 63% rename from public/assets/tests/model.js rename to public/assets/tests/qunit/model.js index e823cdb1c..d129c56df 100644 --- a/public/assets/tests/model.js +++ b/public/assets/tests/qunit/model.js @@ -1,7 +1,7 @@ window.onload = function() { // search -test( "model search tests", function() { +QUnit.test( "model search tests", assert => { App.TicketPriority.refresh( [ { @@ -34,32 +34,32 @@ test( "model search tests", function() { }, ] ) priorities = App.TicketPriority.search({sortBy:'created_at', order: 'ASC'}) - equal('2 normal', priorities[0].name, 'check 1 entry') - equal('3 high', priorities[1].name, 'check 2 entry') - equal('4 very high', priorities[2].name, 'check 3 entry') - equal('1 low', priorities[3].name, 'check 4 entry') - equal(undefined, priorities[4], 'check 5 entry') + assert.equal('2 normal', priorities[0].name, 'check 1 entry') + assert.equal('3 high', priorities[1].name, 'check 2 entry') + assert.equal('4 very high', priorities[2].name, 'check 3 entry') + assert.equal('1 low', priorities[3].name, 'check 4 entry') + assert.equal(undefined, priorities[4], 'check 5 entry') priorities = App.TicketPriority.search({sortBy:'created_at', order: 'DESC'}) - equal('1 low', priorities[0].name, 'check 4 entry') - equal('4 very high', priorities[1].name, 'check 3 entry') - equal('3 high', priorities[2].name, 'check 2 entry') - equal('2 normal', priorities[3].name, 'check 1 entry') - equal(undefined, priorities[4], 'check 5 entry') + assert.equal('1 low', priorities[0].name, 'check 4 entry') + assert.equal('4 very high', priorities[1].name, 'check 3 entry') + assert.equal('3 high', priorities[2].name, 'check 2 entry') + assert.equal('2 normal', priorities[3].name, 'check 1 entry') + assert.equal(undefined, priorities[4], 'check 5 entry') }); // model -test( "model loadAssets tests - 1", function() { +QUnit.test( "model loadAssets tests - 1", assert => { window.refreshCounter1 = 0 var callback1 = function(state, triggerType) { window.refreshCounter1 = window.refreshCounter1 + 1 - equal(state.id, 9999, 'id check') + assert.equal(state.id, 9999, 'id check') if (window.refreshCounter1 == 1) { - equal('full', triggerType, 'trigger type check') + assert.equal('full', triggerType, 'trigger type check') } else { - equal('refresh', triggerType, 'trigger type check') + assert.equal('refresh', triggerType, 'trigger type check') } if ( window.refreshCounter1 == 1 ) { @@ -96,23 +96,23 @@ test( "model loadAssets tests - 1", function() { }); App.Delay.set( function() { - test( "model loadAssets tests - 1 / check refresh counter", function() { - equal(window.refreshCounter1, 2, 'check refresh counter') + QUnit.test( "model loadAssets tests - 1 / check refresh counter", assert => { + assert.equal(window.refreshCounter1, 2, 'check refresh counter') }); }, 1000 ); -test( "model loadAssets tests - 2", function() { +QUnit.test( "model loadAssets tests - 2", assert => { window.refreshCounter2 = 0 var callback2 = function(state, triggerType) { window.refreshCounter2 = window.refreshCounter2 + 1 - equal(state.id, 10000, 'id check') + assert.equal(state.id, 10000, 'id check') if (window.refreshCounter2 == 1) { - equal('full', triggerType, 'trigger type check') + assert.equal('full', triggerType, 'trigger type check') } else { - equal('refresh', triggerType, 'trigger type check') + assert.equal('refresh', triggerType, 'trigger type check') } if ( window.refreshCounter2 == 1 ) { App.Collection.loadAssets({ @@ -147,23 +147,23 @@ test( "model loadAssets tests - 2", function() { }); App.Delay.set( function() { - test( "model loadAssets tests - 2 / check refresh counter", function() { - equal(window.refreshCounter2, 2, 'check refresh counter') + QUnit.test( "model loadAssets tests - 2 / check refresh counter", assert => { + assert.equal(window.refreshCounter2, 2, 'check refresh counter') }); }, 1200 ); -test( "model loadAssets tests - 3", function() { +QUnit.test( "model loadAssets tests - 3", assert => { window.refreshCounter3 = 0 var callback3 = function(state, triggerType) { window.refreshCounter3 = window.refreshCounter3 + 1 - equal(state.id, 10001, 'id check') + assert.equal(state.id, 10001, 'id check') if (window.refreshCounter3 == 1) { - equal('full', triggerType, 'trigger type check') + assert.equal('full', triggerType, 'trigger type check') } else { - equal('refresh', triggerType, 'trigger type check') + assert.equal('refresh', triggerType, 'trigger type check') } if ( window.refreshCounter3 == 1 ) { @@ -199,14 +199,14 @@ test( "model loadAssets tests - 3", function() { }); App.Delay.set( function() { - test( "model loadAssets tests - 3 / check refresh counter", function() { - equal(window.refreshCounter3, 3, 'check refresh counter') + QUnit.test( "model loadAssets tests - 3 / check refresh counter", assert => { + assert.equal(window.refreshCounter3, 3, 'check refresh counter') }); }, 1400 ); -test("updateAttributes will change existing attributes and add new ones", function() { +QUnit.test("updateAttributes will change existing attributes and add new ones", assert => { App.Ticket.resetAttributes(); var attributesBefore = _.clone(App.Ticket.configure_attributes); @@ -226,15 +226,15 @@ test("updateAttributes will change existing attributes and add new ones", functi var attributesAfterUpdate = _.clone(App.Ticket.configure_attributes); - equal(attributesAfterUpdate.length, attributesBefore.length + 1, 'new attributes list contains 1 more elements') - equal(attributesAfterUpdate[attributesAfterUpdate.length - 1]['name'], 'new_attribute_1010101', 'new attributes list contains the new element') - equal(attributesAfterUpdate[0]['new_option_1239393'], 1, 'first element of the new attributes got updated with the new option') + assert.equal(attributesAfterUpdate.length, attributesBefore.length + 1, 'new attributes list contains 1 more elements') + assert.equal(attributesAfterUpdate[attributesAfterUpdate.length - 1]['name'], 'new_attribute_1010101', 'new attributes list contains the new element') + assert.equal(attributesAfterUpdate[0]['new_option_1239393'], 1, 'first element of the new attributes got updated with the new option') App.Ticket.resetAttributes(); var attributesAfterReset = _.clone(App.Ticket.configure_attributes); - equal(attributesAfterReset.length, attributesBefore.length, 'new attributes list has the same elements after reset') - equal(attributesAfterReset[0]['new_option_1239393'], undefined, 'first element of the new attributes has no attribute new_option_1239393') + assert.equal(attributesAfterReset.length, attributesBefore.length, 'new attributes list has the same elements after reset') + assert.equal(attributesAfterReset[0]['new_option_1239393'], undefined, 'first element of the new attributes has no attribute new_option_1239393') }); } diff --git a/public/assets/tests/model_binding.js b/public/assets/tests/qunit/model_binding.js similarity index 61% rename from public/assets/tests/model_binding.js rename to public/assets/tests/qunit/model_binding.js index e102a60a5..acd44f2da 100644 --- a/public/assets/tests/model_binding.js +++ b/public/assets/tests/qunit/model_binding.js @@ -1,51 +1,51 @@ window.onload = function() { -test("model bindings and rebinding", function() { +QUnit.test("model bindings and rebinding", assert => { var callback_count1 = 0 var callbacks = App.Template._callbacks Object.keys(callbacks).forEach(function(key) { callback_count1 = callback_count1 + callbacks[key].length }); - equal(callback_count1, 2) + assert.equal(callback_count1, 2) - equal(App.Template.SUBSCRIPTION_COLLECTION, undefined) + assert.equal(App.Template.SUBSCRIPTION_COLLECTION, undefined) App.Template.clearInMemory() - equal(App.Template.SUBSCRIPTION_COLLECTION, undefined) + assert.equal(App.Template.SUBSCRIPTION_COLLECTION, undefined) var callback_count2 = 0 callbacks = App.Template._callbacks Object.keys(callbacks).forEach(function(key) { callback_count2 = callback_count2 + callbacks[key].length }); - equal(callback_count2, callback_count1) + assert.equal(callback_count2, callback_count1) var render = function() {} var subscribe_id = App.Template.subscribe(render, {initFetch: true}) - ok(_.isObject(App.Template.SUBSCRIPTION_COLLECTION)) - ok(!_.isEmpty(App.Template.SUBSCRIPTION_COLLECTION)) + assert.ok(_.isObject(App.Template.SUBSCRIPTION_COLLECTION)) + assert.ok(!_.isEmpty(App.Template.SUBSCRIPTION_COLLECTION)) var callback_count3 = 0 callbacks = App.Template._callbacks Object.keys(callbacks).forEach(function(key) { callback_count3 = callback_count3 + callbacks[key].length }); - equal(callback_count3, 6) + assert.equal(callback_count3, 6) App.Template.clearInMemory() - ok(_.isObject(App.Template.SUBSCRIPTION_COLLECTION)) - ok(_.isEmpty(App.Template.SUBSCRIPTION_COLLECTION)) + assert.ok(_.isObject(App.Template.SUBSCRIPTION_COLLECTION)) + assert.ok(_.isEmpty(App.Template.SUBSCRIPTION_COLLECTION)) var callback_count4 = 0 callbacks = App.Template._callbacks Object.keys(callbacks).forEach(function(key) { callback_count4 = callback_count4 + callbacks[key].length }); - equal(callback_count4, callback_count3) + assert.equal(callback_count4, callback_count3) }); diff --git a/public/assets/tests/model_ticket.js b/public/assets/tests/qunit/model_ticket.js similarity index 75% rename from public/assets/tests/model_ticket.js rename to public/assets/tests/qunit/model_ticket.js index 91b9101ab..174e62643 100644 --- a/public/assets/tests/model_ticket.js +++ b/public/assets/tests/qunit/model_ticket.js @@ -107,40 +107,40 @@ window.onload = function() { }, ]) - test('ticket.editabe customer user #1', function() { + QUnit.test('ticket.editabe customer user #1', assert => { App.Session.set(33) ticket1 = App.Ticket.find(1); - ok(ticket1.editable(), 'access via customer_id'); + assert.ok(ticket1.editable(), 'access via customer_id'); ticket2 = App.Ticket.find(2); - ok(ticket2.editable(), 'access via organization_id'); + assert.ok(ticket2.editable(), 'access via organization_id'); ticket3 = App.Ticket.find(3); - ok(!ticket3.editable(), 'no access'); + assert.ok(!ticket3.editable(), 'no access'); ticket4 = App.Ticket.find(4); - ok(!ticket4.editable(), 'no access'); + assert.ok(!ticket4.editable(), 'no access'); }); - test('ticket.editabe customer user #2', function() { + QUnit.test('ticket.editabe customer user #2', assert => { App.Session.set(44) ticket1 = App.Ticket.find(1); - ok(!ticket1.editable(), 'no access'); + assert.ok(!ticket1.editable(), 'no access'); ticket2 = App.Ticket.find(2); - ok(ticket2.editable(), 'access via customer_id'); + assert.ok(ticket2.editable(), 'access via customer_id'); ticket3 = App.Ticket.find(3); - ok(!ticket3.editable(), 'no access'); + assert.ok(!ticket3.editable(), 'no access'); ticket4 = App.Ticket.find(4); - ok(!ticket4.editable(), 'no access'); + assert.ok(!ticket4.editable(), 'no access'); }); - test('ticket.editabe customer user #3', function() { + QUnit.test('ticket.editabe customer user #3', assert => { App.Session.set(55) ticket1 = App.Ticket.find(1); - ok(!ticket1.editable(), 'no access'); + assert.ok(!ticket1.editable(), 'no access'); ticket2 = App.Ticket.find(2); - ok(!ticket2.editable(), 'no access'); + assert.ok(!ticket2.editable(), 'no access'); ticket3 = App.Ticket.find(3); - ok(ticket3.editable(), 'access via customer_id'); + assert.ok(ticket3.editable(), 'access via customer_id'); ticket4 = App.Ticket.find(4); - ok(!ticket4.editable(), 'no access'); + assert.ok(!ticket4.editable(), 'no access'); }); } diff --git a/public/assets/tests/qunit/model_ui.js b/public/assets/tests/qunit/model_ui.js new file mode 100644 index 000000000..393c58a42 --- /dev/null +++ b/public/assets/tests/qunit/model_ui.js @@ -0,0 +1,110 @@ +window.onload = function() { + +// model +QUnit.test( "model ui basic tests", assert => { + + // load ref object + App.Collection.loadAssets({ + TicketState: { + 1: { + name: 'new', id: 1, updated_at: "2014-11-07T23:43:08.000Z", + }, + 2: { + name: 'open', id: 2, updated_at: "2014-11-07T23:43:08.000Z", + }, + 3: { + name: 'closed <>&', id: 3, updated_at: "2014-11-07T23:43:08.000Z", + }, + }, + }) + + // create ticket + var attribute1 = { + name: 'date', display: 'date 1', tag: 'date', null: true + }; + App.Ticket.configure_attributes.push( attribute1 ) + var attribute2 = { + name: 'textarea', display: 'textarea 1', tag: 'textarea', null: true + }; + App.Ticket.configure_attributes.push( attribute2 ) + var attribute3 = { + name: 'link1', display: 'link 1', linktemplate: 'http://zammad.com', tag: 'input', null: true, translate: true + }; + App.Ticket.configure_attributes.push( attribute3 ) + var attribute4 = { + name: 'link2', display: 'link 1', linktemplate: 'http://zammad.com', tag: 'input', null: true + }; + App.Ticket.configure_attributes.push( attribute4 ) + + var ticket = new App.Ticket() + ticket.load({ + id: 1000, + title: 'some title <>&', + state_id: 2, + updated_at: '2014-11-07T23:43:08.000Z', + date: '2015-02-07', + textarea: "some new\nline", + link1: 'closed', + link2: 'closed', + }) + + App.i18n.set('en-us') + assert.equal( App.viewPrint( ticket, 'id' ), 1000) + assert.equal( App.viewPrint( ticket, 'title' ), 'some title <>&') + assert.equal( App.viewPrint( ticket, 'state' ), 'open') + assert.equal( App.viewPrint( ticket, 'state_id' ), 'open') + assert.equal( App.viewPrint( ticket, 'not_existing' ), '-') + assert.equal( App.viewPrint( ticket, 'updated_at' ), '') + assert.equal( App.viewPrint( ticket, 'date' ), '02/07/2015') + assert.equal( App.viewPrint( ticket, 'textarea' ), '
        some new
        line
        ') + assert.equal( App.viewPrint( ticket, 'link1' ), 'closed') + assert.equal( App.viewPrint( ticket, 'link2' ), 'closed') + + let stub = sinon.stub(App.Config, 'get') + stub.withArgs('timezone_default').returns('Example/Timezone') + let attr = App.Ticket.configure_attributes.find(e => { return e.name == 'updated_at' }) + attr.include_timezone = true + + assert.equal( App.viewPrint( ticket, 'updated_at' ), '') + + attr.include_timezone = false + stub.restore() + + App.i18n.set('de-de') + assert.equal( App.viewPrint( ticket, 'id' ), 1000) + assert.equal( App.viewPrint( ticket, 'title' ), 'some title <>&') + assert.equal( App.viewPrint( ticket, 'state' ), 'offen') + assert.equal( App.viewPrint( ticket, 'state_id' ), 'offen') + assert.equal( App.viewPrint( ticket, 'not_existing' ), '-') + assert.equal( App.viewPrint( ticket, 'updated_at' ), '') + assert.equal( App.viewPrint( ticket, 'date' ), '07.02.2015') + assert.equal( App.viewPrint( ticket, 'textarea' ), '
        some new
        line
        ') + assert.equal( App.viewPrint( ticket, 'link1' ), 'geschlossen') + assert.equal( App.viewPrint( ticket, 'link2' ), 'closed') + + + App.i18n.set('en-us') + ticket.state_id = 3 + assert.equal( App.viewPrint( ticket, 'state' ), 'closed <>&') + assert.equal( App.viewPrint( ticket, 'state_id' ), 'closed <>&') + + App.i18n.set('de') + assert.equal( App.viewPrint( ticket, 'state' ), 'closed <>&') + assert.equal( App.viewPrint( ticket, 'state_id' ), 'closed <>&') + + // normal string + data = { + a: 1, + b: 'abc', + c: { + displayName: function() { return "my displayName <>&" } + }, + } + assert.equal( App.viewPrint( data, 'a' ), 1) + assert.equal( App.viewPrint( data, 'b' ), 'abc') + assert.equal( App.viewPrint( data, 'c' ), 'my displayName <>&') + +}); + + +} diff --git a/public/assets/tests/qunit/session.js b/public/assets/tests/qunit/session.js new file mode 100644 index 000000000..b65d00595 --- /dev/null +++ b/public/assets/tests/qunit/session.js @@ -0,0 +1,82 @@ +window.onload = function() { + +QUnit.test('test current user behaviour by updating session user via assets', assert => { + + // Wenn App.User updated through asset and set as session user + // expect App.Session.get with new values + App.User.refresh([{ + "login": "hh@example.com", + "firstname": "Harald", + "lastname": "Habebe", + "email": "hh@example.com", + "role_ids": [ 1, 2, 4 ], + "group_ids": [ 1 ], + "active": true, + "updated_at": "2017-02-09T09:17:04.770Z", + "address": "", + "vip": false, + "custom_key": undefined, + "asdf": "", + "id": 6 + }]); + App.Session.set(6) + assert.equal(App.Session.get('id'), 6) + assert.equal(App.Session.get('login'), 'hh@example.com') + assert.equal(App.Session.get('vip'), false) + assert.equal(App.Session.get('custom_key'), undefined) + assert.equal(App.Session.get().id, 6) + assert.equal(App.Session.get().login, 'hh@example.com') + assert.equal(App.Session.get().custom_key, undefined) + assert.equal(App.Session.get().not_existing, undefined) + + // Wenn App.User updated through asset + // expect App.Session.get with new values + App.User.refresh([{ + "login": "hh_new@example.com", + "firstname": "Harald", + "lastname": "Habebe", + "email": "hh_new@example.com", + "role_ids": [ 1, 2, 4 ], + "group_ids": [ 1 ], + "active": true, + "updated_at": "2017-02-09T09:17:04.770Z", + "address": "", + "vip": false, + "custom_key": undefined, + "asdf": "", + "id": 6 + }]); + assert.equal(App.Session.get('id'), 6) + assert.equal(App.Session.get('login'), 'hh_new@example.com') + assert.equal(App.Session.get('vip'), false) + assert.equal(App.Session.get('custom_key'), undefined) + assert.equal(App.Session.get().id, 6) + assert.equal(App.Session.get().login, 'hh_new@example.com') + assert.equal(App.Session.get().custom_key, undefined) + assert.equal(App.Session.get().not_existing, undefined) + + // Wenn App.Session is reseted to inital + // expect undefined for all + App.Session.init() + assert.equal(App.Session.get(), undefined) + assert.equal(App.Session.get('id'), undefined) + assert.equal(App.Session.get('login'), undefined) + assert.equal(App.Session.get('vip'), undefined) + assert.equal(App.Session.get('custom_key'), undefined) + + // When App.Session is set and set to undefined or null, + // expect @current() to return null + App.Session.set(6) + App.Session.set(undefined) + assert.equal(App.User.current(), null, 'with no active session') + App.Session.set(null) + assert.equal(App.User.current(), null, 'with no active session') + + // When App.Session is set with an invalid (not existing) user ID, + // expect @current() to return null + App.Session.set(100) + assert.equal(App.User.current(), null, 'with invalid session user ID') + +}); + +} diff --git a/public/assets/tests/qunit/table.js b/public/assets/tests/qunit/table.js new file mode 100644 index 000000000..d8b7ce582 --- /dev/null +++ b/public/assets/tests/qunit/table.js @@ -0,0 +1,844 @@ +// form +QUnit.test('table test', assert => { + App.i18n.set('de-de') + + $('#qunit').append('

        table simple I

        ') + var el = $('#table1') + App.TicketPriority.refresh( [ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + ] ) + var rowClick = function (id, e) { + e.preventDefault() + console.log('rowClick', id, e.target) + }; + var rowDblClick = function (id, e) { + e.preventDefault() + console.log('rowDblClick', id, e.target) + }; + var rowMouseover = function (id, e) { + e.preventDefault() + console.log('rowMouseover', id, e.target) + }; + var rowMouseout = function (id, e) { + e.preventDefault() + console.log('rowMouseout', id, e.target) + }; + var colClick = function (id, e) { + e.preventDefault() + console.log('colClick', id, e.target) + }; + var colDblClick = function (id, e) { + e.preventDefault() + console.log('colDblClick', id, e.target) + }; + var colMouseover = function (id, e) { + e.preventDefault() + console.log('colMouseover', id, e.target) + }; + var colMouseout = function (id, e) { + e.preventDefault() + console.log('colMouseout', id, e.target) + }; + + new App.ControllerTable({ + el: el, + overview: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), + checkbox: false, + radio: false, + bindRow: { + events: { + 'click': rowClick, + 'mouseover': rowMouseover, + 'mouseout': rowMouseout, + 'dblclick': rowDblClick, + } + }, + bindCol: { + name: { + events: { + 'click': colClick, + 'mouseover': colMouseover, + 'mouseout': colMouseout, + 'dblclick': colDblClick, + } + }, + created_at: { + events: { + 'mouseover': colMouseover, + 'mouseout': colMouseout, + } + } + }, + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2') + + $('#qunit').append('

        table simple II

        ') + el = $('#table2') + new App.ControllerTable({ + el: el, + overview: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'name', order: 'DESC'}), + checkbox: false, + radio: false, + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'false', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + + $('#qunit').append('

        table simple III

        ') + el = $('#table3') + new App.ControllerTable({ + el: el, + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'created_at', order: 'DESC'}), + checkbox: false, + radio: false, + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.notEqual( el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.notEqual( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.notEqual( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '?', 'check row 2') + assert.notEqual( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.notEqual( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '?', 'check row 1') + assert.notEqual( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'false', 'check row 1') + + + + App.Group.refresh( [ + { + id: 1, + name: 'group 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: 'group 2', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ]) + App.User.refresh( [ + { + id: 55, + login: 'login55', + firstname: 'firstname55', + lastname: 'lastname55', + email: 'email55', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 56, + login: 'login56', + firstname: 'firstname56', + lastname: 'lastname56', + email: 'email56', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ]) + + App.TicketState.refresh( [ + { + id: 1, + name: 'new', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: 'open', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + ]) + App.Ticket.refresh( [ + { + id: 1, + title: 'some title 1', + number: '4711', + priority_id: 1, + owner_id: 55, + customer_id: 56, + state_id: 1, + group_id: 2, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 3, + title: 'some title 3', + number: '4713', + priority_id: 2, + owner_id: 56, + state_id: 1, + group_id: 2, + created_at: '2014-07-11T11:19:34.000Z', + }, + { + id: 2, + title: 'some title 2', + number: '4712', + priority_id: 1, + state_id: 2, + group_id: 1, + created_at: '2014-06-10T11:19:34.000Z', + }, + ]) + $('#qunit').append('

        table complex I

        ') + el = $('#table4') + new App.ControllerTable({ + el: el, + overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], + model: App.Ticket, + objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), + checkbox: true, + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Gruppe', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Status', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(9)').text().trim(), 'Erstellt am', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 9, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), '', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '4713', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '-', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(6)').text().trim(), '2 normal', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(7)').text().trim(), 'group 2', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(8)').text().trim(), 'neu', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(9)').text().trim(), '11.07.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 9, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'group 1', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), 'offen', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 9, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), '', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), '', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '4711', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'some title 1', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(4)').text().trim(), 'firstname55 lastname55', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(5)').text().trim(), 'firstname56 lastname56', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(7)').text().trim(), 'group 2', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(8)').text().trim(), 'neu', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 3') + + el.find('input[name="bulk_all"]').click() + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), true, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), true, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), true, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3') + + $('#qunit').append('

        table complex II

        ') + el = $('#table5') + var clickCheckbox = function (id, checked, e) { + console.log('clickCheckbox', id, checked, e.target) + }; + new App.ControllerTable({ + el: el, + overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], + model: App.Ticket, + objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), + checkbox: true, + groupBy: 'group', + bindCheckbox: { + events: { + 'click': clickCheckbox, + } + }, + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Status', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Erstellt am', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'group 1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 8, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'offen', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 1, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), 'group 2', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 8, 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), '', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1)').text().trim(), '', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(2)').text().trim(), '4713', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(5)').text().trim(), '-', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(6)').text().trim(), '2 normal', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(7)').text().trim(), 'neu', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(8)').text().trim(), '11.07.2014', 'check row 4') + + el.find('input[name="bulk"]:eq(1)').click() + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), true, 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), '', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5') + el.find('tbody > tr:nth-child(5) > td:nth-child(1) label').click() + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), true, 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5') + + + $('#qunit').append('

        table Group By Direction DESC

        ') + el = $('#table6') + var clickCheckbox = function (id, checked, e) { + console.log('clickCheckbox', id, checked, e.target) + }; + new App.ControllerTable({ + el: el, + overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], + model: App.Ticket, + objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), + groupBy: 'priority', + groupDirection: 'DESC', + }) + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '2 normal', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), '1 niedrig', 'check row 3') + + $('#qunit').append('

        table Group By Direction ASC

        ') + el = $('#table7') + var clickCheckbox = function (id, checked, e) { + console.log('clickCheckbox', id, checked, e.target) + }; + new App.ControllerTable({ + el: el, + overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], + model: App.Ticket, + objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), + groupBy: 'priority', + groupDirection: 'ASC', + }) + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1)').text().trim(), '2 normal', 'check row 4') +}); + +QUnit.test('table test 2.1', assert => { + App.i18n.set('de-de') + + $('#qunit').append('

        table with hash

        ') + var el = $('#table-hash2_1') + App.Group.refresh( [ + { + id: 5, + name: 'group 5', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ]) + + App.Channel.configure_delete = true + App.Channel.configure_clone = false + App.Channel.configure_attributes = [ + { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } }, + { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false }, + { name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: true, options: { true: 'yes', false: 'no' }, translate: true, default: true}, + { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, nulloption: true, relation: 'Group' }, + { name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true }, + ] + + App.Channel.refresh( [ + { + id: 1, + adapter: 'adapter1', + options: { + host: 'host1', + user: 'user1', + }, + group_id: 5, + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + adapter: 'adapter2', + options: { + host: 'host2', + user: 'user2', + }, + group_id: 5, + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ] ) + new App.ControllerTable({ + el: el, + overview: ['adapter', 'options::host', 'options::user', 'active'], + model: App.Channel, + objects: App.Channel.search({sortBy:'adapter', order: 'ASC'}), + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Aktion', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-delete').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-clone').length, 0, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-delete').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-clone').length, 0, 'check row 1') +}); + +QUnit.test('table test 2.2', assert => { + App.i18n.set('de-de') + + $('#qunit').append('

        table with hash

        ') + var el = $('#table-hash2_2') + App.Group.refresh( [ + { + id: 5, + name: 'group 5', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ]) + + App.Channel.configure_delete = false + App.Channel.configure_clone = true + App.Channel.configure_attributes = [ + { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } }, + { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false }, + { name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: true, options: { true: 'yes', false: 'no' }, translate: true, default: true}, + { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, nulloption: true, relation: 'Group' }, + { name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true }, + ] + + App.Channel.refresh( [ + { + id: 1, + adapter: 'adapter1', + options: { + host: 'host1', + user: 'user1', + }, + group_id: 5, + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + adapter: 'adapter2', + options: { + host: 'host2', + user: 'user2', + }, + group_id: 5, + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ] ) + new App.ControllerTable({ + el: el, + overview: ['adapter', 'options::host', 'options::user', 'active'], + model: App.Channel, + objects: App.Channel.search({sortBy:'adapter', order: 'ASC'}), + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Aktion', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-delete').length, 0, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-clone').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-delete').length, 0, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-clone').length, 1, 'check row 1') +}); + +QUnit.test('table test 3', assert => { + App.i18n.set('de-de') + + $('#qunit').append('

        table with hash

        ') + var el = $('#table-hash2') + App.Group.refresh( [ + { + id: 5, + name: 'group 5', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ]) + + App.Channel.configure_delete = true + App.Channel.configure_clone = true + App.Channel.configure_attributes = [ + { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } }, + { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false }, + { name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: true, options: { true: 'yes', false: 'no' }, translate: true, default: true}, + { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, + { name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, nulloption: true, relation: 'Group' }, + { name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true }, + ] + + App.Channel.refresh( [ + { + id: 1, + adapter: 'adapter1', + options: { + host: 'host1', + user: 'user1', + }, + group_id: 5, + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + adapter: 'adapter2', + options: { + host: 'host2', + user: 'user2', + }, + group_id: 5, + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ] ) + new App.ControllerTable({ + el: el, + overview: ['adapter', 'options::host', 'options::user', 'active'], + model: App.Channel, + objects: App.Channel.search({sortBy:'adapter', order: 'ASC'}), + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Aktion', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions .js-delete').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions .js-clone').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions .js-delete').length, 1, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions .js-clone').length, 1, 'check row 2') +}); + +QUnit.test('table test 4', assert => { + App.i18n.set('de-de') + + $('#qunit').append('

        table with link

        ') + var el = $('#table-link1') + App.EmailAddress.refresh( [ + { + id: 55, + realname: 'realname 55', + email: 'email 55', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 56, + realname: 'realname 56', + email: 'email 56', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ]) + var callbackHeader = function (header) { + console.log('current header is', header); + // add new header item + var attribute = { + name: 'some name', + display: 'Some Name', + }; + header.push(attribute); + console.log('new header is', header); + return header + } + var callbackAttributes = function(value, object, attribute, header, refObject) { + console.log('data of item col', value, object, attribute, header, refObject) + value = ' ' + attribute.class = 'glyphicon glyphicon-user' + attribute.link = '#' + attribute.title = App.i18n.translateInline('Switch to') + if (object.id == 55) { + attribute.data = { + some: 'value55', + xxx: 55, + } + } + else { + attribute.data = { + some: 'value56', + xxx: 56, + } + } + return value + } + var switchTo = function(id, e) { + e.preventDefault() + console.log('switchTo with id', id, e.target) + //@disconnectClient() + //App.Auth._logout() + //window.location = App.Config.get('api_path') + '/sessions/switch/' + id + } + new App.ControllerTable({ + el: el, + model: App.EmailAddress, + objects: App.EmailAddress.search({sortBy:'realname', order: 'ASC'}), + callbackHeader: [callbackHeader], + callbackAttributes: { + 'some name': [ callbackAttributes ] + }, + bindCol: { + 'some name': { + events: { + 'click': switchTo, + } + }, + }, + }) + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Anzeigename', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Some Name', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'realname 55', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'email 55', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), '', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('some'), 'value55', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('xxx'), '55', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'realname 56', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'email 56', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('some'), 'value56', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('xxx'), '56', 'check row 2') + +}); + +QUnit.test('table test 5', assert => { + App.i18n.set('de-de') + + $('#qunit').append('

        table with data

        ') + var el = $('#table-data1') + + data = [ + { name: 'some name 1', data: 'some data 1', active: true }, + { name: 'some name 2', data: 'some data 2', active: false }, + { name: 'some name 3', data: 'some data 3', active: true }, + ] + new App.ControllerTable({ + el: el, + overview: ['name', 'data', 'active'], + attribute_list: [ + { name: 'name', display: 'Name', type: 'text', style: 'width: 10%' }, + { name: 'data', display: 'Data', type: 'text' }, + { name: 'active', display: 'Active', type: 'text' }, + ], + objects: data + }); + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Data', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some name 1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'some data 1', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), 'some name 2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'some data 2', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2') +}); + +QUnit.test('table test 6/7', assert => { + $('#qunit').append('

        sotable table with data

        ') + var el_head_sortable = $('#table-data6') + + $('#qunit').append('

        not sortable table with data

        ') + var el_not_head_sortable = $('#table-data7') + + data = [ + { name: 'a item', data: 'g data', active: true }, + { name: 'b item', data: 'b data', active: false }, + { name: 'c item', data: 'z data', active: false }, + { name: 'd item', data: '', active: false }, + ] + + new App.ControllerTable({ + tableId: 'a', + el: el_head_sortable, + overview: ['name', 'data', 'active'], + attribute_list: [ + { name: 'name', display: 'Name', type: 'text', style: 'width: 10%', unsortable: true }, + { name: 'data', display: 'Data', type: 'text' }, + { name: 'active', display: 'Active', type: 'text' }, + ], + objects: data + }); + + new App.ControllerTable({ + tableId: 'b', + el: el_not_head_sortable, + overview: ['name', 'data', 'active'], + attribute_list: [ + { name: 'name', display: 'Name', type: 'text', style: 'width: 10%', unsortable: true }, + { name: 'data', display: 'Data', type: 'text' }, + { name: 'active', display: 'Active', type: 'text' }, + ], + objects: data, + dndCallback: function() { return true } + }); + + assert.equal(el_head_sortable.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'a item', 'check row 1') + assert.equal(el_not_head_sortable.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'a item', 'check row 1') + + assert.ok(_.isEqual(list_items(el_head_sortable, 1), ['a item', 'b item', 'c item', 'd item']), 'sortable table is rendered correctly') + assert.ok(_.isEqual(list_items(el_not_head_sortable, 2), ['a item', 'b item', 'c item', 'd item']), 'unsortable table is rendered correctly') + + click_sort(el_head_sortable, 2) + click_sort(el_not_head_sortable, 3) + + assert.ok(_.isEqual(list_items(el_head_sortable, 1), ['b item', 'a item', 'c item', 'd item']), 'sortable table is sorted') + assert.ok(_.isEqual(list_items(el_not_head_sortable, 2), ['a item', 'b item', 'c item', 'd item']), 'unsortable table is not sorted') + + click_sort(el_head_sortable, 3) + assert.ok(_.isEqual(list_items(el_head_sortable, 1), ['b item', 'c item', 'd item', 'a item']), 'sorting by boolean column works') + + click_sort(el_head_sortable, 1) + assert.ok(_.isEqual(list_items(el_head_sortable, 1), ['b item', 'c item', 'd item', 'a item']), 'sorting on name column is disabled') +}); + +function click_sort(table, column_number) { + table + .find(`table > thead > tr > th:nth-child(${column_number}) > .js-sort`) + .click() +} + +function list_items(table, column_number) { + return table + .find(`tbody > tr > td:nth-child(${column_number})`) + .text() + .split("\n") + .filter(elem => elem.match(/[\w]+/)) + .map(elem => elem.trim()) +} diff --git a/public/assets/tests/qunit/table_extended.js b/public/assets/tests/qunit/table_extended.js new file mode 100644 index 000000000..25eb2e933 --- /dev/null +++ b/public/assets/tests/qunit/table_extended.js @@ -0,0 +1,1777 @@ +// initial list +QUnit.test('table new - initial list', assert => { + App.i18n.set('de-de') + + $('#qunit').append('

        table with data

        ') + var el = $('#table-new1') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + ], {clear: true}) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), + checkbox: false, + radio: false, + }) + //equal(el.find('table').length, 0, 'row count') + //table.render() + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'noChanges') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + + App.TicketPriority.refresh([ + { + id: 1, + name: 'Priority', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.lenghtChanged') + assert.equal(result[1], 2) + assert.equal(result[2], 1) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'Priorität', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 0, 'check row 2') + + App.TicketPriority.refresh([], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'emptyList') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], undefined) + assert.equal(result[2][0], 2) + assert.equal(result[2][1], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4') + + result = table.update({sync: true, orderDirection: 'DESC', orderBy: 'name'}) + assert.equal(result[0], 'fullRender.contentChanged') + assert.equal(result[1], 0) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '1 niedrig', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4') + + result = table.update({sync: true, orderDirection: 'ASC', orderBy: 'name'}) + assert.equal(result[0], 'fullRender.contentChanged') + assert.equal(result[1], 0) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], 1) + assert.equal(result[1][1], undefined) + assert.notOk(result[1][1]) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') + + result = table.update({sync: true, overviewAttributes: ['name', 'created_at']}) + assert.equal(result[0], 'fullRender.overviewAttributesChanged') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th').length, 2, 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 2, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 2, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') + + App.TicketPriority.refresh([], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'emptyList') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), overviewAttributes: ['name'], orderBy: 'created_at', orderDirection: 'DESC'}) + assert.equal(result[0], 'fullRender') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th').length, 1, 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), overviewAttributes: ['name'], orderBy: 'created_at', orderDirection: 'ASC'}) + assert.equal(result[0], 'fullRender.overviewAttributesChanged') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th').length, 1, 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') + + $('#qunit').append('

        table group by with data

        ') + var el = $('#table-new2') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some other note', + active: true, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), + checkbox: false, + radio: false, + groupBy: 'note', + }) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 1, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td:first').text().trim(), 'some other note', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(5) > td:first').text().trim(), '3 hoch', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(3)').text().trim(), 'true', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(6) > td').length, 0, 'check row 6') + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'noChanges') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 6') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some other note', + active: true, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], undefined) + assert.equal(result[2][0], 3) + assert.equal(result[2][1], 4) + assert.equal(result[2][2], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 1, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td:first').text().trim(), 'some other note', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(5) > td:first').text().trim(), '3 hoch', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(5) > td:nth-child(3)').text().trim(), 'true', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(6) > td').length, 0, 'check row 6') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some other note', + active: true, + created_at: '2014-06-10T10:17:38.000Z', + }, + { + id: 4, + name: '4 high', + note: 'some other note', + active: true, + created_at: '2014-06-10T10:17:39.000Z', + }, + { + id: 5, + name: '5 high', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:39.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], undefined) + assert.equal(result[2][0], 3) + assert.equal(result[2][1], 6) + assert.equal(result[2][2], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 3, 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:first').text().trim(), '5 high', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(4) > td:nth-child(3)').text().trim(), 'true', 'check row 4') + assert.equal(el.find('tbody > tr:nth-child(5) > td').length, 1, 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(5) > td:first').text().trim(), 'some other note', 'check row 5') + assert.equal(el.find('tbody > tr:nth-child(6) > td:first').text().trim(), '3 hoch', 'check row 6') + assert.equal(el.find('tbody > tr:nth-child(6) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 6') + assert.equal(el.find('tbody > tr:nth-child(6) > td:nth-child(3)').text().trim(), 'true', 'check row 6') + assert.equal(el.find('tbody > tr:nth-child(7) > td').length, 3, 'check row 7') + assert.equal(el.find('tbody > tr:nth-child(7) > td:first').text().trim(), '4 high', 'check row 7') + assert.equal(el.find('tbody > tr:nth-child(7) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 7') + assert.equal(el.find('tbody > tr:nth-child(7) > td:nth-child(3)').text().trim(), 'true', 'check row 7') + assert.equal(el.find('tbody > tr:nth-child(8) > td').length, 0, 'check row 8') + + $('#qunit').append('

        table with large data

        ') + var el = $('#table-new3') + + var objects = []; + var created_at = Date.parse('2014-06-10T11:17:34.000Z') + + for (i = 0; i < 1000; i++) { + local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() + item = { + id: i, + name: i + ' prio', + note: 'some note', + active: true, + created_at: local_created_at, + } + objects.push(item) + } + + App.TicketPriority.refresh(objects.reverse(), {clear: true}) + + var table = new App.ControllerTable({ + tableId: 'large_table_test', + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.all(), + checkbox: false, + radio: false, + ttt: true + }) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) + el.find('.js-tableHead[data-column-key="name"] .js-sort').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '10 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '31.05.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-up').length, 1) + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-down').length, 0) + el.find('.js-tableHead[data-column-key="name"] .js-sort').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-down').length, 1) + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-up').length, 0) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon').length, 0) + el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 0) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 1) + el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 1) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 0) + + objects = App.TicketPriority.all().reverse() + objects.shift() + objects.shift() + + result = table.update({sync: true, objects: objects}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], 1) + assert.equal(result[1][1], 0) + assert.equal(result[2][0], 148) + assert.equal(result[2][1], 149) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '07.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(149) > td:first').text().trim(), '150 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(149) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(149) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(150) > td:first').text().trim(), '151 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(150) > td:nth-child(2)').text().trim(), '10.01.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(150) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 1) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 0) + el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 0) + assert.equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 1) + + el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '07.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(149) > td:first').text().trim(), '150 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(149) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(149) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(150) > td:first').text().trim(), '151 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(150) > td:nth-child(2)').text().trim(), '10.01.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(150) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + $('#qunit').append('

        table with now data

        ') + var el = $('#table-new4') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + ], {clear: true}) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), + checkbox: false, + radio: false, + }) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 0) + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], undefined) + assert.equal(result[2][0], 1) + assert.equal(result[2][1], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0) + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some note 3', + active: true, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], undefined) + assert.equal(result[2][0], 2) + assert.equal(result[2][1], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0) + + App.TicketPriority.refresh([ + { + id: 3, + name: '3 high', + note: 'some note 3', + active: true, + created_at: '2014-06-10T10:17:38.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], 0) + assert.equal(result[1][1], undefined) + assert.equal(result[2][0], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0) + + App.TicketPriority.refresh([ + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.lenghtChanged') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 0) + + App.TicketPriority.refresh([], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'emptyList') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1') + + App.TicketPriority.refresh([ + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 0) + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], undefined) + assert.equal(result[2][0], 0) + assert.equal(result[2][1], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0) + + App.TicketPriority.refresh([ + { + id: 2, + name: '2 normal', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.lenghtChanged') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3) + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 0) + + $('#qunit').append('

        table with large data and pager

        ') + var el = $('#table-new5') + + var objects = []; + var created_at = Date.parse('2014-06-10T11:17:34.000Z') + + for (i = 0; i < 151; i++) { + local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() + item = { + id: i, + name: i + ' prio', + note: 'some note', + active: true, + created_at: local_created_at, + } + objects.push(item) + } + + App.TicketPriority.refresh(objects, {clear: true}) + + var table = new App.ControllerTable({ + tableId: 'large_table_test_pager', + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.all(), + checkbox: false, + radio: false, + ttt: true + }) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-pager').first().find('.js-page').length, 2) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') + el.find('.js-pager').first().find('.js-page:nth-child(2)').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '150 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr').length, 1) + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 0) + + objects = [ + { + id: 500, + name: '500 prio', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ] + + App.TicketPriority.refresh(objects) + + result = table.update({sync: true, objects: App.TicketPriority.all()}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], undefined) + assert.equal(result[2][0], 1) + assert.equal(result[2][1], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '150 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '500 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr').length, 2) + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0) + + objects = App.TicketPriority.all() + objects.splice(2,1) + result = table.update({sync: true, objects: objects}) + assert.equal(result[0], 'fullRender.lenghtChanged') + //equal(result[1][0], 1) + //equal(result[1][1], undefined) + //equal(result[2][0], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '500 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr').length, 1) + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 0) + + objects.splice(2,1) + result = table.update({sync: true, objects: objects}) + + assert.equal(result[0], 'fullRender.lenghtChanged') + //equal(result[0], 'fullRender.contentRemoved') + //equal(result[1][0], 1) + //equal(result[1][1], undefined) + //equal(result[2][0], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-pager').first().find('.js-page').length, 0) + + objects = [ + { + id: 500, + name: '500 prio', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ] + App.TicketPriority.refresh(objects) + + objects = App.TicketPriority.all() + + result = table.update({sync: true, objects: objects}) + assert.equal(result[0], 'fullRender.contentRemoved') + + assert.equal(el.find('.js-pager').first().find('.js-page').length, 2) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') + el.find('.js-pager').first().find('.js-page:nth-child(2)').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '150 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '500 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr').length, 2) + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0) + + assert.equal(el.find('.js-pager').first().find('.js-page').length, 2) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '2') + el.find('.js-pager').first().find('.js-page:nth-child(1)').click() + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-pager').first().find('.js-page').length, 2) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') + + objects.splice(2,2) + + result = table.update({sync: true, objects: objects}) + assert.equal(result[0], 'fullRender.contentRemoved') + + assert.equal(el.find('.js-pager').first().find('.js-page').length, 0) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + objects = [ + { + id: 501, + name: '501 prio', + note: 'some note', + active: true, + created_at: '2014-06-10T10:17:30.000Z', + }, + ] + App.TicketPriority.refresh(objects) + objects = App.TicketPriority.all() + + result = table.update({sync: true, objects: objects}) + assert.equal(result[0], 'fullRender.contentRemoved') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') + assert.equal(el.find('tbody > tr').length, 150) + assert.equal(el.find('tbody > tr:nth-child(151) > td').length, 0) + + assert.equal(el.find('.js-pager').first().find('.js-page').length, 2) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) + assert.equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') + + $('#qunit').append('

        table with data 7

        ') + var el = $('#table-new7') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), + checkbox: false, + radio: false, + }) + //equal(el.find('table').length, 0, 'row count') + //table.render() + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-12T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'fullRender.contentRemoved') + assert.equal(result[1][0], 0) + assert.equal(result[1][1], undefined) + assert.equal(result[2][0], 0) + assert.equal(result[2][1], undefined) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') + + $('#qunit').append('

        table with data 8

        ') + var el = $('#table-new8') + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note', + active: true, + created_at: '2014-06-12T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + { + id: 3, + name: '3 high', + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.all(), + checkbox: false, + radio: false, + orderBy: 'not_existing', + orderDirection: 'DESC', + }) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') + + result = table.update({sync: true, objects: App.TicketPriority.all(), orderBy: 'not_existing', orderDirection: 'ASC'}) + assert.equal(result[0], 'noChanges') + + $('#qunit').append('

        table with data 9

        ') + var el = $('#table-new9') + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + external_id: 3, + note: 'some note', + active: true, + created_at: '2014-06-12T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + external_id: 2, + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + { + id: 3, + name: '3 high', + external_id: 1, + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + + App.TicketPriority.resetAttributes() + App.TicketPriority.updateAttributes([{ + name: 'external_id', + display: 'External', + tag: 'input', + readonly: 1, + }]) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.all(), + checkbox: false, + radio: false, + orderBy: 'external', + orderDirection: 'DESC', + }) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') + + result = table.update({sync: true, objects: App.TicketPriority.all(), orderBy: 'external', orderDirection: 'ASC'}) + assert.equal(result[0], 'fullRender.contentChanged') + assert.equal(result[1], 0) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') + + $('#qunit').append('

        table with data 10

        ') + var el = $('#table-new10') + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + external_id: 3, + note: 'some note', + active: true, + created_at: '2014-06-12T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + external_id: 2, + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + { + id: 3, + name: '3 high', + external_id: 1, + note: 'some note 3', + active: false, + created_at: '2014-06-10T10:17:38.000Z', + }, + ], {clear: true}) + App.TicketPriority.resetAttributes() + App.TicketPriority.updateAttributes([{ + name: 'external', + display: 'External', + tag: 'input', + readonly: 1, + }]) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.all(), + checkbox: false, + radio: false, + orderBy: 'external', + orderDirection: 'ASC', + }) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') + + result = table.update({sync: true, objects: App.TicketPriority.all(), orderBy: 'external', orderDirection: 'DESC'}) + assert.equal(result[0], 'fullRender.contentChanged') + assert.equal(result[1], 0) + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + + assert.equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') + + $('#qunit').append('

        table with data 11

        ') + var el = $('#table-new11') + + App.TicketPriority.refresh([ + { + id: 1, + name: '1 low', + note: 'some note 1', + active: true, + created_at: '2014-06-10T11:17:34.000Z', + }, + { + id: 2, + name: '2 normal', + note: 'some note 2', + active: false, + created_at: '2014-06-10T10:17:34.000Z', + }, + ], {clear: true}) + + var table = new App.ControllerTable({ + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), + checkbox: false, + radio: false, + frontendTimeUpdateExecute: false, + }) + //equal(el.find('table').length, 0, 'row count') + //table.render() + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') + + result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) + assert.equal(result[0], 'noChanges') + + assert.equal(el.find('table > thead > tr').length, 1, 'row count') + assert.equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') + assert.equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') + assert.equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') + assert.equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') + assert.equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '', 'check row 2') + + $('#qunit').append('

        table with large data and pager and 10 per page

        ') + var el = $('#table-new12') + + var objects = []; + var created_at = Date.parse('2014-06-10T11:17:34.000Z') + + for (i = 0; i < 35; i++) { + local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() + item = { + id: i, + name: i + ' prio', + note: 'some note', + active: true, + created_at: local_created_at, + } + objects.push(item) + } + + App.TicketPriority.refresh(objects, {clear: true}) + + var table = new App.ControllerTable({ + tableId: 'large_table_test_pager', + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.all(), + checkbox: false, + radio: false, + pagerItemsPerPage: 10, + ttt: true + }) + + assert.equal(el.find('tbody > tr').length, 10) + assert.equal(el.find('.js-pager:first-child .js-page').length, 4) + + $('#qunit').append('

        table with large data and pager disabled

        ') + var el = $('#table-new13') + + var objects = []; + var created_at = Date.parse('2014-06-10T11:17:34.000Z') + + for (i = 0; i < 200; i++) { + local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() + item = { + id: i, + name: i + ' prio', + note: 'some note', + active: true, + created_at: local_created_at, + } + objects.push(item) + } + + App.TicketPriority.refresh(objects, {clear: true}) + + var table = new App.ControllerTable({ + tableId: 'large_table_test_pager', + el: el, + overviewAttributes: ['name', 'created_at', 'active'], + model: App.TicketPriority, + objects: App.TicketPriority.all(), + checkbox: false, + radio: false, + pagerEnabled: false, + ttt: true + }) + + assert.equal(el.find('tbody > tr').length, 200) + assert.equal(el.find('.js-pager:first-child .js-page').length, 0) +}) diff --git a/public/assets/tests/qunit/taskbar.js b/public/assets/tests/qunit/taskbar.js new file mode 100644 index 000000000..ce1dc15f2 --- /dev/null +++ b/public/assets/tests/qunit/taskbar.js @@ -0,0 +1,316 @@ +window.onload = function() { + +QUnit.test( "taskbar basic tests", assert => { + // create task bar div + $('#qunit').append('

        taskbar basic tests

        ') + App.TaskManager.init({ + el: $('#taskbar1'), + offlineModus: true, + force: true, + }) + + // add tasks + App.TaskManager.execute({ + key: 'TestKey1', + controller: 'TestController1', + params: { + message: '#1', + }, + show: true, + persistent: false, + }) + assert.equal($('#qunit .content').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#1',show:'true',hide:'false',active:'true'", "check active content!") + + // verify + task = App.TaskManager.get('TestKey1') + assert.equal(task.notify, false) + assert.deepEqual(task.state, undefined) + assert.deepEqual(task.params, { "message": "#1", "shown": true }) + + // update + App.TaskManager.update('TestKey1', { 'state': 'abc' }) + App.TaskManager.update('TestKey1', { 'params': { a: 12 } }) + App.TaskManager.notify('TestKey1') + + // verify + task = App.TaskManager.get('TestKey1') + assert.equal(task.notify, true) + assert.deepEqual(task.state, 'abc') + assert.deepEqual(task.params, { "a": 12 }) + + App.TaskManager.execute({ + key: 'TestKey2', + controller: 'TestController1', + params: { + message: '#2', + }, + show: true, + persistent: false, + }) + assert.equal($('#qunit .content').length, 2, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'", "check active content!") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'", "check active content!") + + // check task history + assert.equal(App.TaskManager.nextTaskUrl(), '#/some/url/#2') + assert.equal(App.TaskManager.nextTaskUrl(), '#/some/url/#1') + + App.TaskManager.execute({ + key: 'TestKey3', + controller: 'TestController1', + params: { + message: '#3', + }, + show: false, + persistent: false, + }) + assert.equal($('#qunit .content').length, 2, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'", "check active content!") + + App.TaskManager.execute({ + key: 'TestKey3', + controller: 'TestController1', + params: { + message: '#3', + }, + show: true, + persistent: false, + }) + assert.equal($('#qunit .content').length, 3, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") + + App.TaskManager.execute({ + key: 'TestKey4', + controller: 'TestController1', + params: { + message: '#4', + }, + show: false, + persistent: true, + }) + assert.equal($('#qunit .content').length, 3, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") + + App.TaskManager.execute({ + key: 'TestKey5', + controller: 'TestController1', + params: { + message: '#5', + }, + show: true, + persistent: true, + }) + assert.equal($('#qunit .content').length, 4, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#5',show:'true',hide:'false',active:'true'") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'false',active:'true'", "check active content!") + + App.TaskManager.execute({ + key: 'TestKey6', + controller: 'TestController1', + params: { + message: '#6', + }, + show: true, + persistent: false, + }) + assert.equal($('#qunit .content').length, 5, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'", "check active content!") + + // remove task#2 + App.TaskManager.remove('TestKey2') + + assert.equal($('#qunit .content').length, 4, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'", "check active content!") + + // activate task#3 + App.TaskManager.execute({ + key: 'TestKey3', + controller: 'TestController1', + params: { + message: '#3', + }, + show: true, + persistent: false, + }) + assert.equal($('#qunit .content').length, 4, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'true',active:'false'", "check active content!") + + + // activate task#1 + App.TaskManager.execute({ + key: 'TestKey1', + controller: 'TestController1', + params: { + message: '#1', + }, + show: true, + persistent: false, + }) + assert.equal($('#qunit .content').length, 4, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#1',show:'true',hide:'true',active:'true'") + + assert.equal($('#qunit #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'true'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") + assert.equal($('#qunit #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'true',active:'false'", "check active content!") + + // remove task#1 + App.TaskManager.remove('TestKey1') + + // verify if task#3 is active + assert.equal($('#qunit .content').length, 3, "check available active contents") + assert.equal($('#qunit .content.active').length, 0, "check available active contents") + assert.equal($('#qunit .content.active').text(), "") + + // remove task#3 + App.TaskManager.remove('TestKey3') + + // verify if task#5 is active + assert.equal($('#qunit .content').length, 2, "check available active contents") + assert.equal($('#qunit .content.active').length, 0, "check available active contents") + assert.equal($('#qunit .content.active').text(), "") + + // remove task#5 // can not get removed because of permanent task + App.TaskManager.remove('TestKey5') + + // verify if task#5 is active + assert.equal($('#qunit .content').length, 2, "check available active contents") + assert.equal($('#qunit .content.active').length, 0, "check available active contents") + assert.equal($('#qunit .content.active').text(), "") + + // create task#7 + App.TaskManager.execute({ + key: 'TestKey7', + controller: 'TestController1', + params: { + message: '#7', + }, + show: true, + persistent: false, + }) + assert.equal($('#qunit .content').length, 3, "check available active contents") + assert.equal($('#qunit .content.active').length, 1, "check available active contents") + assert.equal($('#qunit .content.active').text(), "some test controller message:'#7',show:'true',hide:'false',active:'true'", "check active content!") + + // remove task#7 + App.TaskManager.remove('TestKey7') + + // verify if task#5 is active + assert.equal($('#qunit .content').length, 2, "check available active contents") + assert.equal($('#qunit .content.active').length, 0, "check available active contents") + assert.equal($('#qunit .content.active').text(), "") + + // check task history + assert.equal(App.TaskManager.nextTaskUrl(), '#/some/url/#6') + assert.equal(App.TaskManager.nextTaskUrl(), '#/some/url/#5') + assert.equal(App.TaskManager.nextTaskUrl(), '#/some/url/#6') + assert.equal(App.TaskManager.nextTaskUrl(), '#/some/url/#6') + + // remove task#6 + App.TaskManager.remove('TestKey6') + + // check task history + assert.equal(App.TaskManager.nextTaskUrl(), false) + assert.equal(App.TaskManager.nextTaskUrl(), false) + + // check max tabs + var times = 5; + App.TaskManager.tasksAutoCleanupDelayTime(200) + App.TaskManager.tasksAutoCleanupTaskMax(3) + + for(var i=0; i < times; i++){ + App.TaskManager.execute({ + key: 'TestKeyLoop' + i, + controller: 'TestController1', + params: { + message: "#" + i, + }, + show: true, + persistent: false, + }) + } + assert.equal(App.TaskManager.all().length, 5) + +}) + +App.Delay.set(function() { + QUnit.test( "taskbar check max tabs 2", assert => { + + assert.equal(App.TaskManager.all().length, 3) + + var times = 5; + for(var i=0; i < times; i++){ + App.TaskManager.execute({ + key: 'TestKeyLoop2' + i, + controller: 'TestController1', + params: { + message: "#" + i, + changedState: true + }, + show: true, + persistent: false, + }) + } + assert.equal(App.TaskManager.all().length, 8) + + }) +}, 1000); + +App.Delay.set(function() { + QUnit.test( "taskbar check max tabs 5", assert => { + + assert.equal(App.TaskManager.all().length, 5) + + // destroy task bar + App.TaskManager.reset() + + // check if any taskar exists + assert.equal($('#qunit .content').length, 0, "check available active contents") + }) +}, 2000); + +} diff --git a/public/assets/tests/text_module.js b/public/assets/tests/qunit/text_module.js similarity index 67% rename from public/assets/tests/text_module.js rename to public/assets/tests/qunit/text_module.js index 06d023a4e..c5e7d8ef9 100644 --- a/public/assets/tests/text_module.js +++ b/public/assets/tests/qunit/text_module.js @@ -1,5 +1,5 @@ // text module -test('test text module behaviour with group_ids', function() { +QUnit.test('test text module behaviour with group_ids', assert => { // active textmodule without group_ids App.TextModule.refresh([ @@ -46,9 +46,9 @@ test('test text module behaviour with group_ids', function() { var currentCollection = textModule.currentCollection(); - equal(currentCollection.length, 2, 'active textmodule') - equal(currentCollection[0].id, 1) - equal(currentCollection[1].id, 3) + assert.equal(currentCollection.length, 2, 'active textmodule') + assert.equal(currentCollection[0].id, 1) + assert.equal(currentCollection[1].id, 3) // trigered TextModulePreconditionUpdate with group_id @@ -59,9 +59,9 @@ test('test text module behaviour with group_ids', function() { currentCollection = textModule.currentCollection(); - equal(currentCollection.length, 2, 'trigered TextModulePreconditionUpdate with group_id') - equal(currentCollection[0].id, 1) - equal(currentCollection[1].id, 3) + assert.equal(currentCollection.length, 2, 'trigered TextModulePreconditionUpdate with group_id') + assert.equal(currentCollection[0].id, 1) + assert.equal(currentCollection[1].id, 3) // trigered TextModulePreconditionUpdate with wrong group_id @@ -72,8 +72,8 @@ test('test text module behaviour with group_ids', function() { currentCollection = textModule.currentCollection(); - equal(currentCollection.length, 1, 'trigered TextModulePreconditionUpdate with wrong group_id') - equal(currentCollection[0].id, 1) + assert.equal(currentCollection.length, 1, 'trigered TextModulePreconditionUpdate with wrong group_id') + assert.equal(currentCollection[0].id, 1) // trigered TextModulePreconditionUpdate with group_id but wrong taskKey @@ -84,8 +84,8 @@ test('test text module behaviour with group_ids', function() { currentCollection = textModule.currentCollection(); - equal(currentCollection.length, 1, 'trigered TextModulePreconditionUpdate with group_id but wrong taskKey - nothing has changed') - equal(currentCollection[0].id, 1) + assert.equal(currentCollection.length, 1, 'trigered TextModulePreconditionUpdate with group_id but wrong taskKey - nothing has changed') + assert.equal(currentCollection[0].id, 1) // trigered TextModulePreconditionUpdate without group_id @@ -96,8 +96,8 @@ test('test text module behaviour with group_ids', function() { currentCollection = textModule.currentCollection(); - equal(currentCollection.length, 2, 'trigered TextModulePreconditionUpdate without group_id') - equal(currentCollection[0].id, 1) - equal(currentCollection[1].id, 3) + assert.equal(currentCollection.length, 2, 'trigered TextModulePreconditionUpdate without group_id') + assert.equal(currentCollection[0].id, 1) + assert.equal(currentCollection[1].id, 3) }); diff --git a/public/assets/tests/ticket_macro.js b/public/assets/tests/qunit/ticket_macro.js similarity index 89% rename from public/assets/tests/ticket_macro.js rename to public/assets/tests/qunit/ticket_macro.js index 0cd63d8ba..a6ec4d9cf 100644 --- a/public/assets/tests/ticket_macro.js +++ b/public/assets/tests/qunit/ticket_macro.js @@ -20,7 +20,7 @@ QUnit.module("ticket macro pending time check", hooks => { return new Date(ticket.pending_time) - new Date() } - test("5 days", assert => { + QUnit.test("5 days", assert => { var rules = { operator: "relative", range: "day", @@ -30,7 +30,7 @@ QUnit.module("ticket macro pending time check", hooks => { assert.equal(calculate_travel_on_ticket(rules), 60 * 60 * 24 * 5 * 1000) }) - test("5 minutes", assert => { + QUnit.test("5 minutes", assert => { var rules = { operator: "relative", range: "minute", @@ -40,7 +40,7 @@ QUnit.module("ticket macro pending time check", hooks => { assert.equal(calculate_travel_on_ticket(rules), 60 * 3 * 1000) }); - test("10 hours", assert => { + QUnit.test("10 hours", assert => { var rules = { operator: "relative", range: "hour", diff --git a/public/assets/tests/ticket_selector.js b/public/assets/tests/qunit/ticket_selector.js similarity index 69% rename from public/assets/tests/ticket_selector.js rename to public/assets/tests/qunit/ticket_selector.js index c4bd22083..0f1f4df1b 100644 --- a/public/assets/tests/ticket_selector.js +++ b/public/assets/tests/qunit/ticket_selector.js @@ -186,7 +186,7 @@ window.onload = function() { * ------------------------------------------------------------------------ */ - var testContains = function (key, value, ticket) { + var testContains = function (assert, key, value, ticket) { setting = { "condition": { [key]: { @@ -196,7 +196,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -207,10 +207,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); }; - var testIs = function (key, value, ticket) { + var testIs = function (assert, key, value, ticket) { setting = { "condition": { [key]: { @@ -220,7 +220,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -231,10 +231,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); }; - var testPreConditionUser = function (key, specificValue, ticket, session) { + var testPreConditionUser = function (assert, key, specificValue, ticket, session) { App.Session.set(6); setting = { @@ -248,7 +248,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -261,7 +261,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -275,7 +275,7 @@ window.onload = function() { }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -288,7 +288,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -301,7 +301,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -312,7 +312,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -323,10 +323,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); }; - var testPreConditionOrganization = function (key, specificValue, ticket, session) { + var testPreConditionOrganization = function (assert, key, specificValue, ticket, session) { App.Session.set(6); setting = { @@ -340,7 +340,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -353,7 +353,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -367,7 +367,7 @@ window.onload = function() { }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -380,7 +380,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -393,7 +393,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -404,7 +404,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -415,10 +415,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); }; - var testPreConditionTags = function (key, ticket) { + var testPreConditionTags = function (assert, key, ticket) { App.Session.set(6); setting = { @@ -430,7 +430,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -441,7 +441,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -452,7 +452,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -463,7 +463,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -474,7 +474,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -485,7 +485,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -496,7 +496,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -507,7 +507,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -518,7 +518,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -529,7 +529,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); setting = { "condition": { @@ -540,7 +540,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); setting = { "condition": { @@ -551,11 +551,11 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); }; - var testTime = function (key, value, ticket) { + var testTime = function (assert, key, value, ticket) { valueDate = new Date(value); compareDate = new Date( valueDate.setHours( valueDate.getHours() - 1 ) ).toISOString(); setting = { @@ -567,7 +567,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); valueDate = new Date(value); compareDate = new Date( valueDate.setHours( valueDate.getHours() + 1 ) ).toISOString(); @@ -580,7 +580,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); valueDate = new Date(value); compareDate = new Date( valueDate.setHours( valueDate.getHours() - 1 ) ).toISOString(); @@ -593,7 +593,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, false, result); + assert.equal(result, false, result); valueDate = new Date(value); compareDate = new Date( valueDate.setHours( valueDate.getHours() + 1 ) ).toISOString(); @@ -606,7 +606,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); valueDate = new Date(value); compareDate = new Date( valueDate.setHours( valueDate.getHours() + 2 ) ).toISOString(); @@ -620,10 +620,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, true, result); + assert.equal(result, true, result); }; - var testTimeBeforeRelative = function (key, value, range, expectedResult, ticket) { + var testTimeBeforeRelative = function (assert, key, value, range, expectedResult, ticket) { setting = { "condition": { [key]: { @@ -634,10 +634,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, expectedResult, result); + assert.equal(result, expectedResult, result); }; - var testTimeAfterRelative = function (key, value, range, expectedResult, ticket) { + var testTimeAfterRelative = function (assert, key, value, range, expectedResult, ticket) { setting = { "condition": { [key]: { @@ -648,10 +648,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, expectedResult, result); + assert.equal(result, expectedResult, result); }; - var testTimeWithinNextRelative = function (key, value, range, expectedResult, ticket) { + var testTimeWithinNextRelative = function (assert, key, value, range, expectedResult, ticket) { setting = { "condition": { [key]: { @@ -662,10 +662,10 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, expectedResult, result); + assert.equal(result, expectedResult, result); }; - var testTimeWithinLastRelative = function (key, value, range, expectedResult, ticket) { + var testTimeWithinLastRelative = function (assert, key, value, range, expectedResult, ticket) { setting = { "condition": { [key]: { @@ -676,7 +676,7 @@ window.onload = function() { } }; result = App.Ticket.selector(ticket, setting['condition']); - equal(result, expectedResult, result); + assert.equal(result, expectedResult, result); }; /* @@ -685,64 +685,64 @@ window.onload = function() { * ------------------------------------------------------------------------ */ - test("ticket number", function() { + QUnit.test("ticket number", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('ticket.number', '72', ticket); + testContains(assert, 'ticket.number', '72', ticket); }); - test("ticket title", function() { + QUnit.test("ticket title", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('ticket.title', 'asd', ticket); + testContains(assert, 'ticket.title', 'asd', ticket); }); - test("ticket customer_id", function() { + QUnit.test("ticket customer_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); App.Session.set(6); - testPreConditionUser('ticket.customer_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'ticket.customer_id', '6', ticket, sessionData); }); - test("ticket organization_id", function() { + QUnit.test("ticket organization_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionUser('ticket.organization_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'ticket.organization_id', '6', ticket, sessionData); }); - test("ticket group_id", function() { + QUnit.test("ticket group_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('ticket.group_id', ['1'], ticket, sessionData); + testIs(assert, 'ticket.group_id', ['1'], ticket, sessionData); }); - test("ticket owner_id", function() { + QUnit.test("ticket owner_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); App.Session.set(6); - testPreConditionUser('ticket.owner_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'ticket.owner_id', '6', ticket, sessionData); }); - test("ticket state_id", function() { + QUnit.test("ticket state_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('ticket.state_id', ['4'], ticket, sessionData); + testIs(assert, 'ticket.state_id', ['4'], ticket, sessionData); }); - test("ticket pending_time", function() { + QUnit.test("ticket pending_time", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.pending_time', ticket.pending_time, ticket); + testTime(assert, 'ticket.pending_time', ticket.pending_time, ticket); // ------------------------- // BEFORE TIME @@ -750,30 +750,30 @@ window.onload = function() { // hour ticket.pending_time = new Date().toISOString(); - testTimeBeforeRelative('ticket.pending_time', 1, 'hour', false, ticket); + testTimeBeforeRelative(assert, 'ticket.pending_time', 1, 'hour', false, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() - 60 * 60 * 2 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeBeforeRelative('ticket.pending_time', 1, 'hour', true, ticket); + testTimeBeforeRelative(assert, 'ticket.pending_time', 1, 'hour', true, ticket); // day ticket.pending_time = new Date().toISOString(); - testTimeBeforeRelative('ticket.pending_time', 1, 'day', false, ticket); + testTimeBeforeRelative(assert, 'ticket.pending_time', 1, 'day', false, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() - 60 * 60 * 48 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeBeforeRelative('ticket.pending_time', 1, 'day', true, ticket); + testTimeBeforeRelative(assert, 'ticket.pending_time', 1, 'day', true, ticket); // year ticket.pending_time = new Date().toISOString(); - testTimeBeforeRelative('ticket.pending_time', 1, 'year', false, ticket); + testTimeBeforeRelative(assert, 'ticket.pending_time', 1, 'year', false, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() - 60 * 60 * 365 * 2 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeBeforeRelative('ticket.pending_time', 1, 'year', true, ticket); + testTimeBeforeRelative(assert, 'ticket.pending_time', 1, 'year', true, ticket); // ------------------------- // AFTER TIME @@ -781,30 +781,30 @@ window.onload = function() { // hour ticket.pending_time = new Date().toISOString(); - testTimeAfterRelative('ticket.pending_time', 1, 'hour', false, ticket); + testTimeAfterRelative(assert, 'ticket.pending_time', 1, 'hour', false, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() + 60 * 60 * 2 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeAfterRelative('ticket.pending_time', 1, 'hour', true, ticket); + testTimeAfterRelative(assert, 'ticket.pending_time', 1, 'hour', true, ticket); // day ticket.pending_time = new Date().toISOString(); - testTimeAfterRelative('ticket.pending_time', 1, 'day', false, ticket); + testTimeAfterRelative(assert, 'ticket.pending_time', 1, 'day', false, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() + 60 * 60 * 48 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeAfterRelative('ticket.pending_time', 1, 'day', true, ticket); + testTimeAfterRelative(assert, 'ticket.pending_time', 1, 'day', true, ticket); // year ticket.pending_time = new Date().toISOString(); - testTimeAfterRelative('ticket.pending_time', 1, 'year', false, ticket); + testTimeAfterRelative(assert, 'ticket.pending_time', 1, 'year', false, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() + 60 * 60 * 365 * 2 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeAfterRelative('ticket.pending_time', 1, 'year', true, ticket); + testTimeAfterRelative(assert, 'ticket.pending_time', 1, 'year', true, ticket); // ------------------------- @@ -815,12 +815,12 @@ window.onload = function() { compareDate = new Date(); compareDate.setTime( compareDate.getTime() - 60 * 60 * 0.5 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeWithinLastRelative('ticket.pending_time', 1, 'hour', true, ticket); + testTimeWithinLastRelative(assert, 'ticket.pending_time', 1, 'hour', true, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() - 60 * 60 * 2 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeWithinLastRelative('ticket.pending_time', 1, 'hour', false, ticket); + testTimeWithinLastRelative(assert, 'ticket.pending_time', 1, 'hour', false, ticket); // ------------------------- // WITHIN NEXT TIME @@ -830,289 +830,289 @@ window.onload = function() { compareDate = new Date(); compareDate.setTime( compareDate.getTime() + 60 * 60 * 0.5 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeWithinNextRelative('ticket.pending_time', 1, 'hour', true, ticket); + testTimeWithinNextRelative(assert, 'ticket.pending_time', 1, 'hour', true, ticket); compareDate = new Date(); compareDate.setTime( compareDate.getTime() + 60 * 60 * 2 * 1000); ticket.pending_time = compareDate.toISOString(); - testTimeWithinNextRelative('ticket.pending_time', 1, 'hour', false, ticket); + testTimeWithinNextRelative(assert, 'ticket.pending_time', 1, 'hour', false, ticket); }); - test("ticket priority_id", function() { + QUnit.test("ticket priority_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('ticket.priority_id', ['2'], ticket, sessionData); + testIs(assert, 'ticket.priority_id', ['2'], ticket, sessionData); }); - test("ticket escalation_at", function() { + QUnit.test("ticket escalation_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.escalation_at', ticket.escalation_at, ticket); + testTime(assert, 'ticket.escalation_at', ticket.escalation_at, ticket); }); - test("ticket last_contact_agent_at", function() { + QUnit.test("ticket last_contact_agent_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.last_contact_agent_at', ticket.last_contact_agent_at, ticket); + testTime(assert, 'ticket.last_contact_agent_at', ticket.last_contact_agent_at, ticket); }); - test("ticket last_contact_at", function() { + QUnit.test("ticket last_contact_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.last_contact_at', ticket.last_contact_at, ticket); + testTime(assert, 'ticket.last_contact_at', ticket.last_contact_at, ticket); }); - test("ticket last_contact_customer_at", function() { + QUnit.test("ticket last_contact_customer_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.last_contact_customer_at', ticket.last_contact_customer_at, ticket); + testTime(assert, 'ticket.last_contact_customer_at', ticket.last_contact_customer_at, ticket); }); - test("ticket first_response_at", function() { + QUnit.test("ticket first_response_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.first_response_at', ticket.first_response_at, ticket); + testTime(assert, 'ticket.first_response_at', ticket.first_response_at, ticket); }); - test("ticket close_at", function() { + QUnit.test("ticket close_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.close_at', ticket.close_at, ticket); + testTime(assert, 'ticket.close_at', ticket.close_at, ticket); }); - test("ticket created_by_id", function() { + QUnit.test("ticket created_by_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); App.Session.set(6); - testPreConditionUser('ticket.created_by_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'ticket.created_by_id', '6', ticket, sessionData); }); - test("ticket created_at", function() { + QUnit.test("ticket created_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.created_at', ticket.created_at, ticket); + testTime(assert, 'ticket.created_at', ticket.created_at, ticket); }); - test("ticket updated_at", function() { + QUnit.test("ticket updated_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('ticket.updated_at', ticket.updated_at, ticket); + testTime(assert, 'ticket.updated_at', ticket.updated_at, ticket); }); - test("ticket updated_by_id", function() { + QUnit.test("ticket updated_by_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); App.Session.set(6); - testPreConditionUser('ticket.updated_by_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'ticket.updated_by_id', '6', ticket, sessionData); }); - test("ticket tags", function() { + QUnit.test("ticket tags", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionTags('ticket.tags', ticket); + testPreConditionTags(assert, 'ticket.tags', ticket); }); - test("article from", function() { + QUnit.test("article from", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('article.from', 'Admin', ticket); + testContains(assert, 'article.from', 'Admin', ticket); }); - test("article to", function() { + QUnit.test("article to", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('article.to', 'agent1', ticket); + testContains(assert, 'article.to', 'agent1', ticket); }); - test("article cc", function() { + QUnit.test("article cc", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('article.cc', 'agent1+cc', ticket); + testContains(assert, 'article.cc', 'agent1+cc', ticket); }); - test("article subject", function() { + QUnit.test("article subject", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('article.subject', 'asdf', ticket); + testContains(assert, 'article.subject', 'asdf', ticket); }); - test("article type_id", function() { + QUnit.test("article type_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('article.type_id', ['1'], ticket); + testIs(assert, 'article.type_id', ['1'], ticket); }); - test("article sender_id", function() { + QUnit.test("article sender_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('article.sender_id', ['1'], ticket); + testIs(assert, 'article.sender_id', ['1'], ticket); }); - test("article internal", function() { + QUnit.test("article internal", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('article.internal', ['false'], ticket); + testIs(assert, 'article.internal', ['false'], ticket); }); - test("article created_by_id", function() { + QUnit.test("article created_by_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionUser('article.created_by_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'article.created_by_id', '6', ticket, sessionData); }); - test("customer login", function() { + QUnit.test("customer login", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('customer.login', 'hc', ticket); + testContains(assert, 'customer.login', 'hc', ticket); }); - test("customer firstname", function() { + QUnit.test("customer firstname", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('customer.firstname', 'Harald', ticket); + testContains(assert, 'customer.firstname', 'Harald', ticket); }); - test("customer lastname", function() { + QUnit.test("customer lastname", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('customer.lastname', 'Customer', ticket); + testContains(assert, 'customer.lastname', 'Customer', ticket); }); - test("customer email", function() { + QUnit.test("customer email", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('customer.email', 'hc', ticket); + testContains(assert, 'customer.email', 'hc', ticket); }); - test("customer organization_id", function() { + QUnit.test("customer organization_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionOrganization('customer.organization_id', '6', ticket, sessionData); + testPreConditionOrganization(assert, 'customer.organization_id', '6', ticket, sessionData); }); - test("customer created_by_id", function() { + QUnit.test("customer created_by_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionUser('customer.created_by_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'customer.created_by_id', '6', ticket, sessionData); }); - test("customer created_at", function() { + QUnit.test("customer created_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('customer.created_at', ticket.customer.created_at, ticket); + testTime(assert, 'customer.created_at', ticket.customer.created_at, ticket); }); - test("customer updated_by_id", function() { + QUnit.test("customer updated_by_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionUser('customer.updated_by_id', '6', ticket, sessionData); + testPreConditionUser(assert, 'customer.updated_by_id', '6', ticket, sessionData); }); - test("customer missing_field", function() { + QUnit.test("customer missing_field", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('customer.missing_field', '', ticket); + testContains(assert, 'customer.missing_field', '', ticket); }); - test("customer web", function() { + QUnit.test("customer web", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('customer.web', 'cool', ticket); + testContains(assert, 'customer.web', 'cool', ticket); }); - test("organization name", function() { + QUnit.test("organization name", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('organization.name', 'gmbh', ticket); + testContains(assert, 'organization.name', 'gmbh', ticket); }); - test("organization shared", function() { + QUnit.test("organization shared", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('organization.shared', true, ticket); + testIs(assert, 'organization.shared', true, ticket); }); - test("organization created_by_id", function() { + QUnit.test("organization created_by_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionUser('organization.created_by_id', 6, ticket); + testPreConditionUser(assert, 'organization.created_by_id', 6, ticket); }); - test("organization updated_by_id", function() { + QUnit.test("organization updated_by_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionUser('organization.updated_by_id', 6, ticket); + testPreConditionUser(assert, 'organization.updated_by_id', 6, ticket); }); - test("organization created_at", function() { + QUnit.test("organization created_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('organization.created_at', ticket.organization.created_at, ticket); + testTime(assert, 'organization.created_at', ticket.organization.created_at, ticket); }); - test("organization updated_at", function() { + QUnit.test("organization updated_at", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testTime('organization.updated_at', ticket.organization.updated_at, ticket); + testTime(assert, 'organization.updated_at', ticket.organization.updated_at, ticket); }); - test("organization domain_assignment", function() { + QUnit.test("organization domain_assignment", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testIs('organization.domain_assignment', false, ticket); + testIs(assert, 'organization.domain_assignment', false, ticket); }); - test("organization domain", function() { + QUnit.test("organization domain", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testContains('organization.domain', 'cool', ticket); + testContains(assert, 'organization.domain', 'cool', ticket); }); - test("ticket mention user_id", function() { + QUnit.test("ticket mention user_id", assert => { ticket = new App.Ticket(); ticket.load(ticketData); - testPreConditionUser('ticket.mention_user_ids', '6', ticket, sessionData); + testPreConditionUser(assert, 'ticket.mention_user_ids', '6', ticket, sessionData); }); } diff --git a/public/assets/tests/ui.js b/public/assets/tests/qunit/ui.js similarity index 62% rename from public/assets/tests/ui.js rename to public/assets/tests/qunit/ui.js index f35f32fe7..df1048b60 100644 --- a/public/assets/tests/ui.js +++ b/public/assets/tests/qunit/ui.js @@ -1,5 +1,5 @@ // date picker timezone conversion for display -test("date picker", function() { +QUnit.test("date picker", assert => { Date.prototype.getTimezoneOffset2 = Date.prototype.getTimezoneOffset Date.prototype.getTimezoneOffset = function() { return -360 } @@ -12,7 +12,7 @@ test("date picker", function() { date_time_parsed = new Date(Date.parse(obj_date_time.value)) date_time_input = el_date_time.find('.js-datepicker').datepicker('getDate') - equal(date_time_parsed.getDate(), date_time_input.getDate(), 'datetime matching day') + assert.equal(date_time_parsed.getDate(), date_time_input.getDate(), 'datetime matching day') obj_date = { name: 'test', @@ -23,14 +23,14 @@ test("date picker", function() { date_parsed = new Date(Date.parse(obj_date.value)) date_input = el_date.find('.js-datepicker').datepicker('getUTCDate') - equal(date_parsed.getDate(), date_input.getDate(), 'date matching day') + assert.equal(date_parsed.getDate(), date_input.getDate(), 'date matching day') Date.prototype.getTimezoneOffset = Date.prototype.getTimezoneOffset2 Date.prototype.getTimezoneOffset2 = undefined }) // pretty date -test("check pretty date", function() { +QUnit.test("check pretty date", assert => { var current = new Date() // use date formatting as functions to make it more flexible prettyDateRelative(current, '', true, 'relative'); @@ -41,43 +41,43 @@ test("check pretty date", function() { function prettyDateRelative(current, escalation, long, type) { var result = App.PrettyDate.humanTime(current, escalation, long, type); - equal(result, 'just now', 'just now') + assert.equal(result, 'just now', 'just now') result = App.PrettyDate.humanTime(current - 15000, escalation, long, type); - equal(result, 'just now', 'just now') + assert.equal(result, 'just now', 'just now') result = App.PrettyDate.humanTime(current - 60000, escalation, long, type); - equal(result, '1 minute ago', '1 min ago') + assert.equal(result, '1 minute ago', '1 min ago') result = App.PrettyDate.humanTime(current - (2 * 60000), escalation, long, type); - equal(result, '2 minutes ago', '2 min ago') + assert.equal(result, '2 minutes ago', '2 min ago') result = App.PrettyDate.humanTime(current - (60000 * 60), escalation, long, type); - equal(result, '1 hour ago', '1 hour') + assert.equal(result, '1 hour ago', '1 hour') result = App.PrettyDate.humanTime(current - (60000 * 60 * 2), escalation, long, type); - equal(result, '2 hours ago', '2 hours') + assert.equal(result, '2 hours ago', '2 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 2.5), escalation, long, type); - equal(result, '2 hours 30 minutes ago', '2.5 hours') + assert.equal(result, '2 hours 30 minutes ago', '2.5 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 12.5), escalation, long, type); - equal(result, '12 hours ago', '12.5 hours') + assert.equal(result, '12 hours ago', '12.5 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24), escalation, long, type); - equal(result, '1 day ago', '1 day') + assert.equal(result, '1 day ago', '1 day') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2), escalation, long, type); - equal(result, '2 days ago', '2 days') + assert.equal(result, '2 days ago', '2 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2) - (60000 * 5), escalation, long, type); - equal(result, '2 days ago', '2 days') + assert.equal(result, '2 days ago', '2 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2.5), escalation, long, type); - equal(result, '2 days 12 hours ago', '2.5 days') + assert.equal(result, '2 days 12 hours ago', '2.5 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2.5) - (60000 * 5), escalation, long, type); - equal(result, '2 days 12 hours ago', '2.5 days') + assert.equal(result, '2 days 12 hours ago', '2.5 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 10.5), escalation, long, type); var pastDate = new Date(current - (60000 * 60 * 24 * 10.5)) @@ -91,7 +91,7 @@ test("check pretty date", function() { } var yyyy = pastDate.getFullYear(); // mm/dd/yyyy - equal(result, mm+'/'+dd+'/'+yyyy, '10.5 days') + assert.equal(result, mm+'/'+dd+'/'+yyyy, '10.5 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 30), escalation, long, type); var pastDate = new Date(current - (60000 * 60 * 24 * 30)) @@ -105,228 +105,228 @@ test("check pretty date", function() { } var yyyy = pastDate.getFullYear(); // mm/dd/yyyy - equal(result, mm+'/'+dd+'/'+yyyy, '30 days') + assert.equal(result, mm+'/'+dd+'/'+yyyy, '30 days') // future current = new Date() result = App.PrettyDate.humanTime(current, escalation, long, type); - equal(result, 'just now', 'just now') + assert.equal(result, 'just now', 'just now') result = App.PrettyDate.humanTime(current.getTime() + 55000, escalation, long, type); - equal(result, 'just now', 'just now') + assert.equal(result, 'just now', 'just now') result = App.PrettyDate.humanTime(current.getTime() + 65000, escalation, long, type); - equal(result, 'in 1 minute', 'in 1 min') + assert.equal(result, 'in 1 minute', 'in 1 min') result = App.PrettyDate.humanTime(current.getTime() + (2 * 65000), escalation, long, type); - equal(result, 'in 2 minutes', 'in 2 min') + assert.equal(result, 'in 2 minutes', 'in 2 min') result = App.PrettyDate.humanTime(current.getTime() + (60500 * 60), escalation, long, type); - equal(result, 'in 1 hour', 'in 1 hour') + assert.equal(result, 'in 1 hour', 'in 1 hour') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 2), escalation, long, type); - equal(result, 'in 2 hours', 'in 2 hours') + assert.equal(result, 'in 2 hours', 'in 2 hours') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 2.5), escalation, long, type); - equal(result, 'in 2 hours 30 minutes', 'in 2.5 hours') + assert.equal(result, 'in 2 hours 30 minutes', 'in 2.5 hours') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24), escalation, long, type) ; - equal(result, 'in 1 day', 'in 1 day') + assert.equal(result, 'in 1 day', 'in 1 day') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 2), escalation, long, type); - equal(result, 'in 2 days', 'in 2 days') + assert.equal(result, 'in 2 days', 'in 2 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 2.5), escalation, long, type); - equal(result, 'in 2 days 12 hours', 'in 2.5 days') + assert.equal(result, 'in 2 days 12 hours', 'in 2.5 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 5.5), escalation, long, type); - equal(result, 'in 5 days 12 hours', 'in 30.5 days') + assert.equal(result, 'in 5 days 12 hours', 'in 30.5 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 30.5), escalation, long, type); - equal(result, 'in 30 days', 'in 30.5 days') + assert.equal(result, 'in 30 days', 'in 30.5 days') }; function prettyDateAbsolute(current, escalation, long, type) { var result = App.PrettyDate.humanTime(current, escalation, long, type); - equal(result, 'just now', 'just now') // by defaul < 1 min is just now + assert.equal(result, 'just now', 'just now') // by defaul < 1 min is just now result = App.PrettyDate.humanTime(current - 15000, escalation, long, type); - equal(result, 'just now', 'just now') // by default < 1 min is just now + assert.equal(result, 'just now', 'just now') // by default < 1 min is just now result = App.PrettyDate.humanTime(current - 60000, escalation, long, type); diff = 60 - equal(result, getAbsolute(new Date(current - 60000), diff), '1 min ago') + assert.equal(result, getAbsolute(new Date(current - 60000), diff), '1 min ago') result = App.PrettyDate.humanTime(current - (2 * 60000), escalation, long, type); diff = 2 * 60 - equal(result, getAbsolute(new Date(current - (2 * 60000)), diff), '2 min ago') + assert.equal(result, getAbsolute(new Date(current - (2 * 60000)), diff), '2 min ago') result = App.PrettyDate.humanTime(current - (60000 * 60), escalation, long, type); diff = 60 * 60 - equal(result, getAbsolute(new Date(current - (60000 * 60)), diff), '1 hour') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60)), diff), '1 hour') result = App.PrettyDate.humanTime(current - (60000 * 60 * 2), escalation, long, type); diff = 60 * 60 * 2 - equal(result, getAbsolute(new Date(current - (60000 * 60 * 2)), diff), '2 hours') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 2)), diff), '2 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 2.5), escalation, long, type); diff = 60 * 60 * 2.5 - equal(result, getAbsolute(new Date(current - (60000 * 60 * 2.5)), diff), '2.5 hours') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 2.5)), diff), '2.5 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 12.5), escalation, long, type); diff = 60 * 60 * 12.5 - equal(result, getAbsolute(new Date(current - (60000 * 60 * 12.5)), diff), '12.5 hours') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 12.5)), diff), '12.5 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24), escalation, long, type); diff = 60 * 60 * 25 - equal(result, getAbsolute(new Date(current - (60000 * 60 * 24)), diff), '1 day') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 24)), diff), '1 day') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2), escalation, long, type); diff = 60 * 60 * 25 * 2 - equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2)), diff), '2 days') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2)), diff), '2 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2) - (60000 * 5), escalation, long, type); diff = (60 * 60 * 24 * 2) - (60 * 5) - equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2) - (60000 * 5)), diff), '2 days') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2) - (60000 * 5)), diff), '2 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2.5), escalation, long, type); diff = (60 * 60 * 24 * 2.5) - equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2.5)), diff), '2.5 days') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2.5)), diff), '2.5 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2.5) - (60000 * 5), escalation, long, type); diff = (60 * 60 * 24 * 2.5) - (60 * 5) - equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2.5) - (60000 * 5)), diff), '2.5 days') + assert.equal(result, getAbsolute(new Date(current - (60000 * 60 * 24 * 2.5) - (60000 * 5)), diff), '2.5 days') // future current = new Date() result = App.PrettyDate.humanTime(current, escalation, long, type); - equal(result, 'just now', 'just now') // no change, because < 1 min = just now + assert.equal(result, 'just now', 'just now') // no change, because < 1 min = just now result = App.PrettyDate.humanTime(current.getTime() + 55000, escalation, long, type); - equal(result, 'just now', 'just now') // no change, because < 1 min = just now + assert.equal(result, 'just now', 'just now') // no change, because < 1 min = just now result = App.PrettyDate.humanTime(current.getTime() + 65000, escalation, long, type); diff = 60 - equal(result, getAbsolute(new Date(current.getTime() + 65000), diff), 'in 1 min') + assert.equal(result, getAbsolute(new Date(current.getTime() + 65000), diff), 'in 1 min') result = App.PrettyDate.humanTime(current.getTime() + (2 * 65000), escalation, long, type); diff = 2 * 60 - equal(result, getAbsolute(new Date(current.getTime() + (2 * 65000)), diff), 'in 2 min') + assert.equal(result, getAbsolute(new Date(current.getTime() + (2 * 65000)), diff), 'in 2 min') result = App.PrettyDate.humanTime(current.getTime() + (60500 * 60), escalation, long, type) ; diff = 60 * 60 - equal(result, getAbsolute(new Date(current.getTime() + (60500 * 60)), diff), 'in 1 hour') + assert.equal(result, getAbsolute(new Date(current.getTime() + (60500 * 60)), diff), 'in 1 hour') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 2), escalation, long, type); diff = 60 * 60 * 2 - equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 2)), diff), 'in 2 hours') + assert.equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 2)), diff), 'in 2 hours') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 2.5), escalation, long, type); diff = 60 * 60 * 2.5 - equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 2.5)), diff), 'in 2.5 hours') + assert.equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 2.5)), diff), 'in 2.5 hours') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24), escalation, long, type); diff = 60 * 60 * 24 - equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24)), diff), 'in 1 day') + assert.equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24)), diff), 'in 1 day') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 2), escalation, long, type); diff = 60 * 60 * 24 * 2 - equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24 * 2)), diff), 'in 2 days') + assert.equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24 * 2)), diff), 'in 2 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 2.5), escalation, long, type); diff = 60 * 60 * 24 * 2.5 - equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24 * 2.5)), diff), 'in 2.5 days') + assert.equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24 * 2.5)), diff), 'in 2.5 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 5.5), escalation, long, type); diff = 60 * 60 * 24 * 5.5 - equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24 * 5.5)), diff), 'in 5.5 days') + assert.equal(result, getAbsolute(new Date(current.getTime() + (60050 * 60 * 24 * 5.5)), diff), 'in 5.5 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 30.5), escalation, long, type); diff = (60 * 60 * 24 * 30.5); - equal(result, getAbsolute(new Date(current.getTime() + 60050 * 60 * 24 * 30.5), diff), 'in 30.5 days') + assert.equal(result, getAbsolute(new Date(current.getTime() + 60050 * 60 * 24 * 30.5), diff), 'in 30.5 days') }; function prettyDateTimestamp(current, escalation, long, type) { var result = App.PrettyDate.humanTime(current, escalation, long, type); - equal(result, 'just now', 'just now') // by defaul < 1 min is just now + assert.equal(result, 'just now', 'just now') // by defaul < 1 min is just now result = App.PrettyDate.humanTime(current - 15000, escalation, long, type); - equal(result, 'just now', 'just now') // by default < 1 min is just now + assert.equal(result, 'just now', 'just now') // by default < 1 min is just now result = App.PrettyDate.humanTime(current - 60000, escalation, long, type); - equal(result, getTimestamp(new Date(current - 60000)), '1 min ago') + assert.equal(result, getTimestamp(new Date(current - 60000)), '1 min ago') result = App.PrettyDate.humanTime(current - (2 * 60000), escalation, long, type); - equal(result, getTimestamp(new Date(current - (2 * 60000))), '2 min ago') + assert.equal(result, getTimestamp(new Date(current - (2 * 60000))), '2 min ago') result = App.PrettyDate.humanTime(current - (60000 * 60), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60))), '1 hour') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60))), '1 hour') result = App.PrettyDate.humanTime(current - (60000 * 60 * 2), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 2))), '2 hours') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 2))), '2 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 2.5), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 2.5))), '2.5 hours') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 2.5))), '2.5 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 12.5), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 12.5))), '12.5 hours') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 12.5))), '12.5 hours') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 24))), '1 day') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 24))), '1 day') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2))), '2 days') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2))), '2 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2) - (60000 * 5), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2) - (60000 * 5))), '2 days') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2) - (60000 * 5))), '2 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2.5), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2.5))), '2.5 days') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2.5))), '2.5 days') result = App.PrettyDate.humanTime(current - (60000 * 60 * 24 * 2.5) - (60000 * 5), escalation, long, type); - equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2.5) - (60000 * 5))), '2.5 days') + assert.equal(result, getTimestamp(new Date(current - (60000 * 60 * 24 * 2.5) - (60000 * 5))), '2.5 days') // future current = new Date() result = App.PrettyDate.humanTime(current, escalation, long, type); - equal(result, 'just now', 'just now') // no change, because < 1 min = just now + assert.equal(result, 'just now', 'just now') // no change, because < 1 min = just now result = App.PrettyDate.humanTime(current.getTime() + 55000, escalation, long, type); - equal(result, 'just now', 'just now') // no change, because < 1 min = just now + assert.equal(result, 'just now', 'just now') // no change, because < 1 min = just now result = App.PrettyDate.humanTime(current.getTime() + 65000, escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + 65000)), 'in 1 min') + assert.equal(result, getTimestamp(new Date(current.getTime() + 65000)), 'in 1 min') result = App.PrettyDate.humanTime(current.getTime() + (2 * 65000), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + (2 * 65000))), 'in 2 min') + assert.equal(result, getTimestamp(new Date(current.getTime() + (2 * 65000))), 'in 2 min') result = App.PrettyDate.humanTime(current.getTime() + (60500 * 60), escalation, long, type) ; - equal(result, getTimestamp(new Date(current.getTime() + (60500 * 60))), 'in 1 hour') + assert.equal(result, getTimestamp(new Date(current.getTime() + (60500 * 60))), 'in 1 hour') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 2), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 2))), 'in 2 hours') + assert.equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 2))), 'in 2 hours') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 2.5), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 2.5))), 'in 2.5 hours') + assert.equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 2.5))), 'in 2.5 hours') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24))), 'in 1 day') + assert.equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24))), 'in 1 day') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 2), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24 * 2))), 'in 2 days') + assert.equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24 * 2))), 'in 2 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 2.5), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24 * 2.5))), 'in 2.5 days') + assert.equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24 * 2.5))), 'in 2.5 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 5.5), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24 * 5.5))), 'in 5.5 days') + assert.equal(result, getTimestamp(new Date(current.getTime() + (60050 * 60 * 24 * 5.5))), 'in 5.5 days') result = App.PrettyDate.humanTime(current.getTime() + (60050 * 60 * 24 * 30.5), escalation, long, type); - equal(result, getTimestamp(new Date(current.getTime() + 60050 * 60 * 24 * 30.5)), 'in 30.5 days') + assert.equal(result, getTimestamp(new Date(current.getTime() + 60050 * 60 * 24 * 30.5)), 'in 30.5 days') }; @@ -369,9 +369,9 @@ test("check pretty date", function() { }); -test("PrettyDate getISOWeeks", function() { - equal(App.PrettyDate.getISOWeeks(2026), 53, '53 weeks') - equal(App.PrettyDate.getISOWeeks(2020), 53, 'leap year and 53 weeks') - equal(App.PrettyDate.getISOWeeks(2019), 52, '52 weeks') - equal(App.PrettyDate.getISOWeeks(2024), 52, 'leap year and 52 weeks') +QUnit.test("PrettyDate getISOWeeks", assert => { + assert.equal(App.PrettyDate.getISOWeeks(2026), 53, '53 weeks') + assert.equal(App.PrettyDate.getISOWeeks(2020), 53, 'leap year and 53 weeks') + assert.equal(App.PrettyDate.getISOWeeks(2019), 52, '52 weeks') + assert.equal(App.PrettyDate.getISOWeeks(2024), 52, 'leap year and 52 weeks') }) diff --git a/public/assets/tests/session.js b/public/assets/tests/session.js deleted file mode 100644 index 0e166eefd..000000000 --- a/public/assets/tests/session.js +++ /dev/null @@ -1,82 +0,0 @@ -window.onload = function() { - -test('test current user behaviour by updating session user via assets', function() { - - // Wenn App.User updated through asset and set as session user - // expect App.Session.get with new values - App.User.refresh([{ - "login": "hh@example.com", - "firstname": "Harald", - "lastname": "Habebe", - "email": "hh@example.com", - "role_ids": [ 1, 2, 4 ], - "group_ids": [ 1 ], - "active": true, - "updated_at": "2017-02-09T09:17:04.770Z", - "address": "", - "vip": false, - "custom_key": undefined, - "asdf": "", - "id": 6 - }]); - App.Session.set(6) - equal(App.Session.get('id'), 6) - equal(App.Session.get('login'), 'hh@example.com') - equal(App.Session.get('vip'), false) - equal(App.Session.get('custom_key'), undefined) - equal(App.Session.get().id, 6) - equal(App.Session.get().login, 'hh@example.com') - equal(App.Session.get().custom_key, undefined) - equal(App.Session.get().not_existing, undefined) - - // Wenn App.User updated through asset - // expect App.Session.get with new values - App.User.refresh([{ - "login": "hh_new@example.com", - "firstname": "Harald", - "lastname": "Habebe", - "email": "hh_new@example.com", - "role_ids": [ 1, 2, 4 ], - "group_ids": [ 1 ], - "active": true, - "updated_at": "2017-02-09T09:17:04.770Z", - "address": "", - "vip": false, - "custom_key": undefined, - "asdf": "", - "id": 6 - }]); - equal(App.Session.get('id'), 6) - equal(App.Session.get('login'), 'hh_new@example.com') - equal(App.Session.get('vip'), false) - equal(App.Session.get('custom_key'), undefined) - equal(App.Session.get().id, 6) - equal(App.Session.get().login, 'hh_new@example.com') - equal(App.Session.get().custom_key, undefined) - equal(App.Session.get().not_existing, undefined) - - // Wenn App.Session is reseted to inital - // expect undefined for all - App.Session.init() - equal(App.Session.get(), undefined) - equal(App.Session.get('id'), undefined) - equal(App.Session.get('login'), undefined) - equal(App.Session.get('vip'), undefined) - equal(App.Session.get('custom_key'), undefined) - - // When App.Session is set and set to undefined or null, - // expect @current() to return null - App.Session.set(6) - App.Session.set(undefined) - equal(App.User.current(), null, 'with no active session') - App.Session.set(null) - equal(App.User.current(), null, 'with no active session') - - // When App.Session is set with an invalid (not existing) user ID, - // expect @current() to return null - App.Session.set(100) - equal(App.User.current(), null, 'with invalid session user ID') - -}); - -} \ No newline at end of file diff --git a/public/assets/tests/syn-0.14.1.js b/public/assets/tests/syn-0.15.0.js similarity index 96% rename from public/assets/tests/syn-0.14.1.js rename to public/assets/tests/syn-0.15.0.js index 540735f4f..6eec4dc76 100644 --- a/public/assets/tests/syn-0.14.1.js +++ b/public/assets/tests/syn-0.15.0.js @@ -1,3 +1,35 @@ +/*[process-shim]*/ +(function(global, env) { + // jshint ignore:line + if (typeof process === "undefined") { + global.process = { + argv: [], + cwd: function() { + return ""; + }, + browser: true, + env: { + NODE_ENV: env || "development" + }, + version: "", + platform: + global.navigator && + global.navigator.userAgent && + /Windows/.test(global.navigator.userAgent) + ? "win" + : "" + }; + } +})( + typeof self == "object" && self.Object == Object + ? self + : typeof process === "object" && + Object.prototype.toString.call(process) === "[object process]" + ? global + : window, + "development" +); + /*[global-shim-start]*/ (function(exports, global, doEval) { // jshint ignore:line @@ -74,8 +106,9 @@ }; args[1] = module.exports; args[2] = module; - } else if (!args[0] && deps[0] === "exports") { - // Babel uses the exports and module object. + } + // Babel uses the exports and module object. + else if (!args[0] && deps[0] === "exports") { module = { exports: {} }; args[0] = module.exports; if (deps[1] === "module") { @@ -120,7 +153,12 @@ }); })( {}, - typeof self == "object" && self.Object == Object ? self : window, + typeof self == "object" && self.Object == Object + ? self + : typeof process === "object" && + Object.prototype.toString.call(process) === "[object process]" + ? global + : window, function(__$source__, __$global__) { // jshint ignore:line eval("(function() { " + __$source__ + " \n }).call(__$global__);"); @@ -613,6 +651,52 @@ define('syn/synthetic', function (require, exports, module) { } module.exports = syn; }); +/*syn@0.14.1#keyboard-event-keys*/ +define('syn/keyboard-event-keys', [ + 'require', + 'exports', + 'module', + 'syn/synthetic' +], function (require, exports, module) { + var syn = require('syn/synthetic'); + syn.key.keyboardEventKeys = { + '\b': 'Backspace', + '\t': 'Tab', + '\r': 'Enter', + 'shift': 'Shift', + 'ctrl': 'Control', + 'alt': 'Alt', + 'meta': 'Meta', + 'pause-break': 'Pause', + 'caps': 'CapsLock', + 'escape': 'Escape', + 'num-lock': 'NumLock', + 'scroll-lock': 'ScrollLock', + 'print': 'Print', + 'page-up': 'PageUp', + 'page-down': 'PageDown', + 'end': 'End', + 'home': 'Home', + 'left': 'ArrowLeft', + 'up': 'ArrowUp', + 'right': 'ArrowRight', + 'down': 'ArrowDown', + 'insert': 'Insert', + 'delete': 'Delete', + 'f1': 'F1', + 'f2': 'F2', + 'f3': 'F3', + 'f4': 'F4', + 'f5': 'F5', + 'f6': 'F6', + 'f7': 'F7', + 'f8': 'F8', + 'f9': 'F9', + 'f10': 'F10', + 'f11': 'F11', + 'f12': 'F12' + }; +}); /*syn@0.14.1#mouse*/ define('syn/mouse', [ 'require', @@ -702,6 +786,7 @@ define('syn/mouse', [ var doc = getWin(element).document || document, event; if (doc.createEvent) { try { + defaults.view = doc.defaultView; event = doc.createEvent('MouseEvents'); event.initMouseEvent(type, defaults.bubbles, defaults.cancelable, defaults.view, defaults.detail, defaults.screenX, defaults.screenY, defaults.clientX, defaults.clientY, defaults.ctrlKey, defaults.altKey, defaults.shiftKey, defaults.metaKey, defaults.button, defaults.relatedTarget); } catch (e) { @@ -1918,7 +2003,7 @@ define('syn/key', [ if (!keyData[event]) { return null; } - var charCode = keyData[event][0], keyCode = keyData[event][1], result = {}; + var charCode = keyData[event][0], keyCode = keyData[event][1], result = { key: key }; if (keyCode === 'key') { result.keyCode = syn.keycodes[key]; } else if (keyCode === 'char') { @@ -2220,7 +2305,15 @@ define('syn/key', [ }, event: function (type, options, element) { var doc = h.getWindow(element).document || document, event; - if (doc.createEvent) { + if (typeof KeyboardEvent !== 'undefined') { + var keyboardEventKeys = syn.key.keyboardEventKeys; + if (options.key && keyboardEventKeys[options.key]) { + options.key = keyboardEventKeys[options.key]; + } + event = new KeyboardEvent(type, options); + event.synthetic = true; + return event; + } else if (doc.createEvent) { try { event = doc.createEvent('KeyEvents'); event.initKeyEvent(type, true, true, window, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.keyCode, options.charCode); @@ -2425,25 +2518,54 @@ define('syn/drag', [ DragonDrop.cleanup(); }); }, - _dragStart: function (node, options) { + _dragStart: function (node) { + var options = { + bubbles: false, + cancelable: false + }; this.createAndDispatchEvent(node, 'dragstart', options); }, - _drag: function (node, options) { + _drag: function (node) { + var options = { + bubbles: true, + cancelable: true + }; this.createAndDispatchEvent(node, 'drag', options); }, - _dragEnter: function (node, options) { + _dragEnter: function (node) { + var options = { + bubbles: true, + cancelable: true + }; this.createAndDispatchEvent(node, 'dragenter', options); }, - _dragOver: function (node, options) { + _dragOver: function (node) { + var options = { + bubbles: true, + cancelable: true + }; this.createAndDispatchEvent(node, 'dragover', options); }, - _dragLeave: function (node, options) { + _dragLeave: function (node) { + var options = { + bubbles: true, + cancelable: false + }; this.createAndDispatchEvent(node, 'dragleave', options); }, - _drop: function (node, options) { + _drop: function (node) { + var options = { + bubbles: true, + cancelable: true, + buttons: 1 + }; this.createAndDispatchEvent(node, 'drop', options); }, - _dragEnd: function (node, options) { + _dragEnd: function (node) { + var options = { + bubbles: true, + cancelable: false + }; this.createAndDispatchEvent(node, 'dragend', options); }, _mouseDown: function (node, options) { @@ -2797,12 +2919,14 @@ define('syn', [ 'exports', 'module', 'syn/synthetic', + 'syn/keyboard-event-keys', 'syn/mouse.support', 'syn/browsers', 'syn/key.support', 'syn/drag' ], function (require, exports, module) { var syn = require('syn/synthetic'); + require('syn/keyboard-event-keys'); require('syn/mouse.support'); require('syn/browsers'); require('syn/key.support'); @@ -2815,4 +2939,4 @@ define('syn', [ global._define = global.define; global.define = global.define.orig; } -)(typeof self == "object" && self.Object == Object ? self : window); \ No newline at end of file +)(typeof self == "object" && self.Object == Object ? self : (typeof process === "object" && Object.prototype.toString.call(process) === "[object process]") ? global : window); \ No newline at end of file diff --git a/public/assets/tests/table.js b/public/assets/tests/table.js deleted file mode 100644 index b7eac8557..000000000 --- a/public/assets/tests/table.js +++ /dev/null @@ -1,844 +0,0 @@ -// form -test('table test', function() { - App.i18n.set('de-de') - - $('#table').append('

        table simple I

        ') - var el = $('#table1') - App.TicketPriority.refresh( [ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - ] ) - var rowClick = function (id, e) { - e.preventDefault() - console.log('rowClick', id, e.target) - }; - var rowDblClick = function (id, e) { - e.preventDefault() - console.log('rowDblClick', id, e.target) - }; - var rowMouseover = function (id, e) { - e.preventDefault() - console.log('rowMouseover', id, e.target) - }; - var rowMouseout = function (id, e) { - e.preventDefault() - console.log('rowMouseout', id, e.target) - }; - var colClick = function (id, e) { - e.preventDefault() - console.log('colClick', id, e.target) - }; - var colDblClick = function (id, e) { - e.preventDefault() - console.log('colDblClick', id, e.target) - }; - var colMouseover = function (id, e) { - e.preventDefault() - console.log('colMouseover', id, e.target) - }; - var colMouseout = function (id, e) { - e.preventDefault() - console.log('colMouseout', id, e.target) - }; - - new App.ControllerTable({ - el: el, - overview: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), - checkbox: false, - radio: false, - bindRow: { - events: { - 'click': rowClick, - 'mouseover': rowMouseover, - 'mouseout': rowMouseout, - 'dblclick': rowDblClick, - } - }, - bindCol: { - name: { - events: { - 'click': colClick, - 'mouseover': colMouseover, - 'mouseout': colMouseout, - 'dblclick': colDblClick, - } - }, - created_at: { - events: { - 'mouseover': colMouseover, - 'mouseout': colMouseout, - } - } - }, - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2') - - $('#table').append('

        table simple II

        ') - el = $('#table2') - new App.ControllerTable({ - el: el, - overview: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'name', order: 'DESC'}), - checkbox: false, - radio: false, - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'false', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - - $('#table').append('

        table simple III

        ') - el = $('#table3') - new App.ControllerTable({ - el: el, - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'created_at', order: 'DESC'}), - checkbox: false, - radio: false, - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - notEqual( el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - notEqual( el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - notEqual( el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '?', 'check row 2') - notEqual( el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - notEqual( el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '?', 'check row 1') - notEqual( el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'false', 'check row 1') - - - - App.Group.refresh( [ - { - id: 1, - name: 'group 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: 'group 2', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ]) - App.User.refresh( [ - { - id: 55, - login: 'login55', - firstname: 'firstname55', - lastname: 'lastname55', - email: 'email55', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 56, - login: 'login56', - firstname: 'firstname56', - lastname: 'lastname56', - email: 'email56', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ]) - - App.TicketState.refresh( [ - { - id: 1, - name: 'new', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: 'open', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - ]) - App.Ticket.refresh( [ - { - id: 1, - title: 'some title 1', - number: '4711', - priority_id: 1, - owner_id: 55, - customer_id: 56, - state_id: 1, - group_id: 2, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 3, - title: 'some title 3', - number: '4713', - priority_id: 2, - owner_id: 56, - state_id: 1, - group_id: 2, - created_at: '2014-07-11T11:19:34.000Z', - }, - { - id: 2, - title: 'some title 2', - number: '4712', - priority_id: 1, - state_id: 2, - group_id: 1, - created_at: '2014-06-10T11:19:34.000Z', - }, - ]) - $('#table').append('

        table complex I

        ') - el = $('#table4') - new App.ControllerTable({ - el: el, - overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], - model: App.Ticket, - objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), - checkbox: true, - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header') - equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header') - equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header') - equal(el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header') - equal(el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Gruppe', 'check header') - equal(el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Status', 'check header') - equal(el.find('table > thead > tr > th:nth-child(9)').text().trim(), 'Erstellt am', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 9, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), '', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '4713', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '-', 'check row 2') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(6)').text().trim(), '2 normal', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(7)').text().trim(), 'group 2', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(8)').text().trim(), 'neu', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(9)').text().trim(), '11.07.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 9, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'group 1', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), 'offen', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 9, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), '', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), '', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '4711', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'some title 1', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(4)').text().trim(), 'firstname55 lastname55', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(5)').text().trim(), 'firstname56 lastname56', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(7)').text().trim(), 'group 2', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(8)').text().trim(), 'neu', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(9)').text().trim(), '10.06.2014', 'check row 3') - - el.find('input[name="bulk_all"]').click() - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').prop('checked'), true, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1) input').val(), '3', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), true, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').prop('checked'), true, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1) input').val(), '1', 'check row 3') - - $('#table').append('

        table complex II

        ') - el = $('#table5') - var clickCheckbox = function (id, checked, e) { - console.log('clickCheckbox', id, checked, e.target) - }; - new App.ControllerTable({ - el: el, - overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], - model: App.Ticket, - objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), - checkbox: true, - groupBy: 'group', - bindCheckbox: { - events: { - 'click': clickCheckbox, - } - }, - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), '', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), '#', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Titel', 'check header') - equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Besitzer', 'check header') - equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Kunde', 'check header') - equal(el.find('table > thead > tr > th:nth-child(6)').text().trim(), 'Priorität', 'check header') - equal(el.find('table > thead > tr > th:nth-child(7)').text().trim(), 'Status', 'check header') - equal(el.find('table > thead > tr > th:nth-child(8)').text().trim(), 'Erstellt am', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'group 1', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 8, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '4712', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'some title 2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), '-', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '-', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(6)').text().trim(), '1 niedrig', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(7)').text().trim(), 'offen', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(8)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 1, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), 'group 2', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td').length, 8, 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), '', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1)').text().trim(), '', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(2)').text().trim(), '4713', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(3)').text().trim(), 'some title 3', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(4)').text().trim(), 'firstname56 lastname56', 'check row 2') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(5)').text().trim(), '-', 'check row 2') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(6)').text().trim(), '2 normal', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(7)').text().trim(), 'neu', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(8)').text().trim(), '11.07.2014', 'check row 4') - - el.find('input[name="bulk"]:eq(1)').click() - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').prop('checked'), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1) input').val(), '2', 'check row 1') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').prop('checked'), true, 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1) input').val(), '3', 'check row 4') - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), '', 'check row 5') - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5') - el.find('tbody > tr:nth-child(5) > td:nth-child(1) label').click() - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').prop('checked'), true, 'check row 5') - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(1) input').val(), '1', 'check row 5') - - - $('#table').append('

        table Group By Direction DESC

        ') - el = $('#table6') - var clickCheckbox = function (id, checked, e) { - console.log('clickCheckbox', id, checked, e.target) - }; - new App.ControllerTable({ - el: el, - overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], - model: App.Ticket, - objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), - groupBy: 'priority', - groupDirection: 'DESC', - }) - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '2 normal', 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(1)').text().trim(), '1 niedrig', 'check row 3') - - $('#table').append('

        table Group By Direction ASC

        ') - el = $('#table7') - var clickCheckbox = function (id, checked, e) { - console.log('clickCheckbox', id, checked, e.target) - }; - new App.ControllerTable({ - el: el, - overview: ['number', 'title', 'owner', 'customer', 'priority', 'group', 'state', 'created_at'], - model: App.Ticket, - objects: App.Ticket.search({sortBy:'created_at', order: 'DESC'}), - groupBy: 'priority', - groupDirection: 'ASC', - }) - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(1)').text().trim(), '2 normal', 'check row 4') -}); - -test('table test 2.1', function() { - App.i18n.set('de-de') - - $('#table').append('

        table with hash

        ') - var el = $('#table-hash2_1') - App.Group.refresh( [ - { - id: 5, - name: 'group 5', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ]) - - App.Channel.configure_delete = true - App.Channel.configure_clone = false - App.Channel.configure_attributes = [ - { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } }, - { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false }, - { name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: true, options: { true: 'yes', false: 'no' }, translate: true, default: true}, - { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, nulloption: true, relation: 'Group' }, - { name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true }, - ] - - App.Channel.refresh( [ - { - id: 1, - adapter: 'adapter1', - options: { - host: 'host1', - user: 'user1', - }, - group_id: 5, - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - adapter: 'adapter2', - options: { - host: 'host2', - user: 'user2', - }, - group_id: 5, - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ] ) - new App.ControllerTable({ - el: el, - overview: ['adapter', 'options::host', 'options::user', 'active'], - model: App.Channel, - objects: App.Channel.search({sortBy:'adapter', order: 'ASC'}), - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header') - equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header') - equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Aktion', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-delete').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-clone').length, 0, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-delete').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-clone').length, 0, 'check row 1') -}); - -test('table test 2.2', function() { - App.i18n.set('de-de') - - $('#table').append('

        table with hash

        ') - var el = $('#table-hash2_2') - App.Group.refresh( [ - { - id: 5, - name: 'group 5', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ]) - - App.Channel.configure_delete = false - App.Channel.configure_clone = true - App.Channel.configure_attributes = [ - { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } }, - { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false }, - { name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: true, options: { true: 'yes', false: 'no' }, translate: true, default: true}, - { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, nulloption: true, relation: 'Group' }, - { name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true }, - ] - - App.Channel.refresh( [ - { - id: 1, - adapter: 'adapter1', - options: { - host: 'host1', - user: 'user1', - }, - group_id: 5, - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - adapter: 'adapter2', - options: { - host: 'host2', - user: 'user2', - }, - group_id: 5, - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ] ) - new App.ControllerTable({ - el: el, - overview: ['adapter', 'options::host', 'options::user', 'active'], - model: App.Channel, - objects: App.Channel.search({sortBy:'adapter', order: 'ASC'}), - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header') - equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header') - equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Aktion', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5)').text().trim(), '', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-delete').length, 0, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .js-clone').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5)').text().trim(), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions').length, 0, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-delete').length, 0, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .js-clone').length, 1, 'check row 1') -}); - -test('table test 3', function() { - App.i18n.set('de-de') - - $('#table').append('

        table with hash

        ') - var el = $('#table-hash2') - App.Group.refresh( [ - { - id: 5, - name: 'group 5', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ]) - - App.Channel.configure_delete = true - App.Channel.configure_clone = true - App.Channel.configure_attributes = [ - { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } }, - { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false }, - { name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: true, options: { true: 'yes', false: 'no' }, translate: true, default: true}, - { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false }, - { name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, nulloption: true, relation: 'Group' }, - { name: 'active', display: 'Active', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true }, - ] - - App.Channel.refresh( [ - { - id: 1, - adapter: 'adapter1', - options: { - host: 'host1', - user: 'user1', - }, - group_id: 5, - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - adapter: 'adapter2', - options: { - host: 'host2', - user: 'user2', - }, - group_id: 5, - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ] ) - new App.ControllerTable({ - el: el, - overview: ['adapter', 'options::host', 'options::user', 'active'], - model: App.Channel, - objects: App.Channel.search({sortBy:'adapter', order: 'ASC'}), - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Typ', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Host', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Benutzer', 'check header') - equal(el.find('table > thead > tr > th:nth-child(4)').text().trim(), 'Aktiv', 'check header') - equal(el.find('table > thead > tr > th:nth-child(5)').text().trim(), 'Aktion', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 5, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'adapter1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'host1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'user1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(4)').text().trim(), 'ja', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions .js-delete').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(5) .dropdown.dropdown--actions .js-clone').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 5, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'adapter2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'host2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'user2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(4)').text().trim(), 'ja', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions .js-delete').length, 1, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(5) .dropdown.dropdown--actions .js-clone').length, 1, 'check row 2') -}); - -test('table test 4', function() { - App.i18n.set('de-de') - - $('#table').append('

        table with link

        ') - var el = $('#table-link1') - App.EmailAddress.refresh( [ - { - id: 55, - realname: 'realname 55', - email: 'email 55', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 56, - realname: 'realname 56', - email: 'email 56', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ]) - var callbackHeader = function (header) { - console.log('current header is', header); - // add new header item - var attribute = { - name: 'some name', - display: 'Some Name', - }; - header.push(attribute); - console.log('new header is', header); - return header - } - var callbackAttributes = function(value, object, attribute, header, refObject) { - console.log('data of item col', value, object, attribute, header, refObject) - value = ' ' - attribute.class = 'glyphicon glyphicon-user' - attribute.link = '#' - attribute.title = App.i18n.translateInline('Switch to') - if (object.id == 55) { - attribute.data = { - some: 'value55', - xxx: 55, - } - } - else { - attribute.data = { - some: 'value56', - xxx: 56, - } - } - return value - } - var switchTo = function(id, e) { - e.preventDefault() - console.log('switchTo with id', id, e.target) - //@disconnectClient() - //App.Auth._logout() - //window.location = App.Config.get('api_path') + '/sessions/switch/' + id - } - new App.ControllerTable({ - el: el, - model: App.EmailAddress, - objects: App.EmailAddress.search({sortBy:'realname', order: 'ASC'}), - callbackHeader: [callbackHeader], - callbackAttributes: { - 'some name': [ callbackAttributes ] - }, - bindCol: { - 'some name': { - events: { - 'click': switchTo, - } - }, - }, - }) - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Anzeigename', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Some Name', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(1)').text().trim(), 'realname 55', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'email 55', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), '', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('some'), 'value55', 'check row 2') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3) > a > span').data('xxx'), '55', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(1)').text().trim(), 'realname 56', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'email 56', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon-user'), true, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').hasClass('glyphicon'), true, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').attr('title'), 'Umschalten zu', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('some'), 'value56', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3) > a > span').data('xxx'), '56', 'check row 2') - -}); - -test('table test 5', function() { - App.i18n.set('de-de') - - $('#table').append('

        table with data

        ') - var el = $('#table-data1') - - data = [ - { name: 'some name 1', data: 'some data 1', active: true }, - { name: 'some name 2', data: 'some data 2', active: false }, - { name: 'some name 3', data: 'some data 3', active: true }, - ] - new App.ControllerTable({ - el: el, - overview: ['name', 'data', 'active'], - attribute_list: [ - { name: 'name', display: 'Name', type: 'text', style: 'width: 10%' }, - { name: 'data', display: 'Data', type: 'text' }, - { name: 'active', display: 'Active', type: 'text' }, - ], - objects: data - }); - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Data', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some name 1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'some data 1', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), 'some name 2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), 'some data 2', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'false', 'check row 2') -}); - -test('table test 6/7', function() { - $('#table').append('

        sotable table with data

        ') - var el_head_sortable = $('#table-data6') - - $('#table').append('

        not sortable table with data

        ') - var el_not_head_sortable = $('#table-data7') - - data = [ - { name: 'a item', data: 'g data', active: true }, - { name: 'b item', data: 'b data', active: false }, - { name: 'c item', data: 'z data', active: false }, - { name: 'd item', data: '', active: false }, - ] - - new App.ControllerTable({ - tableId: 'a', - el: el_head_sortable, - overview: ['name', 'data', 'active'], - attribute_list: [ - { name: 'name', display: 'Name', type: 'text', style: 'width: 10%', unsortable: true }, - { name: 'data', display: 'Data', type: 'text' }, - { name: 'active', display: 'Active', type: 'text' }, - ], - objects: data - }); - - new App.ControllerTable({ - tableId: 'b', - el: el_not_head_sortable, - overview: ['name', 'data', 'active'], - attribute_list: [ - { name: 'name', display: 'Name', type: 'text', style: 'width: 10%', unsortable: true }, - { name: 'data', display: 'Data', type: 'text' }, - { name: 'active', display: 'Active', type: 'text' }, - ], - objects: data, - dndCallback: function() { return true } - }); - - equal(el_head_sortable.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'a item', 'check row 1') - equal(el_not_head_sortable.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), 'a item', 'check row 1') - - ok(_.isEqual(list_items(el_head_sortable, 1), ['a item', 'b item', 'c item', 'd item']), 'sortable table is rendered correctly') - ok(_.isEqual(list_items(el_not_head_sortable, 2), ['a item', 'b item', 'c item', 'd item']), 'unsortable table is rendered correctly') - - click_sort(el_head_sortable, 2) - click_sort(el_not_head_sortable, 3) - - ok(_.isEqual(list_items(el_head_sortable, 1), ['b item', 'a item', 'c item', 'd item']), 'sortable table is sorted') - ok(_.isEqual(list_items(el_not_head_sortable, 2), ['a item', 'b item', 'c item', 'd item']), 'unsortable table is not sorted') - - click_sort(el_head_sortable, 3) - ok(_.isEqual(list_items(el_head_sortable, 1), ['b item', 'c item', 'd item', 'a item']), 'sorting by boolean column works') - - click_sort(el_head_sortable, 1) - ok(_.isEqual(list_items(el_head_sortable, 1), ['b item', 'c item', 'd item', 'a item']), 'sorting on name column is disabled') -}); - -function click_sort(table, column_number) { - table - .find(`table > thead > tr > th:nth-child(${column_number}) > .js-sort`) - .click() -} - -function list_items(table, column_number) { - return table - .find(`tbody > tr > td:nth-child(${column_number})`) - .text() - .split("\n") - .filter(elem => elem.match(/[\w]+/)) - .map(elem => elem.trim()) -} diff --git a/public/assets/tests/table_extended.js b/public/assets/tests/table_extended.js deleted file mode 100644 index 12bba40db..000000000 --- a/public/assets/tests/table_extended.js +++ /dev/null @@ -1,1777 +0,0 @@ -// initial list -test('table new - initial list', function() { - App.i18n.set('de-de') - - $('#table').append('

        table with data

        ') - var el = $('#table-new1') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - ], {clear: true}) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), - checkbox: false, - radio: false, - }) - //equal(el.find('table').length, 0, 'row count') - //table.render() - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'noChanges') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - - App.TicketPriority.refresh([ - { - id: 1, - name: 'Priority', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.lenghtChanged') - equal(result[1], 2) - equal(result[2], 1) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'Priorität', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 0, 'check row 2') - - App.TicketPriority.refresh([], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'emptyList') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], undefined) - equal(result[2][0], 2) - equal(result[2][1], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4') - - result = table.update({sync: true, orderDirection: 'DESC', orderBy: 'name'}) - equal(result[0], 'fullRender.contentChanged') - equal(result[1], 0) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '1 niedrig', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4') - - result = table.update({sync: true, orderDirection: 'ASC', orderBy: 'name'}) - equal(result[0], 'fullRender.contentChanged') - equal(result[1], 0) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 4') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], 1) - equal(result[1][1], undefined) - notOk(result[1][1]) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') - - result = table.update({sync: true, overviewAttributes: ['name', 'created_at']}) - equal(result[0], 'fullRender.overviewAttributesChanged') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th').length, 2, 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 2, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 2, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') - - App.TicketPriority.refresh([], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'emptyList') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), overviewAttributes: ['name'], orderBy: 'created_at', orderDirection: 'DESC'}) - equal(result[0], 'fullRender') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th').length, 1, 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), overviewAttributes: ['name'], orderBy: 'created_at', orderDirection: 'ASC'}) - equal(result[0], 'fullRender.overviewAttributesChanged') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th').length, 1, 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 2') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(2) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') - - $('#table').append('

        table group by with data

        ') - var el = $('#table-new2') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some other note', - active: true, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), - checkbox: false, - radio: false, - groupBy: 'note', - }) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 1, 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td:first').text().trim(), 'some other note', 'check row 3') - equal(el.find('tbody > tr:nth-child(5) > td:first').text().trim(), '3 hoch', 'check row 5') - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 5') - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(3)').text().trim(), 'true', 'check row 5') - equal(el.find('tbody > tr:nth-child(6) > td').length, 0, 'check row 6') - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'noChanges') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 6') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some other note', - active: true, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], undefined) - equal(result[2][0], 3) - equal(result[2][1], 4) - equal(result[2][2], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 1, 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td:first').text().trim(), 'some other note', 'check row 3') - equal(el.find('tbody > tr:nth-child(5) > td:first').text().trim(), '3 hoch', 'check row 5') - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 5') - equal(el.find('tbody > tr:nth-child(5) > td:nth-child(3)').text().trim(), 'true', 'check row 5') - equal(el.find('tbody > tr:nth-child(6) > td').length, 0, 'check row 6') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some other note', - active: true, - created_at: '2014-06-10T10:17:38.000Z', - }, - { - id: 4, - name: '4 high', - note: 'some other note', - active: true, - created_at: '2014-06-10T10:17:39.000Z', - }, - { - id: 5, - name: '5 high', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:39.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], undefined) - equal(result[2][0], 3) - equal(result[2][1], 6) - equal(result[2][2], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 1, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), 'some note', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 niedrig', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 normal', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 3, 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:first').text().trim(), '5 high', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 4') - equal(el.find('tbody > tr:nth-child(4) > td:nth-child(3)').text().trim(), 'true', 'check row 4') - equal(el.find('tbody > tr:nth-child(5) > td').length, 1, 'check row 5') - equal(el.find('tbody > tr:nth-child(5) > td:first').text().trim(), 'some other note', 'check row 5') - equal(el.find('tbody > tr:nth-child(6) > td:first').text().trim(), '3 hoch', 'check row 6') - equal(el.find('tbody > tr:nth-child(6) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 6') - equal(el.find('tbody > tr:nth-child(6) > td:nth-child(3)').text().trim(), 'true', 'check row 6') - equal(el.find('tbody > tr:nth-child(7) > td').length, 3, 'check row 7') - equal(el.find('tbody > tr:nth-child(7) > td:first').text().trim(), '4 high', 'check row 7') - equal(el.find('tbody > tr:nth-child(7) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 7') - equal(el.find('tbody > tr:nth-child(7) > td:nth-child(3)').text().trim(), 'true', 'check row 7') - equal(el.find('tbody > tr:nth-child(8) > td').length, 0, 'check row 8') - - $('#table').append('

        table with large data

        ') - var el = $('#table-new3') - - var objects = []; - var created_at = Date.parse('2014-06-10T11:17:34.000Z') - - for (i = 0; i < 1000; i++) { - local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() - item = { - id: i, - name: i + ' prio', - note: 'some note', - active: true, - created_at: local_created_at, - } - objects.push(item) - } - - App.TicketPriority.refresh(objects.reverse(), {clear: true}) - - var table = new App.ControllerTable({ - tableId: 'large_table_test', - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.all(), - checkbox: false, - radio: false, - ttt: true - }) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) - el.find('.js-tableHead[data-column-key="name"] .js-sort').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '10 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '31.05.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-up').length, 1) - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-down').length, 0) - el.find('.js-tableHead[data-column-key="name"] .js-sort').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-down').length, 1) - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon.icon-arrow-up').length, 0) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon').length, 0) - el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 0) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 1) - el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 1) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 0) - - objects = App.TicketPriority.all().reverse() - objects.shift() - objects.shift() - - result = table.update({sync: true, objects: objects}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], 1) - equal(result[1][1], 0) - equal(result[2][0], 148) - equal(result[2][1], 149) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '07.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(149) > td:first').text().trim(), '150 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(149) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(149) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(150) > td:first').text().trim(), '151 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(150) > td:nth-child(2)').text().trim(), '10.01.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(150) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 1) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 0) - el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '999 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '15.09.2011', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '998 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '16.09.2011', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '997 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '17.09.2011', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-tableHead[data-column-key="name"] .js-sort .icon').length, 0) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-down').length, 0) - equal(el.find('.js-tableHead[data-column-key="created_at"] .js-sort .icon.icon-arrow-up').length, 1) - - el.find('.js-tableHead[data-column-key="created_at"] .js-sort').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '07.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(149) > td:first').text().trim(), '150 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(149) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(149) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr:nth-child(150) > td:first').text().trim(), '151 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(150) > td:nth-child(2)').text().trim(), '10.01.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(150) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - $('#table').append('

        table with now data

        ') - var el = $('#table-new4') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - ], {clear: true}) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), - checkbox: false, - radio: false, - }) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 0) - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], undefined) - equal(result[2][0], 1) - equal(result[2][1], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3) - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0) - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some note 3', - active: true, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], undefined) - equal(result[2][0], 2) - equal(result[2][1], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3) - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3) - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0) - - App.TicketPriority.refresh([ - { - id: 3, - name: '3 high', - note: 'some note 3', - active: true, - created_at: '2014-06-10T10:17:38.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], 0) - equal(result[1][1], undefined) - equal(result[2][0], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3) - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '3 hoch') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0) - - App.TicketPriority.refresh([ - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.lenghtChanged') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 0) - - App.TicketPriority.refresh([], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'emptyList') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Keine Einträge', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 0, 'check row 1') - - App.TicketPriority.refresh([ - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 0) - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], undefined) - equal(result[2][0], 0) - equal(result[2][1], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3) - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0) - - App.TicketPriority.refresh([ - { - id: 2, - name: '2 normal', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.lenghtChanged') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3) - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '2 normal') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true') - equal(el.find('tbody > tr:nth-child(2) > td').length, 0) - - $('#table').append('

        table with large data and pager

        ') - var el = $('#table-new5') - - var objects = []; - var created_at = Date.parse('2014-06-10T11:17:34.000Z') - - for (i = 0; i < 151; i++) { - local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() - item = { - id: i, - name: i + ' prio', - note: 'some note', - active: true, - created_at: local_created_at, - } - objects.push(item) - } - - App.TicketPriority.refresh(objects, {clear: true}) - - var table = new App.ControllerTable({ - tableId: 'large_table_test_pager', - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.all(), - checkbox: false, - radio: false, - ttt: true - }) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-pager').first().find('.js-page').length, 2) - equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) - equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') - el.find('.js-pager').first().find('.js-page:nth-child(2)').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '150 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr').length, 1) - equal(el.find('tbody > tr:nth-child(2) > td').length, 0) - - objects = [ - { - id: 500, - name: '500 prio', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ] - - App.TicketPriority.refresh(objects) - - result = table.update({sync: true, objects: App.TicketPriority.all()}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], undefined) - equal(result[2][0], 1) - equal(result[2][1], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '150 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '500 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr').length, 2) - equal(el.find('tbody > tr:nth-child(3) > td').length, 0) - - objects = App.TicketPriority.all() - objects.splice(2,1) - result = table.update({sync: true, objects: objects}) - equal(result[0], 'fullRender.lenghtChanged') - //equal(result[1][0], 1) - //equal(result[1][1], undefined) - //equal(result[2][0], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '500 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr').length, 1) - equal(el.find('tbody > tr:nth-child(2) > td').length, 0) - - objects.splice(2,1) - result = table.update({sync: true, objects: objects}) - - equal(result[0], 'fullRender.lenghtChanged') - //equal(result[0], 'fullRender.contentRemoved') - //equal(result[1][0], 1) - //equal(result[1][1], undefined) - //equal(result[2][0], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-pager').first().find('.js-page').length, 0) - - objects = [ - { - id: 500, - name: '500 prio', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ] - App.TicketPriority.refresh(objects) - - objects = App.TicketPriority.all() - - result = table.update({sync: true, objects: objects}) - equal(result[0], 'fullRender.contentRemoved') - - equal(el.find('.js-pager').first().find('.js-page').length, 2) - equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) - equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') - el.find('.js-pager').first().find('.js-page:nth-child(2)').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '150 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '11.01.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '500 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr').length, 2) - equal(el.find('tbody > tr:nth-child(3) > td').length, 0) - - equal(el.find('.js-pager').first().find('.js-page').length, 2) - equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) - equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '2') - el.find('.js-pager').first().find('.js-page:nth-child(1)').click() - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-pager').first().find('.js-page').length, 2) - equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) - equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') - - objects.splice(2,2) - - result = table.update({sync: true, objects: objects}) - equal(result[0], 'fullRender.contentRemoved') - - equal(el.find('.js-pager').first().find('.js-page').length, 0) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '4 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '06.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - objects = [ - { - id: 501, - name: '501 prio', - note: 'some note', - active: true, - created_at: '2014-06-10T10:17:30.000Z', - }, - ] - App.TicketPriority.refresh(objects) - objects = App.TicketPriority.all() - - result = table.update({sync: true, objects: objects}) - equal(result[0], 'fullRender.contentRemoved') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '0 prio', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '1 prio', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '09.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(3)').text().trim(), 'true', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '2 prio', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '08.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 3') - equal(el.find('tbody > tr').length, 150) - equal(el.find('tbody > tr:nth-child(151) > td').length, 0) - - equal(el.find('.js-pager').first().find('.js-page').length, 2) - equal(el.find('.js-pager').first().find('.js-page.is-selected').length, 1) - equal(el.find('.js-pager').first().find('.js-page.is-selected').text(), '1') - - $('#table').append('

        table with data 7

        ') - var el = $('#table-new7') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), - checkbox: false, - radio: false, - }) - //equal(el.find('table').length, 0, 'row count') - //table.render() - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-12T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'fullRender.contentRemoved') - equal(result[1][0], 0) - equal(result[1][1], undefined) - equal(result[2][0], 0) - equal(result[2][1], undefined) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') - - $('#table').append('

        table with data 8

        ') - var el = $('#table-new8') - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note', - active: true, - created_at: '2014-06-12T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - { - id: 3, - name: '3 high', - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.all(), - checkbox: false, - radio: false, - orderBy: 'not_existing', - orderDirection: 'DESC', - }) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') - - result = table.update({sync: true, objects: App.TicketPriority.all(), orderBy: 'not_existing', orderDirection: 'ASC'}) - equal(result[0], 'noChanges') - - $('#table').append('

        table with data 9

        ') - var el = $('#table-new9') - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - external_id: 3, - note: 'some note', - active: true, - created_at: '2014-06-12T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - external_id: 2, - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - { - id: 3, - name: '3 high', - external_id: 1, - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - - App.TicketPriority.resetAttributes() - App.TicketPriority.updateAttributes([{ - name: 'external_id', - display: 'External', - tag: 'input', - readonly: 1, - }]) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.all(), - checkbox: false, - radio: false, - orderBy: 'external', - orderDirection: 'DESC', - }) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') - - result = table.update({sync: true, objects: App.TicketPriority.all(), orderBy: 'external', orderDirection: 'ASC'}) - equal(result[0], 'fullRender.contentChanged') - equal(result[1], 0) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') - - $('#table').append('

        table with data 10

        ') - var el = $('#table-new10') - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - external_id: 3, - note: 'some note', - active: true, - created_at: '2014-06-12T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - external_id: 2, - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - { - id: 3, - name: '3 high', - external_id: 1, - note: 'some note 3', - active: false, - created_at: '2014-06-10T10:17:38.000Z', - }, - ], {clear: true}) - App.TicketPriority.resetAttributes() - App.TicketPriority.updateAttributes([{ - name: 'external', - display: 'External', - tag: 'input', - readonly: 1, - }]) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.all(), - checkbox: false, - radio: false, - orderBy: 'external', - orderDirection: 'ASC', - }) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') - - result = table.update({sync: true, objects: App.TicketPriority.all(), orderBy: 'external', orderDirection: 'DESC'}) - equal(result[0], 'fullRender.contentChanged') - equal(result[1], 0) - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 3') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '3 hoch', 'check row 3') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 3') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '10.06.2014', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(2)').text().trim(), '12.06.2014', 'check row 1') - equal(el.find('tbody > tr:nth-child(3) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - - equal(el.find('tbody > tr:nth-child(4) > td').length, 0, 'check row 3') - - $('#table').append('

        table with data 11

        ') - var el = $('#table-new11') - - App.TicketPriority.refresh([ - { - id: 1, - name: '1 low', - note: 'some note 1', - active: true, - created_at: '2014-06-10T11:17:34.000Z', - }, - { - id: 2, - name: '2 normal', - note: 'some note 2', - active: false, - created_at: '2014-06-10T10:17:34.000Z', - }, - ], {clear: true}) - - var table = new App.ControllerTable({ - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'}), - checkbox: false, - radio: false, - frontendTimeUpdateExecute: false, - }) - //equal(el.find('table').length, 0, 'row count') - //table.render() - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '', 'check row 2') - equal(el.find('tbody > tr:nth-child(3) > td').length, 0, 'check row 3') - - result = table.update({sync: true, objects: App.TicketPriority.search({sortBy:'name', order: 'ASC'})}) - equal(result[0], 'noChanges') - - equal(el.find('table > thead > tr').length, 1, 'row count') - equal(el.find('table > thead > tr > th:nth-child(1)').text().trim(), 'Name', 'check header') - equal(el.find('table > thead > tr > th:nth-child(2)').text().trim(), 'Erstellt', 'check header') - equal(el.find('table > thead > tr > th:nth-child(3)').text().trim(), 'Aktiv', 'check header') - equal(el.find('tbody > tr:nth-child(1) > td').length, 3, 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:first').text().trim(), '1 niedrig', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(), '', 'check row 1') - equal(el.find('tbody > tr:nth-child(1) > td:nth-child(3)').text().trim(), 'true', 'check row 1') - equal(el.find('tbody > tr:nth-child(2) > td').length, 3, 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:first').text().trim(), '2 normal', 'check row 2') - equal(el.find('tbody > tr:nth-child(2) > td:nth-child(2)').text().trim(), '', 'check row 2') - - $('#table').append('

        table with large data and pager and 10 per page

        ') - var el = $('#table-new12') - - var objects = []; - var created_at = Date.parse('2014-06-10T11:17:34.000Z') - - for (i = 0; i < 35; i++) { - local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() - item = { - id: i, - name: i + ' prio', - note: 'some note', - active: true, - created_at: local_created_at, - } - objects.push(item) - } - - App.TicketPriority.refresh(objects, {clear: true}) - - var table = new App.ControllerTable({ - tableId: 'large_table_test_pager', - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.all(), - checkbox: false, - radio: false, - pagerItemsPerPage: 10, - ttt: true - }) - - equal(el.find('tbody > tr').length, 10) - equal(el.find('.js-pager:first-child .js-page').length, 4) - - $('#table').append('

        table with large data and pager disabled

        ') - var el = $('#table-new13') - - var objects = []; - var created_at = Date.parse('2014-06-10T11:17:34.000Z') - - for (i = 0; i < 200; i++) { - local_created_at = new Date(created_at - (1000 * 60 * 60 * 24 * i)).toISOString() - item = { - id: i, - name: i + ' prio', - note: 'some note', - active: true, - created_at: local_created_at, - } - objects.push(item) - } - - App.TicketPriority.refresh(objects, {clear: true}) - - var table = new App.ControllerTable({ - tableId: 'large_table_test_pager', - el: el, - overviewAttributes: ['name', 'created_at', 'active'], - model: App.TicketPriority, - objects: App.TicketPriority.all(), - checkbox: false, - radio: false, - pagerEnabled: false, - ttt: true - }) - - equal(el.find('tbody > tr').length, 200) - equal(el.find('.js-pager:first-child .js-page').length, 0) -}) diff --git a/public/assets/tests/taskbar.js b/public/assets/tests/taskbar.js deleted file mode 100644 index 87c6af8a7..000000000 --- a/public/assets/tests/taskbar.js +++ /dev/null @@ -1,316 +0,0 @@ -window.onload = function() { - -test( "taskbar basic tests", function() { - // create task bar div - $('#taskbars').append('

        taskbar basic tests

        ') - App.TaskManager.init({ - el: $('#taskbar1'), - offlineModus: true, - force: true, - }) - - // add tasks - App.TaskManager.execute({ - key: 'TestKey1', - controller: 'TestController1', - params: { - message: '#1', - }, - show: true, - persistent: false, - }) - equal($('#taskbars .content').length, 1, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#1',show:'true',hide:'false',active:'true'", "check active content!") - - // verify - task = App.TaskManager.get('TestKey1') - equal(task.notify, false) - deepEqual(task.state, undefined) - deepEqual(task.params, { "message": "#1", "shown": true }) - - // update - App.TaskManager.update('TestKey1', { 'state': 'abc' }) - App.TaskManager.update('TestKey1', { 'params': { a: 12 } }) - App.TaskManager.notify('TestKey1') - - // verify - task = App.TaskManager.get('TestKey1') - equal(task.notify, true) - deepEqual(task.state, 'abc') - deepEqual(task.params, { "a": 12 }) - - App.TaskManager.execute({ - key: 'TestKey2', - controller: 'TestController1', - params: { - message: '#2', - }, - show: true, - persistent: false, - }) - equal($('#taskbars .content').length, 2, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'", "check active content!") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'", "check active content!") - - // check task history - equal(App.TaskManager.nextTaskUrl(), '#/some/url/#2') - equal(App.TaskManager.nextTaskUrl(), '#/some/url/#1') - - App.TaskManager.execute({ - key: 'TestKey3', - controller: 'TestController1', - params: { - message: '#3', - }, - show: false, - persistent: false, - }) - equal($('#taskbars .content').length, 2, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'", "check active content!") - - App.TaskManager.execute({ - key: 'TestKey3', - controller: 'TestController1', - params: { - message: '#3', - }, - show: true, - persistent: false, - }) - equal($('#taskbars .content').length, 3, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") - - App.TaskManager.execute({ - key: 'TestKey4', - controller: 'TestController1', - params: { - message: '#4', - }, - show: false, - persistent: true, - }) - equal($('#taskbars .content').length, 3, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") - - App.TaskManager.execute({ - key: 'TestKey5', - controller: 'TestController1', - params: { - message: '#5', - }, - show: true, - persistent: true, - }) - equal($('#taskbars .content').length, 4, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#5',show:'true',hide:'false',active:'true'") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'false',active:'true'", "check active content!") - - App.TaskManager.execute({ - key: 'TestKey6', - controller: 'TestController1', - params: { - message: '#6', - }, - show: true, - persistent: false, - }) - equal($('#taskbars .content').length, 5, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'", "check active content!") - - // remove task#2 - App.TaskManager.remove('TestKey2') - - equal($('#taskbars .content').length, 4, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'", "check active content!") - - // activate task#3 - App.TaskManager.execute({ - key: 'TestKey3', - controller: 'TestController1', - params: { - message: '#3', - }, - show: true, - persistent: false, - }) - equal($('#taskbars .content').length, 4, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'", "check active content!") - equal($('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'true',active:'false'", "check active content!") - - - // activate task#1 - App.TaskManager.execute({ - key: 'TestKey1', - controller: 'TestController1', - params: { - message: '#1', - }, - show: true, - persistent: false, - }) - equal($('#taskbars .content').length, 4, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#1',show:'true',hide:'true',active:'true'") - - equal($('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'true'", "check active content!") - equal($('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!") - equal($('#taskbars #content_permanent_TestKey6').text(), "some test controller message:'#6',show:'true',hide:'true',active:'false'", "check active content!") - - // remove task#1 - App.TaskManager.remove('TestKey1') - - // verify if task#3 is active - equal($('#taskbars .content').length, 3, "check available active contents") - equal($('#taskbars .content.active').length, 0, "check available active contents") - equal($('#taskbars .content.active').text(), "") - - // remove task#3 - App.TaskManager.remove('TestKey3') - - // verify if task#5 is active - equal($('#taskbars .content').length, 2, "check available active contents") - equal($('#taskbars .content.active').length, 0, "check available active contents") - equal($('#taskbars .content.active').text(), "") - - // remove task#5 // can not get removed because of permanent task - App.TaskManager.remove('TestKey5') - - // verify if task#5 is active - equal($('#taskbars .content').length, 2, "check available active contents") - equal($('#taskbars .content.active').length, 0, "check available active contents") - equal($('#taskbars .content.active').text(), "") - - // create task#7 - App.TaskManager.execute({ - key: 'TestKey7', - controller: 'TestController1', - params: { - message: '#7', - }, - show: true, - persistent: false, - }) - equal($('#taskbars .content').length, 3, "check available active contents") - equal($('#taskbars .content.active').length, 1, "check available active contents") - equal($('#taskbars .content.active').text(), "some test controller message:'#7',show:'true',hide:'false',active:'true'", "check active content!") - - // remove task#7 - App.TaskManager.remove('TestKey7') - - // verify if task#5 is active - equal($('#taskbars .content').length, 2, "check available active contents") - equal($('#taskbars .content.active').length, 0, "check available active contents") - equal($('#taskbars .content.active').text(), "") - - // check task history - equal(App.TaskManager.nextTaskUrl(), '#/some/url/#6') - equal(App.TaskManager.nextTaskUrl(), '#/some/url/#5') - equal(App.TaskManager.nextTaskUrl(), '#/some/url/#6') - equal(App.TaskManager.nextTaskUrl(), '#/some/url/#6') - - // remove task#6 - App.TaskManager.remove('TestKey6') - - // check task history - equal(App.TaskManager.nextTaskUrl(), false) - equal(App.TaskManager.nextTaskUrl(), false) - - // check max tabs - var times = 5; - App.TaskManager.tasksAutoCleanupDelayTime(200) - App.TaskManager.tasksAutoCleanupTaskMax(3) - - for(var i=0; i < times; i++){ - App.TaskManager.execute({ - key: 'TestKeyLoop' + i, - controller: 'TestController1', - params: { - message: "#" + i, - }, - show: true, - persistent: false, - }) - } - equal(App.TaskManager.all().length, 5) - -}) - -App.Delay.set(function() { - test( "taskbar check max tabs 2", function() { - - equal(App.TaskManager.all().length, 3) - - var times = 5; - for(var i=0; i < times; i++){ - App.TaskManager.execute({ - key: 'TestKeyLoop2' + i, - controller: 'TestController1', - params: { - message: "#" + i, - changedState: true - }, - show: true, - persistent: false, - }) - } - equal(App.TaskManager.all().length, 8) - - }) -}, 1000); - -App.Delay.set(function() { - test( "taskbar check max tabs 5", function() { - - equal(App.TaskManager.all().length, 5) - - // destroy task bar - App.TaskManager.reset() - - // check if any taskar exists - equal($('#taskbars .content').length, 0, "check available active contents") - }) -}, 2000); - -} diff --git a/spec/system/js/q_unit_spec.rb b/spec/system/js/q_unit_spec.rb index ffa1fe604..2eb156cb6 100644 --- a/spec/system/js/q_unit_spec.rb +++ b/spec/system/js/q_unit_spec.rb @@ -2,174 +2,62 @@ require 'rails_helper' -RSpec.describe 'QUnit', type: :system, authenticated_as: false, set_up: true, websocket: false do +RSpec.describe 'QUnit', type: :system, authenticated_as: false, set_up: true, websocket: false, time_zone: 'Europe/London' do + matcher :pass_qunit_test do + match do + actual.has_css?('.total', wait: 120) - def q_unit_tests(test_name) + actual.has_css? '.result .failed', text: '0', wait: 0 + end - visit "/tests_#{test_name}" + failure_message do + messages = actual + .all('.qunit-assert-list li.fail') + .map { |elem| "> #{failure_name(elem)}\n#{failure_source(elem)}" } + .join("\n") - yield if block_given? + "Failed #{failed_count} out of #{total_count}:\n#{messages}" + end - expect(page).to have_css('.result', text: 'Tests completed') - expect(page).to have_css('.result .failed', text: '0') - end + def failure_source(row) + row + .find('.test-source pre') + .text + .strip + .lines[0, 2] + .reject { |line| line.include? 'qunit-' } + .join + end - def async_q_unit_tests(*args) - q_unit_tests(*args) do - wait(120, interval: 3).until_constant do - page.has_css?('.total', wait: 0) ? find('.total').text : nil - end + def failure_name(row) + row + .find('.test-message') + .text + .strip + end + + def failed_count + actual.find('.result .failed').text + end + + def total_count + actual.find('.result .total').text end end - it 'Core' do - async_q_unit_tests('core') - end + files = if (basename = ENV['QUNIT_TEST']) + [basename] + else + Pathname + .glob('public/assets/tests/qunit/*.js') + .map { |elem| elem.basename(elem.extname).to_s } + .sort + end - it 'I18n' do - async_q_unit_tests('i18n') - end - - context 'UI' do - - it 'Base' do - q_unit_tests('ui') - end - - it 'Local storage' do - q_unit_tests('local_storage') - end - - it 'Model' do - async_q_unit_tests('model') - end - - it 'Model binding' do - q_unit_tests('model_binding') - end - - it 'Model UI' do - - if !ENV['CI'] - skip("Can't run locally because of dependence of special Timezone") - end - - q_unit_tests('model_ui') - end - - it 'Model Ticket' do - q_unit_tests('model_ticket') - end - - it 'Ticket selector' do - q_unit_tests('ticket_selector') - end - - it 'Image Service' do - q_unit_tests('image_service') - end - end - - context 'Form' do - - it 'Base' do - async_q_unit_tests('form') - end - - it 'Trim' do - q_unit_tests('form_trim') - end - - it 'Find' do - q_unit_tests('form_find') - end - - it 'Timer' do - q_unit_tests('form_timer') - end - - it 'Color' do - q_unit_tests('form_color') - end - - it 'Extended' do - q_unit_tests('form_extended') - end - - it 'Searchable select' do - q_unit_tests('form_searchable_select') - end - - it 'Tree select' do - q_unit_tests('form_tree_select') - end - - it 'Column select' do - q_unit_tests('form_column_select') - end - - it 'Ticket perform action' do - async_q_unit_tests('form_ticket_perform_action') - end - - it 'Ticket macro' do - q_unit_tests('ticket_macro') - end - - it 'Validation' do - q_unit_tests('form_validation') - end - - it 'Skip rendering' do - q_unit_tests('form_skip_rendering') - end - - it 'SLA times' do - q_unit_tests('form_sla_times') - end - - it 'DateTime' do - q_unit_tests('form_datetime') - end - - it 'Core Workflow' do - q_unit_tests('form_core_workflow') - end - end - - context 'Form AJAX', searchindex: true do - before do - configure_elasticsearch - rebuild_searchindex - end - - it 'autocompletion ajax' do - async_q_unit_tests('form_autocompletion_ajax') - end - end - - context 'Table' do - - it 'Base' do - q_unit_tests('table') - end - - it 'Extended' do - q_unit_tests('table_extended') - end - - it 'HTML utils' do - q_unit_tests('html_utils') - end - - it 'Taskbar' do - q_unit_tests('taskbar') - end - end - - context 'Knowlede Base Editor' do - it 'Vdeo Embeding' do - q_unit_tests('kb_video_embeding') + files.each do |elem| + it elem.humanize do + visit "/tests_#{elem}" + expect(page).to pass_qunit_test end end end