summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2015-06-15 11:29:36 +0000
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2015-06-15 11:29:36 +0000
commit7300729190f4e61c4e71f18d0a81ea044eaad98a (patch)
tree03cef3fbfd21712f1b19ea21c84ab62253940671 /spec
parent168d5eabd40f5767d1287fe194e57ed05ef5d990 (diff)
parent9eec51d914bc79fed479a4e3e7b86fda58ad77c8 (diff)
downloadgitlab-ce-7300729190f4e61c4e71f18d0a81ea044eaad98a.tar.gz
Merge branch 'rs-dev-issue-2228' into 'master'
Allow user to customize default Dashboard page Renames the "Design" profile page to "Preferences" and adds a field to customize the default Dashboard page: > ![Screen_Shot_2015-06-11_at_11.12.53_PM](https://gitlab.com/gitlab-org/gitlab-ce/uploads/b5282a3be7861d1148528c6bc9e7a0e0/Screen_Shot_2015-06-11_at_11.12.53_PM.png) See merge request !778
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/profiles/preferences_controller_spec.rb88
-rw-r--r--spec/controllers/root_controller_spec.rb32
-rw-r--r--spec/features/profiles/preferences_spec.rb82
-rw-r--r--spec/features/security/profile_access_spec.rb4
-rw-r--r--spec/helpers/application_helper_spec.rb21
-rw-r--r--spec/helpers/preferences_helper_spec.rb72
-rw-r--r--spec/lib/gitlab/themes_spec.rb51
-rw-r--r--spec/models/user_spec.rb7
-rw-r--r--spec/routing/routing_spec.rb25
-rw-r--r--spec/support/capybara.rb33
-rw-r--r--spec/support/login_helpers.rb24
11 files changed, 404 insertions, 35 deletions
diff --git a/spec/controllers/profiles/preferences_controller_spec.rb b/spec/controllers/profiles/preferences_controller_spec.rb
new file mode 100644
index 00000000000..1f0943c93d8
--- /dev/null
+++ b/spec/controllers/profiles/preferences_controller_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe Profiles::PreferencesController do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+
+ allow(subject).to receive(:current_user).and_return(user)
+ end
+
+ describe 'GET show' do
+ it 'renders' do
+ get :show
+ expect(response).to render_template :show
+ end
+
+ it 'assigns user' do
+ get :show
+ expect(assigns[:user]).to eq user
+ end
+ end
+
+ describe 'PATCH update' do
+ def go(params: {}, format: :js)
+ params.reverse_merge!(
+ color_scheme_id: '1',
+ dashboard: 'stars',
+ theme_id: '1'
+ )
+
+ patch :update, user: params, format: format
+ end
+
+ context 'on successful update' do
+ it 'sets the flash' do
+ go
+ expect(flash[:notice]).to eq 'Preferences saved.'
+ end
+
+ it "changes the user's preferences" do
+ prefs = {
+ color_scheme_id: '1',
+ dashboard: 'stars',
+ theme_id: '2'
+ }.with_indifferent_access
+
+ expect(user).to receive(:update_attributes).with(prefs)
+
+ go params: prefs
+ end
+ end
+
+ context 'on failed update' do
+ it 'sets the flash' do
+ expect(user).to receive(:update_attributes).and_return(false)
+
+ go
+
+ expect(flash[:alert]).to eq('Failed to save preferences.')
+ end
+ end
+
+ context 'on invalid dashboard setting' do
+ it 'sets the flash' do
+ prefs = {dashboard: 'invalid'}
+
+ go params: prefs
+
+ expect(flash[:alert]).to match(/\AFailed to save preferences \(.+\)\.\z/)
+ end
+ end
+
+ context 'as js' do
+ it 'renders' do
+ go
+ expect(response).to render_template :update
+ end
+ end
+
+ context 'as html' do
+ it 'redirects' do
+ go format: :html
+ expect(response).to redirect_to(profile_preferences_path)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb
new file mode 100644
index 00000000000..abbbf6855fc
--- /dev/null
+++ b/spec/controllers/root_controller_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe RootController do
+ describe 'GET show' do
+ context 'with a user' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ allow(subject).to receive(:current_user).and_return(user)
+ end
+
+ context 'who has customized their dashboard setting' do
+ before do
+ user.update_attribute(:dashboard, 'stars')
+ end
+
+ it 'redirects to their specified dashboard' do
+ get :show
+ expect(response).to redirect_to starred_dashboard_projects_path
+ end
+ end
+
+ context 'who uses the default dashboard setting' do
+ it 'renders the default dashboard' do
+ get :show
+ expect(response).to render_template 'dashboard/show'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/profiles/preferences_spec.rb b/spec/features/profiles/preferences_spec.rb
new file mode 100644
index 00000000000..69d15f41706
--- /dev/null
+++ b/spec/features/profiles/preferences_spec.rb
@@ -0,0 +1,82 @@
+require 'spec_helper'
+
+describe 'Profile > Preferences' do
+ let(:user) { create(:user) }
+
+ before do
+ login_as(user)
+ visit profile_preferences_path
+ end
+
+ describe 'User changes their application theme', js: true do
+ let(:default) { Gitlab::Themes.default }
+ let(:theme) { Gitlab::Themes.by_id(5) }
+
+ it 'creates a flash message' do
+ choose "user_theme_id_#{theme.id}"
+
+ expect_preferences_saved_message
+ end
+
+ it 'updates their preference' do
+ choose "user_theme_id_#{theme.id}"
+
+ allowing_for_delay do
+ visit page.current_path
+ expect(page).to have_checked_field("user_theme_id_#{theme.id}")
+ end
+ end
+
+ it 'reflects the changes immediately' do
+ expect(page).to have_selector("body.#{default.css_class}")
+
+ choose "user_theme_id_#{theme.id}"
+
+ expect(page).not_to have_selector("body.#{default.css_class}")
+ expect(page).to have_selector("body.#{theme.css_class}")
+ end
+ end
+
+ describe 'User changes their syntax highlighting theme', js: true do
+ it 'creates a flash message' do
+ choose 'user_color_scheme_id_5'
+
+ expect_preferences_saved_message
+ end
+
+ it 'updates their preference' do
+ choose 'user_color_scheme_id_5'
+
+ allowing_for_delay do
+ visit page.current_path
+ expect(page).to have_checked_field('user_color_scheme_id_5')
+ end
+ end
+ end
+
+ describe 'User changes their default dashboard' do
+ it 'creates a flash message' do
+ select 'Starred Projects', from: 'user_dashboard'
+ click_button 'Save'
+
+ expect_preferences_saved_message
+ end
+
+ it 'updates their preference' do
+ select 'Starred Projects', from: 'user_dashboard'
+ click_button 'Save'
+
+ click_link 'Dashboard'
+ expect(page.current_path).to eq starred_dashboard_projects_path
+
+ click_link 'Your Projects'
+ expect(page.current_path).to eq dashboard_path
+ end
+ end
+
+ def expect_preferences_saved_message
+ within('.flash-container') do
+ expect(page).to have_content('Preferences saved.')
+ end
+ end
+end
diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index 2512a9c0e3d..2b09771851e 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -36,8 +36,8 @@ describe "Profile access", feature: true do
it { is_expected.to be_denied_for :visitor }
end
- describe "GET /profile/design" do
- subject { design_profile_path }
+ describe "GET /profile/preferences" do
+ subject { profile_preferences_path }
it { is_expected.to be_allowed_for @u1 }
it { is_expected.to be_allowed_for :admin }
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 3307ac776fc..47e10197f5c 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -185,27 +185,6 @@ describe ApplicationHelper do
end
end
- describe 'user_color_scheme_class' do
- context 'with current_user is nil' do
- it 'should return a string' do
- allow(self).to receive(:current_user).and_return(nil)
- expect(user_color_scheme_class).to be_kind_of(String)
- end
- end
-
- context 'with a current_user' do
- (1..5).each do |color_scheme_id|
- context "with color_scheme_id == #{color_scheme_id}" do
- it 'should return a string' do
- current_user = double(:color_scheme_id => color_scheme_id)
- allow(self).to receive(:current_user).and_return(current_user)
- expect(user_color_scheme_class).to be_kind_of(String)
- end
- end
- end
- end
- end
-
describe 'simple_sanitize' do
let(:a_tag) { '<a href="#">Foo</a>' }
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
new file mode 100644
index 00000000000..920de8c4325
--- /dev/null
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -0,0 +1,72 @@
+require 'spec_helper'
+
+describe PreferencesHelper do
+ describe 'user_application_theme' do
+ context 'with a user' do
+ it "returns user's theme's css_class" do
+ user = double('user', theme_id: 3)
+ allow(self).to receive(:current_user).and_return(user)
+ expect(user_application_theme).to eq 'ui_green'
+ end
+
+ it 'returns the default when id is invalid' do
+ user = double('user', theme_id: Gitlab::Themes::THEMES.size + 5)
+
+ allow(Gitlab.config.gitlab).to receive(:default_theme).and_return(2)
+ allow(self).to receive(:current_user).and_return(user)
+
+ expect(user_application_theme).to eq 'ui_charcoal'
+ end
+ end
+
+ context 'without a user' do
+ before do
+ allow(self).to receive(:current_user).and_return(nil)
+ end
+
+ it 'returns the default theme' do
+ expect(user_application_theme).to eq Gitlab::Themes.default.css_class
+ end
+ end
+ end
+
+ describe 'dashboard_choices' do
+ it 'raises an exception when defined choices may be missing' do
+ expect(User).to receive(:dashboards).and_return(foo: 'foo')
+ expect { dashboard_choices }.to raise_error(RuntimeError)
+ end
+
+ it 'raises an exception when defined choices may be using the wrong key' do
+ expect(User).to receive(:dashboards).and_return(foo: 'foo', bar: 'bar')
+ expect { dashboard_choices }.to raise_error(KeyError)
+ end
+
+ it 'provides better option descriptions' do
+ expect(dashboard_choices).to match_array [
+ ['Your Projects (default)', 'projects'],
+ ['Starred Projects', 'stars']
+ ]
+ end
+ end
+
+ describe 'user_color_scheme_class' do
+ context 'with current_user is nil' do
+ it 'should return a string' do
+ allow(self).to receive(:current_user).and_return(nil)
+ expect(user_color_scheme_class).to be_kind_of(String)
+ end
+ end
+
+ context 'with a current_user' do
+ (1..5).each do |color_scheme_id|
+ context "with color_scheme_id == #{color_scheme_id}" do
+ it 'should return a string' do
+ current_user = double(:color_scheme_id => color_scheme_id)
+ allow(self).to receive(:current_user).and_return(current_user)
+ expect(user_color_scheme_class).to be_kind_of(String)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/themes_spec.rb b/spec/lib/gitlab/themes_spec.rb
new file mode 100644
index 00000000000..9c6c3fd8104
--- /dev/null
+++ b/spec/lib/gitlab/themes_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe Gitlab::Themes do
+ describe '.body_classes' do
+ it 'returns a space-separated list of class names' do
+ css = described_class.body_classes
+
+ expect(css).to include('ui_graphite')
+ expect(css).to include(' ui_charcoal ')
+ expect(css).to include(' ui_blue')
+ end
+ end
+
+ describe '.by_id' do
+ it 'returns a Theme by its ID' do
+ expect(described_class.by_id(1).name).to eq 'Graphite'
+ expect(described_class.by_id(6).name).to eq 'Blue'
+ end
+ end
+
+ describe '.default' do
+ it 'returns the default application theme' do
+ allow(described_class).to receive(:default_id).and_return(2)
+ expect(described_class.default.id).to eq 2
+ end
+
+ it 'prevents an infinite loop when configuration default is invalid' do
+ default = described_class::APPLICATION_DEFAULT
+ themes = described_class::THEMES
+
+ config = double(default_theme: 0).as_null_object
+ allow(Gitlab).to receive(:config).and_return(config)
+ expect(described_class.default.id).to eq default
+
+ config = double(default_theme: themes.size + 5).as_null_object
+ allow(Gitlab).to receive(:config).and_return(config)
+ expect(described_class.default.id).to eq default
+ end
+ end
+
+ describe '.each' do
+ it 'passes the block to the THEMES Array' do
+ ids = []
+ described_class.each { |theme| ids << theme.id }
+ expect(ids).not_to be_empty
+
+ # TODO (rspeicher): RSpec 3.x
+ # expect(described_class.each).to yield_with_arg(described_class::Theme)
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index f1b8afa5854..f3e278e5c5f 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -50,12 +50,13 @@
# bitbucket_access_token :string(255)
# bitbucket_access_token_secret :string(255)
# location :string(255)
+# public_email :string(255) default(""), not null
# encrypted_otp_secret :string(255)
# encrypted_otp_secret_iv :string(255)
# encrypted_otp_secret_salt :string(255)
# otp_required_for_login :boolean
# otp_backup_codes :text
-# public_email :string(255) default(""), not null
+# dashboard :integer default(0)
#
require 'spec_helper'
@@ -329,12 +330,12 @@ describe User do
end
describe 'with default overrides' do
- let(:user) { User.new(projects_limit: 123, can_create_group: false, can_create_team: true, theme_id: Gitlab::Theme::BASIC) }
+ let(:user) { User.new(projects_limit: 123, can_create_group: false, can_create_team: true, theme_id: 1) }
it "should apply defaults to user" do
expect(user.projects_limit).to eq(123)
expect(user.can_create_group).to be_falsey
- expect(user.theme_id).to eq(Gitlab::Theme::BASIC)
+ expect(user.theme_id).to eq(1)
end
end
end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 953c8dd8ddc..f268e4755d1 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -102,7 +102,6 @@ end
# profile_token GET /profile/token(.:format) profile#token
# profile_reset_private_token PUT /profile/reset_private_token(.:format) profile#reset_private_token
# profile GET /profile(.:format) profile#show
-# profile_design GET /profile/design(.:format) profile#design
# profile_update PUT /profile/update(.:format) profile#update
describe ProfilesController, "routing" do
it "to #account" do
@@ -120,9 +119,19 @@ describe ProfilesController, "routing" do
it "to #show" do
expect(get("/profile")).to route_to('profiles#show')
end
+end
- it "to #design" do
- expect(get("/profile/design")).to route_to('profiles#design')
+# profile_preferences GET /profile/preferences(.:format) profiles/preferences#show
+# PATCH /profile/preferences(.:format) profiles/preferences#update
+# PUT /profile/preferences(.:format) profiles/preferences#update
+describe Profiles::PreferencesController, 'routing' do
+ it 'to #show' do
+ expect(get('/profile/preferences')).to route_to('profiles/preferences#show')
+ end
+
+ it 'to #update' do
+ expect(put('/profile/preferences')).to route_to('profiles/preferences#update')
+ expect(patch('/profile/preferences')).to route_to('profiles/preferences#update')
end
end
@@ -195,11 +204,9 @@ end
# dashboard GET /dashboard(.:format) dashboard#show
# dashboard_issues GET /dashboard/issues(.:format) dashboard#issues
# dashboard_merge_requests GET /dashboard/merge_requests(.:format) dashboard#merge_requests
-# root / dashboard#show
describe DashboardController, "routing" do
it "to #index" do
expect(get("/dashboard")).to route_to('dashboard#show')
- expect(get("/")).to route_to('dashboard#show')
end
it "to #issues" do
@@ -211,6 +218,14 @@ describe DashboardController, "routing" do
end
end
+# root / root#show
+describe RootController, 'routing' do
+ it 'to #show' do
+ expect(get('/')).to route_to('root#show')
+ end
+end
+
+
# new_user_session GET /users/sign_in(.:format) devise/sessions#new
# user_session POST /users/sign_in(.:format) devise/sessions#create
# destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index fed1ab6ee33..3e41aec425a 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -19,3 +19,36 @@ unless ENV['CI'] || ENV['CI_SERVER']
# Keep only the screenshots generated from the last failing test suite
Capybara::Screenshot.prune_strategy = :keep_last_run
end
+
+module CapybaraHelpers
+ # Execute a block a certain number of times before considering it a failure
+ #
+ # The given block is called, and if it raises a `Capybara::ExpectationNotMet`
+ # error, we wait `interval` seconds and then try again, until `retries` is
+ # met.
+ #
+ # This allows for better handling of timing-sensitive expectations in a
+ # sketchy CI environment, for example.
+ #
+ # interval - Delay between retries in seconds (default: 0.5)
+ # retries - Number of times to execute before failing (default: 5)
+ def allowing_for_delay(interval: 0.5, retries: 5)
+ tries = 0
+
+ begin
+ yield
+ rescue Capybara::ExpectationNotMet => ex
+ if tries <= retries
+ tries += 1
+ sleep interval
+ retry
+ else
+ raise ex
+ end
+ end
+ end
+end
+
+RSpec.configure do |config|
+ config.include CapybaraHelpers, type: :feature
+end
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
index 791d2a1fd64..1bd68552012 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/login_helpers.rb
@@ -1,9 +1,25 @@
module LoginHelpers
- # Internal: Create and log in as a user of the specified role
+ # Internal: Log in as a specific user or a new user of a specific role
#
- # role - User role (e.g., :admin, :user)
- def login_as(role)
- @user = create(role)
+ # user_or_role - User object, or a role to create (e.g., :admin, :user)
+ #
+ # Examples:
+ #
+ # # Create a user automatically
+ # login_as(:user)
+ #
+ # # Create an admin automatically
+ # login_as(:admin)
+ #
+ # # Provide an existing User record
+ # user = create(:user)
+ # login_as(user)
+ def login_as(user_or_role)
+ if user_or_role.kind_of?(User)
+ @user = user_or_role
+ else
+ @user = create(user_or_role)
+ end
login_with(@user)
end