Commit 52bcd7af authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents e91fd7f9 6ab0df04
......@@ -47,6 +47,7 @@ export default {
{ variant: 'success' },
{ category: 'primary' },
{ 'data-testid': 'submit-commit' },
{ 'data-qa-selector': 'submit_commit_button' },
],
},
actionCancel: {
......
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import { referenceQueries } from '~/sidebar/constants';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CopyableField from '~/vue_shared/components/sidebar/copyable_field.vue';
export default {
i18n: {
copyReference: __('Copy reference'),
text: __('Reference'),
},
components: {
ClipboardButton,
GlLoadingIcon,
CopyableField,
},
inject: ['fullPath', 'iid'],
props: {
......@@ -56,31 +50,10 @@ export default {
</script>
<template>
<div class="sub-block">
<clipboard-button
v-if="!isLoading"
:title="$options.i18n.copyReference"
:text="reference"
category="tertiary"
css-class="sidebar-collapsed-icon dont-change-state"
tooltip-placement="left"
/>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-mb-2 hide-collapsed"
>
<span class="gl-overflow-hidden gl-text-overflow-ellipsis gl-white-space-nowrap">
{{ $options.i18n.text }}: {{ reference }}
<gl-loading-icon v-if="isLoading" inline :label="$options.i18n.text" />
</span>
<clipboard-button
v-if="!isLoading"
:title="$options.i18n.copyReference"
:text="reference"
size="small"
category="tertiary"
css-class="gl-mr-1"
tooltip-placement="left"
/>
</div>
</div>
<copyable-field
class="sub-block"
:is-loading="isLoading"
:name="__('Reference')"
:value="reference"
/>
</template>
......@@ -151,6 +151,7 @@ export default {
v-gl-tooltip.hover
:title="cherryPickTitle"
size="small"
data-qa-selector="cherry_pick_button"
@click="openCherryPickModal"
>
{{ cherryPickLabel }}
......
......@@ -67,7 +67,7 @@ export default {
<div>
<clipboard-button
v-if="!isLoading"
css-class="sidebar-collapsed-icon dont-change-state"
css-class="sidebar-collapsed-icon dont-change-state gl-rounded-0! gl-hover-bg-transparent"
v-bind="clipboardProps"
/>
......
......@@ -24,7 +24,7 @@ module Ci
def execute(params = {})
@metrics.increment_queue_operation(:queue_attempt)
@metrics.observe_queue_time(:process) do
@metrics.observe_queue_time(:process, @runner.runner_type) do
process_queue(params)
end
end
......@@ -128,7 +128,7 @@ module Ci
# rubocop: enable CodeReuse/ActiveRecord
def retrieve_queue(queue_query_proc)
@metrics.observe_queue_time(:retrieve) do
@metrics.observe_queue_time(:retrieve, @runner.runner_type) do
queue_query_proc.call
end
end
......
......@@ -3,7 +3,7 @@
Project: <%= @project.name %> ( <%= project_url(@project) %> )
Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> )
<% if @merge_request -%>
Merge Request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
Merge request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
<% end -%>
Commit: <%= @pipeline.short_sha %> ( <%= commit_url(@pipeline) %> )
......
%p
Merge Request #{merge_request_reference_link(@merge_request)}
Merge request #{merge_request_reference_link(@merge_request)}
was closed by #{sanitize_name(@updated_by.name)}
Merge Request #{@merge_request.to_reference} was closed by #{sanitize_name(@updated_by.name)}
Merge request #{@merge_request.to_reference} was closed by #{sanitize_name(@updated_by.name)}
Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
......
%p
Merge Request #{merge_request_reference_link(@merge_request)}
Merge request #{merge_request_reference_link(@merge_request)}
was #{@mr_status} by #{sanitize_name(@updated_by.name)}
Merge Request #{@merge_request.to_reference} was #{@mr_status} by #{sanitize_name(@updated_by.name)}
Merge request #{@merge_request.to_reference} was #{@mr_status} by #{sanitize_name(@updated_by.name)}
Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
......
%p
Merge Request #{merge_request_reference_link(@merge_request)} can no longer be merged due to conflict.
Merge request #{merge_request_reference_link(@merge_request)} can no longer be merged due to conflict.
Merge Request #{@merge_request.to_reference} can no longer be merged due to conflict.
Merge request #{@merge_request.to_reference} can no longer be merged due to conflict.
Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
......
Merge Request #{@merge_request.to_reference} was scheduled to merge after pipeline succeeds by #{sanitize_name(@mwps_set_by.name)}
Merge request #{@merge_request.to_reference} was scheduled to merge after pipeline succeeds by #{sanitize_name(@mwps_set_by.name)}
Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
Merge request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
......
%p
Merge Request #{merge_request_reference_link(@merge_request)} was merged
Merge request #{merge_request_reference_link(@merge_request)} was merged
Merge Request #{@merge_request.to_reference} was merged
Merge request #{@merge_request.to_reference} was merged
Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
......
%p
You have been mentioned in Merge Request #{merge_request_reference_link(@merge_request)}
You have been mentioned in merge request #{merge_request_reference_link(@merge_request)}
= render template: 'notify/new_merge_request_email'
You have been mentioned in Merge Request <%= @merge_request.to_reference %>
You have been mentioned in merge request <%= @merge_request.to_reference %>
<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
......
......@@ -3,7 +3,7 @@ Pipeline #<%= @pipeline.id %> has failed!
Project: <%= @project.name %> ( <%= project_url(@project) %> )
Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> )
<% if @merge_request -%>
Merge Request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
Merge request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
<% end -%>
Commit: <%= @pipeline.short_sha %> ( <%= commit_url(@pipeline) %> )
......
#{sanitize_name(@updated_by_user.name)} pushed new commits to merge request #{@merge_request.to_reference}
Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
\
- if @existing_commits.any?
- count = @existing_commits.size
......
Reassigned Merge Request <%= @merge_request.iid %>
Reassigned merge request <%= @merge_request.iid %>
<%= url_for([@merge_request.project, @merge_request, { only_path: false }]) %>
......
%p
All discussions on Merge Request #{merge_request_reference_link(@merge_request)}
All discussions on merge request #{merge_request_reference_link(@merge_request)}
were resolved by #{sanitize_name(@resolved_by.name)}
All discussions on Merge Request <%= @merge_request.to_reference %> were resolved by <%= sanitize_name(@resolved_by.name) %>
All discussions on merge request <%= @merge_request.to_reference %> were resolved by <%= sanitize_name(@resolved_by.name) %>
<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
......@@ -18,14 +18,14 @@
- elsif @project && can?(current_user, :read_issue, @project)
- issues_link = link_to s_('WikiEmptyIssueMessage|issue tracker'), project_issues_path(@project)
- new_issue_link = link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn gl-button btn-confirm', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement')
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_logout_empty.svg' } do
%h4
= messages.dig(:issuable, :title)
%p.text-left
= messages.dig(:issuable, :body).html_safe % { issues_link: issues_link }
= new_issue_link
- if show_new_issue_link?(@project)
= link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn gl-button btn-confirm', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement')
- else
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_logout_empty.svg' } do
......
......@@ -6,7 +6,7 @@
= form_tag [:bulk_update, @project, type], method: :post, class: "bulk-update" do
.block.issuable-sidebar-header
.filter-item.inline.update-issues-btn.float-left
= button_tag _('Update all'), class: "gl-button btn update-selected-issues btn-info", disabled: true
= button_tag _('Update all'), class: "gl-button btn update-selected-issues btn-confirm", disabled: true
= button_tag _('Cancel'), class: "gl-button btn btn-default js-bulk-update-menu-hide float-right"
- if params[:state] != 'merged'
.block
......
---
title: Remove deprecated info button from issue list view
merge_request: 57762
author:
type: other
---
redirect_to: 'index.md'
---
This document was moved to [another location](index.md).
<!-- This redirect file can be deleted after 2021-06-30. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
......@@ -10,7 +10,7 @@ export const returnToPreviousPageFactory = ({
onDemandScansPath,
profilesLibraryPath,
urlParamKey,
}) => (gid) => {
}) => ({ id } = {}) => {
// when previous page is not On-demand scans page
// redirect user to profiles library page
if (!document.referrer?.includes(onDemandScansPath)) {
......@@ -20,9 +20,9 @@ export const returnToPreviousPageFactory = ({
// Otherwise, redirect them back to On-demand scans page
// with corresponding profile id, if available
// for example, /on_demand_scans?site_profile_id=35
const previousPagePath = gid
const previousPagePath = id
? setUrlParams(
{ [urlParamKey]: getIdFromGraphQLId(gid) },
{ [urlParamKey]: getIdFromGraphQLId(id) },
relativePathToAbsolute(onDemandScansPath, getBaseURL()),
)
: onDemandScansPath;
......
......@@ -11,7 +11,6 @@ import {
} from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import { isEqual } from 'lodash';
import { returnToPreviousPageFactory } from 'ee/security_configuration/dast_profiles/redirect';
import { initFormField } from 'ee/security_configuration/utils';
import { serializeFormObject } from '~/lib/utils/forms';
import { __, s__, n__, sprintf } from '~/locale';
......@@ -50,19 +49,16 @@ export default {
type: String,
required: true,
},
profilesLibraryPath: {
type: String,
required: true,
},
onDemandScansPath: {
type: String,
required: true,
},
siteProfile: {
type: Object,
required: false,
default: null,
},
showHeader: {
type: Boolean,
required: false,
default: true,
},
},
data() {
const { name = '', targetUrl = '', excludedUrls = [], auth = {} } = this.siteProfile || {};
......@@ -96,11 +92,6 @@ export default {
token: null,
errorMessage: '',
errors: [],
returnToPreviousPage: returnToPreviousPageFactory({
onDemandScansPath: this.onDemandScansPath,
profilesLibraryPath: this.profilesLibraryPath,
urlParamKey: 'site_profile_id',
}),
};
},
computed: {
......@@ -216,7 +207,9 @@ export default {
this.showErrors({ message: errorMessage, errors });
this.isLoading = false;
} else {
this.returnToPreviousPage(id);
this.$emit('success', {
id,
});
}
},
)
......@@ -234,7 +227,7 @@ export default {
}
},
discard() {
this.returnToPreviousPage();
this.$emit('cancel');
},
captureException(exception) {
Sentry.captureException(exception);
......@@ -265,7 +258,7 @@ export default {
<template>
<gl-form novalidate @submit.prevent="onSubmit">
<h2 class="gl-mb-6">
<h2 v-if="showHeader" class="gl-mb-6">
{{ i18n.title }}
</h2>
......
import Vue from 'vue';
import { returnToPreviousPageFactory } from 'ee/security_configuration/dast_profiles/redirect';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import DastSiteProfileForm from './components/dast_site_profile_form.vue';
import apolloProvider from './graphql/provider';
......@@ -13,14 +14,18 @@ export default () => {
const props = {
fullPath,
profilesLibraryPath,
onDemandScansPath,
};
if (el.dataset.siteProfile) {
props.siteProfile = convertObjectPropsToCamelCase(JSON.parse(el.dataset.siteProfile));
}
const factoryParams = {
onDemandScansPath,
profilesLibraryPath,
urlParamKey: 'site_profile_id',
};
// eslint-disable-next-line no-new
new Vue({
el,
......@@ -28,6 +33,10 @@ export default () => {
render(h) {
return h(DastSiteProfileForm, {
props,
on: {
success: returnToPreviousPageFactory(factoryParams),
cancel: returnToPreviousPageFactory(factoryParams),
},
});
},
});
......
---
title: Hide "Suggest wiki improvement" button from Auditors on project wiki page
merge_request: 56897
author:
type: fixed
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User sees Scanner profile' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository) }
let(:profile_form_path) {new_project_security_configuration_dast_scans_dast_site_profile_path(project)}
let(:profile_library_path) { project_security_configuration_dast_scans_path(project) }
before_all do
project.add_developer(user)
end
before do
sign_in(user)
end
context 'when feature is available' do
before do
stub_licensed_features(security_on_demand_scans: true)
visit(profile_form_path)
end
it 'shows the form' do
expect(page).to have_gitlab_http_status(:ok)
expect(page).to have_content("New site profile")
end
it 'on submit', :js do
fill_in_profile_form
expect(current_path).to eq(profile_library_path)
end
it 'on cancel', :js do
click_button 'Cancel'
expect(current_path).to eq(profile_library_path)
end
end
context 'when feature is not available' do
before do
visit(profile_form_path)
end
it 'renders a 404' do
expect(page).to have_gitlab_http_status(:not_found)
end
end
def fill_in_profile_form
fill_in 'profileName', with: "hello"
fill_in 'targetUrl', with: "https://example.com"
click_button 'Save profile'
wait_for_requests
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Project > User views empty wiki' do
let_it_be(:auditor) { create(:user, auditor: true) }
let_it_be(:project) { create(:project, :private) }
let_it_be(:wiki) { create(:project_wiki, project: project) }
it_behaves_like 'User views empty wiki' do
context 'when signed in user is an Auditor' do
before do
sign_in(auditor)
end
context 'when user is not a member of the project' do
it_behaves_like 'empty wiki message', issuable: true, expect_button: false
end
context 'when user is a member of the project' do
before do
project.add_guest(auditor)
end
it_behaves_like 'empty wiki message', issuable: true, expect_button: true
end
end
end
end
......@@ -53,7 +53,7 @@ describe('DAST Profiles redirector', () => {
});
it('redirects to previous page with id', () => {
factory(2);
factory({ id: 2 });
expect(urlUtility.redirectTo).toHaveBeenCalledWith(
`${onDemandScansPath}?site_profile_id=2`,
);
......
......@@ -13,7 +13,6 @@ import * as responses from 'ee_jest/security_configuration/dast_site_profiles_fo
import { TEST_HOST } from 'helpers/test_constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import * as urlUtility from '~/lib/utils/url_utility';
const localVue = createLocalVue();
localVue.use(VueApollo);
......@@ -134,7 +133,18 @@ describe('DastSiteProfileForm', () => {
it('renders properly', () => {
createComponent();
expect(wrapper.html()).not.toBe('');
expect(findForm().exists()).toBe(true);
expect(findForm().text()).toContain('New site profile');
});
it('when showHeader prop is disabled', () => {
createComponent({
propsData: {
...defaultProps,
showHeader: false,
},
});
expect(findForm().text()).not.toContain('New site profile');
});
describe('target URL input', () => {
......@@ -215,8 +225,6 @@ describe('DastSiteProfileForm', () => {
siteProfile,
},
});
jest.spyOn(urlUtility, 'redirectTo').mockImplementation();
});
it('sets the correct title', () => {
......@@ -260,8 +268,10 @@ describe('DastSiteProfileForm', () => {
});
});
it('redirects to the profiles library', () => {
expect(urlUtility.redirectTo).toHaveBeenCalledWith(profilesLibraryPath);
it('emits success event with correct params', () => {
expect(wrapper.emitted('success')).toBeTruthy();
expect(wrapper.emitted('success')).toHaveLength(1);
expect(wrapper.emitted('success')[0]).toStrictEqual([{ id: '3083' }]);
});
it('does not show an alert', () => {
......@@ -319,9 +329,9 @@ describe('DastSiteProfileForm', () => {
describe('cancellation', () => {
describe('form unchanged', () => {
it('redirects to the profiles library', () => {
it('emits cancel event', () => {
findCancelButton().vm.$emit('click');
expect(urlUtility.redirectTo).toHaveBeenCalledWith(profilesLibraryPath);
expect(wrapper.emitted('cancel')).toBeTruthy();
});
});
......@@ -337,9 +347,9 @@ describe('DastSiteProfileForm', () => {
expect(findCancelModal().vm.show).toHaveBeenCalled();
});
it('redirects to the profiles library if confirmed', () => {
it('emits cancel event', () => {
findCancelModal().vm.$emit('ok');
expect(urlUtility.redirectTo).toHaveBeenCalledWith(profilesLibraryPath);
expect(wrapper.emitted('cancel')).toBeTruthy();
});
});
});
......
......@@ -100,7 +100,7 @@ module Gitlab
self.class.queue_size_total.observe({ runner_type: runner_type }, size_proc.call.to_f)
end
def observe_queue_time(metric)
def observe_queue_time(metric, runner_type)
start_time = ::Gitlab::Metrics::System.monotonic_time
result = yield
......@@ -111,9 +111,9 @@ module Gitlab
case metric
when :process
self.class.queue_iteration_duration_seconds.observe({}, seconds.to_f)
self.class.queue_iteration_duration_seconds.observe({ runner_type: runner_type }, seconds.to_f)
when :retrieve
self.class.queue_retrieval_duration_seconds.observe({}, seconds.to_f)
self.class.queue_retrieval_duration_seconds.observe({ runner_type: runner_type }, seconds.to_f)
else
raise ArgumentError unless Rails.env.production?
end
......
......@@ -500,6 +500,7 @@ module QA
autoload :Wiki, 'qa/page/component/wiki'
autoload :WikiSidebar, 'qa/page/component/wiki_sidebar'
autoload :WikiPageForm, 'qa/page/component/wiki_page_form'
autoload :CommitModal, 'qa/page/component/commit_modal'
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
......
# frozen_string_literal: true
module QA
module Page
module Component
class CommitModal < Page::Base
view 'app/assets/javascripts/projects/commit/components/form_modal.vue' do
element :submit_commit_button, required: true
end
end
end
end
end
......@@ -107,6 +107,10 @@ module QA
element :suggestion_button
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
element :cherry_pick_button
end
def start_review
click_element(:start_review_button)
......@@ -359,6 +363,11 @@ module QA
def apply_suggestions_batch
all_elements(:apply_suggestions_batch_button, minimum: 1).first.click
end
def cherry_pick!
click_element(:cherry_pick_button, Page::Component::CommitModal)
click_element(:submit_commit_button)
end
end
end
end
......
......@@ -35,7 +35,7 @@ module QA
attribute :target do
Repository::ProjectPush.fabricate! do |resource|
resource.project = project
resource.branch_name = project.default_branch
resource.branch_name = target_branch
resource.new_branch = @target_new_branch
resource.remote_branch = target_branch
end
......@@ -62,6 +62,7 @@ module QA
@labels = []
@file_name = "added_file-#{SecureRandom.hex(8)}.txt"
@file_content = "File Added"
@target_branch = "master"
@target_new_branch = true
@no_preparation = false
@wait_for_merge = true
......
# frozen_string_literal: true
module QA
RSpec.describe 'Create' do
describe 'Cherry picking from a merge request' do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project'
project.initialize_with_readme = true
end
end
let(:feature_mr) do
Resource::MergeRequest.fabricate_via_api! do |merge_request|
merge_request.project = project
merge_request.target_branch = 'development'
merge_request.target_new_branch = true
end
end
before do
Flow::Login.sign_in
end
it 'cherry picks a basic merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1616' do
feature_mr.visit!
Page::MergeRequest::Show.perform do |merge_request|
merge_request.merge!
merge_request.cherry_pick!
end
Page::MergeRequest::New.perform do |merge_request|
expect(merge_request).to have_content('The merge request has been successfully cherry-picked')
end
end
end
end
end
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
......@@ -8,18 +7,21 @@ import { IssuableType } from '~/issue_show/constants';
import SidebarReferenceWidget from '~/sidebar/components/reference/sidebar_reference_widget.vue';
import issueReferenceQuery from '~/sidebar/queries/issue_reference.query.graphql';
import mergeRequestReferenceQuery from '~/sidebar/queries/merge_request_reference.query.graphql';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CopyableField from '~/vue_shared/components/sidebar/copyable_field.vue';
import { issueReferenceResponse } from '../../mock_data';
describe('Sidebar Reference Widget', () => {
let wrapper;
let fakeApollo;
const referenceText = 'reference';
const mockReferenceValue = 'reference-1234';
const findCopyableField = () => wrapper.findComponent(CopyableField);
const createComponent = ({
issuableType,
issuableType = IssuableType.Issue,
referenceQuery = issueReferenceQuery,
referenceQueryHandler = jest.fn().mockResolvedValue(issueReferenceResponse(referenceText)),
referenceQueryHandler = jest.fn().mockResolvedValue(issueReferenceResponse(mockReferenceValue)),
} = {}) => {
Vue.use(VueApollo);
......@@ -39,14 +41,20 @@ describe('Sidebar Reference Widget', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('when reference is loading', () => {
it('sets CopyableField `is-loading` prop to `true`', () => {
createComponent({ referenceQueryHandler: jest.fn().mockReturnValue(new Promise(() => {})) });
expect(findCopyableField().props('isLoading')).toBe(true);
});
});
describe.each([
[IssuableType.Issue, issueReferenceQuery],
[IssuableType.MergeRequest, mergeRequestReferenceQuery],
])('when issuableType is %s', (issuableType, referenceQuery) => {
it('displays the reference text', async () => {
it('sets CopyableField `value` prop to reference value', async () => {
createComponent({
issuableType,
referenceQuery,
......@@ -54,40 +62,32 @@ describe('Sidebar Reference Widget', () => {
await waitForPromises();
expect(wrapper.text()).toContain(referenceText);
expect(findCopyableField().props('value')).toBe(mockReferenceValue);
});
it('displays loading icon while fetching and hides clipboard icon', async () => {
createComponent({
issuableType,
referenceQuery,
});
describe('when error occurs', () => {
it('calls createFlash with correct parameters', async () => {
const mockError = new Error('mayday');
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
expect(wrapper.find(ClipboardButton).exists()).toBe(false);
});
createComponent({
issuableType,
referenceQuery,
referenceQueryHandler: jest.fn().mockRejectedValue(mockError),
});
it('calls createFlash with correct parameters', async () => {
const mockError = new Error('mayday');
await waitForPromises();
createComponent({
issuableType,
referenceQuery,
referenceQueryHandler: jest.fn().mockRejectedValue(mockError),
const [
[
{
message,
error: { networkError },
},
],
] = wrapper.emitted('fetch-error');
expect(message).toBe('An error occurred while fetching reference');
expect(networkError).toEqual(mockError);
});
await waitForPromises();
const [
[
{
message,
error: { networkError },
},
],
] = wrapper.emitted('fetch-error');
expect(message).toBe('An error occurred while fetching reference');
expect(networkError).toEqual(mockError);
});
});
});
......@@ -31,7 +31,7 @@ RSpec.describe Emails::MergeRequests do
aggregate_failures do
is_expected.to have_referable_subject(merge_request, reply: true)
is_expected.to have_body_text(project_merge_request_path(project, merge_request))
is_expected.to have_body_text('You have been mentioned in Merge Request')
is_expected.to have_body_text('You have been mentioned in merge request')
is_expected.to have_link(merge_request.to_reference, href: project_merge_request_url(merge_request.target_project, merge_request))
is_expected.to have_text_part_content(assignee.name)
is_expected.to have_text_part_content(reviewer.name)
......
......@@ -615,13 +615,25 @@ module Ci
create(:ci_build, pipeline: pipeline, tag_list: %w[non-matching])
end
it "observes queue size of only matching jobs" do
it 'observes queue size of only matching jobs' do
# pending_job + 2 x matching ones
expect(Gitlab::Ci::Queue::Metrics.queue_size_total).to receive(:observe)
.with({ runner_type: specific_runner.runner_type }, 3)
expect(execute(specific_runner)).to eq(pending_job)
end
it 'observes queue processing time by the runner type' do
expect(Gitlab::Ci::Queue::Metrics.queue_iteration_duration_seconds)
.to receive(:observe)
.with({ runner_type: specific_runner.runner_type }, anything)
expect(Gitlab::Ci::Queue::Metrics.queue_retrieval_duration_seconds)
.to receive(:observe)
.with({ runner_type: specific_runner.runner_type }, anything)
expect(execute(specific_runner)).to eq(pending_job)
end
end
context 'when ci_register_job_temporary_lock is enabled' do
......
......@@ -20,7 +20,7 @@ RSpec.shared_examples 'User views empty wiki' do
end
end
shared_examples 'empty wiki message' do |writable: false, issuable: false, confluence: false|
shared_examples 'empty wiki message' do |writable: false, issuable: false, confluence: false, expect_button: true|
# This mirrors the logic in:
# - app/views/shared/empty_states/_wikis.html.haml
# - WikiHelper#wiki_empty_state_messages
......@@ -37,7 +37,7 @@ RSpec.shared_examples 'User views empty wiki' do
if issuable && !writable
expect(element).to have_content("improve the wiki for this #{container_name}")
expect(element).to have_link("issue tracker", href: project_issues_path(project))
expect(element).to have_link("Suggest wiki improvement", href: new_project_issue_path(project))
expect(element.has_link?("Suggest wiki improvement", href: new_project_issue_path(project))).to be(expect_button)
else
expect(element).not_to have_content("improve the wiki for this #{container_name}")
expect(element).not_to have_link("issue tracker")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment