diff --git a/spec/fixtures/mail_handler/wp_on_given_project_group_assignment.eml b/spec/fixtures/mail_handler/wp_on_given_project_group_assignment.eml new file mode 100644 index 0000000000..faac68474d --- /dev/null +++ b/spec/fixtures/mail_handler/wp_on_given_project_group_assignment.eml @@ -0,0 +1,60 @@ +Return-Path: +Received: from osiris ([127.0.0.1]) + by OSIRIS + with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200 +Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris> +From: "John Smith" +To: +Subject: New ticket on a given project +Date: Sun, 22 Jun 2008 12:28:07 +0200 +MIME-Version: 1.0 +Content-Type: text/plain; + format=flowed; + charset="iso-8859-1"; + reply-type=original +Content-Transfer-Encoding: 7bit +X-Priority: 3 +X-MSMail-Priority: Normal +X-Mailer: Microsoft Outlook Express 6.00.2900.2869 +X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869 + +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet +turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus +blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti +sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In +in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras +sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum +id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus +eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique +sed, mauris --- Pellentesque habitant morbi tristique senectus et netus et +malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse +platea dictumst. + +--- This line starts with a delimiter and should not be stripped + +This paragraph is before delimiters. + +BREAK + +This paragraph is between delimiters. + +--- + +This paragraph is after the delimiter so it shouldn't appear. + +Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque +sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem. +Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et, +dictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed, +massa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo +pulvinar dui, a gravida orci mi eget odio. Nunc a lacus. + +Project: onlinestore +Status: Resolved +due date: 2010-12-31 +Start Date:2010-01-01 +Assigned to: A-Team +Version: alpha +estimated hours: 2.5 +done ratio: 30 + diff --git a/spec_legacy/fixtures/mail_handler/ticket_without_from_header.eml b/spec/fixtures/mail_handler/wp_without_from_header.eml similarity index 100% rename from spec_legacy/fixtures/mail_handler/ticket_without_from_header.eml rename to spec/fixtures/mail_handler/wp_without_from_header.eml diff --git a/spec/helpers/sort_helper_spec.rb b/spec/helpers/sort_helper_spec.rb index 1e127c625b..7c3e29b0de 100644 --- a/spec/helpers/sort_helper_spec.rb +++ b/spec/helpers/sort_helper_spec.rb @@ -29,6 +29,93 @@ require 'spec_helper' describe SortHelper, type: :helper do + describe '#sort_init/#sort_update/#sort_clause' do + # Needed to mimic being included in a controller + def controller_name; 'foo'; end + + def action_name; 'bar'; end + + before do + sort_init 'attr1', 'desc' + end + + context 'with arrays' do + before do + sort_update(%w[attr1 attr2]) + end + + it 'returns the first attr in descending order' do + expect(sort_clause) + .to eql 'attr1 DESC' + end + end + + context 'with hashes' do + before do + sort_update('attr1' => 'table1.attr1', 'attr2' => 'table2.attr2') + end + + it 'returns the first attr in descending order with the table name prefixed' do + expect(sort_clause) + .to eql 'table1.attr1 DESC' + end + end + + context 'with hashes sorting by multiple values' do + before do + sort_update('attr1' => %w[table1.attr1 table1.attr2], 'attr2' => 'table2.attr2') + end + + it 'returns the first attr in descending order' do + expect(sort_clause) + .to eql 'table1.attr1 DESC, table1.attr2 DESC' + end + end + end + + describe '#sort_init/#sort_update/params/session' do + # Needed to mimic being included in a controller + def controller_name; 'foo'; end + + def action_name; 'bar'; end + + def params; { sort: sort_param }; end + + def session; @session ||= {}; end + + before do + sort_init 'attr1', 'desc' + sort_update('attr1' => %w[table1.attr1 table1.attr2], 'attr2' => 'table2.attr2') + end + + context 'with valid sort params' do + let(:sort_param) { 'attr1,attr2:desc' } + + it 'persists the order in the session' do + expect(session['foo_bar_sort']) + .to eql 'attr1,attr2:desc' + end + end + + context 'with invalid sort key' do + let(:sort_param) { 'invalid_key' } + + it 'keeps the default sort in the session' do + expect(session['foo_bar_sort']) + .to eql 'attr1:desc' + end + end + + context 'with invalid sort direction' do + let(:sort_param) { 'attr1:blubs,attr2' } + + it 'falls back to the default sort order in the session' do + expect(session['foo_bar_sort']) + .to eql 'attr1,attr2' + end + end + end + describe '#sort_header_tag' do let(:output) do helper.sort_header_tag('id') @@ -36,9 +123,10 @@ describe SortHelper, type: :helper do let(:sort_key) { '' } let(:sort_asc) { true } let(:sort_criteria) do - double('sort_criteria', first_key: sort_key, - first_asc?: sort_asc, - to_param: 'sort_criteria_params').as_null_object + instance_double(SortHelper::SortCriteria, + first_key: sort_key, + first_asc?: sort_asc, + to_param: 'sort_criteria_params').as_null_object end before do diff --git a/spec/models/mail_handler_spec.rb b/spec/models/mail_handler_spec.rb index b99fd68ce5..9dd2a6468a 100644 --- a/spec/models/mail_handler_spec.rb +++ b/spec/models/mail_handler_spec.rb @@ -84,6 +84,29 @@ describe MailHandler, type: :model do end end + shared_context 'for wp on given project group assignment' do + let(:permissions) { %i[add_work_packages] } + let!(:user) do + create(:user, + mail: 'JSmith@somenet.foo', + firstname: 'John', + lastname: 'Smith', + member_in_project: project, + member_with_permissions: permissions) + end + let!(:group) do + create(:group, + lastname: 'A-Team', + member_in_project: project, + member_with_permissions: [:work_package_assigned]) + end + let(:submit_options) { { } } + + subject do + submit_email('wp_on_given_project_group_assignment.eml', **submit_options) + end + end + shared_context 'with a reply to a wp mention with quotes above' do let(:permissions) { %i[edit_work_packages view_work_packages] } let!(:user) do @@ -350,7 +373,7 @@ describe MailHandler, type: :model do end end - context 'in given project with a default type' do + context 'for a given project with a default type' do let(:default_type) do create(:type, is_default: true).tap do |t| project.types << t @@ -369,35 +392,63 @@ describe MailHandler, type: :model do end end - context 'email by unknown user' do - it 'adds a work_package by create user on public project' do - Role.non_member.update_attribute :permissions, [:add_work_packages] - project.update_attribute :public, true - expect do - work_package = submit_email('ticket_by_unknown_user.eml', issue: { project: 'onlinestore' }, unknown_user: 'create') - work_package_created(work_package) - expect(work_package.author.active?).to be_truthy - expect(work_package.author.mail).to eq('john.doe@somenet.foo') - expect(work_package.author.firstname).to eq('John') - expect(work_package.author.lastname).to eq('Doe') - - # account information - perform_enqueued_jobs - - email = ActionMailer::Base.deliveries.first - expect(email).not_to be_nil - expect(email.subject).to eq(I18n.t('mail_subject_register', value: Setting.app_title)) - login = email.body.encoded.match(/\* Username: (\S+)\s?$/)[1] - password = email.body.encoded.match(/\* Password: (\S+)\s?$/)[1] - - # Can't log in here since randomly assigned password must be changed - found_user = User.find_by_login(login) - expect(work_package.author).to eq(found_user) - expect(found_user.check_password?(password)).to be_truthy - end.to change(User, :count).by(1) - end - - context 'with unknown_user=default' do + context 'for a given project with a locked user' do + let!(:status) { create(:status, name: 'Resolved') } + + before do + user.locked! + end + + include_context 'wp_on_given_project' + + it 'does not create the work package' do + expect { subject } + .not_to change(WorkPackage, :count) + end + end + + context 'for a given project with group assignment' do + include_context 'for wp on given project group assignment' + + it_behaves_like 'work package created' + + it 'sets the assignee to the group' do + expect(subject.assigned_to) + .to eql(group) + end + end + + context 'for an email by unknown user' do + context 'with unknown_user: \'create\'' do + it 'adds a work_package by create user on public project' do + Role.non_member.update_attribute :permissions, [:add_work_packages] + project.update_attribute :public, true + expect do + work_package = submit_email('ticket_by_unknown_user.eml', issue: { project: 'onlinestore' }, unknown_user: 'create') + work_package_created(work_package) + expect(work_package.author.active?).to be_truthy + expect(work_package.author.mail).to eq('john.doe@somenet.foo') + expect(work_package.author.firstname).to eq('John') + expect(work_package.author.lastname).to eq('Doe') + + # account information + perform_enqueued_jobs + + email = ActionMailer::Base.deliveries.first + expect(email).not_to be_nil + expect(email.subject).to eq(I18n.t('mail_subject_register', value: Setting.app_title)) + login = email.body.encoded.match(/\* Username: (\S+)\s?$/)[1] + password = email.body.encoded.match(/\* Password: (\S+)\s?$/)[1] + + # Can't log in here since randomly assigned password must be changed + found_user = User.find_by_login(login) + expect(work_package.author).to eq(found_user) + expect(found_user.check_password?(password)).to be_truthy + end.to change(User, :count).by(1) + end + end + + context 'with unknown_user: nil (default)' do let(:results) { [] } before do @@ -417,7 +468,7 @@ describe MailHandler, type: :model do end end - context 'with unknown_user=accept and permision check present' do + context 'with unknown_user: \'accept\' and permission check present' do let(:expected) do 'MailHandler: work_package could not be created by Anonymous due to ' \ '#["may not be accessed.", ' \ @@ -426,55 +477,133 @@ describe MailHandler, type: :model do '"Subject was attempted to be written but is not writable.", ' \ '"Description was attempted to be written but is not writable."]' end + let(:permission) { nil } - let(:results) { [] } - - before do - allow(Rails.logger).to receive(:error).with(expected) - - results << submit_email( + subject(:work_package) do + submit_email( 'ticket_by_unknown_user.eml', issue: { project: project.identifier }, unknown_user: 'accept' ) end - it 'rejects the email' do - expect(results).to eq [false] + before do + allow(Rails.logger).to receive(:error).with(expected) + Role.anonymous.add_permission!(permission) if permission end - it 'logs the error' do - expect(Rails.logger).to have_received(:error).with(expected) - end + context 'with anonymous lacking permissions' do + before do + work_package + end - context 'with report_incoming_email_errors true (default)' do - it 'responds with an error email' do - expect(UserMailer).to have_received(:incoming_email_error) do |user, mail, logs| - expect(user).to eq anno_user - expect(mail.subject).to eq "Ticket by unknown user" - expect(logs).to eq [expected.sub(/^MailHandler/, "error")] + it 'rejects the email' do + expect(work_package).to be false + end + + it 'logs the error' do + expect(Rails.logger).to have_received(:error).with(expected) + end + + context 'with report_incoming_email_errors true (default)' do + it 'responds with an error email' do + expect(UserMailer).to have_received(:incoming_email_error) do |user, mail, logs| + expect(user).to eq anno_user + expect(mail.subject).to eq "Ticket by unknown user" + expect(logs).to eq [expected.sub(/^MailHandler/, "error")] + end end end + + context 'with report_incoming_email_errors false', with_settings: { report_incoming_email_errors: false } do + it 'does not respond with an error email' do + expect(UserMailer).not_to have_received(:incoming_email_error) + end + end + end + + context 'with anonymous having permissions in a public project' do + let(:permission) { :add_work_packages } + + before do + project.update_attribute(:public, true) + end + + it_behaves_like 'work package created' + + it 'sets the author to anonymous' do + expect(work_package.author) + .to eql User.anonymous + end + + it 'creates no user' do + expect { work_package } + .not_to change(User, :count) + end end - context( - 'with report_incoming_email_errors false', - with_settings: { report_incoming_email_errors: false } - ) do - it 'does not respond with an error email' do - expect(UserMailer).not_to have_received(:incoming_email_error) + context 'with anonymous having permissions in a private project' do + let(:permission) { :add_work_packages } + + before do + project.update_attribute(:public, false) + end + + it 'creates no work package' do + expect { work_package } + .not_to change(WorkPackage, :count) + end + + it 'creates no user' do + expect { work_package } + .not_to change(User, :count) end end end - it 'accepts if unknown_user=accept and no_permission_check' do - work_package = submit_email 'ticket_by_unknown_user.eml', - issue: { project: project.identifier }, - unknown_user: 'accept', - no_permission_check: 1 + context 'for unknown_user: \'accept\' and no_permission_check' do + subject(:work_package) do + submit_email 'ticket_by_unknown_user.eml', + issue: { project: project.identifier }, + unknown_user: 'accept', + no_permission_check: 1 + end + + it_behaves_like 'work package created' + + it 'sets the author to anonymous' do + expect(work_package.author).to eq(User.anonymous) + end + end - work_package_created(work_package) - expect(work_package.author).to eq(User.anonymous) + context 'for unknown_user: \'accept\' and without from header' do + subject(:work_package) do + Role.anonymous.add_permission!(:add_work_packages) + + submit_email 'wp_without_from_header.eml', + issue: { project: project.identifier }, + unknown_user: 'accept' + end + + it 'creates no work package' do + expect { work_package } + .not_to change(WorkPackage, :count) + end + end + + context 'for unknown_user: \'accept\' and without permission checks and without from header' do + subject(:work_package) do + submit_email 'wp_without_from_header.eml', + issue: { project: project.identifier }, + unknown_user: 'accept', + no_permission_check: 1 + end + + it_behaves_like 'work package created' + + it 'sets the author to anonymous' do + expect(work_package.author).to eq(User.anonymous) + end end end @@ -495,12 +624,12 @@ describe MailHandler, type: :model do it 'does not create the user' do expect { subject } - .not_to(change { User.count }) + .not_to(change(User, :count)) end it 'does not create the work_package' do expect { subject } - .not_to(change { WorkPackage.count }) + .not_to(change(WorkPackage, :count)) end it 'does not result in an error email response' do diff --git a/spec_legacy/fixtures/mail_handler/ticket_by_empty_user.eml b/spec_legacy/fixtures/mail_handler/ticket_by_empty_user.eml deleted file mode 100644 index 850f05db1a..0000000000 --- a/spec_legacy/fixtures/mail_handler/ticket_by_empty_user.eml +++ /dev/null @@ -1,17 +0,0 @@ -Return-Path: -Received: from osiris ([127.0.0.1]) - by OSIRIS - with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200 -Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris> -To: -Subject: Ticket by unknown user -Date: Sun, 22 Jun 2008 12:28:07 +0200 -MIME-Version: 1.0 -Content-Type: text/plain; - format=flowed; - charset="iso-8859-1"; - reply-type=original -Content-Transfer-Encoding: 7bit - -This is a ticket submitted by an unknown user. - diff --git a/spec_legacy/unit/helpers/sort_helper_spec.rb b/spec_legacy/unit/helpers/sort_helper_spec.rb deleted file mode 100644 index 88ba1e0440..0000000000 --- a/spec_legacy/unit/helpers/sort_helper_spec.rb +++ /dev/null @@ -1,98 +0,0 @@ -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) 2012-2022 the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ -require_relative '../../legacy_spec_helper' - -describe SortHelper, type: :helper do - include SortHelper - - before do - @session = nil - @sort_param = nil - end - - it 'default_sort_clause_with_arrays' do - sort_init 'attr1', 'desc' - sort_update(['attr1', 'attr2']) - - assert_equal 'attr1 DESC', sort_clause - end - - it 'default_sort_clause_with_hashes' do - sort_init 'attr1', 'desc' - sort_update('attr1' => 'table1.attr1', 'attr2' => 'table2.attr2') - - assert_equal 'table1.attr1 DESC', sort_clause - end - - it 'default_sort_clause_with_multiple_columnses' do - sort_init 'attr1', 'desc' - sort_update('attr1' => ['table1.attr1', 'table1.attr2'], 'attr2' => 'table2.attr2') - - assert_equal 'table1.attr1 DESC, table1.attr2 DESC', sort_clause - end - - it 'params_sorts' do - @sort_param = 'attr1,attr2:desc' - - sort_init 'attr1', 'desc' - sort_update('attr1' => 'table1.attr1', 'attr2' => 'table2.attr2') - - assert_equal 'table1.attr1, table2.attr2 DESC', sort_clause - assert_equal 'attr1,attr2:desc', @session['foo_bar_sort'] - end - - it 'invalid_params_sorts' do - @sort_param = 'invalid_key' - - sort_init 'attr1', 'desc' - sort_update('attr1' => 'table1.attr1', 'attr2' => 'table2.attr2') - - assert_equal 'table1.attr1 DESC', sort_clause - assert_equal 'attr1:desc', @session['foo_bar_sort'] - end - - it 'invalid_order_params_sorts' do - @sort_param = 'attr1:foo:bar,attr2' - - sort_init 'attr1', 'desc' - sort_update('attr1' => 'table1.attr1', 'attr2' => 'table2.attr2') - - assert_equal 'table1.attr1, table2.attr2', sort_clause - assert_equal 'attr1,attr2', @session['foo_bar_sort'] - end - - private - - def controller_name; 'foo'; end - - def action_name; 'bar'; end - - def params; { sort: @sort_param }; end - - def session; @session ||= {}; end -end diff --git a/spec_legacy/unit/mail_handler_spec.rb b/spec_legacy/unit/mail_handler_spec.rb index 92859bdf1b..ce150c623b 100644 --- a/spec_legacy/unit/mail_handler_spec.rb +++ b/spec_legacy/unit/mail_handler_spec.rb @@ -46,16 +46,6 @@ describe MailHandler, type: :model, with_settings: { report_incoming_email_error assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') end - it 'adds work package with group assignment' do - work_package = submit_email('ticket_on_given_project.eml') do |email| - email.gsub!('Assigned to: John Smith', 'Assigned to: B Team') - end - assert work_package.is_a?(WorkPackage) - assert !work_package.new_record? - work_package.reload - assert_equal Group.find(11), work_package.assigned_to - end - it 'adds work package with partial attributes override' do issue = submit_email('ticket_with_attributes.eml', issue: { priority: 'High' }, allow_override: ['type']) assert issue.is_a?(WorkPackage) @@ -110,71 +100,6 @@ describe MailHandler, type: :model, with_settings: { report_incoming_email_error assert !issue.description.match(/^searchable field:/i) end - it 'adds work package should match assignee on display name' do # added from redmine - not sure if it is ok here - user = create(:user, firstname: 'Foo', lastname: 'Bar') - role = create(:role, name: 'Superhero', permissions: ['work_package_assigned']) - create(:member, user:, project: Project.find(2), role_ids: [role.id]) - issue = submit_email('ticket_on_given_project.eml') do |email| - email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar') - end - assert issue.is_a?(WorkPackage) - assert_equal user, issue.assigned_to - end - - it 'adds work package by unknown user' do - assert_no_difference 'User.count' do - assert_equal false, submit_email('ticket_by_unknown_user.eml', issue: { project: 'ecookbook' }) - end - end - - it 'adds work package by anonymous user' do - Role.anonymous.add_permission!(:add_work_packages) - assert_no_difference 'User.count' do - issue = submit_email('ticket_by_unknown_user.eml', issue: { project: 'ecookbook' }, unknown_user: 'accept') - assert issue.is_a?(WorkPackage) - assert issue.author.anonymous? - end - end - - it 'adds work package by anonymous user with no from address' do - Role.anonymous.add_permission!(:add_work_packages) - assert_no_difference 'User.count' do - issue = submit_email('ticket_by_empty_user.eml', issue: { project: 'ecookbook' }, unknown_user: 'accept') - assert issue.is_a?(WorkPackage) - assert issue.author.anonymous? - end - end - - it 'adds work package by anonymous user on private project' do - Role.anonymous.add_permission!(:add_work_packages) - assert_no_difference 'User.count' do - assert_no_difference 'WorkPackage.count' do - assert_equal false, submit_email('ticket_by_unknown_user.eml', issue: { project: 'onlinestore' }, unknown_user: 'accept') - end - end - end - - it 'adds work package by anonymous user on private project without permission check' do - assert_no_difference 'User.count' do - assert_difference 'WorkPackage.count' do - issue = submit_email('ticket_by_unknown_user.eml', - issue: { project: 'onlinestore' }, - no_permission_check: '1', - unknown_user: 'accept') - assert issue.is_a?(WorkPackage) - assert issue.author.anonymous? - assert !issue.project.public? - assert issue.root? - assert issue.leaf? - end - end - end - - it 'adds work package without from header' do - Role.anonymous.add_permission!(:add_work_packages) - assert_equal false, submit_email('ticket_without_from_header.eml') - end - context 'without default start_date', with_legacy_settings: { work_package_startdate_is_adddate: false } do it 'adds work package with invalid attributes' do issue = submit_email('ticket_with_invalid_attributes.eml', allow_override: 'type,category,priority') @@ -239,15 +164,6 @@ describe MailHandler, type: :model, with_settings: { report_incoming_email_error assert_equal 'Testmail from Webmail: ä ö ü...', issue.subject end - it 'ignores emails from locked users' do - User.find(2).locked! - - expect_any_instance_of(MailHandler).not_to receive(:dispatch) - assert_no_difference 'WorkPackage.count' do - assert_equal false, submit_email('ticket_on_given_project.eml') - end - end - it 'ignores auto replied emails' do expect_any_instance_of(MailHandler).not_to receive(:dispatch) [