diff --git a/spec/controllers/auth_sources_controller_spec.rb b/spec/controllers/auth_sources_controller_spec.rb
index ee86a236dc..27d70fd446 100644
--- a/spec/controllers/auth_sources_controller_spec.rb
+++ b/spec/controllers/auth_sources_controller_spec.rb
@@ -32,6 +32,8 @@ describe AuthSourcesController do
let(:current_user) { FactoryGirl.create(:admin) }
before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+
allow(User).to receive(:current).and_return current_user
end
@@ -119,4 +121,46 @@ describe AuthSourcesController do
end
end
end
+
+ context 'with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+ end
+
+ it 'cannot find index' do
+ get :index
+
+ expect(response.status).to eq 404
+ end
+
+ it 'cannot find new' do
+ get :new
+
+ expect(response.status).to eq 404
+ end
+
+ it 'cannot find create' do
+ post :create, auth_source: { name: 'Test' }
+
+ expect(response.status).to eq 404
+ end
+
+ it 'cannot find edit' do
+ get :edit, id: 42
+
+ expect(response.status).to eq 404
+ end
+
+ it 'cannot find update' do
+ post :update, id: 42, auth_source: { name: 'TestUpdate' }
+
+ expect(response.status).to eq 404
+ end
+
+ it 'cannot find destroy' do
+ post :destroy, id: 42
+
+ expect(response.status).to eq 404
+ end
+ end
end
diff --git a/spec/controllers/settings_controller_spec.rb b/spec/controllers/settings_controller_spec.rb
index fdc3080085..1d9f978c4e 100644
--- a/spec/controllers/settings_controller_spec.rb
+++ b/spec/controllers/settings_controller_spec.rb
@@ -119,5 +119,120 @@ describe SettingsController do
expect(response.body).not_to have_selector "input[@name='settings[default_projects_modules][]'][@value='activity'][@checked='checked']"
end
end
+
+ describe 'password settings' do
+ let(:old_settings) do
+ {
+ password_min_length: 10,
+ password_active_rules: [],
+ password_min_adhered_rules: 0,
+ password_days_valid: 365,
+ password_count_former_banned: 2,
+ lost_password: '1'
+ }
+ end
+
+ let(:new_settings) do
+ {
+ password_min_length: 42,
+ password_active_rules: %w(uppercase lowercase),
+ password_min_adhered_rules: 7,
+ password_days_valid: 13,
+ password_count_former_banned: 80,
+ lost_password: '3'
+ }
+ end
+
+ let(:original_settings) { Hash.new }
+
+ before do
+ old_settings.keys.each do |key|
+ original_settings[key] = Setting[key]
+ end
+
+ old_settings.keys.each do |key|
+ Setting[key] = old_settings[key]
+ end
+ end
+
+ after do
+ # restore settings
+ old_settings.keys.each do |key|
+ Setting[key] = original_settings[key]
+ end
+ end
+
+ describe 'POST #edit with password login enabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+
+ post 'edit', tab: 'authentication', settings: new_settings
+ end
+
+ it 'is successful' do
+ expect(response).to be_redirect # to auth tab
+ end
+
+ it 'sets the minimum password length to 42' do
+ expect(Setting[:password_min_length]).to eq '42'
+ end
+
+ it 'sets the active character classes to lowercase and uppercase' do
+ expect(Setting[:password_active_rules]).to eq ['uppercase', 'lowercase']
+ end
+
+ it 'sets the required number of classes to 7' do
+ expect(Setting[:password_min_adhered_rules]).to eq '7'
+ end
+
+ it 'sets passwords to expire after 13 days' do
+ expect(Setting[:password_days_valid]).to eq '13'
+ end
+
+ it 'bans the last 80 passwords' do
+ expect(Setting[:password_count_former_banned]).to eq '80'
+ end
+
+ it 'sets the lost password option to the nonsensical 3' do
+ expect(Setting[:lost_password]).to eq '3'
+ end
+ end
+
+ describe 'POST #edit with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+
+ post 'edit', tab: 'authentication', settings: new_settings
+ end
+
+ it 'is successful' do
+ expect(response).to be_redirect # to auth tab
+ end
+
+ it 'does not set the minimum password length to 42' do
+ expect(Setting[:password_min_length]).to eq '10'
+ end
+
+ it 'does not set the active character classes to lowercase and uppercase' do
+ expect(Setting[:password_active_rules]).to eq []
+ end
+
+ it 'does not set the required number of classes to 7' do
+ expect(Setting[:password_min_adhered_rules]).to eq '0'
+ end
+
+ it 'does not set passwords to expire after 13 days' do
+ expect(Setting[:password_days_valid]).to eq '365'
+ end
+
+ it 'does not ban the last 80 passwords' do
+ expect(Setting[:password_count_former_banned]).to eq '2'
+ end
+
+ it 'does not set the lost password option to the nonsensical 3' do
+ expect(Setting[:lost_password]).to eq '1'
+ end
+ end
+ end
end
end
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 3429fb9a8d..82e68b4d95 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -247,6 +247,40 @@ describe UsersController do
end
describe "index" do
+ describe 'new user button' do
+ render_views
+
+ context 'with password login enabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+
+ as_logged_in_user admin do
+ get :index
+ end
+ end
+
+ it 'is shown' do
+ expect(response.body).to have_selector('a', text: I18n.t('label_user_new'))
+ end
+ end
+
+ context 'with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+
+ as_logged_in_user admin do
+ get :index
+ end
+ end
+
+ # you must not be able to create new users if password login is disabled
+ # as users are managed externally
+ it 'is hidden' do
+ expect(response.body).not_to have_selector('a', text: I18n.t('label_user_new'))
+ end
+ end
+ end
+
describe "with session lifetime" do
# TODO move this section to a proper place because we test a
# before_filter from the application controller
@@ -347,6 +381,68 @@ describe UsersController do
end
end
+ describe '#new' do
+ context 'with password login enabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+
+ as_logged_in_user admin do
+ get :new
+ end
+ end
+
+ it 'should return HTTP 200' do
+ expect(response.status).to eq 200
+ end
+ end
+
+ context 'with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+
+ as_logged_in_user admin do
+ get :new
+ end
+ end
+
+ # you must not be able to create new users if password login is disabled
+ it 'should return HTTP 404' do
+ expect(response.status).to eq 404
+ end
+ end
+ end
+
+ describe '#create' do
+ context 'with password login enabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+
+ as_logged_in_user admin do
+ post :create
+ end
+ end
+
+ it 'should return HTTP 400 due to missing parameters' do
+ expect(response.status).to eq 400
+ end
+ end
+
+ context 'with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+
+ as_logged_in_user admin do
+ post :create
+ end
+ end
+
+ # you must not be able to create new users if password login is disabled
+ it 'should return HTTP 404' do
+ expect(response.status).to eq 404
+ end
+ end
+ end
+
describe "update" do
context "fields" do
let(:user) { FactoryGirl.create(:user, :firstname => 'Firstname',
diff --git a/spec/features/accessibility/work_packages/work_package_query_spec.rb b/spec/features/accessibility/work_packages/work_package_query_spec.rb
index 3fd0c2d82e..0308a41605 100644
--- a/spec/features/accessibility/work_packages/work_package_query_spec.rb
+++ b/spec/features/accessibility/work_packages/work_package_query_spec.rb
@@ -66,6 +66,18 @@ describe 'Work package index accessibility' do
describe 'Change state', js: true do
# TODO
end
+
+ after do
+ # Ensure that all requests have fired and are answered. Otherwise one
+ # spec can interfere with the next when a request of the former is still
+ # running in the one process but the other process has already removed
+ # the data in the db to prepare for the next spec.
+ #
+ # Taking an element, that get's activated late in the page setup.
+ page.should_not have_selector('ul.dropdown-menu a.inactive',
+ :text => Regexp.new("^#{I18n.t(:button_save)}$"),
+ :visible => false)
+ end
end
describe 'Sort link', js: true do
diff --git a/spec/features/omniauth/omniauth_spec.rb b/spec/features/omniauth/omniauth_spec.rb
index 23cfd4c212..2a4e4c63ee 100644
--- a/spec/features/omniauth/omniauth_spec.rb
+++ b/spec/features/omniauth/omniauth_spec.rb
@@ -46,6 +46,12 @@ describe 'Omniauth authentication' do
OmniAuth.config.logger = @omniauth_logger
end
+ ##
+ # Returns a given translation up until the first occurrence of a parameter (exclusive).
+ def translation_substring(translation)
+ translation.scan(/(^.*) %\{/).first.first
+ end
+
context 'sign in existing user' do
let(:user) do
FactoryGirl.create(:user,
@@ -101,6 +107,20 @@ describe 'Omniauth authentication' do
end
end
+ describe 'sign out a user with direct login and login required' do
+ before do
+ Setting.stub(:login_required?).and_return(true)
+ Concerns::OmniauthLogin.stub(:direct_login_provider).and_return('developer')
+ end
+
+ it 'shows a notice that the user has been logged out' do
+ visit signout_path
+
+ expect(page).to have_content(I18n.t(:notice_logged_out))
+ expect(page).to have_content translation_substring(I18n.t(:instructions_after_logout))
+ end
+ end
+
shared_examples 'omniauth user registration' do
it 'should register new user' do
visit '/auth/developer'
@@ -166,15 +186,81 @@ describe 'Omniauth authentication' do
end
end
+ context 'registration by email' do
+ before do
+ allow(Setting).to receive(:self_registration?).and_return(true)
+ allow(Setting).to receive(:self_registration).and_return('1')
+ end
+
+ shared_examples 'registration with registration by email' do
+ it 'shows a note explaining that the account has to be activated' do
+ visit login_path
+
+ # login form developer strategy
+ fill_in 'first_name', with: 'Ifor'
+ fill_in 'last_name', with: 'McAlistar'
+ fill_in 'email', with: 'i.mcalistar@example.com'
+
+ click_link_or_button 'Sign In'
+
+ expect(page).to have_content(I18n.t(:notice_account_register_done))
+
+ if defined? instructions
+ expect(page).to have_content instructions
+ end
+ end
+ end
+
+ it_behaves_like 'registration with registration by email' do
+ let(:login_path) { '/auth/developer' }
+ end
+
+ context 'with direct login enabled and login required' do
+ before do
+ Setting.stub(:login_required?).and_return(true)
+ Concerns::OmniauthLogin.stub(:direct_login_provider).and_return('developer')
+ end
+
+ it_behaves_like 'registration with registration by email' do
+ # i.e. it still shows a notice
+ # instead of redirecting straight back to the omniauth login provider
+ let(:login_path) { signin_path }
+ let(:instructions) { translation_substring I18n.t(:instructions_after_registration) }
+ end
+ end
+ end
+
context 'error occurs' do
- it 'should fail with generic error message' do
- # set omniauth to test mode will redirect all calls to omniauth
- # directly to the callback and by setting the mock_auth provider
- # to a symbol will force omniauth to fail /auth/failure
- OmniAuth.config.test_mode = true
- OmniAuth.config.mock_auth[:developer] = :invalid_credentials
- visit '/auth/developer'
- expect(page).to have_content(I18n.t(:error_external_authentication_failed))
+ shared_examples 'omniauth signin error' do
+ it 'should fail with generic error message' do
+ # set omniauth to test mode will redirect all calls to omniauth
+ # directly to the callback and by setting the mock_auth provider
+ # to a symbol will force omniauth to fail /auth/failure
+ OmniAuth.config.test_mode = true
+ OmniAuth.config.mock_auth[:developer] = :invalid_credentials
+ visit login_path
+ expect(page).to have_content(I18n.t(:error_external_authentication_failed))
+
+ if defined? instructions
+ expect(page).to have_content instructions
+ end
+ end
+ end
+
+ it_behaves_like 'omniauth signin error' do
+ let(:login_path) { '/auth/developer' }
+ end
+
+ context 'with direct login and login required' do
+ before do
+ Setting.stub(:login_required?).and_return(true)
+ Concerns::OmniauthLogin.stub(:direct_login_provider).and_return('developer')
+ end
+
+ it_behaves_like 'omniauth signin error' do
+ let(:login_path) { signin_path }
+ let(:instructions) { translation_substring I18n.t(:instructions_after_error) }
+ end
end
end
end
diff --git a/spec/features/users/edit_users_spec.rb b/spec/features/users/edit_users_spec.rb
new file mode 100644
index 0000000000..29b88ca856
--- /dev/null
+++ b/spec/features/users/edit_users_spec.rb
@@ -0,0 +1,86 @@
+#-- copyright
+# OpenProject is a project management system.
+# Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
+#
+# 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 doc/COPYRIGHT.rdoc for more details.
+#++
+
+require 'spec_helper'
+require 'features/projects/projects_page'
+
+describe 'edit users', js: true do
+ let(:current_user) { FactoryGirl.create :admin }
+ let(:user) { FactoryGirl.create :user }
+
+ let!(:auth_source) { FactoryGirl.create :auth_source }
+
+ before do
+ allow(User).to receive(:current).and_return current_user
+ end
+
+ def auth_select
+ find :css, 'select#user_auth_source_id'
+ end
+
+ def user_password
+ find :css, 'input#user_password'
+ end
+
+ context 'with internal authentication' do
+ before do
+ visit edit_user_path(user)
+ end
+
+ it 'shows internal authentication being selected including password settings' do
+ expect(auth_select.value).to eq '' # selected internal
+ expect(user_password).to be_visible
+ end
+
+ it 'hides password settings when switching to an LDAP auth source' do
+ auth_select.select auth_source.name
+
+ expect(page).not_to have_selector('input#user_password')
+ end
+ end
+
+ context 'with external authentication' do
+ before do
+ user.auth_source = auth_source
+ user.save!
+
+ visit edit_user_path(user)
+ end
+
+ it 'shows external authentication being selected and no password settings' do
+ expect(auth_select.value).to eq auth_source.id.to_s
+ expect(page).not_to have_selector('input#user_password')
+ end
+
+ it 'shows password settings when switching back to internal authentication' do
+ auth_select.select I18n.t('label_internal')
+
+ expect(user_password).to be_visible
+ end
+ end
+end
diff --git a/spec/lib/api/v3/work_packages/work_package_model_spec.rb b/spec/lib/api/v3/work_packages/work_package_model_spec.rb
index 623614d563..4cb10b5082 100644
--- a/spec/lib/api/v3/work_packages/work_package_model_spec.rb
+++ b/spec/lib/api/v3/work_packages/work_package_model_spec.rb
@@ -70,5 +70,35 @@ h2. Plan for this month
it { expect(model.is_closed).to be_false }
end
end
+
+ describe 'visibility to related work packages' do
+ let(:project) { FactoryGirl.create(:project, is_public: false) }
+ let(:forbidden_project) { FactoryGirl.create(:project, is_public: false) }
+ let(:user) { FactoryGirl.create(:user, member_in_project: project) }
+
+ let(:work_package) { FactoryGirl.create(:work_package, project: project) }
+ let(:work_package_2) { FactoryGirl.create(:work_package, project: project) }
+ let(:forbidden_work_package) { FactoryGirl.create(:work_package, project: forbidden_project) }
+
+ before do
+ allow(User).to receive(:current).and_return(user)
+ allow(Setting).to receive(:cross_project_work_package_relations?).and_return(true)
+ end
+
+ describe 'relations' do
+ let!(:relation) { FactoryGirl.create(:relation,
+ from: work_package,
+ to: work_package_2) }
+ let!(:forbidden_relation) { FactoryGirl.create(:relation,
+ from: work_package,
+ to: forbidden_work_package) }
+
+ it { expect(model.relations.count).to eq(1) }
+
+ it { expect(model.relations[0].from_id).to eq(work_package.id) }
+
+ it { expect(model.relations[0].to_id).to eq(work_package_2.id) }
+ end
+ end
end
end
diff --git a/spec/lib/api/v3/work_packages/work_package_representer_spec.rb b/spec/lib/api/v3/work_packages/work_package_representer_spec.rb
index f403d3dc67..f8b3135467 100644
--- a/spec/lib/api/v3/work_packages/work_package_representer_spec.rb
+++ b/spec/lib/api/v3/work_packages/work_package_representer_spec.rb
@@ -184,6 +184,45 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
expect(subject).to_not have_json_path('_links/addRelation/href')
end
end
+
+ describe 'linked relations' do
+ let(:project) { FactoryGirl.create(:project, is_public: false) }
+ let(:forbidden_project) { FactoryGirl.create(:project, is_public: false) }
+ let(:user) { FactoryGirl.create(:user, member_in_project: project) }
+
+ before do
+ allow(User).to receive(:current).and_return(user)
+ allow(Setting).to receive(:cross_project_work_package_relations?).and_return(true)
+ end
+
+ context 'parent' do
+ let(:work_package) { FactoryGirl.create(:work_package,
+ project: project,
+ parent_id: forbidden_work_package.id) }
+ let!(:forbidden_work_package) { FactoryGirl.create(:work_package, project: forbidden_project) }
+
+ it { expect(subject).to_not have_json_path('_links/parent') }
+ end
+
+ context 'children' do
+ let(:work_package) { FactoryGirl.create(:work_package, project: project) }
+ let!(:forbidden_work_package) { FactoryGirl.create(:work_package,
+ project: forbidden_project,
+ parent_id: work_package.id) }
+
+ it { expect(subject).to_not have_json_path('_links/children') }
+
+ describe 'visible and invisible children' do
+ let!(:child) { FactoryGirl.create(:work_package,
+ project: project,
+ parent_id: work_package.id) }
+
+ it { expect(subject).to have_json_size(1).at_path('_links/children') }
+
+ it { expect(parse_json(subject)["_links"]["children"][0]["title"]).to eq(child.subject) }
+ end
+ end
+ end
end
describe '_embedded' do
diff --git a/spec/models/custom_field_spec.rb b/spec/models/custom_field_spec.rb
index 6beeda0ebc..38a10d9ff3 100644
--- a/spec/models/custom_field_spec.rb
+++ b/spec/models/custom_field_spec.rb
@@ -382,5 +382,23 @@ describe CustomField do
end
it { expect(field).not_to be_valid }
end
+
+ describe "WITH a text field
+ WITH negative minimum length" do
+ before do
+ field.field_format = 'text'
+ field.min_length = -2
+ end
+ it { expect(field).not_to be_valid }
+ end
+
+ describe "WITH a text field
+ WITH negative maximum length" do
+ before do
+ field.field_format = 'text'
+ field.max_length = -2
+ end
+ it { expect(field).not_to be_valid }
+ end
end
end
diff --git a/spec/views/api/experimental/work_packages/index_api_json_spec.rb b/spec/views/api/experimental/work_packages/index_api_json_spec.rb
index 015771221b..530aa2a62e 100644
--- a/spec/views/api/experimental/work_packages/index_api_json_spec.rb
+++ b/spec/views/api/experimental/work_packages/index_api_json_spec.rb
@@ -76,11 +76,29 @@ describe 'api/experimental/work_packages/index.api.rabl' do
it { should have_json_size(0).at_path('work_packages') }
end
+ describe 'created/updated at' do
+ let(:wp) { FactoryGirl.build(:work_package,
+ created_at: DateTime.now,
+ updated_at: (DateTime.now + 1.day)) }
+ let(:work_packages) { [ wp ] }
+ let(:column_names) { [] }
+ let(:custom_field_column_names) { [] }
+
+ it { expect(parse_json(subject)['work_packages'][0]['updated_at']).to eq(wp.updated_at.utc.iso8601) }
+ it { expect(parse_json(subject)['work_packages'][0]['created_at']).to eq(wp.created_at.utc.iso8601) }
+ end
+
describe 'with 3 work packages but no columns' do
let(:work_packages) { [
- FactoryGirl.build(:work_package),
- FactoryGirl.build(:work_package),
- FactoryGirl.build(:work_package)
+ FactoryGirl.build(:work_package,
+ created_at: DateTime.now,
+ updated_at: DateTime.now),
+ FactoryGirl.build(:work_package,
+ created_at: DateTime.now,
+ updated_at: DateTime.now),
+ FactoryGirl.build(:work_package,
+ created_at: DateTime.now,
+ updated_at: DateTime.now)
] }
let(:column_names) { [] }
let(:custom_field_column_names) { [] }
@@ -93,8 +111,12 @@ describe 'api/experimental/work_packages/index.api.rabl' do
describe 'with 2 work packages and columns' do
let(:work_packages) { [
- FactoryGirl.build(:work_package),
- FactoryGirl.build(:work_package)
+ FactoryGirl.build(:work_package,
+ created_at: DateTime.now,
+ updated_at: DateTime.now),
+ FactoryGirl.build(:work_package,
+ created_at: DateTime.now,
+ updated_at: DateTime.now)
] }
let(:column_names) { %w(subject description due_date) }
let(:custom_field_column_names) { [] }
@@ -109,7 +131,11 @@ describe 'api/experimental/work_packages/index.api.rabl' do
end
describe 'with project column' do
- let(:work_packages) { [FactoryGirl.build(:work_package)] }
+ let(:work_packages) { [
+ FactoryGirl.build(:work_package,
+ created_at: DateTime.now,
+ updated_at: DateTime.now)
+ ] }
let(:column_names) { %w(subject project) }
let(:custom_field_column_names) { [] }
diff --git a/spec/views/layouts/admin.html.erb_spec.rb b/spec/views/layouts/admin.html.erb_spec.rb
new file mode 100644
index 0000000000..7f3e9f0800
--- /dev/null
+++ b/spec/views/layouts/admin.html.erb_spec.rb
@@ -0,0 +1,71 @@
+#-- copyright
+# OpenProject is a project management system.
+# Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
+#
+# 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 doc/COPYRIGHT.rdoc for more details.
+#++
+
+require 'spec_helper'
+
+describe 'layouts/admin' do
+ include Redmine::MenuManager::MenuHelper
+ helper Redmine::MenuManager::MenuHelper
+
+ let(:admin) { FactoryGirl.create :admin }
+
+ before do
+ view.stub(:current_menu_item).and_return('overview')
+ view.stub(:default_breadcrumb)
+ controller.stub(:default_search_scope)
+
+ User.stub(:current).and_return admin
+ view.stub(:current_user).and_return admin
+ end
+
+ # All password-based authentication is to be hidden and disabled if
+ # `disable_password_login` is true. This includes LDAP.
+ describe 'LDAP authentication menu entry' do
+ context 'with password login enabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+ render
+ end
+
+ it 'is shown' do
+ expect(rendered).to have_selector('a', text: I18n.t('label_ldap_authentication'))
+ end
+ end
+
+ context 'with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+ render
+ end
+
+ it 'is hidden' do
+ expect(rendered).not_to have_selector('a', text: I18n.t('label_ldap_authentication'))
+ end
+ end
+ end
+end
diff --git a/spec/views/settings/_authentication.html.erb_spec.rb b/spec/views/settings/_authentication.html.erb_spec.rb
new file mode 100644
index 0000000000..c343942ddf
--- /dev/null
+++ b/spec/views/settings/_authentication.html.erb_spec.rb
@@ -0,0 +1,61 @@
+#-- copyright
+# OpenProject is a project management system.
+# Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
+#
+# 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 doc/COPYRIGHT.rdoc for more details.
+#++
+
+require 'spec_helper'
+
+describe 'settings/_authentication' do
+ context 'with password login enabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+ render
+ end
+
+ it 'shows password settings' do
+ expect(rendered).to have_text I18n.t('label_password_lost')
+ end
+
+ it 'shows automated user blocking options' do
+ expect(rendered).to have_text I18n.t(:brute_force_prevention, :scope => [:settings])
+ end
+ end
+
+ context 'with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+ render
+ end
+
+ it 'does not show password settings' do
+ expect(rendered).not_to have_text I18n.t('label_password_lost')
+ end
+
+ it 'does not show automated user blocking options' do
+ expect(rendered).not_to have_text I18n.t(:brute_force_prevention, :scope => [:settings])
+ end
+ end
+end
diff --git a/spec/views/users/edit.html.erb_spec.rb b/spec/views/users/edit.html.erb_spec.rb
index 8f7b30371b..d8b899f963 100644
--- a/spec/views/users/edit.html.erb_spec.rb
+++ b/spec/views/users/edit.html.erb_spec.rb
@@ -40,12 +40,82 @@ describe 'users/edit' do
assign(:auth_sources, [])
allow(view).to receive(:current_user).and_return(current_user)
-
- render
end
it 'shows the authentication provider' do
+ render
+
expect(response.body).to include('Test Provider')
end
+
+ it 'does not show a no-login warning when password login is disabled' do
+ OpenProject::Configuration.stub(:disable_password_login).and_return(true)
+ render
+
+ expect(response.body).not_to include I18n.t('user.no_login')
+ end
+ end
+
+ context 'with password-based login' do
+ let(:user) { FactoryGirl.build :user, id: 42 }
+
+ before do
+ assign :user, user
+ assign :auth_sources, []
+
+ allow(view).to receive(:current_user).and_return(current_user)
+ end
+
+ context 'with password login disabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(true)
+ end
+
+ it 'warns that the user cannot login' do
+ render
+
+ expect(response.body).to include I18n.t('user.no_login')
+ end
+
+ context 'with auth sources' do
+ let(:auth_sources) { [FactoryGirl.create(:auth_source)]}
+
+ before do
+ assign :auth_sources, auth_sources
+ end
+
+ it 'does not show the auth source selection' do
+ render
+
+ expect(rendered).not_to have_selector('#user_auth_source_id')
+ end
+ end
+ end
+
+ context 'with password login enabled' do
+ before do
+ OpenProject::Configuration.stub(:disable_password_login?).and_return(false)
+ end
+
+ it 'shows password options' do
+ render
+
+ expect(rendered).to have_text I18n.t('user.assign_random_password')
+ end
+
+ context 'with auth sources' do
+ let(:auth_sources) { [FactoryGirl.create(:auth_source)] }
+
+ before do
+ assign :auth_sources, auth_sources
+ end
+
+ it 'shows the auth source selection' do
+ render
+
+ expect(rendered).to have_selector('#user_auth_source_id')
+ end
+ end
+ end
end
end