summaryrefslogtreecommitdiff
path: root/spec/features
diff options
context:
space:
mode:
Diffstat (limited to 'spec/features')
-rw-r--r--spec/features/admin/admin_users_spec.rb10
-rw-r--r--spec/features/builds_spec.rb168
-rw-r--r--spec/features/issues/award_emoji_spec.rb2
-rw-r--r--spec/features/issues/award_spec.rb49
-rw-r--r--spec/features/issues/bulk_assigment_labels_spec.rb196
-rw-r--r--spec/features/issues/update_issues_spec.rb23
-rw-r--r--spec/features/issues_spec.rb10
-rw-r--r--spec/features/login_spec.rb28
-rw-r--r--spec/features/merge_requests/award_spec.rb49
-rw-r--r--spec/features/notes_on_merge_requests_spec.rb25
-rw-r--r--spec/features/projects/shortcuts_spec.rb (renamed from spec/features/project/shortcuts_spec.rb)0
-rw-r--r--spec/features/todos/target_state_spec.rb2
-rw-r--r--spec/features/todos/todos_spec.rb17
-rw-r--r--spec/features/u2f_spec.rb239
14 files changed, 720 insertions, 98 deletions
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 96621843b30..b72ad405479 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -19,7 +19,7 @@ describe "Admin::Users", feature: true do
describe 'Two-factor Authentication filters' do
it 'counts users who have enabled 2FA' do
- create(:user, two_factor_enabled: true)
+ create(:user, :two_factor)
visit admin_users_path
@@ -29,7 +29,7 @@ describe "Admin::Users", feature: true do
end
it 'filters by users who have enabled 2FA' do
- user = create(:user, two_factor_enabled: true)
+ user = create(:user, :two_factor)
visit admin_users_path
click_link '2FA Enabled'
@@ -38,7 +38,7 @@ describe "Admin::Users", feature: true do
end
it 'counts users who have not enabled 2FA' do
- create(:user, two_factor_enabled: false)
+ create(:user)
visit admin_users_path
@@ -48,7 +48,7 @@ describe "Admin::Users", feature: true do
end
it 'filters by users who have not enabled 2FA' do
- user = create(:user, two_factor_enabled: false)
+ user = create(:user)
visit admin_users_path
click_link '2FA Disabled'
@@ -173,7 +173,7 @@ describe "Admin::Users", feature: true do
describe 'Two-factor Authentication status' do
it 'shows when enabled' do
- @user.update_attribute(:two_factor_enabled, true)
+ @user.update_attribute(:otp_required_for_login, true)
visit admin_user_path(@user)
diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb
index 7a05d30e8b5..e268d76755f 100644
--- a/spec/features/builds_spec.rb
+++ b/spec/features/builds_spec.rb
@@ -7,6 +7,7 @@ describe "Builds" do
login_as(:user)
@commit = FactoryGirl.create :ci_commit
@build = FactoryGirl.create :ci_build, commit: @commit
+ @build2 = FactoryGirl.create :ci_build
@project = @commit.project
@project.team << [@user, :developer]
end
@@ -66,13 +67,24 @@ describe "Builds" do
end
describe "GET /:project/builds/:id" do
- before do
- visit namespace_project_build_path(@project.namespace, @project, @build)
+ context "Build from project" do
+ before do
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ end
+
+ it { expect(page.status_code).to eq(200) }
+ it { expect(page).to have_content @commit.sha[0..7] }
+ it { expect(page).to have_content @commit.git_commit_message }
+ it { expect(page).to have_content @commit.git_author_name }
end
- it { expect(page).to have_content @commit.sha[0..7] }
- it { expect(page).to have_content @commit.git_commit_message }
- it { expect(page).to have_content @commit.git_author_name }
+ context "Build from other project" do
+ before do
+ visit namespace_project_build_path(@project.namespace, @project, @build2)
+ end
+
+ it { expect(page.status_code).to eq(404) }
+ end
context "Download artifacts" do
before do
@@ -103,51 +115,143 @@ describe "Builds" do
end
describe "POST /:project/builds/:id/cancel" do
- before do
- @build.run!
- visit namespace_project_build_path(@project.namespace, @project, @build)
- click_link "Cancel"
+ context "Build from project" do
+ before do
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ click_link "Cancel"
+ end
+
+ it { expect(page.status_code).to eq(200) }
+ it { expect(page).to have_content 'canceled' }
+ it { expect(page).to have_content 'Retry' }
end
- it { expect(page).to have_content 'canceled' }
- it { expect(page).to have_content 'Retry' }
+ context "Build from other project" do
+ before do
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ page.driver.post(cancel_namespace_project_build_path(@project.namespace, @project, @build2))
+ end
+
+ it { expect(page.status_code).to eq(404) }
+ end
end
describe "POST /:project/builds/:id/retry" do
- before do
- @build.run!
- visit namespace_project_build_path(@project.namespace, @project, @build)
- click_link "Cancel"
- click_link 'Retry'
+ context "Build from project" do
+ before do
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ click_link 'Cancel'
+ click_link 'Retry'
+ end
+
+ it { expect(page.status_code).to eq(200) }
+ it { expect(page).to have_content 'pending' }
+ it { expect(page).to have_content 'Cancel' }
end
- it { expect(page).to have_content 'pending' }
- it { expect(page).to have_content 'Cancel' }
+ context "Build from other project" do
+ before do
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ click_link 'Cancel'
+ page.driver.post(retry_namespace_project_build_path(@project.namespace, @project, @build2))
+ end
+
+ it { expect(page.status_code).to eq(404) }
+ end
end
describe "GET /:project/builds/:id/download" do
- before do
- @build.update_attributes(artifacts_file: artifacts_file)
- visit namespace_project_build_path(@project.namespace, @project, @build)
- page.within('.artifacts') { click_link 'Download' }
+ context "Build from project" do
+ before do
+ @build.update_attributes(artifacts_file: artifacts_file)
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ page.within('.artifacts') { click_link 'Download' }
+ end
+
+ it { expect(page.status_code).to eq(200) }
+ it { expect(page.response_headers['Content-Type']).to eq(artifacts_file.content_type) }
end
- it { expect(page.response_headers['Content-Type']).to eq(artifacts_file.content_type) }
+ context "Build from other project" do
+ before do
+ @build2.update_attributes(artifacts_file: artifacts_file)
+ visit download_namespace_project_build_artifacts_path(@project.namespace, @project, @build2)
+ end
+
+ it { expect(page.status_code).to eq(404) }
+ end
end
describe "GET /:project/builds/:id/raw" do
- before do
- Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
- @build.run!
- @build.trace = 'BUILD TRACE'
- visit namespace_project_build_path(@project.namespace, @project, @build)
+ context "Build from project" do
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
+ @build.run!
+ @build.trace = 'BUILD TRACE'
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ page.within('.build-controls') { click_link 'Raw' }
+ end
+
+ it 'sends the right headers' do
+ expect(page.status_code).to eq(200)
+ expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
+ expect(page.response_headers['X-Sendfile']).to eq(@build.path_to_trace)
+ end
+ end
+
+ context "Build from other project" do
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
+ @build2.run!
+ @build2.trace = 'BUILD TRACE'
+ visit raw_namespace_project_build_path(@project.namespace, @project, @build2)
+ puts page.status_code
+ puts current_url
+ end
+
+ it 'sends the right headers' do
+ expect(page.status_code).to eq(404)
+ end
+ end
+ end
+
+ describe "GET /:project/builds/:id/trace.json" do
+ context "Build from project" do
+ before do
+ visit trace_namespace_project_build_path(@project.namespace, @project, @build, format: :json)
+ end
+
+ it { expect(page.status_code).to eq(200) }
+ end
+
+ context "Build from other project" do
+ before do
+ visit trace_namespace_project_build_path(@project.namespace, @project, @build2, format: :json)
+ end
+
+ it { expect(page.status_code).to eq(404) }
+ end
+ end
+
+ describe "GET /:project/builds/:id/status" do
+ context "Build from project" do
+ before do
+ visit status_namespace_project_build_path(@project.namespace, @project, @build)
+ end
+
+ it { expect(page.status_code).to eq(200) }
end
- it 'sends the right headers' do
- page.within('.build-controls') { click_link 'Raw' }
+ context "Build from other project" do
+ before do
+ visit status_namespace_project_build_path(@project.namespace, @project, @build2)
+ end
- expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(page.response_headers['X-Sendfile']).to eq(@build.path_to_trace)
+ it { expect(page.status_code).to eq(404) }
end
end
end
diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb
index 41af789aae2..07a854ea014 100644
--- a/spec/features/issues/award_emoji_spec.rb
+++ b/spec/features/issues/award_emoji_spec.rb
@@ -28,7 +28,6 @@ describe 'Awards Emoji', feature: true do
end
context 'click the thumbsup emoji' do
-
it 'should increment the thumbsup emoji', js: true do
find('[data-emoji="thumbsup"]').click
sleep 2
@@ -41,7 +40,6 @@ describe 'Awards Emoji', feature: true do
end
context 'click the thumbsdown emoji' do
-
it 'should increment the thumbsdown emoji', js: true do
find('[data-emoji="thumbsdown"]').click
sleep 2
diff --git a/spec/features/issues/award_spec.rb b/spec/features/issues/award_spec.rb
new file mode 100644
index 00000000000..63efecf8780
--- /dev/null
+++ b/spec/features/issues/award_spec.rb
@@ -0,0 +1,49 @@
+require 'rails_helper'
+
+feature 'Issue awards', js: true, feature: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+ let(:issue) { create(:issue, project: project) }
+
+ describe 'logged in' do
+ before do
+ login_as(user)
+ visit namespace_project_issue_path(project.namespace, project, issue)
+ end
+
+ it 'should add award to issue' do
+ first('.js-emoji-btn').click
+ expect(page).to have_selector('.js-emoji-btn.active')
+ expect(first('.js-emoji-btn')).to have_content '1'
+
+ visit namespace_project_issue_path(project.namespace, project, issue)
+ expect(first('.js-emoji-btn')).to have_content '1'
+ end
+
+ it 'should remove award from issue' do
+ first('.js-emoji-btn').click
+ find('.js-emoji-btn.active').click
+ expect(first('.js-emoji-btn')).to have_content '0'
+
+ visit namespace_project_issue_path(project.namespace, project, issue)
+ expect(first('.js-emoji-btn')).to have_content '0'
+ end
+
+ it 'should only have one menu on the page' do
+ first('.js-add-award').click
+ expect(page).to have_selector('.emoji-menu')
+
+ expect(page).to have_selector('.emoji-menu', count: 1)
+ end
+ end
+
+ describe 'logged out' do
+ before do
+ visit namespace_project_issue_path(project.namespace, project, issue)
+ end
+
+ it 'should not see award menu button' do
+ expect(page).not_to have_selector('.js-award-holder')
+ end
+ end
+end
diff --git a/spec/features/issues/bulk_assigment_labels_spec.rb b/spec/features/issues/bulk_assigment_labels_spec.rb
new file mode 100644
index 00000000000..c58b87281a3
--- /dev/null
+++ b/spec/features/issues/bulk_assigment_labels_spec.rb
@@ -0,0 +1,196 @@
+require 'rails_helper'
+
+feature 'Issues > Labels bulk assignment', feature: true do
+ include WaitForAjax
+
+ let(:user) { create(:user) }
+ let!(:project) { create(:project) }
+ let!(:issue1) { create(:issue, project: project, title: "Issue 1") }
+ let!(:issue2) { create(:issue, project: project, title: "Issue 2") }
+ let!(:bug) { create(:label, project: project, title: 'bug') }
+ let!(:feature) { create(:label, project: project, title: 'feature') }
+
+ context 'as a allowed user', js: true do
+ before do
+ project.team << [user, :master]
+
+ login_as user
+ end
+
+ context 'can bulk assign' do
+ before do
+ visit namespace_project_issues_path(project.namespace, project)
+ end
+
+ context 'a label' do
+ context 'to all issues' do
+ before do
+ check 'check_all_issues'
+ open_labels_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'bug'
+ end
+ end
+
+ context 'to a issue' do
+ before do
+ check "selected_issue_#{issue1.id}"
+ open_labels_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ end
+ end
+ end
+
+ context 'multiple labels' do
+ context 'to all issues' do
+ before do
+ check 'check_all_issues'
+ open_labels_dropdown ['bug', 'feature']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ end
+ end
+
+ context 'to a issue' do
+ before do
+ check "selected_issue_#{issue1.id}"
+ open_labels_dropdown ['bug', 'feature']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
+ end
+ end
+ end
+ end
+
+ context 'can bulk un-assign' do
+ context 'all labels to all issues' do
+ before do
+ issue1.labels << bug
+ issue1.labels << feature
+ issue2.labels << bug
+ issue2.labels << feature
+
+ visit namespace_project_issues_path(project.namespace, project)
+
+ check 'check_all_issues'
+ unmark_labels_in_dropdown ['bug', 'feature']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
+ end
+ end
+
+ context 'a label to a issue' do
+ before do
+ issue1.labels << bug
+ issue2.labels << feature
+
+ visit namespace_project_issues_path(project.namespace, project)
+
+ check_issue issue1
+ unmark_labels_in_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ end
+ end
+
+ context 'a label and keep the others label' do
+ before do
+ issue1.labels << bug
+ issue1.labels << feature
+ issue2.labels << bug
+ issue2.labels << feature
+
+ visit namespace_project_issues_path(project.namespace, project)
+
+ check_issue issue1
+ check_issue issue2
+ unmark_labels_in_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ end
+ end
+ end
+ end
+
+ context 'as a guest' do
+ before do
+ login_as user
+
+ visit namespace_project_issues_path(project.namespace, project)
+ end
+
+ context 'cannot bulk assign labels' do
+ it do
+ expect(page).not_to have_css '.check_all_issues'
+ expect(page).not_to have_css '.issue-check'
+ end
+ end
+ end
+
+ def open_labels_dropdown(items = [], unmark = false)
+ page.within('.issues_bulk_update') do
+ click_button 'Label'
+ wait_for_ajax
+ items.map do |item|
+ click_link item
+ end
+ if unmark
+ items.map do |item|
+ click_link item
+ end
+ end
+ end
+ end
+
+ def unmark_labels_in_dropdown(items = [])
+ open_labels_dropdown(items, true)
+ end
+
+ def check_issue(issue)
+ page.within('.issues-list') do
+ check "selected_issue_#{issue.id}"
+ end
+ end
+
+ def update_issues
+ click_button 'Update issues'
+ wait_for_ajax
+ end
+end
diff --git a/spec/features/issues/update_issues_spec.rb b/spec/features/issues/update_issues_spec.rb
index 466a6f7dfa7..ddbd69b2891 100644
--- a/spec/features/issues/update_issues_spec.rb
+++ b/spec/features/issues/update_issues_spec.rb
@@ -1,6 +1,8 @@
require 'rails_helper'
feature 'Multiple issue updating from issues#index', feature: true do
+ include WaitForAjax
+
let!(:project) { create(:project) }
let!(:issue) { create(:issue, project: project) }
let!(:user) { create(:user)}
@@ -24,9 +26,7 @@ feature 'Multiple issue updating from issues#index', feature: true do
it 'should be set to open' do
create_closed
- visit namespace_project_issues_path(project.namespace, project)
-
- find('.issues-state-filters a', text: 'Closed').click
+ visit namespace_project_issues_path(project.namespace, project, state: 'closed')
find('#check_all_issues').click
find('.js-issue-status').click
@@ -42,7 +42,7 @@ feature 'Multiple issue updating from issues#index', feature: true do
visit namespace_project_issues_path(project.namespace, project)
find('#check_all_issues').click
- find('.js-update-assignee').click
+ click_update_assignee_button
find('.dropdown-menu-user-link', text: user.username).click
click_update_issues_button
@@ -57,14 +57,11 @@ feature 'Multiple issue updating from issues#index', feature: true do
visit namespace_project_issues_path(project.namespace, project)
find('#check_all_issues').click
- find('.js-update-assignee').click
+ click_update_assignee_button
click_link 'Unassigned'
click_update_issues_button
-
- within first('.issue .controls') do
- expect(page).to have_no_selector('.author_link')
- end
+ expect(find('.issue:first-child .controls')).not_to have_css('.author_link')
end
end
@@ -95,7 +92,7 @@ feature 'Multiple issue updating from issues#index', feature: true do
find('.dropdown-menu-milestone a', text: "No Milestone").click
click_update_issues_button
- expect(first('.issue')).not_to have_content milestone.title
+ expect(find('.issue:first-child')).not_to have_content milestone.title
end
end
@@ -111,7 +108,13 @@ feature 'Multiple issue updating from issues#index', feature: true do
create(:issue, project: project, milestone: milestone)
end
+ def click_update_assignee_button
+ find('.js-update-assignee').click
+ wait_for_ajax
+ end
+
def click_update_issues_button
find('.update_selected_issues').click
+ wait_for_ajax
end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 9271964166a..460d7f82b36 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -125,7 +125,7 @@ describe 'Issues', feature: true do
describe 'Issue info' do
it 'excludes award_emoji from comment count' do
issue = create(:issue, author: @user, assignee: @user, project: project, title: 'foobar')
- create(:upvote_note, noteable: issue, project: project)
+ create(:award_emoji, awardable: issue)
visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)
@@ -365,13 +365,9 @@ describe 'Issues', feature: true do
page.within('.assignee') do
expect(page).to have_content "#{@user.name}"
- end
- find('.block.assignee .edit-link').click
- sleep 2 # wait for ajax stuff to complete
- first('.dropdown-menu-user-link').click
- sleep 2
- page.within('.assignee') do
+ click_link 'Edit'
+ click_link 'Unassigned'
expect(page).to have_content 'No assignee'
end
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index a7dc3b2701b..72b5ff231f7 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -33,11 +33,11 @@ feature 'Login', feature: true do
before do
login_with(user, remember: true)
- expect(page).to have_content('Two-factor Authentication')
+ expect(page).to have_content('Two-Factor Authentication')
end
def enter_code(code)
- fill_in 'Two-factor Authentication code', with: code
+ fill_in 'Two-Factor Authentication code', with: code
click_button 'Verify code'
end
@@ -127,7 +127,7 @@ feature 'Login', feature: true do
user = create(:user, password: 'not-the-default')
login_with(user)
- expect(page).to have_content('Invalid login or password.')
+ expect(page).to have_content('Invalid Login or password.')
end
end
@@ -143,12 +143,12 @@ feature 'Login', feature: true do
context 'within the grace period' do
it 'redirects to two-factor configuration page' do
- expect(current_path).to eq new_profile_two_factor_auth_path
- expect(page).to have_content('You must enable Two-factor Authentication for your account before')
+ expect(current_path).to eq profile_two_factor_auth_path
+ expect(page).to have_content('You must enable Two-Factor Authentication for your account before')
end
- it 'disallows skipping two-factor configuration' do
- expect(current_path).to eq new_profile_two_factor_auth_path
+ it 'allows skipping two-factor configuration', js: true do
+ expect(current_path).to eq profile_two_factor_auth_path
click_link 'Configure it later'
expect(current_path).to eq root_path
@@ -159,26 +159,26 @@ feature 'Login', feature: true do
let(:user) { create(:user, otp_grace_period_started_at: 9999.hours.ago) }
it 'redirects to two-factor configuration page' do
- expect(current_path).to eq new_profile_two_factor_auth_path
- expect(page).to have_content('You must enable Two-factor Authentication for your account.')
+ expect(current_path).to eq profile_two_factor_auth_path
+ expect(page).to have_content('You must enable Two-Factor Authentication for your account.')
end
- it 'disallows skipping two-factor configuration' do
- expect(current_path).to eq new_profile_two_factor_auth_path
+ it 'disallows skipping two-factor configuration', js: true do
+ expect(current_path).to eq profile_two_factor_auth_path
expect(page).not_to have_link('Configure it later')
end
end
end
- context 'without grace pariod defined' do
+ context 'without grace period defined' do
before(:each) do
stub_application_setting(two_factor_grace_period: 0)
login_with(user)
end
it 'redirects to two-factor configuration page' do
- expect(current_path).to eq new_profile_two_factor_auth_path
- expect(page).to have_content('You must enable Two-factor Authentication for your account.')
+ expect(current_path).to eq profile_two_factor_auth_path
+ expect(page).to have_content('You must enable Two-Factor Authentication for your account.')
end
end
end
diff --git a/spec/features/merge_requests/award_spec.rb b/spec/features/merge_requests/award_spec.rb
new file mode 100644
index 00000000000..007f67d6080
--- /dev/null
+++ b/spec/features/merge_requests/award_spec.rb
@@ -0,0 +1,49 @@
+require 'rails_helper'
+
+feature 'Merge request awards', js: true, feature: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+
+ describe 'logged in' do
+ before do
+ login_as(user)
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+
+ it 'should add award to merge request' do
+ first('.js-emoji-btn').click
+ expect(page).to have_selector('.js-emoji-btn.active')
+ expect(first('.js-emoji-btn')).to have_content '1'
+
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ expect(first('.js-emoji-btn')).to have_content '1'
+ end
+
+ it 'should remove award from merge request' do
+ first('.js-emoji-btn').click
+ find('.js-emoji-btn.active').click
+ expect(first('.js-emoji-btn')).to have_content '0'
+
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ expect(first('.js-emoji-btn')).to have_content '0'
+ end
+
+ it 'should only have one menu on the page' do
+ first('.js-add-award').click
+ expect(page).to have_selector('.emoji-menu')
+
+ expect(page).to have_selector('.emoji-menu', count: 1)
+ end
+ end
+
+ describe 'logged out' do
+ before do
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+
+ it 'should not see award menu button' do
+ expect(page).not_to have_selector('.js-award-holder')
+ end
+ end
+end
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 2835cf44494..737efcef45d 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -4,20 +4,6 @@ describe 'Comments', feature: true do
include RepoHelpers
include WaitForAjax
- describe 'On merge requests page', feature: true do
- it 'excludes award_emoji from comment count' do
- merge_request = create(:merge_request)
- project = merge_request.source_project
- create(:upvote_note, noteable: merge_request, project: project)
-
- login_as :admin
- visit namespace_project_merge_requests_path(project.namespace, project)
-
- expect(merge_request.mr_and_commit_notes.count).to eq 1
- expect(page.all('.merge-request-no-comments').first.text).to eq "0"
- end
- end
-
describe 'On a merge request', js: true, feature: true do
let!(:project) { create(:project) }
let!(:merge_request) do
@@ -147,17 +133,6 @@ describe 'Comments', feature: true do
end
end
end
-
- describe 'comment info' do
- it 'excludes award_emoji from comment count' do
- create(:upvote_note, noteable: merge_request, project: project)
-
- visit namespace_project_merge_request_path(project.namespace, project, merge_request)
-
- expect(merge_request.mr_and_commit_notes.count).to eq 2
- expect(find('.notes-tab span.badge').text).to eq "1"
- end
- end
end
describe 'On a merge request diff', js: true, feature: true do
diff --git a/spec/features/project/shortcuts_spec.rb b/spec/features/projects/shortcuts_spec.rb
index 54aa9c66a08..54aa9c66a08 100644
--- a/spec/features/project/shortcuts_spec.rb
+++ b/spec/features/projects/shortcuts_spec.rb
diff --git a/spec/features/todos/target_state_spec.rb b/spec/features/todos/target_state_spec.rb
index 72491ac7e61..32fa88a2b21 100644
--- a/spec/features/todos/target_state_spec.rb
+++ b/spec/features/todos/target_state_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
feature 'Todo target states', feature: true do
let(:user) { create(:user) }
let(:author) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
before do
login_as user
diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb
index 4e627753cc7..8e1833a069e 100644
--- a/spec/features/todos/todos_spec.rb
+++ b/spec/features/todos/todos_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'Dashboard Todos', feature: true do
let(:user) { create(:user) }
let(:author) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
let(:issue) { create(:issue) }
describe 'GET /dashboard/todos' do
@@ -49,7 +49,7 @@ describe 'Dashboard Todos', feature: true do
note1 = create(:note_on_issue, note: "Hello #{label1.to_reference(format: :name)}", noteable_id: issue.id, noteable_type: 'Issue', project: issue.project)
create(:todo, :mentioned, project: project, target: issue, user: user, note_id: note1.id)
- project2 = create(:project)
+ project2 = create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
label2 = create(:label, project: project2)
issue2 = create(:issue, project: project2)
note2 = create(:note_on_issue, note: "Test #{label2.to_reference(format: :name)}", noteable_id: issue2.id, noteable_type: 'Issue', project: project2)
@@ -98,5 +98,18 @@ describe 'Dashboard Todos', feature: true do
end
end
end
+
+ context 'User has a Todo in a project pending deletion' do
+ before do
+ deleted_project = create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC, pending_delete: true)
+ create(:todo, :mentioned, user: user, project: deleted_project, target: issue, author: author)
+ login_as(user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows "All done" message' do
+ expect(page).to have_content "You're all done!"
+ end
+ end
end
end
diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb
new file mode 100644
index 00000000000..366a90228b1
--- /dev/null
+++ b/spec/features/u2f_spec.rb
@@ -0,0 +1,239 @@
+require 'spec_helper'
+
+feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: true, js: true do
+ def register_u2f_device(u2f_device = nil)
+ u2f_device ||= FakeU2fDevice.new(page)
+ u2f_device.respond_to_u2f_registration
+ click_on 'Setup New U2F Device'
+ expect(page).to have_content('Your device was successfully set up')
+ click_on 'Register U2F Device'
+ u2f_device
+ end
+
+ describe "registration" do
+ let(:user) { create(:user) }
+ before { login_as(user) }
+
+ describe 'when 2FA via OTP is disabled' do
+ it 'allows registering a new device' do
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+
+ register_u2f_device
+
+ expect(page.body).to match('Your U2F device was registered')
+ end
+
+ it 'allows registering more than one device' do
+ visit profile_account_path
+
+ # First device
+ click_on 'Enable Two-Factor Authentication'
+ register_u2f_device
+ expect(page.body).to match('Your U2F device was registered')
+
+ # Second device
+ click_on 'Manage Two-Factor Authentication'
+ register_u2f_device
+ expect(page.body).to match('Your U2F device was registered')
+ click_on 'Manage Two-Factor Authentication'
+
+ expect(page.body).to match('You have 2 U2F devices registered')
+ end
+ end
+
+ describe 'when 2FA via OTP is enabled' do
+ before { user.update_attributes(otp_required_for_login: true) }
+
+ it 'allows registering a new device' do
+ visit profile_account_path
+ click_on 'Manage Two-Factor Authentication'
+ expect(page.body).to match("You've already enabled two-factor authentication using mobile")
+
+ register_u2f_device
+
+ expect(page.body).to match('Your U2F device was registered')
+ end
+
+ it 'allows registering more than one device' do
+ visit profile_account_path
+
+ # First device
+ click_on 'Manage Two-Factor Authentication'
+ register_u2f_device
+ expect(page.body).to match('Your U2F device was registered')
+
+ # Second device
+ click_on 'Manage Two-Factor Authentication'
+ register_u2f_device
+ expect(page.body).to match('Your U2F device was registered')
+
+ click_on 'Manage Two-Factor Authentication'
+ expect(page.body).to match('You have 2 U2F devices registered')
+ end
+ end
+
+ it 'allows the same device to be registered for multiple users' do
+ # First user
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+ u2f_device = register_u2f_device
+ expect(page.body).to match('Your U2F device was registered')
+ logout
+
+ # Second user
+ login_as(:user)
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+ register_u2f_device(u2f_device)
+ expect(page.body).to match('Your U2F device was registered')
+
+ expect(U2fRegistration.count).to eq(2)
+ end
+
+ context "when there are form errors" do
+ it "doesn't register the device if there are errors" do
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+
+ # Have the "u2f device" respond with bad data
+ page.execute_script("u2f.register = function(_,_,_,callback) { callback('bad response'); };")
+ click_on 'Setup New U2F Device'
+ expect(page).to have_content('Your device was successfully set up')
+ click_on 'Register U2F Device'
+
+ expect(U2fRegistration.count).to eq(0)
+ expect(page.body).to match("The form contains the following error")
+ expect(page.body).to match("did not send a valid JSON response")
+ end
+
+ it "allows retrying registration" do
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+
+ # Failed registration
+ page.execute_script("u2f.register = function(_,_,_,callback) { callback('bad response'); };")
+ click_on 'Setup New U2F Device'
+ expect(page).to have_content('Your device was successfully set up')
+ click_on 'Register U2F Device'
+ expect(page.body).to match("The form contains the following error")
+
+ # Successful registration
+ register_u2f_device
+
+ expect(page.body).to match('Your U2F device was registered')
+ expect(U2fRegistration.count).to eq(1)
+ end
+ end
+ end
+
+ describe "authentication" do
+ let(:user) { create(:user) }
+
+ before do
+ # Register and logout
+ login_as(user)
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+ @u2f_device = register_u2f_device
+ logout
+ end
+
+ describe "when 2FA via OTP is disabled" do
+ it "allows logging in with the U2F device" do
+ login_with(user)
+
+ @u2f_device.respond_to_u2f_authentication
+ click_on "Login Via U2F Device"
+ expect(page.body).to match('We heard back from your U2F device')
+ click_on "Authenticate via U2F Device"
+
+ expect(page.body).to match('Signed in successfully')
+ end
+ end
+
+ describe "when 2FA via OTP is enabled" do
+ it "allows logging in with the U2F device" do
+ user.update_attributes(otp_required_for_login: true)
+ login_with(user)
+
+ @u2f_device.respond_to_u2f_authentication
+ click_on "Login Via U2F Device"
+ expect(page.body).to match('We heard back from your U2F device')
+ click_on "Authenticate via U2F Device"
+
+ expect(page.body).to match('Signed in successfully')
+ end
+ end
+
+ describe "when a given U2F device has already been registered by another user" do
+ describe "but not the current user" do
+ it "does not allow logging in with that particular device" do
+ # Register current user with the different U2F device
+ current_user = login_as(:user)
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+ register_u2f_device
+ logout
+
+ # Try authenticating user with the old U2F device
+ login_as(current_user)
+ @u2f_device.respond_to_u2f_authentication
+ click_on "Login Via U2F Device"
+ expect(page.body).to match('We heard back from your U2F device')
+ click_on "Authenticate via U2F Device"
+
+ expect(page.body).to match('Authentication via U2F device failed')
+ end
+ end
+
+ describe "and also the current user" do
+ it "allows logging in with that particular device" do
+ # Register current user with the same U2F device
+ current_user = login_as(:user)
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+ register_u2f_device(@u2f_device)
+ logout
+
+ # Try authenticating user with the same U2F device
+ login_as(current_user)
+ @u2f_device.respond_to_u2f_authentication
+ click_on "Login Via U2F Device"
+ expect(page.body).to match('We heard back from your U2F device')
+ click_on "Authenticate via U2F Device"
+
+ expect(page.body).to match('Signed in successfully')
+ end
+ end
+ end
+
+ describe "when a given U2F device has not been registered" do
+ it "does not allow logging in with that particular device" do
+ unregistered_device = FakeU2fDevice.new(page)
+ login_as(user)
+ unregistered_device.respond_to_u2f_authentication
+ click_on "Login Via U2F Device"
+ expect(page.body).to match('We heard back from your U2F device')
+ click_on "Authenticate via U2F Device"
+
+ expect(page.body).to match('Authentication via U2F device failed')
+ end
+ end
+ end
+
+ describe "when two-factor authentication is disabled" do
+ let(:user) { create(:user) }
+
+ before do
+ login_as(user)
+ visit profile_account_path
+ click_on 'Enable Two-Factor Authentication'
+ register_u2f_device
+ end
+
+ it "deletes u2f registrations" do
+ expect { click_on "Disable" }.to change { U2fRegistration.count }.from(1).to(0)
+ end
+ end
+end