From c32c9866d2262d695bb20987d9064fc3876c47c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Wed, 30 Nov 2016 13:31:00 +0100 Subject: [PATCH 01/19] added build & doc badge to README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e5094c097..c075f3306 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ with a team of agents? You're going to love Zammad! +## Statuses + +[![Build Status](https://travis-ci.org/zammad/zammad.svg?branch=develop)](https://travis-ci.org/zammad/zammad) [![Documentation Status](https://readthedocs.org/projects/zammad/badge/?version=latest)](https://docs.zammad.org) ## Installing & Getting Started @@ -32,3 +35,4 @@ https://zammad.org/participate Thanks! ❤️ ❤️ ❤️ Your Zammad Team + From 7c43024aacbac84b15249435322605f8a7f527a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Wed, 30 Nov 2016 13:52:58 +0100 Subject: [PATCH 02/19] added codeclimete & docker badges --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c075f3306..1a3d7bb91 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,12 @@ with a team of agents? You're going to love Zammad! -## Statuses +## Statusbadges -[![Build Status](https://travis-ci.org/zammad/zammad.svg?branch=develop)](https://travis-ci.org/zammad/zammad) [![Documentation Status](https://readthedocs.org/projects/zammad/badge/?version=latest)](https://docs.zammad.org) +- Build: [![Build Status](https://travis-ci.org/zammad/zammad.svg?branch=develop)](https://travis-ci.org/zammad/zammad) +- Code: [![Code Climate](https://codeclimate.com/github/zammad/zammad/badges/gpa.svg)](https://codeclimate.com/github/zammad/zammad) +- Docs: [![Documentation Status](https://readthedocs.org/projects/zammad/badge/?version=latest)](https://docs.zammad.org) +- Docker Image: [![](https://images.microbadger.com/badges/image/zammad/zammad.svg)](https://microbadger.com/images/zammad/zammad) [![](https://images.microbadger.com/badges/version/zammad/zammad.svg)](https://microbadger.com/images/zammad/zammad) ## Installing & Getting Started From 23c9316f1153b09c48a880d21f20390ab804b70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Wed, 30 Nov 2016 13:54:36 +0100 Subject: [PATCH 03/19] docker badges links to https://hub.docker.com/r/zammad/zammad/ --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a3d7bb91..cf12bd032 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ You're going to love Zammad! - Build: [![Build Status](https://travis-ci.org/zammad/zammad.svg?branch=develop)](https://travis-ci.org/zammad/zammad) - Code: [![Code Climate](https://codeclimate.com/github/zammad/zammad/badges/gpa.svg)](https://codeclimate.com/github/zammad/zammad) - Docs: [![Documentation Status](https://readthedocs.org/projects/zammad/badge/?version=latest)](https://docs.zammad.org) -- Docker Image: [![](https://images.microbadger.com/badges/image/zammad/zammad.svg)](https://microbadger.com/images/zammad/zammad) [![](https://images.microbadger.com/badges/version/zammad/zammad.svg)](https://microbadger.com/images/zammad/zammad) +- Docker Image: [![](https://images.microbadger.com/badges/image/zammad/zammad.svg)](https://hub.docker.com/r/zammad/zammad/) [![](https://images.microbadger.com/badges/version/zammad/zammad.svg)](https://hub.docker.com/r/zammad/zammad/) ## Installing & Getting Started From 9633d211ed605b3dc5425605443a28ab065e9e2c Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 30 Nov 2016 14:34:15 +0100 Subject: [PATCH 04/19] Travis ci improvements (mysql + postgresql + more tests). --- .travis.yml | 36 +++++++++++++++++++++++++------ test/unit/ticket_overview_test.rb | 3 ++- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 316927f57..a2b5bf217 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,20 @@ dist: trusty sudo: required notifications: - email: false + email: + - me+tv@zammad.com +env: + - DB=mysql + - DB=postgresql addons: + postgresql: "9.4" apt: packages: - mysql-server-5.6 - mysql-client-core-5.6 - mysql-client-5.6 services: + - postgresql - mysql language: ruby rvm: @@ -16,13 +22,17 @@ rvm: before_install: - sudo apt-get -qq update - sudo apt-get install -y curl git-core patch build-essential bison zlib1g-dev libssl-dev libxml2-dev libxml2-dev sqlite3 libsqlite3-dev autotools-dev libxslt1-dev libyaml-0-2 autoconf automake libreadline6-dev libyaml-dev libtool libgmp-dev libgdbm-dev libncurses5-dev pkg-config libffi-dev libmysqlclient-dev postfix - - mysql -u root -e "CREATE USER 'some_user'@'localhost' IDENTIFIED BY 'some_pass';" - - mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO 'some_user'@'localhost';" - - export RAILS_ENV=development - - cp config/database.yml.dist config/database.yml + - if [ "${DB}" = "mysql" ]; then mysql -u root -e "CREATE USER 'some_user'@'localhost' IDENTIFIED BY 'some_pass';"; fi + - if [ "${DB}" = "mysql" ]; then mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO 'some_user'@'localhost';"; fi + - if [ "${DB}" = "mysql" ]; then cp config/database.yml.test-mysql config/database.yml; fi + - if [ "${DB}" = "postgresql" ]; then psql -c 'create database zammad_test;' -U postgres; fi + - if [ "${DB}" = "postgresql" ]; then cp config/database.yml.test-postgresql config/database.yml; fi + - export RAILS_ENV=test install: -- bundle install --without postgres + - if [ "${DB}" = "mysql" ]; then bundle install --without postgres; fi + - if [ "${DB}" = "postgresql" ]; then bundle install; fi script: +- bundle exec rubocop - rake db:create - rake db:migrate - rake db:seed @@ -30,3 +40,17 @@ script: - rake test:controllers - rake assets:precompile - rake db:drop +- rake db:create +- rake db:migrate +- rake db:seed +- ruby -I test/ test/integration/auto_wizard_test.rb +- rake db:drop +- rake db:create +- rake db:migrate +- rake db:seed +- ruby -I test/ test/integration/geo_location_test.rb +- ruby -I test/ test/integration/geo_calendar_test.rb +- ruby -I test/ test/integration/user_agent_test.rb +- ruby -I test/ test/integration/user_device_controller_test.rb +- ruby -I test/ test/integration/sipgate_controller_test.rb +- rake db:drop diff --git a/test/unit/ticket_overview_test.rb b/test/unit/ticket_overview_test.rb index c31952e26..3f49d40ec 100644 --- a/test/unit/ticket_overview_test.rb +++ b/test/unit/ticket_overview_test.rb @@ -548,7 +548,8 @@ class TicketOverviewTest < ActiveSupport::TestCase assert_equal(result[2][:tickets].class, Array) assert(result[2][:tickets].empty?) - sleep 1 + travel_to Time.zone.now + 1.second # because of mysql millitime issues + ticket3 = Ticket.create( title: 'overview test 3', group: Group.lookup(name: 'OverviewTest'), From abd304faa0ece09feadf954ad118349f0abe4aaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Wed, 30 Nov 2016 14:47:32 +0100 Subject: [PATCH 05/19] added missing database.yml-test... for travis --- config/database.yml.dist | 14 -------------- config/database.yml.test-mysql | 11 +++++++++++ config/database.yml.test-postgresql | 11 +++++++++++ 3 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 config/database.yml.test-mysql create mode 100644 config/database.yml.test-postgresql diff --git a/config/database.yml.dist b/config/database.yml.dist index 70dc993dc..4f3ef68f3 100644 --- a/config/database.yml.dist +++ b/config/database.yml.dist @@ -17,17 +17,3 @@ development: username: some_user password: some_pass host: 127.0.0.1 - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. -test: - adapter: mysql2 - database: zammad_test - pool: 50 - timeout: 5000 - encoding: utf8 - username: some_user - password: some_pass - host: 127.0.0.1 - diff --git a/config/database.yml.test-mysql b/config/database.yml.test-mysql new file mode 100644 index 000000000..f6b525b4c --- /dev/null +++ b/config/database.yml.test-mysql @@ -0,0 +1,11 @@ +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: mysql2 + database: zammad_test + pool: 50 + timeout: 5000 + encoding: utf8 + username: some_user + password: some_pass diff --git a/config/database.yml.test-postgresql b/config/database.yml.test-postgresql new file mode 100644 index 000000000..bda094235 --- /dev/null +++ b/config/database.yml.test-postgresql @@ -0,0 +1,11 @@ +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: postgresql + database: zammad_test + pool: 50 + timeout: 5000 + encoding: utf8 + username: postgres + password: From f995ae23260206c0809d7899a807060337030784 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 30 Nov 2016 15:12:16 +0100 Subject: [PATCH 06/19] Fixed time travel (travel_back again). --- test/unit/ticket_overview_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/ticket_overview_test.rb b/test/unit/ticket_overview_test.rb index 3f49d40ec..de881b401 100644 --- a/test/unit/ticket_overview_test.rb +++ b/test/unit/ticket_overview_test.rb @@ -549,7 +549,6 @@ class TicketOverviewTest < ActiveSupport::TestCase assert(result[2][:tickets].empty?) travel_to Time.zone.now + 1.second # because of mysql millitime issues - ticket3 = Ticket.create( title: 'overview test 3', group: Group.lookup(name: 'OverviewTest'), @@ -572,6 +571,7 @@ class TicketOverviewTest < ActiveSupport::TestCase updated_by_id: 1, created_by_id: 1, ) + travel_back result = Ticket::Overviews.index(agent1) assert_equal(result[0][:overview][:id], overview1.id) From 5238a6b5b65493c7b567480b1eed9e4f0ced2563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Wed, 30 Nov 2016 15:36:28 +0100 Subject: [PATCH 07/19] removed php & python tests --- .codeclimate.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.codeclimate.yml b/.codeclimate.yml index 54e14b269..3991067f6 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -14,14 +14,12 @@ engines: languages: - ruby - javascript - - python - - php eslint: enabled: true fixme: enabled: true phpmd: - enabled: true + enabled: false rubocop: enabled: true ratings: @@ -38,8 +36,6 @@ ratings: - "**.js" - "**.jsx" - "**.module" - - "**.php" - - "**.py" exclude_paths: - config/ - db/ From dfbe15cb0e4c08935be785b49cb89c37d746d72c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Wed, 30 Nov 2016 15:39:13 +0100 Subject: [PATCH 08/19] added eslint & csslint config for codeclimate --- .csslintrc | 2 + .eslintignore | 1 + .eslintrc | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 .csslintrc create mode 100644 .eslintignore create mode 100644 .eslintrc diff --git a/.csslintrc b/.csslintrc new file mode 100644 index 000000000..aacba956e --- /dev/null +++ b/.csslintrc @@ -0,0 +1,2 @@ +--exclude-exts=.min.css +--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..96212a359 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +**/*{.,-}min.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..9faa37508 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,213 @@ +ecmaFeatures: + modules: true + jsx: true + +env: + amd: true + browser: true + es6: true + jquery: true + node: true + +# http://eslint.org/docs/rules/ +rules: + # Possible Errors + comma-dangle: [2, never] + no-cond-assign: 2 + no-console: 0 + no-constant-condition: 2 + no-control-regex: 2 + no-debugger: 2 + no-dupe-args: 2 + no-dupe-keys: 2 + no-duplicate-case: 2 + no-empty: 2 + no-empty-character-class: 2 + no-ex-assign: 2 + no-extra-boolean-cast: 2 + no-extra-parens: 0 + no-extra-semi: 2 + no-func-assign: 2 + no-inner-declarations: [2, functions] + no-invalid-regexp: 2 + no-irregular-whitespace: 2 + no-negated-in-lhs: 2 + no-obj-calls: 2 + no-regex-spaces: 2 + no-sparse-arrays: 2 + no-unexpected-multiline: 2 + no-unreachable: 2 + use-isnan: 2 + valid-jsdoc: 0 + valid-typeof: 2 + + # Best Practices + accessor-pairs: 2 + block-scoped-var: 0 + complexity: [2, 6] + consistent-return: 0 + curly: 0 + default-case: 0 + dot-location: 0 + dot-notation: 0 + eqeqeq: 2 + guard-for-in: 2 + no-alert: 2 + no-caller: 2 + no-case-declarations: 2 + no-div-regex: 2 + no-else-return: 0 + no-empty-label: 2 + no-empty-pattern: 2 + no-eq-null: 2 + no-eval: 2 + no-extend-native: 2 + no-extra-bind: 2 + no-fallthrough: 2 + no-floating-decimal: 0 + no-implicit-coercion: 0 + no-implied-eval: 2 + no-invalid-this: 0 + no-iterator: 2 + no-labels: 0 + no-lone-blocks: 2 + no-loop-func: 2 + no-magic-number: 0 + no-multi-spaces: 0 + no-multi-str: 0 + no-native-reassign: 2 + no-new-func: 2 + no-new-wrappers: 2 + no-new: 2 + no-octal-escape: 2 + no-octal: 2 + no-proto: 2 + no-redeclare: 2 + no-return-assign: 2 + no-script-url: 2 + no-self-compare: 2 + no-sequences: 0 + no-throw-literal: 0 + no-unused-expressions: 2 + no-useless-call: 2 + no-useless-concat: 2 + no-void: 2 + no-warning-comments: 0 + no-with: 2 + radix: 2 + vars-on-top: 0 + wrap-iife: 2 + yoda: 0 + + # Strict + strict: 0 + + # Variables + init-declarations: 0 + no-catch-shadow: 2 + no-delete-var: 2 + no-label-var: 2 + no-shadow-restricted-names: 2 + no-shadow: 0 + no-undef-init: 2 + no-undef: 0 + no-undefined: 0 + no-unused-vars: 0 + no-use-before-define: 0 + + # Node.js and CommonJS + callback-return: 2 + global-require: 2 + handle-callback-err: 2 + no-mixed-requires: 0 + no-new-require: 0 + no-path-concat: 2 + no-process-exit: 2 + no-restricted-modules: 0 + no-sync: 0 + + # Stylistic Issues + array-bracket-spacing: 0 + block-spacing: 0 + brace-style: 0 + camelcase: 0 + comma-spacing: 0 + comma-style: 0 + computed-property-spacing: 0 + consistent-this: 0 + eol-last: 0 + func-names: 0 + func-style: 0 + id-length: 0 + id-match: 0 + indent: 0 + jsx-quotes: 0 + key-spacing: 0 + linebreak-style: 0 + lines-around-comment: 0 + max-depth: 0 + max-len: 0 + max-nested-callbacks: 0 + max-params: 0 + max-statements: [2, 30] + new-cap: 0 + new-parens: 0 + newline-after-var: 0 + no-array-constructor: 0 + no-bitwise: 0 + no-continue: 0 + no-inline-comments: 0 + no-lonely-if: 0 + no-mixed-spaces-and-tabs: 0 + no-multiple-empty-lines: 0 + no-negated-condition: 0 + no-nested-ternary: 0 + no-new-object: 0 + no-plusplus: 0 + no-restricted-syntax: 0 + no-spaced-func: 0 + no-ternary: 0 + no-trailing-spaces: 0 + no-underscore-dangle: 0 + no-unneeded-ternary: 0 + object-curly-spacing: 0 + one-var: 0 + operator-assignment: 0 + operator-linebreak: 0 + padded-blocks: 0 + quote-props: 0 + quotes: 0 + require-jsdoc: 0 + semi-spacing: 0 + semi: 0 + sort-vars: 0 + space-after-keywords: 0 + space-before-blocks: 0 + space-before-function-paren: 0 + space-before-keywords: 0 + space-in-parens: 0 + space-infix-ops: 0 + space-return-throw-case: 0 + space-unary-ops: 0 + spaced-comment: 0 + wrap-regex: 0 + + # ECMAScript 6 + arrow-body-style: 0 + arrow-parens: 0 + arrow-spacing: 0 + constructor-super: 0 + generator-star-spacing: 0 + no-arrow-condition: 0 + no-class-assign: 0 + no-const-assign: 0 + no-dupe-class-members: 0 + no-this-before-super: 0 + no-var: 0 + object-shorthand: 0 + prefer-arrow-callback: 0 + prefer-const: 0 + prefer-reflect: 0 + prefer-spread: 0 + prefer-template: 0 + require-yield: 0 From c548502d8485adc968ca234c3da171f1e68f5b22 Mon Sep 17 00:00:00 2001 From: Julian Kornberger Date: Wed, 30 Nov 2016 19:06:15 +0100 Subject: [PATCH 09/19] Move calendar mapping to config directory --- app/models/calendar.rb | 93 ++++-------------------------------- config/holiday_calendars.yml | 78 ++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 83 deletions(-) create mode 100644 config/holiday_calendars.yml diff --git a/app/models/calendar.rb b/app/models/calendar.rb index c27d0fc64..460567cde 100644 --- a/app/models/calendar.rb +++ b/app/models/calendar.rb @@ -75,92 +75,19 @@ returnes preset of ical feeds returns { - 'US' => 'http://www.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics', + 'http://www.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics' => 'US', ... } =end def self.ical_feeds - gfeeds = { - 'Australia' => 'en.australian', - 'Austria' => 'de.austrian', - 'Argentina' => 'en.ar', - 'Bahamas' => 'en.bs', - 'Belarus' => 'en.by', - 'Brazil' => 'en.brazilian', - 'Bulgaria' => 'en.bulgarian', - 'Canada' => 'en.canadian', - 'China' => 'en.china', - 'Chile' => 'en.cl', - 'Costa Rica' => 'en.cr', - 'Colombia' => 'en.co', - 'Croatia' => 'en.croatian', - 'Cuba' => 'en.cu', - 'Cyprus' => 'de.cy', - 'Switzerland' => 'de.ch', - 'Denmark' => 'da.danish', - 'Netherlands' => 'nl.dutch', - 'Egypt' => 'en.eg', - 'Ethiopia' => 'en.et', - 'Ecuador' => 'en.ec', - 'Estonia' => 'en.ee', - 'Finland' => 'en.finnish', - 'France' => 'en.french', - 'Germany' => 'de.german', - 'Greece' => 'en.greek', - 'Ghana' => 'en.gh', - 'Hong Kong' => 'en.hong_kong', - 'Haiti' => 'en.ht', - 'Hungary' => 'en.hungarian', - 'India' => 'en.indian', - 'Indonesia' => 'en.indonesian', - 'Iran' => 'en.ir', - 'Ireland' => 'en.irish', - 'Italy' => 'it.italian', - 'Israel' => 'en.jewish', - 'Japan' => 'en.japanese', - 'Kuwait' => 'en.kw', - 'Latvia' => 'en.latvian', - 'Liechtenstein' => 'en.li', - 'Lithuania' => 'en.lithuanian', - 'Luxembourg' => 'en.lu', - 'Malaysia' => 'en.malaysia', - 'Mexico' => 'en.mexican', - 'Morocco' => 'en.ma', - 'Mauritius' => 'en.mu', - 'Moldova' => 'en.md', - 'New Zealand' => 'en.new_zealand', - 'Norway' => 'en.norwegian', - 'Philippines' => 'en.philippines', - 'Poland' => 'en.polish', - 'Portugal' => 'en.portuguese', - 'Pakistan' => 'en.pk', - 'Russia' => 'en.russian', - 'Senegal' => 'en.sn', - 'Singapore' => 'en.singapore', - 'South Africa' => 'en.sa', - 'South Korean' => 'en.south_korea', - 'Spain' => 'en.spain', - 'Slovakia' => 'en.slovak', - 'Serbia' => 'en.rs', - 'Slovenia' => 'en.slovenian', - 'Sweden' => 'en.swedish', - 'Taiwan' => 'en.taiwan', - 'Thai' => 'en.th', - 'Turkey' => 'en.turkish', - 'UK' => 'en.uk', - 'US' => 'en.usa', - 'Ukraine' => 'en.ukrainian', - 'Uruguay' => 'en.uy', - 'Vietnam' => 'en.vietnamese', - 'Venezuela' => 'en.ve', - } - all_feeds = {} - gfeeds.each { |key, name| - all_feeds["http://www.google.com/calendar/ical/#{name}%23holiday%40group.v.calendar.google.com/public/basic.ics"] = key - } - all_feeds + data = YAML.load_file(Rails.root.join('config/holiday_calendars.yml')) + url = data['url'] + + data['countries'].map do |country, domain| + [(url % { domain: domain }), country] + end.to_h end =begin @@ -201,7 +128,7 @@ returns =end def self.sync - Calendar.all.each(&:sync) + Calendar.find_each(&:sync) true end @@ -313,7 +240,7 @@ returns # if changed calendar is default, set all others default to false def sync_default return if !default - Calendar.all.each { |calendar| + Calendar.find_each { |calendar| next if calendar.id == id next if !calendar.default calendar.default = false @@ -331,7 +258,7 @@ returns # check if sla's are refer to an existing calendar default_calendar = Calendar.find_by(default: true) - Sla.all.each { |sla| + Sla.find_each { |sla| if !sla.calendar_id sla.calendar_id = default_calendar.id sla.save! diff --git a/config/holiday_calendars.yml b/config/holiday_calendars.yml new file mode 100644 index 000000000..c105772f3 --- /dev/null +++ b/config/holiday_calendars.yml @@ -0,0 +1,78 @@ +--- +# % character in the URL has to be escaped (% => %%) +url: "http://www.google.com/calendar/ical/%{domain}%%23holiday%%40group.v.calendar.google.com/public/basic.ics" + +# Mapping from country to domain +countries: + Australia: en.australian + Austria: de.austrian + Argentina: en.ar + Bahamas: en.bs + Belarus: en.by + Brazil: en.brazilian + Bulgaria: en.bulgarian + Canada: en.canadian + China: en.china + Chile: en.cl + Costa Rica: en.cr + Colombia: en.co + Croatia: en.croatian + Cuba: en.cu + Cyprus: de.cy + Switzerland: de.ch + Denmark: da.danish + Netherlands: nl.dutch + Egypt: en.eg + Ethiopia: en.et + Ecuador: en.ec + Estonia: en.ee + Finland: en.finnish + France: en.french + Germany: de.german + Greece: en.greek + Ghana: en.gh + Hong Kong: en.hong_kong + Haiti: en.ht + Hungary: en.hungarian + India: en.indian + Indonesia: en.indonesian + Iran: en.ir + Ireland: en.irish + Italy: it.italian + Israel: en.jewish + Japan: en.japanese + Kuwait: en.kw + Latvia: en.latvian + Liechtenstein: en.li + Lithuania: en.lithuanian + Luxembourg: en.lu + Malaysia: en.malaysia + Mexico: en.mexican + Morocco: en.ma + Mauritius: en.mu + Moldova: en.md + New Zealand: en.new_zealand + Norway: en.norwegian + Philippines: en.philippines + Poland: en.polish + Portugal: en.portuguese + Pakistan: en.pk + Russia: en.russian + Senegal: en.sn + Singapore: en.singapore + South Africa: en.sa + South Korean: en.south_korea + Spain: en.spain + Slovakia: en.slovak + Serbia: en.rs + Slovenia: en.slovenian + Sweden: en.swedish + Taiwan: en.taiwan + Thai: en.th + Turkey: en.turkish + UK: en.uk + US: en.usa + Ukraine: en.ukrainian + Uruguay: en.uy + Vietnam: en.vietnamese + Venezuela: en.ve From 7388217510691a403199be6fb08bb6493eafa8ba Mon Sep 17 00:00:00 2001 From: Julian Kornberger Date: Wed, 30 Nov 2016 18:53:09 +0100 Subject: [PATCH 10/19] Small refactoring of logical expressions --- app/models/avatar.rb | 7 ++-- app/models/channel/driver/facebook.rb | 3 +- app/models/channel/driver/pop3.rb | 2 +- app/models/channel/driver/smtp.rb | 4 +-- app/models/channel/driver/twitter.rb | 21 ++++------- app/models/channel/email_parser.rb | 10 ++---- .../communicate_facebook/background_job.rb | 6 ++-- app/models/organization.rb | 3 +- app/models/ticket/escalation.rb | 2 +- app/models/ticket/number/date.rb | 2 +- app/models/ticket/number/increment.rb | 2 +- app/models/ticket/search_index.rb | 2 +- app/models/user.rb | 36 +++++-------------- app/models/user_device.rb | 6 ++-- 14 files changed, 35 insertions(+), 71 deletions(-) diff --git a/app/models/avatar.rb b/app/models/avatar.rb index 396683bb7..6ea423f41 100644 --- a/app/models/avatar.rb +++ b/app/models/avatar.rb @@ -21,8 +21,7 @@ add an avatar based on auto detection (email address) # return if we run import mode return if Setting.get('import_mode') - return if !data[:url] - return if data[:url].empty? + return if data[:url].blank? Avatar.add( object: data[:object], @@ -96,7 +95,7 @@ add avatar by url # check if avatar with url already exists avatar_already_exists = nil - if data[:source] && !data[:source].empty? + if data[:source].present? avatar_already_exists = Avatar.find_by( object_lookup_id: object_id, o_id: data[:o_id], @@ -105,7 +104,7 @@ add avatar by url end # fetch image based on http url - if data[:url] && data[:url] =~ /^http/ + if data[:url] =~ /^http/ # check if source ist already updated within last 2 minutes if avatar_already_exists && avatar_already_exists.source_url == data[:url] diff --git a/app/models/channel/driver/facebook.rb b/app/models/channel/driver/facebook.rb index 62320b31d..4ec9447c3 100644 --- a/app/models/channel/driver/facebook.rb +++ b/app/models/channel/driver/facebook.rb @@ -82,8 +82,7 @@ class Channel::Driver::Facebook @sync['pages'].each { |page_to_sync_id, page_to_sync_params| page = get_page(page_to_sync_id) next if !page - next if !page_to_sync_params['group_id'] - next if page_to_sync_params['group_id'].empty? + next if page_to_sync_params['group_id'].blank? page_client = Facebook.new(page['access_token']) posts = page_client.client.get_connection('me', 'feed', fields: 'id,from,to,message,created_time,permalink_url,comments{id,from,to,message,created_time}') diff --git a/app/models/channel/driver/pop3.rb b/app/models/channel/driver/pop3.rb index a227b68eb..01597e025 100644 --- a/app/models/channel/driver/pop3.rb +++ b/app/models/channel/driver/pop3.rb @@ -51,7 +51,7 @@ returns ssl = false port = 110 end - if options.key?(:port) && !options[:port].empty? + if options.key?(:port) && options[:port].present? port = options[:port] end diff --git a/app/models/channel/driver/smtp.rb b/app/models/channel/driver/smtp.rb index 23d6d5256..646706d25 100644 --- a/app/models/channel/driver/smtp.rb +++ b/app/models/channel/driver/smtp.rb @@ -30,8 +30,8 @@ class Channel::Driver::Smtp if !options.key?(:port) || options[:port].empty? options[:port] = 25 end - if !options.key?(:domain) + if !options.key?(:domain) # set fqdn, if local fqdn - use domain of sender fqdn = Setting.get('fqdn') if fqdn =~ /(localhost|\.local^|\.loc^)/i && (attr['from'] || attr[:from]) @@ -58,7 +58,7 @@ class Channel::Driver::Smtp } # add authentication only if needed - if options[:user] && !options[:user].empty? + if options[:user].present? smtp_params[:user_name] = options[:user] smtp_params[:password] = options[:password] smtp_params[:authentication] = options[:authentication] diff --git a/app/models/channel/driver/twitter.rb b/app/models/channel/driver/twitter.rb index cf0db3306..cce2b4cff 100644 --- a/app/models/channel/driver/twitter.rb +++ b/app/models/channel/driver/twitter.rb @@ -269,13 +269,10 @@ returns private def fetch_search - return if !@sync[:search] - return if @sync[:search].empty? + return if @sync[:search].blank? @sync[:search].each { |search| - next if !search[:term] - next if search[:term].to_s.empty? - next if !search[:group_id] - next if search[:group_id].to_s.empty? + next if search[:term].blank? + next if search[:group_id].blank? result_type = search[:type] || 'mixed' Rails.logger.debug " - searching for '#{search[:term]}'" older_import = 0 @@ -296,10 +293,8 @@ returns end def fetch_mentions - return if !@sync[:mentions] - return if @sync[:mentions].empty? - return if !@sync[:mentions][:group_id] - return if @sync[:mentions][:group_id].to_s.empty? + return if @sync[:mentions].blank? + return if @sync[:mentions][:group_id].blank? Rails.logger.debug ' - searching for mentions' older_import = 0 older_import_max = 20 @@ -318,10 +313,8 @@ returns end def fetch_direct_messages - return if !@sync[:direct_messages] - return if @sync[:direct_messages].empty? - return if !@sync[:direct_messages][:group_id] - return if @sync[:direct_messages][:group_id].to_s.empty? + return if @sync[:direct_messages].blank? + return if @sync[:direct_messages][:group_id].blank? Rails.logger.debug ' - searching for direct_messages' older_import = 0 older_import_max = 20 diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb index 571f64645..e2d42fa26 100644 --- a/app/models/channel/email_parser.rb +++ b/app/models/channel/email_parser.rb @@ -74,9 +74,7 @@ class Channel::EmailParser mail = Mail.new(msg) # set all headers - mail.header.fields.each { |field| - next if !field.name - + mail.header.fields.select(&:name).each { |field| # full line, encode, ready for storage data[field.name.to_s.downcase.to_sym] = Encode.conv('utf8', field.to_s) @@ -318,12 +316,10 @@ class Channel::EmailParser end # for some broken sm mail clients (X-MimeOLE: Produced By Microsoft Exchange V6.5) - if !filename - filename = file.header[:content_location].to_s - end + filename ||= file.header[:content_location].to_s # generate file name - if !filename || filename.empty? + if filename.blank? attachment_count = 0 (1..1000).each { |count| filename_exists = false diff --git a/app/models/observer/ticket/article/communicate_facebook/background_job.rb b/app/models/observer/ticket/article/communicate_facebook/background_job.rb index bdbe1d1dd..c48d61e78 100644 --- a/app/models/observer/ticket/article/communicate_facebook/background_job.rb +++ b/app/models/observer/ticket/article/communicate_facebook/background_job.rb @@ -7,9 +7,7 @@ class Observer::Ticket::Article::CommunicateFacebook::BackgroundJob article = Ticket::Article.find(@article_id) # set retry count - if !article.preferences['delivery_retry'] - article.preferences['delivery_retry'] = 0 - end + article.preferences['delivery_retry'] ||= 0 article.preferences['delivery_retry'] += 1 ticket = Ticket.lookup(id: article.ticket_id) @@ -24,7 +22,7 @@ class Observer::Ticket::Article::CommunicateFacebook::BackgroundJob end # fill in_reply_to - if !article.in_reply_to || article.in_reply_to.empty? + if article.in_reply_to.blank? article.in_reply_to = ticket.articles.first.message_id end diff --git a/app/models/organization.rb b/app/models/organization.rb index ad984b287..d8af2a25c 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -25,8 +25,7 @@ class Organization < ApplicationModel private def domain_cleanup - return if !domain - return if domain.empty? + return if domain.blank? domain.gsub!(/@/, '') domain.gsub!(/\s*/, '') domain.strip! diff --git a/app/models/ticket/escalation.rb b/app/models/ticket/escalation.rb index a584930e7..8e21c786b 100644 --- a/app/models/ticket/escalation.rb +++ b/app/models/ticket/escalation.rb @@ -163,7 +163,7 @@ returns } } config.hours = hours - if !hours || hours.empty? + if hours.blank? raise "No configured hours found in calendar #{calendar.inspect}" end diff --git a/app/models/ticket/number/date.rb b/app/models/ticket/number/date.rb index 609488532..300d96b99 100644 --- a/app/models/ticket/number/date.rb +++ b/app/models/ticket/number/date.rb @@ -73,7 +73,7 @@ module Ticket::Number::Date end def check(string) - return if !string || string.empty? + return if string.blank? # get config system_id = Setting.get('system_id') || '' diff --git a/app/models/ticket/number/increment.rb b/app/models/ticket/number/increment.rb index 567d1358c..a84574c87 100644 --- a/app/models/ticket/number/increment.rb +++ b/app/models/ticket/number/increment.rb @@ -70,7 +70,7 @@ module Ticket::Number::Increment end def check(string) - return if !string || string.empty? + return if string.blank? # get config system_id = Setting.get('system_id') || '' diff --git a/app/models/ticket/search_index.rb b/app/models/ticket/search_index.rb index 9451ca405..43c5b6a81 100644 --- a/app/models/ticket/search_index.rb +++ b/app/models/ticket/search_index.rb @@ -21,7 +21,7 @@ returns # collect article data # add tags tags = Tag.tag_list(object: 'Ticket', o_id: id) - if tags && !tags.empty? + if tags.present? attributes[:tag] = tags end diff --git a/app/models/user.rb b/app/models/user.rb index 6d3714fc2..cd87c04e3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -154,18 +154,7 @@ returns =end def role?(role_name) - - result = false - roles.each { |role| - if role_name.class == Array - next if !role_name.include?(role.name) - elsif role.name != role_name - next - end - result = true - break - } - result + roles.where(name: role_name).any? end =begin @@ -226,16 +215,13 @@ returns def self.authenticate(username, password) # do not authenticate with nothing - return if !username || username == '' - return if !password || password == '' + return if username.blank? || password.blank? # try to find user based on login user = User.find_by(login: username.downcase, active: true) # try second lookup with email - if !user - user = User.find_by(email: username.downcase, active: true) - end + user ||= User.find_by(email: username.downcase, active: true) # check failed logins max_login_failed = Setting.get('password_max_login_failed').to_i || 10 @@ -249,7 +235,7 @@ returns # set login failed +1 if !user_auth && user sleep 1 - user.login_failed = user.login_failed + 1 + user.login_failed += 1 user.save end @@ -454,15 +440,13 @@ returns =end def self.password_reset_new_token(username) - return if !username || username == '' + return if username.blank? # try to find user based on login user = User.find_by(login: username.downcase, active: true) # try second lookup with email - if !user - user = User.find_by(email: username.downcase, active: true) - end + user ||= User.find_by(email: username.downcase, active: true) # check if email address exists return if !user @@ -737,8 +721,7 @@ returns end def check_preferences_default - return if !@preferences_default - return if @preferences_default.empty? + return if @preferences_default.blank? preferences_tmp = @preferences_default.merge(preferences) self.preferences = preferences_tmp @@ -871,8 +854,7 @@ returns end def avatar_for_email_check - return if !email - return if email.empty? + return if email.blank? return if email !~ /@/ return if !changes['email'] && updated_at > Time.zone.now - 10.days @@ -900,7 +882,7 @@ returns def check_password # set old password again if not given - if password == '' || !password + if password.blank? # get current record if id diff --git a/app/models/user_device.rb b/app/models/user_device.rb index 402a25ea9..15d7b3698 100644 --- a/app/models/user_device.rb +++ b/app/models/user_device.rb @@ -22,9 +22,7 @@ store new device for user if device not already known def self.add(user_agent, ip, user_id, fingerprint, type) # since gem browser 2 is not handling nil for user_agent, set it to '' - if user_agent.nil? - user_agent = '' - end + user_agent ||= '' # get location info location_details = Service::GeoIp.location(ip) @@ -79,7 +77,7 @@ store new device for user if device not already known name = browser[:plattform] end if browser[:name] && browser[:name] != 'Other' - if name && !name.empty? + if name.present? name += ', ' end name += browser[:name] From 8e8cc4555b78e9abc9d9839487623d2004669fbf Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 30 Nov 2016 21:22:33 +0100 Subject: [PATCH 11/19] =?UTF-8?q?Extended=20search=20result=20not=20shown?= =?UTF-8?q?=20after=20clicking=20=E2=80=9Csearch=20details=E2=80=9D=20on?= =?UTF-8?q?=20quick=20search.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/controllers/navigation.coffee | 21 ++++---- .../javascripts/app/controllers/search.coffee | 15 +++--- .../app/lib/app_post/global_search.coffee | 49 ++++++++----------- .../app/views/navigation/personal.jst.eco | 4 +- 4 files changed, 43 insertions(+), 46 deletions(-) diff --git a/app/assets/javascripts/app/controllers/navigation.coffee b/app/assets/javascripts/app/controllers/navigation.coffee index c63dd0427..8abf6f51a 100644 --- a/app/assets/javascripts/app/controllers/navigation.coffee +++ b/app/assets/javascripts/app/controllers/navigation.coffee @@ -25,6 +25,10 @@ class App.Navigation extends App.ControllerWidgetPermanent @throttledSearch = _.throttle @search, 200 + @globalSearch = new App.GlobalSearch( + render: @renderResult + ) + # rerender view, e. g. on langauge change @bind 'ui:rerender', => @renderMenu() @@ -127,15 +131,15 @@ class App.Navigation extends App.ControllerWidgetPermanent items = @getItems(navbar: @Config.get('NavBarRight')) # get open tabs to repopen on rerender - open_tab = {} + openTab = {} @$('.open').children('a').each( (i,d) -> href = $(d).attr('href') - open_tab[href] = true + openTab[href] = true ) @$('.navbar-items-personal').html App.view('navigation/personal')( - items: items - open_tab: open_tab + items: items + openTab: openTab ) # only start avatar widget on existing session @@ -151,6 +155,7 @@ class App.Navigation extends App.ControllerWidgetPermanent # remove result if not result exists if _.isEmpty(result) @searchContainer.removeClass('open') + @globalSearch.close() @searchResult.html('') return @@ -275,6 +280,7 @@ class App.Navigation extends App.ControllerWidgetPermanent emptyAndClose: => @searchInput.val('') @searchContainer.removeClass('filled').removeClass('open').removeClass('focused') + @globalSearch.close() # remove not needed popovers @delay(@anyPopoversDestroy, 100, 'removePopovers') @@ -282,6 +288,7 @@ class App.Navigation extends App.ControllerWidgetPermanent andClose: => @searchInput.blur() @searchContainer.removeClass('open') + @globalSearch.close() @delay(@anyPopoversDestroy, 100, 'removePopovers') search: => @@ -290,11 +297,7 @@ class App.Navigation extends App.ControllerWidgetPermanent return if query is @query @query = query @searchContainer.toggleClass('filled', !!@query) - - App.GlobalSearch.execute( - query: @query - render: @renderResult - ) + @globalSearch.search(query: @query) getItems: (data) -> navbar = _.values(data.navbar) diff --git a/app/assets/javascripts/app/controllers/search.coffee b/app/assets/javascripts/app/controllers/search.coffee index 90043b952..9a6f45052 100644 --- a/app/assets/javascripts/app/controllers/search.coffee +++ b/app/assets/javascripts/app/controllers/search.coffee @@ -1,5 +1,4 @@ class App.Search extends App.Controller - searchResultCache: {} elements: '.js-search': 'searchInput' @@ -25,6 +24,11 @@ class App.Search extends App.Controller @throttledSearch = _.throttle @search, 200 + @globalSearch = new App.GlobalSearch( + render: @renderResult + limit: 50 + ) + @render() # rerender view, e. g. on langauge change @@ -52,10 +56,11 @@ class App.Search extends App.Controller @navupdate(url: '#search', type: 'menu') return if _.isEmpty(params.query) @$('.js-search').val(params.query).trigger('change') + return if @shown @throttledSearch(true) hide: -> - # nothing + @shown = false changed: -> # nothing @@ -117,11 +122,7 @@ class App.Search extends App.Controller @query = query @updateTask() - App.GlobalSearch.execute( - query: @query - render: @renderResult - limit: 50 - ) + @globalSearch.search(query: @query) renderResult: (result = []) => @result = result diff --git a/app/assets/javascripts/app/lib/app_post/global_search.coffee b/app/assets/javascripts/app/lib/app_post/global_search.coffee index 42061f3f7..2724624fe 100644 --- a/app/assets/javascripts/app/lib/app_post/global_search.coffee +++ b/app/assets/javascripts/app/lib/app_post/global_search.coffee @@ -1,37 +1,27 @@ -class App.GlobalSearch - _instance = undefined - - @execute: (args) -> - if _instance == undefined - _instance ?= new _globalSearchSingleton - _instance.execute(args) - -class _globalSearchSingleton extends Spine.Module - +class App.GlobalSearch extends App.Controller constructor: -> - @searchResultCache = undefined - @searchResultCacheByKey = {} + super + @searchResultCache = {} + @lastQuery = undefined @apiPath = App.Config.get('api_path') + @ajaxId = "search-#{Math.floor( Math.random() * 999999 )}" - execute: (params) -> - query = params.query - render = params.render - limit = params.limit || 10 - cacheKey = "#{query}_#{limit}" + search: (params) => + query = params.query # use cache for search result currentTime = new Date - if @searchResultCacheByKey[cacheKey] && @searchResultCacheByKey[cacheKey].time > currentTime.setSeconds(currentTime.getSeconds() - 20) - @renderTry(render, @searchResultCacheByKey[cacheKey].result, cacheKey) + if @searchResultCache[query] && @searchResultCache[query].time > currentTime.setSeconds(currentTime.getSeconds() - 20) + @renderTry(@searchResultCache[query].result, query) return App.Ajax.request( - id: 'search' + id: @ajaxId type: 'GET' url: "#{@apiPath}/search" data: query: query - limit: limit + limit: @limit || 10 processData: true success: (data, status, xhr) => App.Collection.loadAssets(data.assets) @@ -49,21 +39,24 @@ class _globalSearchSingleton extends Spine.Module else App.Log.error('_globalSearchSingleton', "No such model App.#{item.type}") - @renderTry(render, result, cacheKey) + @renderTry(result, query) ) - renderTry: (render, result, cacheKey) => + renderTry: (result, query) => # if result hasn't changed, do not rerender diff = false - if @searchResultCache - diff = difference(@searchResultCache, result) + if @lastQuery is query && @searchResultCache[query] + diff = difference(@searchResultCache[query].result, result) return if diff isnt false && _.isEmpty(diff) + @lastQuery = query # cache search result - @searchResultCache = result - @searchResultCacheByKey[cacheKey] = + @searchResultCache[query] = result: result time: new Date - render(result) + @render(result) + + close: => + @lastQuery = undefined diff --git a/app/assets/javascripts/app/views/navigation/personal.jst.eco b/app/assets/javascripts/app/views/navigation/personal.jst.eco index 5a8aeb488..22377fe81 100644 --- a/app/assets/javascripts/app/views/navigation/personal.jst.eco +++ b/app/assets/javascripts/app/views/navigation/personal.jst.eco @@ -1,6 +1,6 @@ <% for item in @items: %> <% if item.child: %> -
  • +
  • <% if item.class is 'user': %> @@ -15,7 +15,7 @@
  • <% end %> <% if item.navheader: %> - + <% end %>
  • From c706306d0997f58d18a9d37b8f886db6520a9c52 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 30 Nov 2016 23:35:24 +0100 Subject: [PATCH 12/19] Fixed adding/changing notes. --- app/assets/javascripts/app/models/macro.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/app/models/macro.coffee b/app/assets/javascripts/app/models/macro.coffee index 99a60c96f..593e1df6d 100644 --- a/app/assets/javascripts/app/models/macro.coffee +++ b/app/assets/javascripts/app/models/macro.coffee @@ -1,5 +1,5 @@ class App.Macro extends App.Model - @configure 'Macro', 'name', 'perform', 'active' + @configure 'Macro', 'name', 'perform', 'note', 'active' @extend Spine.Model.Ajax @url: @apiPath + '/macros' @configure_attributes = [ From b2434c1a38343214c0745eda39c8802083c32998 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 1 Dec 2016 00:30:45 +0100 Subject: [PATCH 13/19] Improved browser form tests. --- test/browser/form_test.rb | 47 +++++++++++++++++++++++++++++-------- test/browser_test_helper.rb | 33 +++++++++++++++++--------- 2 files changed, 59 insertions(+), 21 deletions(-) diff --git a/test/browser/form_test.rb b/test/browser/form_test.rb index 0a761f4b0..5bb89f5d0 100644 --- a/test/browser/form_test.rb +++ b/test/browser/form_test.rb @@ -52,10 +52,14 @@ class FormTest < TestCase browser: agent, css: 'body div.zammad-form-modal button[type="submit"]', ) - exists( + watch_for( browser: agent, css: 'body div.zammad-form-modal .has-error [name="body"]', ) + watch_for_disappear( + browser: agent, + css: 'body div.zammad-form-modal button[type="submit"][disabled]', + ) set( browser: agent, css: 'body div.zammad-form-modal [name="body"]', @@ -70,10 +74,14 @@ class FormTest < TestCase browser: agent, css: 'body div.zammad-form-modal button[type="submit"]', ) - exists( + watch_for( browser: agent, css: 'body div.zammad-form-modal .has-error [name="email"]', ) + watch_for_disappear( + browser: agent, + css: 'body div.zammad-form-modal button[type="submit"][disabled]', + ) set( browser: agent, css: 'body div.zammad-form-modal [name="email"]', @@ -83,10 +91,14 @@ class FormTest < TestCase browser: agent, css: 'body div.zammad-form-modal button[type="submit"]', ) - exists( + watch_for( browser: agent, css: 'body div.zammad-form-modal .has-error [name="email"]', ) + watch_for_disappear( + browser: agent, + css: 'body div.zammad-form-modal button[type="submit"][disabled]', + ) set( browser: agent, css: 'body div.zammad-form-modal [name="email"]', @@ -111,8 +123,7 @@ class FormTest < TestCase browser: customer, url: "#{browser_url}/assets/form/form.html", ) - sleep 4 - match( + watch_for( browser: customer, css: '.js-logDisplay', value: 'Faild to load form config, feature is disabled', @@ -143,7 +154,7 @@ class FormTest < TestCase browser: customer, css: '#feedback-form-modal', ) - exists( + watch_for( browser: customer, css: 'body div.zammad-form-modal', ) @@ -252,10 +263,14 @@ class FormTest < TestCase browser: customer, css: 'body div.zammad-form-modal button[type="submit"]', ) - exists( + watch_for( browser: customer, css: 'body div.zammad-form-modal .has-error [name="name"]', ) + watch_for_disappear( + browser: customer, + css: 'body div.zammad-form-modal button[type="submit"][disabled]', + ) set( browser: customer, css: 'body div.zammad-form-modal [name="name"]', @@ -270,10 +285,14 @@ class FormTest < TestCase browser: customer, css: 'body div.zammad-form-modal button[type="submit"]', ) - exists( + watch_for( browser: customer, css: 'body div.zammad-form-modal .has-error [name="body"]', ) + watch_for_disappear( + browser: customer, + css: 'body div.zammad-form-modal button[type="submit"][disabled]', + ) set( browser: customer, css: 'body div.zammad-form-modal [name="body"]', @@ -288,10 +307,14 @@ class FormTest < TestCase browser: customer, css: 'body div.zammad-form-modal button[type="submit"]', ) - exists( + watch_for( browser: customer, css: 'body div.zammad-form-modal .has-error [name="email"]', ) + watch_for_disappear( + browser: customer, + css: 'body div.zammad-form-modal button[type="submit"][disabled]', + ) set( browser: customer, css: 'body div.zammad-form-modal [name="email"]', @@ -301,10 +324,14 @@ class FormTest < TestCase browser: customer, css: 'body div.zammad-form-modal button[type="submit"]', ) - exists( + watch_for( browser: customer, css: 'body div.zammad-form-modal .has-error [name="email"]', ) + watch_for_disappear( + browser: customer, + css: 'body div.zammad-form-modal button[type="submit"][disabled]', + ) set( browser: customer, css: 'body div.zammad-form-modal [name="email"]', diff --git a/test/browser_test_helper.rb b/test/browser_test_helper.rb index bab23df05..974094733 100644 --- a/test/browser_test_helper.rb +++ b/test/browser_test_helper.rb @@ -1240,18 +1240,26 @@ class TestCase < Test::Unit::TestCase if element #&& element.displayed? begin - # match pn attribute - text = if params[:attribute] - element.attribute(params[:attribute]) - elsif params[:css] =~ /(input|textarea)/i - element.attribute('value') - else - element.text - end - if text =~ /#{params[:value]}/i - assert(true, "'#{params[:value]}' found in '#{text}'") + # watch for selector + if !params[:attribute] && !params[:value] + assert(true, "'#{params[:css]}' found") sleep 0.5 return true + + # match pn attribute + else + text = if params[:attribute] + element.attribute(params[:attribute]) + elsif params[:css] =~ /(input|textarea)/i + element.attribute('value') + else + element.text + end + if text =~ /#{params[:value]}/i + assert(true, "'#{params[:value]}' found in '#{text}'") + sleep 0.5 + return true + end end rescue # try again @@ -1260,7 +1268,10 @@ class TestCase < Test::Unit::TestCase sleep 0.5 } screenshot(browser: instance, comment: 'watch_for_failed') - raise "'#{params[:value]}' found in '#{text}'" + if !params[:attribute] && !params[:value] + raise "'#{params[:css]}' not found" + end + raise "'#{params[:value]}' not found in '#{text}'" end =begin From d548dc56136e6ad2754d97308738d1f96341ba7e Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Thu, 1 Dec 2016 15:07:58 +0100 Subject: [PATCH 14/19] Added new labels and remove no longer needed ones. --- .github_changelog_generator | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github_changelog_generator b/.github_changelog_generator index f2af86221..bfaec92a2 100644 --- a/.github_changelog_generator +++ b/.github_changelog_generator @@ -5,6 +5,6 @@ since-tag=1.0.0 bug-labels=bug,minor bug,security enhancement-labels=enhancement,feature issues-wo-labels=false -include-labels=security,trigger,UX/UI,admin area,API,blocker,browser,bug,channel,chat,duplicate,enhancement,feature,import,minor bug,notification,email filter,ticket templates -issue-line-labels=enhancement,feature,bug,minor bug,security +include-labels=security,trigger,UX/UI,admin area,API,browser,bug,channel,chat,email filter,enhancement,feature,import,minor bug,notification,email filter,ticket templates, +issue-line-labels=enhancement,feature,bug,minor bug,notification,reporting,security,ticket templates,translation,trigger,UX/UI exclude-tags=9.0.1,0.9.1,v0.1.8,v0.1.7,unittests_passed From 7c23e334a80bc1a4cdb8d7e9d2010e2738335207 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 1 Dec 2016 16:59:34 +0100 Subject: [PATCH 15/19] Disable ssl on on ssl ports. --- app/models/channel/driver/imap.rb | 5 +++++ app/models/channel/driver/pop3.rb | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/app/models/channel/driver/imap.rb b/app/models/channel/driver/imap.rb index 733efd836..0f55f9c9f 100644 --- a/app/models/channel/driver/imap.rb +++ b/app/models/channel/driver/imap.rb @@ -68,6 +68,11 @@ example end if options.key?(:port) && !options[:port].empty? port = options[:port] + + # disable ssl for non ssl ports + if port == 143 && !options.key?(:ssl) + ssl = false + end end Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl})" diff --git a/app/models/channel/driver/pop3.rb b/app/models/channel/driver/pop3.rb index a227b68eb..295e34fc7 100644 --- a/app/models/channel/driver/pop3.rb +++ b/app/models/channel/driver/pop3.rb @@ -53,6 +53,11 @@ returns end if options.key?(:port) && !options[:port].empty? port = options[:port] + + # disable ssl for non ssl ports + if port == 110 && !options.key?(:ssl) + ssl = false + end end Rails.logger.info "fetching pop3 (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl})" From 2298184266faa834a6fba54bc89c15e6e2f2e055 Mon Sep 17 00:00:00 2001 From: Julian Kornberger Date: Thu, 1 Dec 2016 17:00:05 +0100 Subject: [PATCH 16/19] Fix spelling mistake definde -> defined --- .../ticket/article/communicate_email/background_job.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/observer/ticket/article/communicate_email/background_job.rb b/app/models/observer/ticket/article/communicate_email/background_job.rb index 571cd0b18..888ffb903 100644 --- a/app/models/observer/ticket/article/communicate_email/background_job.rb +++ b/app/models/observer/ticket/article/communicate_email/background_job.rb @@ -23,9 +23,9 @@ class Observer::Ticket::Article::CommunicateEmail::BackgroundJob # send email if !ticket.group.email_address_id - log_error(record, "No email address definde for group id '#{ticket.group.id}'!") + log_error(record, "No email address defined for group id '#{ticket.group.id}'!") elsif !ticket.group.email_address.channel_id - log_error(record, "No channel definde for email_address id '#{ticket.group.email_address_id}'!") + log_error(record, "No channel defined for email_address id '#{ticket.group.email_address_id}'!") end channel = ticket.group.email_address.channel From 2ed9ed5897f5ee559f02797b0a64bb1cac85cf30 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Thu, 1 Dec 2016 17:22:07 +0100 Subject: [PATCH 17/19] Use deliver_method :test for in test environment - thanks to @corny. --- app/models/channel/driver/sendmail.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/channel/driver/sendmail.rb b/app/models/channel/driver/sendmail.rb index f94fd9d2c..9b040eb86 100644 --- a/app/models/channel/driver/sendmail.rb +++ b/app/models/channel/driver/sendmail.rb @@ -7,7 +7,14 @@ class Channel::Driver::Sendmail return if Setting.get('import_mode') mail = Channel::EmailBuild.build(attr, notification) - mail.delivery_method :sendmail + mail.delivery_method delivery_method mail.deliver end + + private + + def delivery_method + return :test if Rails.env.test? + :sendmail + end end From c656148cbdddb2549acfd81e87b666374ac06b11 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 2 Dec 2016 11:36:00 +0100 Subject: [PATCH 18/19] Use only certain zammad ui locales (for faster build). --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a2b5bf217..8d17f5b1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ notifications: env: - DB=mysql - DB=postgresql + - Z_LOCALES=en-us:de-de addons: postgresql: "9.4" apt: From a7e44f4ae36bb08a33872a5c1fa9f5691cecb878 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 2 Dec 2016 11:41:25 +0100 Subject: [PATCH 19/19] Revert "Use only certain zammad ui locales (for faster build)." This reverts commit c656148cbdddb2549acfd81e87b666374ac06b11. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8d17f5b1d..a2b5bf217 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ notifications: env: - DB=mysql - DB=postgresql - - Z_LOCALES=en-us:de-de addons: postgresql: "9.4" apt: