Show the status of a user in interactions
The status is shown for - The author of a commit when viewing a commit - Notes on a commit (regular/diff) - The user that triggered a pipeline when viewing a pipeline - The author of a merge request when viewing a merge request - The author of notes on a merge request (regular/diff) - The author of an issue when viewing an issue - The author of notes on an issue - The author of a snippet when viewing a snippet - The author of notes on a snippet - A user's profile page - The list of members of a group/user
This commit is contained in:
parent
b4c4b48a8c
commit
f1d3ea63cf
|
|
@ -74,6 +74,9 @@ export default {
|
|||
</div>
|
||||
<a :href="author.path">
|
||||
<span class="note-header-author-name">{{ author.name }}</span>
|
||||
<span
|
||||
v-if="author.status_tooltip_html"
|
||||
v-html="author.status_tooltip_html"></span>
|
||||
<span class="note-headline-light">
|
||||
@{{ author.username }}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -113,6 +113,9 @@ export default {
|
|||
|
||||
{{ user.name }}
|
||||
</a>
|
||||
<span
|
||||
v-if="user.status_tooltip_html"
|
||||
v-html="user.status_tooltip_html"></span>
|
||||
</template>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,18 @@ module MembersPresentation
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
def present_members(members)
|
||||
preload_associations(members)
|
||||
Gitlab::View::Presenter::Factory.new(
|
||||
members,
|
||||
current_user: current_user,
|
||||
presenter_class: MembersPresenter
|
||||
).fabricate!
|
||||
end
|
||||
|
||||
def preload_associations(members)
|
||||
ActiveRecord::Associations::Preloader.new.preload(members, :user)
|
||||
ActiveRecord::Associations::Preloader.new.preload(members, :source)
|
||||
ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :status)
|
||||
ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :u2f_registrations)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
module MembershipActions
|
||||
include MembersPresentation
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def create
|
||||
|
|
@ -20,6 +21,7 @@ module MembershipActions
|
|||
.execute(member)
|
||||
.present(current_user: current_user)
|
||||
|
||||
present_members([member])
|
||||
respond_to do |format|
|
||||
format.js { render 'shared/members/update', locals: { member: member } }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module NotesActions
|
|||
@note = Notes::CreateService.new(note_project, current_user, create_params).execute
|
||||
|
||||
if @note.is_a?(Note)
|
||||
Notes::RenderService.new(current_user).execute([@note])
|
||||
prepare_notes_for_rendering([@note], noteable)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
|
|
@ -56,7 +56,7 @@ module NotesActions
|
|||
@note = Notes::UpdateService.new(project, current_user, note_params).execute(note)
|
||||
|
||||
if @note.is_a?(Note)
|
||||
Notes::RenderService.new(current_user).execute([@note])
|
||||
prepare_notes_for_rendering([@note])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ module RendersNotes
|
|||
preload_noteable_for_regular_notes(notes)
|
||||
preload_max_access_for_authors(notes, @project)
|
||||
preload_first_time_contribution_for_authors(noteable, notes)
|
||||
preload_author_status(notes)
|
||||
Notes::RenderService.new(current_user).execute(notes)
|
||||
|
||||
notes
|
||||
|
|
@ -28,4 +29,8 @@ module RendersNotes
|
|||
|
||||
notes.each {|n| n.specialize_for_first_contribution!(noteable)}
|
||||
end
|
||||
|
||||
def preload_author_status(notes)
|
||||
ActiveRecord::Associations::Preloader.new.preload(notes, { author: :status })
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
@members = @members.page(params[:page]).per(50)
|
||||
@members = present_members(@members.includes(:user))
|
||||
@members = present_members(@members)
|
||||
|
||||
@requesters = present_members(
|
||||
AccessRequestsFinder.new(@group).execute(current_user))
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
apply_diff_view_cookie!
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render }
|
||||
format.html do
|
||||
render
|
||||
end
|
||||
format.diff do
|
||||
send_git_diff(@project.repository, @commit.diff_refs)
|
||||
end
|
||||
|
|
@ -124,7 +126,10 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def commit
|
||||
@noteable = @commit ||= @project.commit_by(oid: params[:id])
|
||||
@noteable = @commit ||= @project.commit_by(oid: params[:id]).tap do |commit|
|
||||
# preload author and their status for rendering
|
||||
commit&.author&.status
|
||||
end
|
||||
end
|
||||
|
||||
def define_commit_vars
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
return @issue if defined?(@issue)
|
||||
|
||||
# The Sortable default scope causes performance issues when used with find_by
|
||||
@issuable = @noteable = @issue ||= @project.issues.where(iid: params[:id]).reorder(nil).take!
|
||||
@issuable = @noteable = @issue ||= @project.issues.includes(author: :status).where(iid: params[:id]).reorder(nil).take!
|
||||
@note = @project.notes.new(noteable: @issuable)
|
||||
|
||||
return render_404 unless can?(current_user, :read_issue, @issue)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
|
|||
private
|
||||
|
||||
def merge_request
|
||||
@issuable = @merge_request ||= @project.merge_requests.find_by!(iid: params[:id])
|
||||
@issuable = @merge_request ||= @project.merge_requests.includes(author: :status).find_by!(iid: params[:id])
|
||||
end
|
||||
|
||||
def merge_request_params
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
class Projects::NotesController < Projects::ApplicationController
|
||||
include RendersNotes
|
||||
include NotesActions
|
||||
include NotesHelper
|
||||
include ToggleAwardEmoji
|
||||
|
|
@ -53,7 +54,7 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
private
|
||||
|
||||
def render_json_with_notes_serializer
|
||||
Notes::RenderService.new(current_user).execute([note])
|
||||
prepare_notes_for_rendering([note])
|
||||
|
||||
render json: note_serializer.represent(note)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -161,7 +161,11 @@ class Projects::PipelinesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def pipeline
|
||||
@pipeline ||= project.pipelines.find_by!(id: params[:id]).present(current_user: current_user)
|
||||
@pipeline ||= project
|
||||
.pipelines
|
||||
.includes(user: :status)
|
||||
.find_by!(id: params[:id])
|
||||
.present(current_user: current_user)
|
||||
end
|
||||
|
||||
def commit
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
protected
|
||||
|
||||
def snippet
|
||||
@snippet ||= @project.snippets.find(params[:id])
|
||||
@snippet ||= @project.snippets.inc_relations_for_view.find(params[:id])
|
||||
end
|
||||
alias_method :awardable, :snippet
|
||||
alias_method :spammable, :snippet
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class Snippets::NotesController < ApplicationController
|
|||
private
|
||||
|
||||
def note
|
||||
@note ||= snippet.notes.find(params[:id])
|
||||
@note ||= snippet.notes.inc_relations_for_view.find(params[:id])
|
||||
end
|
||||
alias_method :awardable, :note
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class SnippetsController < ApplicationController
|
|||
protected
|
||||
|
||||
def snippet
|
||||
@snippet ||= PersonalSnippet.find_by(id: params[:id])
|
||||
@snippet ||= PersonalSnippet.inc_relations_for_view.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
alias_method :awardable, :snippet
|
||||
|
|
|
|||
|
|
@ -159,6 +159,12 @@ module IssuablesHelper
|
|||
output << content_tag(:strong) do
|
||||
author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "d-none d-sm-inline", tooltip: true)
|
||||
author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "d-block d-sm-none")
|
||||
|
||||
if status = user_status(issuable.author)
|
||||
author_output << "  #{status}".html_safe
|
||||
end
|
||||
|
||||
author_output
|
||||
end
|
||||
|
||||
output << " ".html_safe
|
||||
|
|
|
|||
|
|
@ -39,6 +39,24 @@ module UsersHelper
|
|||
"access:#{max_project_member_access(project)}"
|
||||
end
|
||||
|
||||
def user_status(user)
|
||||
return unless user
|
||||
|
||||
unless user.association(:status).loaded?
|
||||
exception = RuntimeError.new("Status was not preloaded")
|
||||
Gitlab::Sentry.track_exception(exception, extra: { user: user.inspect })
|
||||
end
|
||||
|
||||
return unless user.status
|
||||
|
||||
content_tag :span,
|
||||
class: 'user-status-emoji has-tooltip',
|
||||
title: user.status.message_html,
|
||||
data: { html: true, placement: 'top' } do
|
||||
emoji_icon user.status.emoji
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_profile_tabs
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ class Note < ActiveRecord::Base
|
|||
scope :inc_author_project, -> { includes(:project, :author) }
|
||||
scope :inc_author, -> { includes(:author) }
|
||||
scope :inc_relations_for_view, -> do
|
||||
includes(:project, :author, :updated_by, :resolved_by, :award_emoji,
|
||||
includes(:project, { author: :status }, :updated_by, :resolved_by, :award_emoji,
|
||||
:system_note_metadata, :note_diff_file)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ class Snippet < ActiveRecord::Base
|
|||
scope :are_public, -> { where(visibility_level: Snippet::PUBLIC) }
|
||||
scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) }
|
||||
scope :fresh, -> { order("created_at DESC") }
|
||||
scope :inc_relations_for_view, -> { includes(author: :status) }
|
||||
|
||||
participant :author
|
||||
participant :notes_with_associations
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
class UserStatus < ActiveRecord::Base
|
||||
include CacheMarkdownField
|
||||
|
||||
self.primary_key = :user_id
|
||||
|
||||
DEFAULT_EMOJI = 'speech_balloon'.freeze
|
||||
|
||||
belongs_to :user
|
||||
|
||||
validates :user, presence: true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module UserStatusTooltip
|
||||
extend ActiveSupport::Concern
|
||||
include ActionView::Helpers::TagHelper
|
||||
include ActionView::Context
|
||||
include EmojiHelper
|
||||
include UsersHelper
|
||||
|
||||
included do
|
||||
expose :user_status_if_loaded, as: :status_tooltip_html
|
||||
|
||||
def user_status_if_loaded
|
||||
return nil unless object.association(:status).loaded?
|
||||
|
||||
user_status(object)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class UserEntity < API::Entities::UserBasic
|
||||
include RequestAwareEntity
|
||||
include UserStatusTooltip
|
||||
|
||||
expose :path do |user|
|
||||
user_path(user)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ module Users
|
|||
private
|
||||
|
||||
def set_status
|
||||
params[:emoji] = UserStatus::DEFAULT_EMOJI if params[:emoji].blank?
|
||||
user_status.update(params)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
= author_avatar(@commit, size: 24, has_tooltip: false)
|
||||
%strong
|
||||
= commit_author_link(@commit, avatar: true, size: 24)
|
||||
= user_status(@commit.author)
|
||||
- if @commit.different_committer?
|
||||
%span.light= _('Committed by')
|
||||
%strong
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
= image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: ''
|
||||
.user-info
|
||||
= link_to user.name, user_path(user), class: 'member'
|
||||
= user_status(user)
|
||||
%span.cgray= user.to_reference
|
||||
|
||||
- if user == current_user
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@
|
|||
.note-header
|
||||
.note-header-info
|
||||
%a{ href: user_path(note.author) }
|
||||
%span.note-header-author-name= sanitize(note.author.name)
|
||||
%span.note-header-author-name
|
||||
= sanitize(note.author.name)
|
||||
= user_status(note.author)
|
||||
%span.note-headline-light
|
||||
= note.author.to_reference
|
||||
%span.note-headline-light
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
Authored
|
||||
= time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
|
||||
by #{link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title", avatar_class: "d-none d-sm-inline")}
|
||||
= user_status(@snippet.author)
|
||||
|
||||
.detail-page-header-actions
|
||||
- if @snippet.project_id?
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@
|
|||
.cover-title
|
||||
= @user.name
|
||||
|
||||
- if @user.status
|
||||
.cover-status
|
||||
= emoji_icon(@user.status.emoji)
|
||||
= markdown_field(@user.status, :message)
|
||||
|
||||
.cover-desc.member-date
|
||||
%p
|
||||
%span.middle-dot-divider
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Users can set a status message and emoji
|
||||
merge_request: 20614
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -993,6 +993,29 @@ describe Projects::IssuesController do
|
|||
expect(json_response.first.keys).to match_array(%w[id reply_id expanded notes diff_discussion discussion_path individual_note resolvable resolved resolved_at resolved_by resolved_by_push commit_id for_commit project_id])
|
||||
end
|
||||
|
||||
it 'renders the author status html if there is a status' do
|
||||
create(:user_status, user: discussion.author)
|
||||
|
||||
get :discussions, namespace_id: project.namespace, project_id: project, id: issue.iid
|
||||
|
||||
note_json = json_response.first['notes'].first
|
||||
|
||||
expect(note_json['author']['status_tooltip_html']).to be_present
|
||||
end
|
||||
|
||||
it 'does not cause an extra query for the status' do
|
||||
control = ActiveRecord::QueryRecorder.new do
|
||||
get :discussions, namespace_id: project.namespace, project_id: project, id: issue.iid
|
||||
end
|
||||
|
||||
create(:user_status, user: discussion.author)
|
||||
second_discussion = create(:discussion_note_on_issue, noteable: issue, project: issue.project, author: create(:user))
|
||||
create(:user_status, user: second_discussion.author)
|
||||
|
||||
expect { get :discussions, namespace_id: project.namespace, project_id: project, id: issue.iid }
|
||||
.not_to exceed_query_limit(control)
|
||||
end
|
||||
|
||||
context 'with cross-reference system note', :request_store do
|
||||
let(:new_issue) { create(:issue) }
|
||||
let(:cross_reference) { "mentioned in #{new_issue.to_reference(issue.project)}" }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ describe 'Groups > Members > List members' do
|
|||
let(:nested_group) { create(:group, parent: group) }
|
||||
|
||||
before do
|
||||
gitlab_sign_in(user1)
|
||||
sign_in(user1)
|
||||
end
|
||||
|
||||
it 'show members from current group and parent', :nested_groups do
|
||||
|
|
@ -32,6 +32,18 @@ describe 'Groups > Members > List members' do
|
|||
expect(second_row).to be_blank
|
||||
end
|
||||
|
||||
describe 'showing status of members' do
|
||||
before do
|
||||
group.add_developer(user2)
|
||||
end
|
||||
|
||||
subject { visit group_group_members_path(group) }
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { user2 }
|
||||
end
|
||||
end
|
||||
|
||||
def first_row
|
||||
page.all('ul.content-list > li')[0]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'Project > Commit > View user status' do
|
||||
include RepoHelpers
|
||||
|
||||
set(:project) { create(:project, :repository) }
|
||||
set(:user) { create(:user) }
|
||||
let(:commit_author) { create(:user, email: sample_commit.author_email) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
project.add_developer(user)
|
||||
end
|
||||
|
||||
subject { visit(project_commit_path(project, sample_commit.id)) }
|
||||
|
||||
describe 'status for the commit author' do
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { commit_author }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'status for a comment on the commit' do
|
||||
let(:note) { create(:note, :on_commit, project: project) }
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { note.author }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'status for a diff note on the commit' do
|
||||
let(:note) { create(:diff_note_on_commit, project: project) }
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { note.author }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -29,4 +29,22 @@ describe "User views issue" do
|
|||
expect(page).not_to have_link('Close issue')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'user status' do
|
||||
subject { visit(project_issue_path(project, issue)) }
|
||||
|
||||
describe 'showing status of the author of the issue' do
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { issue.author }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'showing status of a user who commented on an issue', :js do
|
||||
let!(:note) { create(:note, noteable: issue, project: project, author: user_with_status) }
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { create(:user) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -87,4 +87,12 @@ describe 'Projects members' do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'showing status of members' do
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { developer }
|
||||
|
||||
subject { visit project_settings_members_path(project) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'Project > Merge request > View user status' do
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
let(:merge_request) do
|
||||
create(:merge_request, source_project: project, target_project: project, author: create(:user))
|
||||
end
|
||||
|
||||
subject { visit merge_request_path(merge_request) }
|
||||
|
||||
describe 'the status of the merge request author' do
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { merge_request.author }
|
||||
end
|
||||
end
|
||||
|
||||
context 'for notes', :js do
|
||||
describe 'the status of the author of a note on a merge request' do
|
||||
let(:note) { create(:note, noteable: merge_request, project: project, author: create(:user)) }
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { note.author }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'the status of the author of a diff note on a merge request' do
|
||||
let(:note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, author: create(:user)) }
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { note.author }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -63,6 +63,12 @@ describe 'Pipeline', :js do
|
|||
expect(page).to have_css('#js-tab-pipeline.active')
|
||||
end
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:user_with_status) { pipeline.user }
|
||||
|
||||
subject { visit project_pipeline_path(project, pipeline) }
|
||||
end
|
||||
|
||||
describe 'pipeline graph' do
|
||||
context 'when pipeline has running builds' do
|
||||
it 'shows a running icon and a cancel action for the running build' do
|
||||
|
|
|
|||
|
|
@ -141,4 +141,16 @@ describe 'Projects > Snippets > Project snippet', :js do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:file_name) { 'ruby-style-guide.md' }
|
||||
let(:content) { project.repository.blob_at('master', 'files/markdown/ruby-style-guide.md').data }
|
||||
|
||||
let(:user_with_status) { snippet.author }
|
||||
|
||||
subject do
|
||||
visit project_snippet_path(project, snippet)
|
||||
wait_for_requests
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ describe 'Comments on personal snippets', :js do
|
|||
before do
|
||||
sign_in user
|
||||
visit snippet_path(snippet)
|
||||
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
subject { page }
|
||||
|
|
@ -42,6 +44,15 @@ describe 'Comments on personal snippets', :js do
|
|||
expect(page).to have_selector('.note-emoji-button')
|
||||
end
|
||||
end
|
||||
|
||||
it 'shows the status of a note author' do
|
||||
status = create(:user_status, user: user)
|
||||
visit snippet_path(snippet)
|
||||
|
||||
within("#note_#{snippet_notes[0].id}") do
|
||||
expect(page).to show_user_status(status)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when submitting a note' do
|
||||
|
|
|
|||
|
|
@ -155,4 +155,12 @@ describe 'Snippet', :js do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'showing user status' do
|
||||
let(:file_name) { 'popen.rb' }
|
||||
let(:content) { project.repository.blob_at('master', 'files/ruby/popen.rb').data }
|
||||
let(:user_with_status) { snippet.author }
|
||||
|
||||
subject { visit snippet_path(snippet) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,6 +53,14 @@ describe 'User page' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'shows the status if there was one' do
|
||||
create(:user_status, user: user, message: "Working hard!")
|
||||
|
||||
visit(user_path(user))
|
||||
|
||||
expect(page).to have_content("Working hard!")
|
||||
end
|
||||
|
||||
context 'signup disabled' do
|
||||
it 'shows the sign in link' do
|
||||
stub_application_setting(signup_enabled: false)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec::Matchers.define :show_user_status do |status|
|
||||
match do |page|
|
||||
expect(page).to have_selector(".user-status-emoji[title='#{status.message}']")
|
||||
|
||||
# The same user status might be displayed multiple times on the page
|
||||
emoji_span = page.first(".user-status-emoji[title='#{status.message}']")
|
||||
page.within(emoji_span) do
|
||||
expect(page).to have_emoji(status.emoji)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
shared_examples 'showing user status' do
|
||||
let!(:status) { create(:user_status, user: user_with_status, emoji: 'smirk', message: 'Authoring this object') }
|
||||
|
||||
it 'shows the status' do
|
||||
subject
|
||||
|
||||
expect(page).to show_user_status(status)
|
||||
end
|
||||
end
|
||||
|
|
@ -17,6 +17,13 @@ describe 'projects/merge_requests/show.html.haml' do
|
|||
author: user)
|
||||
end
|
||||
|
||||
def preload_view_requirements
|
||||
# This will load the status fields of the author of the note and merge request
|
||||
# to avoid queries in when rendering the view being tested.
|
||||
closed_merge_request.author.status
|
||||
note.author.status
|
||||
end
|
||||
|
||||
before do
|
||||
assign(:project, project)
|
||||
assign(:merge_request, closed_merge_request)
|
||||
|
|
@ -26,6 +33,8 @@ describe 'projects/merge_requests/show.html.haml' do
|
|||
assign(:notes, [])
|
||||
assign(:pipelines, Ci::Pipeline.none)
|
||||
|
||||
preload_view_requirements
|
||||
|
||||
allow(view).to receive_messages(current_user: user,
|
||||
can?: true,
|
||||
current_application_settings: Gitlab::CurrentSettings.current_application_settings)
|
||||
|
|
@ -42,6 +51,7 @@ describe 'projects/merge_requests/show.html.haml' do
|
|||
it 'does not show the "Reopen" button when the source project does not exist' do
|
||||
unlink_project.execute
|
||||
closed_merge_request.reload
|
||||
preload_view_requirements
|
||||
|
||||
render
|
||||
|
||||
|
|
@ -56,6 +66,7 @@ describe 'projects/merge_requests/show.html.haml' do
|
|||
forked_project.destroy
|
||||
# Reload merge request so MergeRequest#source_project turns to `nil`
|
||||
closed_merge_request.reload
|
||||
preload_view_requirements
|
||||
|
||||
render
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue