Commit b7bfa9d4 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 40df9a8a a2e9af71
...@@ -179,9 +179,9 @@ const Api = { ...@@ -179,9 +179,9 @@ const Api = {
}); });
}, },
groupLabels(namespace) { groupLabels(namespace, options = {}) {
const url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespace); const url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespace);
return axios.get(url).then(({ data }) => data); return axios.get(url, options).then(({ data }) => data);
}, },
// Return namespaces list. Filtered by query // Return namespaces list. Filtered by query
......
...@@ -139,6 +139,12 @@ export default { ...@@ -139,6 +139,12 @@ export default {
<div class="issuable-main-info"> <div class="issuable-main-info">
<div data-testid="issuable-title" class="issue-title title"> <div data-testid="issuable-title" class="issue-title title">
<span class="issue-title-text" dir="auto"> <span class="issue-title-text" dir="auto">
<gl-icon
v-if="issuable.confidential"
v-gl-tooltip
name="eye-slash"
:title="__('Confidential')"
/>
<gl-link :href="issuable.webUrl" v-bind="issuableTitleProps" <gl-link :href="issuable.webUrl" v-bind="issuableTitleProps"
>{{ issuable.title >{{ issuable.title
}}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2" }}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2"
......
...@@ -230,7 +230,7 @@ export default { ...@@ -230,7 +230,7 @@ export default {
:initial-sort-by="initialSortBy" :initial-sort-by="initialSortBy"
:show-checkbox="showBulkEditSidebar" :show-checkbox="showBulkEditSidebar"
:checkbox-checked="allIssuablesChecked" :checkbox-checked="allIssuablesChecked"
class="gl-flex-grow-1 row-content-block" class="gl-flex-grow-1 gl-border-t-none row-content-block"
@checked-input="handleAllIssuablesCheckedInput" @checked-input="handleAllIssuablesCheckedInput"
@onFilter="$emit('filter', $event)" @onFilter="$emit('filter', $event)"
@onSort="$emit('sort', $event)" @onSort="$emit('sort', $event)"
......
...@@ -32,7 +32,10 @@ export default { ...@@ -32,7 +32,10 @@ export default {
<template> <template>
<div class="top-area"> <div class="top-area">
<gl-tabs class="nav-links mobile-separator issuable-state-filters"> <gl-tabs
class="gl-display-flex gl-flex-fill-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters"
nav-class="gl-border-b-0"
>
<gl-tab <gl-tab
v-for="tab in tabs" v-for="tab in tabs"
:key="tab.id" :key="tab.id"
...@@ -41,7 +44,7 @@ export default { ...@@ -41,7 +44,7 @@ export default {
> >
<template #title> <template #title>
<span :title="tab.titleTooltip">{{ tab.title }}</span> <span :title="tab.titleTooltip">{{ tab.title }}</span>
<gl-badge v-if="tabCounts" variant="neutral" size="sm" class="gl-px-2 gl-py-1!">{{ <gl-badge v-if="tabCounts" variant="neutral" size="sm" class="gl-tab-counter-badge">{{
tabCounts[tab.name] tabCounts[tab.name]
}}</gl-badge> }}</gl-badge>
</template> </template>
......
...@@ -475,6 +475,15 @@ ...@@ -475,6 +475,15 @@
} }
} }
.sort-dropdown-container {
// This property is set to have borders
// around sort dropdown match with filter
// input field.
.gl-button {
box-shadow: inset 0 0 0 1px $gray-400;
}
}
@include media-breakpoint-up(md) { @include media-breakpoint-up(md) {
.sort-dropdown-container { .sort-dropdown-container {
margin-left: 10px; margin-left: 10px;
......
...@@ -20,6 +20,10 @@ module RuboCop ...@@ -20,6 +20,10 @@ module RuboCop
(def :down ...) (def :down ...)
PATTERN PATTERN
def_node_matcher :set_text_limit?, <<~PATTERN
(send _ :text_limit ...)
PATTERN
def_node_matcher :add_text_limit?, <<~PATTERN def_node_matcher :add_text_limit?, <<~PATTERN
(send _ :add_text_limit ...) (send _ :add_text_limit ...)
PATTERN PATTERN
...@@ -111,18 +115,29 @@ module RuboCop ...@@ -111,18 +115,29 @@ module RuboCop
limit_found = false limit_found = false
node.each_descendant(:send) do |send_node| node.each_descendant(:send) do |send_node|
next unless add_text_limit?(send_node) if set_text_limit?(send_node)
limit_found = matching_set_text_limit?(send_node, attribute_name)
elsif add_text_limit?(send_node)
limit_found = matching_add_text_limit?(send_node, table_name, attribute_name)
end
limit_table = send_node.children[2].value break if limit_found
limit_attribute = send_node.children[3].value end
if limit_table == table_name && limit_attribute == attribute_name !limit_found
limit_found = true
break
end end
def matching_set_text_limit?(send_node, attribute_name)
limit_attribute = send_node.children[2].value
limit_attribute == attribute_name
end end
!limit_found def matching_add_text_limit?(send_node, table_name, attribute_name)
limit_table = send_node.children[2].value
limit_attribute = send_node.children[3].value
limit_table == table_name && limit_attribute == attribute_name
end end
def encrypted_attribute_name?(attribute_name) def encrypted_attribute_name?(attribute_name)
......
...@@ -19,7 +19,7 @@ module RuboCop ...@@ -19,7 +19,7 @@ module RuboCop
# or through a create/alter table (TABLE_METHODS) # or through a create/alter table (TABLE_METHODS)
ADD_COLUMN_METHODS = %i(add_column add_column_with_default change_column_type_concurrently).freeze ADD_COLUMN_METHODS = %i(add_column add_column_with_default change_column_type_concurrently).freeze
TABLE_METHODS = %i(create_table create_table_if_not_exists change_table).freeze TABLE_METHODS = %i(create_table create_table_if_not_exists change_table create_table_with_constraints).freeze
def high_traffic_tables def high_traffic_tables
@high_traffic_tables ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'HighTrafficTables') @high_traffic_tables ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'HighTrafficTables')
......
...@@ -260,6 +260,28 @@ describe('Api', () => { ...@@ -260,6 +260,28 @@ describe('Api', () => {
}); });
}); });
describe('groupLabels', () => {
it('fetches group labels', (done) => {
const options = { params: { search: 'foo' } };
const expectedGroup = 'gitlab-org';
const expectedUrl = `${dummyUrlRoot}/groups/${expectedGroup}/-/labels`;
mock.onGet(expectedUrl).reply(httpStatus.OK, [
{
id: 1,
title: 'Foo Label',
},
]);
Api.groupLabels(expectedGroup, options)
.then((res) => {
expect(res.length).toBe(1);
expect(res[0].title).toBe('Foo Label');
})
.then(done)
.catch(done.fail);
});
});
describe('namespaces', () => { describe('namespaces', () => {
it('fetches namespaces', (done) => { it('fetches namespaces', (done) => {
const query = 'dummy query'; const query = 'dummy query';
......
...@@ -257,6 +257,23 @@ describe('IssuableItem', () => { ...@@ -257,6 +257,23 @@ describe('IssuableItem', () => {
); );
}); });
it('renders issuable confidential icon when issuable is confidential', async () => {
wrapper.setProps({
issuable: {
...mockIssuable,
confidential: true,
},
});
await wrapper.vm.$nextTick();
const confidentialEl = wrapper.find('[data-testid="issuable-title"]').find(GlIcon);
expect(confidentialEl.exists()).toBe(true);
expect(confidentialEl.props('name')).toBe('eye-slash');
expect(confidentialEl.attributes('title')).toBe('Confidential');
});
it('renders issuable reference', () => { it('renders issuable reference', () => {
const referenceEl = wrapper.find('[data-testid="issuable-reference"]'); const referenceEl = wrapper.find('[data-testid="issuable-reference"]');
......
import Vue from 'vue'; import { shallowMount, mount } from '@vue/test-utils';
import mountComponent from 'helpers/vue_mount_component_helper'; import PipelineBlockedComponent from '~/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue';
import { removeBreakLine } from 'helpers/text_helper';
import pipelineBlockedComponent from '~/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue';
describe('MRWidgetPipelineBlocked', () => { describe('MRWidgetPipelineBlocked', () => {
let vm; let wrapper;
beforeEach(() => {
const Component = Vue.extend(pipelineBlockedComponent); const createWrapper = (mountFn = shallowMount) => {
vm = mountComponent(Component); wrapper = mountFn(PipelineBlockedComponent);
}); };
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.destroy();
}); });
it('renders warning icon', () => { it('renders warning icon', () => {
expect(vm.$el.querySelector('.ci-status-icon-warning')).not.toBe(null); createWrapper(mount);
expect(wrapper.find('.ci-status-icon-warning').exists()).toBe(true);
}); });
it('renders information text', () => { it('renders information text', () => {
expect(removeBreakLine(vm.$el.textContent).trim()).toContain( createWrapper();
expect(wrapper.text()).toBe(
'Pipeline blocked. The pipeline for this merge request requires a manual action to proceed', 'Pipeline blocked. The pipeline for this merge request requires a manual action to proceed',
); );
}); });
......
...@@ -28,6 +28,15 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do ...@@ -28,6 +28,15 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
^^^^ #{described_class::MSG} ^^^^ #{described_class::MSG}
end end
create_table_with_constraints :test_text_limits_create do |t|
t.integer :test_id, null: false
t.text :title
t.text :description
^^^^ #{described_class::MSG}
t.text_limit :title, 100
end
add_column :test_text_limits, :email, :text add_column :test_text_limits, :email, :text
^^^^^^^^^^ #{described_class::MSG} ^^^^^^^^^^ #{described_class::MSG}
...@@ -57,6 +66,15 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do ...@@ -57,6 +66,15 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
t.text :name t.text :name
end end
create_table_with_constraints :test_text_limits_create do |t|
t.integer :test_id, null: false
t.text :title
t.text :description
t.text_limit :title, 100
t.text_limit :description, 255
end
add_column :test_text_limits, :email, :text add_column :test_text_limits, :email, :text
add_column_with_default :test_text_limits, :role, :text, default: 'default' add_column_with_default :test_text_limits, :role, :text, default: 'default'
change_column_type_concurrently :test_text_limits, :test_id, :text change_column_type_concurrently :test_text_limits, :test_id, :text
......
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