2019-09-30 12:06:01 +00:00
# frozen_string_literal: true
2021-08-16 12:09:17 +00:00
require 'spec_helper'
2013-02-11 13:32:29 +00:00
2020-06-24 09:08:32 +00:00
RSpec . describe IssuesHelper do
2017-08-02 19:55:11 +00:00
let ( :project ) { create ( :project ) }
2013-02-19 13:21:59 +00:00
let ( :issue ) { create :issue , project : project }
let ( :ext_project ) { create :redmine_project }
2013-02-11 13:32:29 +00:00
2021-08-16 12:09:17 +00:00
describe '#work_item_type_icon' do
it 'returns icon of all standard base types' do
2021-12-22 12:16:22 +00:00
WorkItems :: Type . base_types . each do | type |
2021-08-16 12:09:17 +00:00
expect ( work_item_type_icon ( type [ 0 ] ) ) . to eq " issue-type- #{ type [ 0 ] . to_s . dasherize } "
end
end
it 'defaults to issue icon if type is unknown' do
expect ( work_item_type_icon ( 'invalid' ) ) . to eq 'issue-type-issue'
end
end
2016-06-19 23:06:57 +00:00
describe '#award_user_list' do
2021-08-16 12:09:17 +00:00
it 'returns a comma-separated list of the first X users' do
2016-10-06 18:00:51 +00:00
user = build_stubbed ( :user , name : 'Joe' )
awards = Array . new ( 3 , build_stubbed ( :award_emoji , user : user ) )
2016-06-19 23:06:57 +00:00
2017-02-22 22:54:59 +00:00
expect ( award_user_list ( awards , nil , limit : 3 ) )
. to eq ( 'Joe, Joe, and Joe' )
2016-06-19 23:06:57 +00:00
end
2016-07-11 18:53:07 +00:00
it " displays the current user's name as 'You' " do
2016-10-06 18:00:51 +00:00
user = build_stubbed ( :user , name : 'Joe' )
award = build_stubbed ( :award_emoji , user : user )
2016-06-19 23:06:57 +00:00
2016-10-06 18:00:51 +00:00
expect ( award_user_list ( [ award ] , user ) ) . to eq ( 'You' )
expect ( award_user_list ( [ award ] , nil ) ) . to eq 'Joe'
2016-06-21 22:22:03 +00:00
end
2021-08-16 12:09:17 +00:00
it 'truncates lists' do
2016-10-06 18:00:51 +00:00
user = build_stubbed ( :user , name : 'Jane' )
awards = Array . new ( 5 , build_stubbed ( :award_emoji , user : user ) )
2017-02-22 22:54:59 +00:00
expect ( award_user_list ( awards , nil , limit : 3 ) )
. to eq ( 'Jane, Jane, Jane, and 2 more.' )
2016-06-21 22:22:03 +00:00
end
2021-08-16 12:09:17 +00:00
it 'displays the current user in front of other users' do
2016-10-06 18:00:51 +00:00
current_user = build_stubbed ( :user )
my_award = build_stubbed ( :award_emoji , user : current_user )
award = build_stubbed ( :award_emoji , user : build_stubbed ( :user , name : 'Jane' ) )
awards = Array . new ( 5 , award ) . push ( my_award )
2017-06-21 13:48:12 +00:00
expect ( award_user_list ( awards , current_user , limit : 2 ) )
2021-08-16 12:09:17 +00:00
. to eq ( 'You, Jane, and 4 more.' )
2016-06-19 23:06:57 +00:00
end
end
2016-12-30 14:44:21 +00:00
describe '#award_state_class' do
2016-04-16 19:09:08 +00:00
let! ( :upvote ) { create ( :award_emoji ) }
2018-04-06 18:19:37 +00:00
let ( :awardable ) { upvote . awardable }
let ( :user ) { upvote . user }
before do
allow ( helper ) . to receive ( :can? ) do | * args |
Ability . allowed? ( * args )
end
end
2015-11-19 12:41:05 +00:00
2021-08-16 12:09:17 +00:00
it 'returns disabled string for unauthenticated user' do
expect ( helper . award_state_class ( awardable , AwardEmoji . all , nil ) ) . to eq ( 'disabled' )
2018-04-06 18:19:37 +00:00
end
2021-08-16 12:09:17 +00:00
it 'returns disabled for a user that does not have access to the awardable' do
expect ( helper . award_state_class ( awardable , AwardEmoji . all , build ( :user ) ) ) . to eq ( 'disabled' )
2015-11-19 12:41:05 +00:00
end
2022-04-16 00:09:28 +00:00
it 'returns selected class for author' do
expect ( helper . award_state_class ( awardable , AwardEmoji . all , upvote . user ) ) . to eq ( 'selected' )
2018-04-06 18:19:37 +00:00
end
2021-08-16 12:09:17 +00:00
it 'is blank for a user that has access to the awardable' do
2018-04-06 18:19:37 +00:00
user = build ( :user )
expect ( helper ) . to receive ( :can? ) . with ( user , :award_emoji , awardable ) . and_return ( true )
expect ( helper . award_state_class ( awardable , AwardEmoji . all , user ) ) . to be_blank
2015-11-19 12:41:05 +00:00
end
end
2015-12-25 10:08:53 +00:00
2021-08-16 12:09:17 +00:00
describe 'awards_sort' do
it 'sorts a hash so thumbsup and thumbsdown are always on top' do
data = { 'thumbsdown' = > 'some value' , 'lifter' = > 'some value' , 'thumbsup' = > 'some value' }
2017-02-22 17:46:57 +00:00
expect ( awards_sort ( data ) . keys ) . to eq ( %w( thumbsup thumbsdown lifter ) )
2015-12-25 10:08:53 +00:00
end
end
2016-04-06 14:02:22 +00:00
2021-08-16 12:09:17 +00:00
describe '#link_to_discussions_to_resolve' do
describe 'passing only a merge request' do
2017-03-08 15:39:20 +00:00
let ( :merge_request ) { create ( :merge_request ) }
2021-08-16 12:09:17 +00:00
it 'links just the merge request' do
2017-06-29 17:06:35 +00:00
expected_path = project_merge_request_path ( merge_request . project , merge_request )
2017-03-08 15:39:20 +00:00
expect ( link_to_discussions_to_resolve ( merge_request , nil ) ) . to include ( expected_path )
end
2021-08-16 12:09:17 +00:00
it 'contains the reference to the merge request' do
2017-03-08 15:39:20 +00:00
expect ( link_to_discussions_to_resolve ( merge_request , nil ) ) . to include ( merge_request . to_reference )
end
end
2021-08-16 12:09:17 +00:00
describe 'when passing a discussion' do
2019-01-16 12:09:29 +00:00
let ( :diff_note ) { create ( :diff_note_on_merge_request ) }
2017-03-08 15:39:20 +00:00
let ( :merge_request ) { diff_note . noteable }
2017-03-17 19:25:52 +00:00
let ( :discussion ) { diff_note . to_discussion }
2017-03-08 15:39:20 +00:00
2021-08-16 12:09:17 +00:00
it 'links to the merge request with first note if a single discussion was passed' do
2017-03-08 15:39:20 +00:00
expected_path = Gitlab :: UrlBuilder . build ( diff_note )
expect ( link_to_discussions_to_resolve ( merge_request , discussion ) ) . to include ( expected_path )
end
2021-08-16 12:09:17 +00:00
it 'contains both the reference to the merge request and a mention of the discussion' do
2017-03-08 15:39:20 +00:00
expect ( link_to_discussions_to_resolve ( merge_request , discussion ) ) . to include ( " #{ merge_request . to_reference } (discussion #{ diff_note . id } ) " )
end
end
end
2018-04-10 17:49:26 +00:00
describe '#show_new_issue_link?' do
before do
allow ( helper ) . to receive ( :current_user )
end
it 'is false when no project there is no project' do
expect ( helper . show_new_issue_link? ( nil ) ) . to be_falsey
end
it 'is true when there is a project and no logged in user' do
expect ( helper . show_new_issue_link? ( build ( :project ) ) ) . to be_truthy
end
it 'is true when the current user does not have access to the project' do
project = build ( :project )
allow ( helper ) . to receive ( :current_user ) . and_return ( project . owner )
expect ( helper ) . to receive ( :can? ) . with ( project . owner , :create_issue , project ) . and_return ( true )
expect ( helper . show_new_issue_link? ( project ) ) . to be_truthy
end
end
2019-09-13 13:26:31 +00:00
describe '#issue_closed_link' do
let ( :new_issue ) { create ( :issue , project : project ) }
let ( :guest ) { create ( :user ) }
before do
allow ( helper ) . to receive ( :can? ) do | * args |
Ability . allowed? ( * args )
end
end
shared_examples 'successfully displays link to issue and with css class' do | action |
it 'returns link' do
2020-03-02 15:08:01 +00:00
link = " <a class= \" #{ css_class } \" href= \" / #{ new_issue . project . full_path } /-/issues/ #{ new_issue . iid } \" >( #{ action } )</a> "
2019-09-13 13:26:31 +00:00
expect ( helper . issue_closed_link ( issue , user , css_class : css_class ) ) . to match ( link )
end
end
shared_examples 'does not display link' do
it 'returns nil' do
expect ( helper . issue_closed_link ( issue , user ) ) . to be_nil
end
end
context 'with linked issue' do
context 'with moved issue' do
before do
2020-07-27 12:09:50 +00:00
issue . update! ( moved_to : new_issue )
2019-09-13 13:26:31 +00:00
end
context 'when user has permission to see new issue' do
let ( :user ) { project . owner }
let ( :css_class ) { 'text-white text-underline' }
it_behaves_like 'successfully displays link to issue and with css class' , 'moved'
end
context 'when user has no permission to see new issue' do
let ( :user ) { guest }
it_behaves_like 'does not display link'
end
end
context 'with duplicated issue' do
before do
2020-07-27 12:09:50 +00:00
issue . update! ( duplicated_to : new_issue )
2019-09-13 13:26:31 +00:00
end
context 'when user has permission to see new issue' do
let ( :user ) { project . owner }
let ( :css_class ) { 'text-white text-underline' }
it_behaves_like 'successfully displays link to issue and with css class' , 'duplicated'
end
context 'when user has no permission to see new issue' do
let ( :user ) { guest }
it_behaves_like 'does not display link'
end
end
end
context 'without linked issue' do
let ( :user ) { project . owner }
before do
2020-07-27 12:09:50 +00:00
issue . update! ( moved_to : nil , duplicated_to : nil )
2019-09-13 13:26:31 +00:00
end
it_behaves_like 'does not display link'
end
end
2020-07-15 21:09:26 +00:00
describe '#show_moved_service_desk_issue_warning?' do
let ( :project1 ) { create ( :project , service_desk_enabled : true ) }
let ( :project2 ) { create ( :project , service_desk_enabled : true ) }
let! ( :old_issue ) { create ( :issue , author : User . support_bot , project : project1 ) }
let! ( :new_issue ) { create ( :issue , author : User . support_bot , project : project2 ) }
before do
allow ( Gitlab :: IncomingEmail ) . to receive ( :enabled? ) { true }
allow ( Gitlab :: IncomingEmail ) . to receive ( :supports_wildcard? ) { true }
2020-07-27 12:09:50 +00:00
old_issue . update! ( moved_to : new_issue )
2020-07-15 21:09:26 +00:00
end
it 'is true when moved issue project has service desk disabled' do
project2 . update! ( service_desk_enabled : false )
expect ( helper . show_moved_service_desk_issue_warning? ( new_issue ) ) . to be ( true )
end
it 'is false when moved issue project has service desk enabled' do
expect ( helper . show_moved_service_desk_issue_warning? ( new_issue ) ) . to be ( false )
end
end
2020-09-21 09:09:29 +00:00
2021-01-26 18:09:30 +00:00
describe '#issue_header_actions_data' do
let ( :current_user ) { create ( :user ) }
before do
allow ( helper ) . to receive ( :current_user ) . and_return ( current_user )
allow ( helper ) . to receive ( :can? ) . and_return ( true )
end
it 'returns expected result' do
expected = {
2021-08-16 12:09:17 +00:00
can_create_issue : 'true' ,
2021-12-16 12:15:41 +00:00
can_destroy_issue : 'true' ,
2021-08-16 12:09:17 +00:00
can_reopen_issue : 'true' ,
can_report_spam : 'false' ,
can_update_issue : 'true' ,
2021-01-26 18:09:30 +00:00
iid : issue . iid ,
2021-08-16 12:09:17 +00:00
is_issue_author : 'false' ,
2021-12-16 12:15:41 +00:00
issue_path : issue_path ( issue ) ,
2021-08-16 12:09:17 +00:00
issue_type : 'issue' ,
2022-03-03 18:19:46 +00:00
new_issue_path : new_project_issue_path ( project , { add_related_issue : issue . iid } ) ,
2021-01-26 18:09:30 +00:00
project_path : project . full_path ,
report_abuse_path : new_abuse_report_path ( user_id : issue . author . id , ref_url : issue_url ( issue ) ) ,
submit_as_spam_path : mark_as_spam_project_issue_path ( project , issue )
}
expect ( helper . issue_header_actions_data ( project , issue , current_user ) ) . to include ( expected )
end
end
2021-04-01 18:13:56 +00:00
shared_examples 'issues list data' do
it 'returns expected result' do
allow ( helper ) . to receive ( :current_user ) . and_return ( current_user )
allow ( helper ) . to receive ( :can? ) . and_return ( true )
2021-04-09 18:09:24 +00:00
allow ( helper ) . to receive ( :image_path ) . and_return ( '#' )
2021-04-01 18:13:56 +00:00
allow ( helper ) . to receive ( :import_csv_namespace_project_issues_path ) . and_return ( '#' )
2021-11-18 18:14:27 +00:00
allow ( helper ) . to receive ( :issue_repositioning_disabled? ) . and_return ( true )
2021-04-09 18:09:24 +00:00
allow ( helper ) . to receive ( :url_for ) . and_return ( '#' )
2021-04-01 18:13:56 +00:00
expected = {
2021-04-27 12:10:12 +00:00
autocomplete_award_emojis_path : autocomplete_award_emojis_path ,
2021-04-01 18:13:56 +00:00
calendar_path : '#' ,
can_bulk_update : 'true' ,
can_edit : 'true' ,
2021-04-09 18:09:24 +00:00
can_import_issues : 'true' ,
2021-09-16 15:12:47 +00:00
email : current_user & . notification_email_or_default ,
2021-04-28 18:10:12 +00:00
emails_help_page_path : help_page_path ( 'development/emails' , anchor : 'email-namespace' ) ,
2021-04-09 18:09:24 +00:00
empty_state_svg_path : '#' ,
2021-04-01 18:13:56 +00:00
export_csv_path : export_csv_project_issues_path ( project ) ,
2021-09-01 12:10:15 +00:00
full_path : project . full_path ,
has_any_issues : project_issues ( project ) . exists? . to_s ,
2021-04-01 18:13:56 +00:00
import_csv_issues_path : '#' ,
2021-04-28 18:10:12 +00:00
initial_email : project . new_issuable_address ( current_user , 'issue' ) ,
2022-02-04 03:15:11 +00:00
initial_sort : current_user & . user_preference & . issues_sort ,
2021-12-16 18:14:09 +00:00
is_anonymous_search_disabled : 'true' ,
2021-11-18 18:14:27 +00:00
is_issue_repositioning_disabled : 'true' ,
2021-09-15 12:11:13 +00:00
is_project : 'true' ,
2022-06-01 18:09:44 +00:00
is_public_visibility_restricted : Gitlab :: CurrentSettings . restricted_visibility_levels ? 'false' : '' ,
2021-04-09 18:09:24 +00:00
is_signed_in : current_user . present? . to_s ,
2021-08-16 15:10:05 +00:00
jira_integration_path : help_page_url ( 'integration/jira/issues' , anchor : 'view-jira-issues' ) ,
2021-04-28 18:10:12 +00:00
markdown_help_path : help_page_path ( 'user/markdown' ) ,
2021-04-01 18:13:56 +00:00
max_attachment_size : number_to_human_size ( Gitlab :: CurrentSettings . max_attachment_size . megabytes ) ,
2022-03-17 09:07:30 +00:00
new_issue_path : new_project_issue_path ( project ) ,
2021-04-01 18:13:56 +00:00
project_import_jira_path : project_import_jira_path ( project ) ,
2021-04-28 18:10:12 +00:00
quick_actions_help_path : help_page_path ( 'user/project/quick_actions' ) ,
2021-10-27 12:09:41 +00:00
releases_path : project_releases_path ( project , format : :json ) ,
2021-04-28 18:10:12 +00:00
reset_path : new_issuable_address_project_path ( project , issuable_type : 'issue' ) ,
2021-04-01 18:13:56 +00:00
rss_path : '#' ,
2021-04-09 18:09:24 +00:00
show_new_issue_link : 'true' ,
sign_in_path : new_user_session_path
2021-04-01 18:13:56 +00:00
}
2022-03-17 09:07:30 +00:00
expect ( helper . project_issues_list_data ( project , current_user ) ) . to include ( expected )
2021-04-01 18:13:56 +00:00
end
end
2021-09-15 12:11:13 +00:00
describe '#project_issues_list_data' do
2021-12-16 18:14:09 +00:00
before do
stub_feature_flags ( disable_anonymous_search : true )
end
2021-04-01 18:13:56 +00:00
context 'when user is signed in' do
it_behaves_like 'issues list data' do
let ( :current_user ) { double . as_null_object }
end
end
context 'when user is anonymous' do
it_behaves_like 'issues list data' do
let ( :current_user ) { nil }
end
end
2022-06-01 18:09:44 +00:00
context 'when restricted visibility levels is nil' do
before do
allow ( Gitlab :: CurrentSettings ) . to receive ( :restricted_visibility_levels ) . and_return ( nil )
end
it_behaves_like 'issues list data' do
let ( :current_user ) { double . as_null_object }
end
end
2021-09-15 12:11:13 +00:00
end
describe '#group_issues_list_data' do
let ( :group ) { create ( :group ) }
let ( :current_user ) { double . as_null_object }
it 'returns expected result' do
allow ( helper ) . to receive ( :current_user ) . and_return ( current_user )
allow ( helper ) . to receive ( :can? ) . and_return ( true )
allow ( helper ) . to receive ( :image_path ) . and_return ( '#' )
allow ( helper ) . to receive ( :url_for ) . and_return ( '#' )
2022-02-02 18:15:35 +00:00
assign ( :has_issues , false )
assign ( :has_projects , true )
2021-09-15 12:11:13 +00:00
expected = {
autocomplete_award_emojis_path : autocomplete_award_emojis_path ,
calendar_path : '#' ,
2022-05-31 06:09:17 +00:00
can_create_projects : 'true' ,
2021-09-15 12:11:13 +00:00
empty_state_svg_path : '#' ,
full_path : group . full_path ,
2022-02-02 18:15:35 +00:00
has_any_issues : false . to_s ,
has_any_projects : true . to_s ,
2021-09-15 12:11:13 +00:00
is_signed_in : current_user . present? . to_s ,
jira_integration_path : help_page_url ( 'integration/jira/issues' , anchor : 'view-jira-issues' ) ,
2022-05-31 06:09:17 +00:00
new_project_path : new_project_path ( namespace_id : group . id ) ,
2021-09-15 12:11:13 +00:00
rss_path : '#' ,
sign_in_path : new_user_session_path
}
2022-02-02 18:15:35 +00:00
expect ( helper . group_issues_list_data ( group , current_user ) ) . to include ( expected )
2021-09-15 12:11:13 +00:00
end
2022-03-22 12:07:28 +00:00
end
describe '#issues_form_data' do
it 'returns expected result' do
expected = {
new_issue_path : new_project_issue_path ( project )
}
expect ( helper . issues_form_data ( project ) ) . to include ( expected )
end
2021-04-01 18:13:56 +00:00
end
2021-05-17 18:10:42 +00:00
describe '#issue_manual_ordering_class' do
context 'when sorting by relative position' do
before do
assign ( :sort , 'relative_position' )
end
it 'returns manual ordering class' do
2021-08-16 12:09:17 +00:00
expect ( helper . issue_manual_ordering_class ) . to eq ( 'manual-ordering' )
2021-05-17 18:10:42 +00:00
end
context 'when manual sorting disabled' do
before do
allow ( helper ) . to receive ( :issue_repositioning_disabled? ) . and_return ( true )
end
it 'returns nil' do
expect ( helper . issue_manual_ordering_class ) . to eq ( nil )
end
end
end
end
describe '#issue_repositioning_disabled?' do
let_it_be ( :group ) { create ( :group ) }
let_it_be ( :project ) { create ( :project , group : group ) }
subject { helper . issue_repositioning_disabled? }
context 'for project' do
before do
assign ( :project , project )
end
it { is_expected . to eq ( false ) }
context 'when block_issue_repositioning feature flag is enabled' do
before do
stub_feature_flags ( block_issue_repositioning : group )
end
it { is_expected . to eq ( true ) }
end
end
context 'for group' do
before do
assign ( :group , group )
end
it { is_expected . to eq ( false ) }
context 'when block_issue_repositioning feature flag is enabled' do
before do
stub_feature_flags ( block_issue_repositioning : group )
end
it { is_expected . to eq ( true ) }
end
end
end
2021-08-25 09:10:52 +00:00
2022-05-25 15:08:05 +00:00
describe '#status_box_class' do
2022-05-26 15:08:29 +00:00
context 'when object is expired' do
it 'returns orange background' do
milestone = build ( :milestone , due_date : Date . today . prev_month )
expect ( helper . status_box_class ( milestone ) ) . to eq ( 'gl-bg-orange-500' )
2022-05-25 15:08:05 +00:00
end
end
2022-05-26 15:08:29 +00:00
context 'when object is merged' do
it 'returns blue background' do
merge_request = build ( :merge_request , :merged )
expect ( helper . status_box_class ( merge_request ) ) . to eq ( 'badge-info' )
2022-05-25 15:08:05 +00:00
end
2022-05-26 15:08:29 +00:00
end
2022-05-25 15:08:05 +00:00
2022-05-26 15:08:29 +00:00
context 'when object is closed' do
it 'returns red background' do
merge_request = build ( :merge_request , :closed )
expect ( helper . status_box_class ( merge_request ) ) . to eq ( 'badge-danger' )
2022-05-25 15:08:05 +00:00
end
2022-05-26 15:08:29 +00:00
end
2022-05-25 15:08:05 +00:00
2022-05-26 15:08:29 +00:00
context 'when object is upcoming' do
it 'returns gray background' do
milestone = build ( :milestone , start_date : Date . today . next_month )
expect ( helper . status_box_class ( milestone ) ) . to eq ( 'gl-bg-gray-500' )
2022-05-25 15:08:05 +00:00
end
2022-05-26 15:08:29 +00:00
end
2022-05-25 15:08:05 +00:00
2022-05-26 15:08:29 +00:00
context 'when object is opened' do
it 'returns green background' do
merge_request = build ( :merge_request , :opened )
expect ( helper . status_box_class ( merge_request ) ) . to eq ( 'badge-success' )
2022-05-25 15:08:05 +00:00
end
end
end
2021-08-25 09:10:52 +00:00
describe '#issue_hidden?' do
context 'when issue is hidden' do
let_it_be ( :banned_user ) { build ( :user , :banned ) }
let_it_be ( :hidden_issue ) { build ( :issue , author : banned_user ) }
context 'when `ban_user_feature_flag` feature flag is enabled' do
it 'returns `true`' do
expect ( helper . issue_hidden? ( hidden_issue ) ) . to eq ( true )
end
end
context 'when `ban_user_feature_flag` feature flag is disabled' do
before do
stub_feature_flags ( ban_user_feature_flag : false )
end
it 'returns `false`' do
expect ( helper . issue_hidden? ( hidden_issue ) ) . to eq ( false )
end
end
end
context 'when issue is not hidden' do
it 'returns `false`' do
expect ( helper . issue_hidden? ( issue ) ) . to eq ( false )
end
end
end
describe '#hidden_issue_icon' do
let_it_be ( :banned_user ) { build ( :user , :banned ) }
let_it_be ( :hidden_issue ) { build ( :issue , author : banned_user ) }
let_it_be ( :mock_svg ) { '<svg></svg>' . html_safe }
before do
allow ( helper ) . to receive ( :sprite_icon ) . and_return ( mock_svg )
end
context 'when issue is hidden' do
it 'returns icon with tooltip' do
expect ( helper . hidden_issue_icon ( hidden_issue ) ) . to eq ( " <span class= \" has-tooltip \" title= \" This issue is hidden because its author has been banned \" > #{ mock_svg } </span> " )
end
end
context 'when issue is not hidden' do
it 'returns `nil`' do
expect ( helper . hidden_issue_icon ( issue ) ) . to be_nil
end
end
end
2013-02-11 13:32:29 +00:00
end