Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
dac0f02eea
commit
c898498c37
|
|
@ -727,11 +727,9 @@ const Api = {
|
|||
.replace(':id', encodeURIComponent(id))
|
||||
.replace(':merge_request_iid', mergeRequestId);
|
||||
|
||||
const params = {};
|
||||
|
||||
if (gon.features.asyncMergeRequestPipelineCreation) {
|
||||
params.async = true;
|
||||
}
|
||||
const params = {
|
||||
async: true,
|
||||
};
|
||||
|
||||
return axios.post(url, params);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import PipelinesMixin from '~/ci/pipeline_details/mixins/pipelines_mixin';
|
|||
import PipelinesService from '~/ci/pipelines_page/services/pipelines_service';
|
||||
import PipelineStore from '~/ci/pipeline_details/stores/pipelines_store';
|
||||
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { s__, __ } from '~/locale';
|
||||
|
||||
export default {
|
||||
|
|
@ -23,8 +22,13 @@ export default {
|
|||
PipelinesTable,
|
||||
TablePagination,
|
||||
},
|
||||
mixins: [PipelinesMixin, glFeatureFlagMixin()],
|
||||
mixins: [PipelinesMixin],
|
||||
props: {
|
||||
canCreatePipelineInTargetProject: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
endpoint: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
@ -37,16 +41,21 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
viewType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'root',
|
||||
},
|
||||
canCreatePipelineInTargetProject: {
|
||||
isMergeRequestTable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
mergeRequestId: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
projectId: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
sourceProjectFullPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
|
@ -57,15 +66,10 @@ export default {
|
|||
required: false,
|
||||
default: '',
|
||||
},
|
||||
projectId: {
|
||||
viewType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
mergeRequestId: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
default: 'root',
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -82,9 +86,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
isUsingAsyncPipelineCreation() {
|
||||
return this.glFeatures?.asyncMergeRequestPipelineCreation;
|
||||
},
|
||||
shouldRenderTable() {
|
||||
return !this.isLoading && this.state.pipelines.length > 0 && !this.hasError;
|
||||
},
|
||||
|
|
@ -145,7 +146,7 @@ export default {
|
|||
const pipelines = resp.data.pipelines || resp.data;
|
||||
|
||||
this.store.storePagination(resp.headers);
|
||||
this.setCommonData(pipelines, this.isUsingAsyncPipelineCreation);
|
||||
this.setCommonData(pipelines, this.isMergeRequestTable);
|
||||
|
||||
if (resp.headers?.['x-total']) {
|
||||
const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
|
||||
|
|
@ -172,7 +173,7 @@ export default {
|
|||
eventHub.$emit('runMergeRequestPipeline', {
|
||||
projectId: this.projectId,
|
||||
mergeRequestId: this.mergeRequestId,
|
||||
isAsync: this.isUsingAsyncPipelineCreation,
|
||||
isAsync: this.isMergeRequestTable,
|
||||
});
|
||||
},
|
||||
tryRunPipeline() {
|
||||
|
|
|
|||
|
|
@ -83,9 +83,6 @@ export default {
|
|||
kubernetes: 'kubernetes-overview',
|
||||
},
|
||||
methods: {
|
||||
linkClass(index) {
|
||||
return index === this.currentTabIndex ? 'gl-shadow-inner-b-2-theme-accent' : '';
|
||||
},
|
||||
updateCurrentTab() {
|
||||
const hasKubernetesIntegration = this.environment?.clusterAgent;
|
||||
const selectedTabFromUrl = getParameterValues('tab');
|
||||
|
|
@ -109,7 +106,6 @@ export default {
|
|||
<gl-tab
|
||||
:title="$options.i18n.kubernetesOverview"
|
||||
:query-param-value="$options.params.kubernetes"
|
||||
:title-link-class="linkClass(0)"
|
||||
>
|
||||
<kubernetes-overview
|
||||
:environment-name="environmentName"
|
||||
|
|
@ -120,7 +116,7 @@ export default {
|
|||
/>
|
||||
</gl-tab>
|
||||
|
||||
<gl-tab :query-param-value="$options.params.deployments" :title-link-class="linkClass(1)">
|
||||
<gl-tab :query-param-value="$options.params.deployments">
|
||||
<template #title>
|
||||
{{ $options.i18n.deploymentHistory }}
|
||||
<gl-badge class="gl-tab-counter-badge">{{ environment.deploymentsDisplayCount }}</gl-badge>
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ export default class LabelsSelect {
|
|||
const tooltipTitleTemplate = template(
|
||||
[
|
||||
'<% if (isScopedLabel(label) && enableScopedLabels) { %>',
|
||||
"<span class='font-weight-bold scoped-label-tooltip-title'>Scoped label</span>",
|
||||
"<span class='font-weight-bold'>Scoped label</span>",
|
||||
'<br>',
|
||||
'<%= escapeStr(label.description) %>',
|
||||
'<% } else { %>',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
import { pick, has } from 'lodash';
|
||||
|
||||
/**
|
||||
* @param source
|
||||
* @param properties original list of searched collection
|
||||
* @returns {{}} reduced source to only include properties
|
||||
*/
|
||||
export const pickProperties = (source, properties = []) => {
|
||||
if (!source) {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* If no properties provided
|
||||
* search would be executed on provided properties
|
||||
*/
|
||||
if (!properties || properties.length === 0) {
|
||||
return source;
|
||||
}
|
||||
|
||||
properties.forEach((property) => {
|
||||
if (!has(source, property)) {
|
||||
throw new Error(`${property} does not exist on object. Please provide valid property list.`);
|
||||
}
|
||||
});
|
||||
|
||||
return pick(source, properties);
|
||||
};
|
||||
|
||||
/**
|
||||
* Search among provided properties on items
|
||||
* @param items original list of searched collection
|
||||
* @param properties list of properties to search in
|
||||
* @param searchQuery search query
|
||||
* @returns {*[]}
|
||||
*/
|
||||
export const searchInItemsProperties = ({ items = [], properties = [], searchQuery = '' } = {}) => {
|
||||
if (!items || items.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (searchQuery === '') {
|
||||
return items;
|
||||
}
|
||||
|
||||
const containsValue = (value) =>
|
||||
value.toString().toLowerCase().includes(searchQuery.toLowerCase());
|
||||
|
||||
return items.filter((item) => {
|
||||
const reducedSource = pickProperties(item, properties);
|
||||
|
||||
return Object.values(reducedSource).some((value) => containsValue(value));
|
||||
});
|
||||
};
|
||||
|
|
@ -119,6 +119,7 @@ function mountPipelines() {
|
|||
targetProjectFullPath: mrWidgetData?.target_project_full_path || '',
|
||||
projectId: pipelineTableViewEl.dataset.projectId,
|
||||
mergeRequestId: mrWidgetData ? mrWidgetData.iid : null,
|
||||
isMergeRequestTable: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Default.args = {
|
|||
status: {
|
||||
icon: 'status_success',
|
||||
text: 'Success',
|
||||
detailsPath: 'https://gitab.com/',
|
||||
detailsPath: 'https://gitlab.com/',
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ WithText.args = {
|
|||
status: {
|
||||
icon: 'status_success',
|
||||
text: 'Success',
|
||||
detailsPath: 'https://gitab.com/',
|
||||
detailsPath: 'https://gitlab.com/',
|
||||
},
|
||||
showStatusText: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { GlFormGroup, GlCollapsibleListbox } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import { searchInItemsProperties } from '~/lib/utils/search_utils';
|
||||
|
||||
const MIN_ITEMS_COUNT_FOR_SEARCHING = 10;
|
||||
|
||||
|
|
@ -112,7 +113,11 @@ export default {
|
|||
.map(({ text, options }) => {
|
||||
return {
|
||||
text,
|
||||
options: options.filter((option) => option.text.toLowerCase().includes(searchString)),
|
||||
options: searchInItemsProperties({
|
||||
items: options,
|
||||
properties: ['text'],
|
||||
searchQuery: searchString,
|
||||
}),
|
||||
};
|
||||
})
|
||||
.filter(({ options }) => options.length);
|
||||
|
|
|
|||
|
|
@ -495,11 +495,6 @@ li.note {
|
|||
padding-right: $gl-spacing-scale-3;
|
||||
}
|
||||
|
||||
// used in the Markdown rendering of labels
|
||||
.scoped-label-tooltip-title {
|
||||
color: var(--theme-indigo-300, $theme-indigo-300);
|
||||
}
|
||||
|
||||
.gl-label-scoped {
|
||||
box-shadow: 0 0 0 2px currentColor inset;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ $gl-bronze-plan: #cd7f32;
|
|||
Performance Bar
|
||||
*/
|
||||
$perf-bar-production: $gray-950;
|
||||
$perf-bar-staging: $theme-indigo-950;
|
||||
$perf-bar-staging: $purple-950;
|
||||
$perf-bar-development: $red-900;
|
||||
$perf-bar-bucket-bg: $black;
|
||||
$perf-bar-bucket-box-shadow-from: rgba($white, 0.2);
|
||||
|
|
|
|||
|
|
@ -9,35 +9,35 @@
|
|||
margin-bottom: $gl-padding-8;
|
||||
|
||||
&.ui-indigo {
|
||||
background-color: $theme-indigo-900;
|
||||
background-color: var(--gl-color-theme-indigo-900);
|
||||
}
|
||||
|
||||
&.ui-light-indigo {
|
||||
background-color: $theme-indigo-700;
|
||||
background-color: var(--gl-color-theme-indigo-700);
|
||||
}
|
||||
|
||||
&.ui-blue {
|
||||
background-color: $theme-blue-900;
|
||||
background-color: var(--gl-color-theme-blue-900);
|
||||
}
|
||||
|
||||
&.ui-light-blue {
|
||||
background-color: $theme-light-blue-800;
|
||||
background-color: var(--gl-color-theme-light-blue-800);
|
||||
}
|
||||
|
||||
&.ui-green {
|
||||
background-color: $theme-green-900;
|
||||
background-color: var(--gl-color-theme-green-900);
|
||||
}
|
||||
|
||||
&.ui-light-green {
|
||||
background-color: $theme-green-800;
|
||||
background-color: var(--gl-color-theme-green-800);
|
||||
}
|
||||
|
||||
&.ui-red {
|
||||
background-color: $theme-red-900;
|
||||
background-color: var(--gl-color-theme-red-900);
|
||||
}
|
||||
|
||||
&.ui-light-red {
|
||||
background-color: $theme-light-red-700;
|
||||
background-color: var(--gl-color-theme-light-red-700);
|
||||
}
|
||||
|
||||
&.ui-gray {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
push_frontend_feature_flag(:ci_graphql_pipeline_mini_graph, project)
|
||||
push_frontend_feature_flag(:notifications_todos_buttons, current_user)
|
||||
push_frontend_feature_flag(:reviewer_assign_drawer, current_user)
|
||||
push_frontend_feature_flag(:async_merge_request_pipeline_creation, current_user)
|
||||
end
|
||||
|
||||
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :diffs, :rapid_diffs, :discussions]
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ module Repositories
|
|||
return unless project
|
||||
return if Gitlab::Database.read_only?
|
||||
return unless repo_type.project?
|
||||
return if skip_fetch_statistics_increment?
|
||||
return if Feature.enabled?(:disable_git_http_fetch_writes)
|
||||
|
||||
Projects::FetchStatisticsIncrementService.new(project).execute
|
||||
end
|
||||
|
|
@ -146,14 +146,6 @@ module Repositories
|
|||
payload[:metadata] ||= {}
|
||||
payload[:metadata][:repository_storage] = project&.repository_storage
|
||||
end
|
||||
|
||||
def skip_fetch_statistics_increment?
|
||||
# Since disable_git_http_fetch_writes FF does not define a feature flag actor,
|
||||
# it is currently not possible to increment the project statistics without enabling
|
||||
# or disabling it for all projects. The allow_git_http_fetch_writes FF allow us to control this.
|
||||
Feature.enabled?(:disable_git_http_fetch_writes) &&
|
||||
Feature.disabled?(:allow_git_http_fetch_writes, project, type: :beta)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
name: allow_git_http_fetch_writes
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/426270
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159835
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/473133
|
||||
milestone: '17.3'
|
||||
group: group::source code
|
||||
type: beta
|
||||
default_enabled: false
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
name: async_merge_request_pipeline_creation
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/463355
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/161407
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/476625
|
||||
milestone: '17.3'
|
||||
group: group::pipeline authoring
|
||||
type: wip
|
||||
default_enabled: false
|
||||
|
|
@ -221,7 +221,6 @@ class ConvertTableToListPartitioning < Gitlab::Database::Migration[2.1]
|
|||
disable_ddl_transaction!
|
||||
|
||||
TABLE_NAME = :table_name
|
||||
TABLE_FK = :table_references_by_fk
|
||||
PARENT_TABLE_NAME = :p_table_name
|
||||
FIRST_PARTITION = 100
|
||||
PARTITION_COLUMN = :partition_id
|
||||
|
|
@ -231,8 +230,7 @@ class ConvertTableToListPartitioning < Gitlab::Database::Migration[2.1]
|
|||
table_name: TABLE_NAME,
|
||||
partitioning_column: PARTITION_COLUMN,
|
||||
parent_table_name: PARENT_TABLE_NAME,
|
||||
initial_partitioning_value: FIRST_PARTITION,
|
||||
lock_tables: [TABLE_FK, TABLE_NAME]
|
||||
initial_partitioning_value: FIRST_PARTITION
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -205,8 +205,8 @@ To clean up a repository:
|
|||
`filter-repo` directory.
|
||||
|
||||
If your `commit-map` file is too large, the background cleanup process might time out and fail.
|
||||
As a result, the repository size isn't reduced as expected.
|
||||
To address this, split the file and upload it in parts, for example:
|
||||
As a result, the repository size isn't reduced as expected. To address this, split the file and
|
||||
upload it in parts. Start with `20000` and reduce as needed. For example:
|
||||
|
||||
```shell
|
||||
split -l 20000 filter-repo/commit-map filter-repo/commit-map-
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ To insert a table:
|
|||
1. Select **Insert table** **{table}**.
|
||||
1. From the dropdown list, select the dimensions of the new table.
|
||||
|
||||

|
||||

|
||||
|
||||
### Edit a table
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ Inside a table cell, you can use a menu to insert or delete rows or columns.
|
|||
|
||||
To open the menu: In the upper-right corner of a cell, select the chevron **{chevron-down}**.
|
||||
|
||||

|
||||

|
||||
|
||||
### Operations on multiple cells
|
||||
|
||||
|
|
|
|||
|
|
@ -26,14 +26,6 @@ RSpec.describe Repositories::GitHttpController, feature_category: :source_code_m
|
|||
end
|
||||
end
|
||||
|
||||
shared_examples 'increments fetch statistics' do
|
||||
it 'calls Projects::FetchStatisticsIncrementService service' do
|
||||
expect(Projects::FetchStatisticsIncrementService).to receive(:new).with(project).and_call_original
|
||||
|
||||
send_request
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'handles user activity' do
|
||||
it 'updates the user activity' do
|
||||
activity_project = container.is_a?(PersonalSnippet) ? nil : project
|
||||
|
|
@ -149,24 +141,10 @@ RSpec.describe Repositories::GitHttpController, feature_category: :source_code_m
|
|||
stub_feature_flags(disable_git_http_fetch_writes: true)
|
||||
end
|
||||
|
||||
context 'and allow_git_http_fetch_writes is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_git_http_fetch_writes: false)
|
||||
end
|
||||
it 'does not increment statistics' do
|
||||
expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
|
||||
|
||||
it 'does not increment statistics' do
|
||||
expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
|
||||
|
||||
send_request
|
||||
end
|
||||
end
|
||||
|
||||
context 'and allow_git_http_fetch_writes is enabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_git_http_fetch_writes: true)
|
||||
end
|
||||
|
||||
it_behaves_like 'increments fetch statistics'
|
||||
send_request
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -175,20 +153,10 @@ RSpec.describe Repositories::GitHttpController, feature_category: :source_code_m
|
|||
stub_feature_flags(disable_git_http_fetch_writes: false)
|
||||
end
|
||||
|
||||
context 'and allow_git_http_fetch_writes is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_git_http_fetch_writes: false)
|
||||
end
|
||||
it 'increments statistics' do
|
||||
expect(Projects::FetchStatisticsIncrementService).to receive(:new).with(project).and_call_original
|
||||
|
||||
it_behaves_like 'increments fetch statistics'
|
||||
end
|
||||
|
||||
context 'and allow_git_http_fetch_writes is enabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_git_http_fetch_writes: true)
|
||||
end
|
||||
|
||||
it_behaves_like 'increments fetch statistics'
|
||||
send_request
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -955,11 +955,9 @@ describe('Api', () => {
|
|||
const dummyProjectId = 5;
|
||||
const dummyMergeRequestIid = 123;
|
||||
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/5/merge_requests/123/pipelines`;
|
||||
const features = { asyncMergeRequestPipelineCreation: true };
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
window.gon.features = features;
|
||||
});
|
||||
|
||||
it('creates a merge request pipeline async', () => {
|
||||
|
|
@ -976,25 +974,6 @@ describe('Api', () => {
|
|||
expect(axios.post).toHaveBeenCalledWith(expectedUrl, { async: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('when asyncMergeRequestPipelineCreation is disabled', () => {
|
||||
it('creates a merge request pipeline synchronously', () => {
|
||||
window.gon.features.asyncMergeRequestPipelineCreation = false;
|
||||
|
||||
jest.spyOn(axios, 'post');
|
||||
|
||||
mock.onPost(expectedUrl).replyOnce(HTTP_STATUS_OK, {
|
||||
id: 456,
|
||||
});
|
||||
|
||||
return Api.postMergeRequestPipeline(dummyProjectId, {
|
||||
mergeRequestId: dummyMergeRequestIid,
|
||||
}).then(({ data }) => {
|
||||
expect(data.id).toBe(456);
|
||||
expect(axios.post).toHaveBeenCalledWith(expectedUrl, {});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('projectForks', () => {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ describe('Pipelines Store', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
store = new PipelineStore();
|
||||
|
||||
window.gon.features = { asyncMergeRequestPipelineCreation: false };
|
||||
});
|
||||
|
||||
it('should be initialized with an empty state', () => {
|
||||
|
|
@ -32,11 +30,7 @@ describe('Pipelines Store', () => {
|
|||
expect(store.state.pipelines).toEqual(array);
|
||||
});
|
||||
|
||||
describe('when asyncMergeRequestPipelineCreation is enabled', () => {
|
||||
beforeEach(() => {
|
||||
window.gon.features.asyncMergeRequestPipelineCreation = true;
|
||||
});
|
||||
|
||||
describe('when pipeline creation is async', () => {
|
||||
describe('when a new pipeline is added to the store', () => {
|
||||
it('sets the value of `isRunningMergeRequestPipeline` to false', () => {
|
||||
const existingPipelines = [{ created_at: '2023' }];
|
||||
|
|
@ -53,11 +47,11 @@ describe('Pipelines Store', () => {
|
|||
describe('when no new pipelines are added to the store', () => {
|
||||
it('does not change the value of `isRunningMergeRequestPipeline`', () => {
|
||||
const existingPipelines = [{ created_at: '2023' }];
|
||||
store.storePipelines(existingPipelines);
|
||||
store.storePipelines(existingPipelines, true);
|
||||
store.state.isRunningMergeRequestPipeline = true;
|
||||
|
||||
const updatedPipelines = [{ created_at: '2023' }];
|
||||
store.storePipelines(updatedPipelines);
|
||||
store.storePipelines(updatedPipelines, true);
|
||||
|
||||
expect(store.state.isRunningMergeRequestPipeline).toBe(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -42,11 +42,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
|||
const findUserPermissionsDocsLink = () => wrapper.findByTestId('user-permissions-docs-link');
|
||||
const findPipelinesTable = () => wrapper.findComponent(PipelinesTable);
|
||||
|
||||
const createComponent = ({
|
||||
props = {},
|
||||
mountFn = mountExtended,
|
||||
asyncMergeRequestPipelineCreation = true,
|
||||
} = {}) => {
|
||||
const createComponent = ({ props = {}, mountFn = mountExtended } = {}) => {
|
||||
wrapper = mountFn(LegacyPipelinesTableWrapper, {
|
||||
propsData: {
|
||||
endpoint: 'endpoint.json',
|
||||
|
|
@ -54,11 +50,6 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
|||
errorStateSvgPath: 'foo',
|
||||
...props,
|
||||
},
|
||||
provide: {
|
||||
glFeatures: {
|
||||
asyncMergeRequestPipelineCreation,
|
||||
},
|
||||
},
|
||||
mocks: {
|
||||
$toast,
|
||||
},
|
||||
|
|
@ -236,7 +227,20 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
|||
jest.spyOn(Api, 'postMergeRequestPipeline').mockResolvedValue();
|
||||
});
|
||||
|
||||
describe('when asyncMergeRequestPipelineCreation is enabled', () => {
|
||||
describe('when the table is a merge request table', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
props: {
|
||||
canRunPipeline: true,
|
||||
isMergeRequestTable: true,
|
||||
mergeRequestId: 3,
|
||||
projectId: '5',
|
||||
},
|
||||
});
|
||||
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('on desktop, shows a loading button', async () => {
|
||||
await findRunPipelineBtn().trigger('click');
|
||||
|
||||
|
|
@ -262,20 +266,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when asyncMergeRequestPipelineCreation is disabled', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
props: {
|
||||
canRunPipeline: true,
|
||||
projectId: '5',
|
||||
mergeRequestId: 3,
|
||||
},
|
||||
asyncMergeRequestPipelineCreation: false,
|
||||
});
|
||||
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
describe('when the table is not a merge request table', () => {
|
||||
it('displays a toast message during pipeline creation', async () => {
|
||||
await findRunPipelineBtn().trigger('click');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { GlLoadingIcon, GlTabs, GlTab, GlBadge } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { updateHistory, getParameterValues, setUrlParams } from '~/lib/utils/url_utility';
|
||||
import EnvironmentsDetailPage from '~/environments/environment_details/index.vue';
|
||||
|
|
@ -91,19 +91,6 @@ describe('~/environments/environment_details/index.vue', () => {
|
|||
it('renders tabs component with the correct prop', () => {
|
||||
expect(findTabs().props('syncActiveTabWithQueryParams')).toBe(true);
|
||||
});
|
||||
|
||||
it('sets proper CSS class to the active tab', () => {
|
||||
expect(findTabByIndex(0).props('titleLinkClass')).toBe('gl-shadow-inner-b-2-theme-accent');
|
||||
expect(findTabByIndex(1).props('titleLinkClass')).toBe('');
|
||||
});
|
||||
|
||||
it('updates the CSS class when the active tab changes', async () => {
|
||||
findTabs().vm.$emit('input', 1);
|
||||
await nextTick();
|
||||
|
||||
expect(findTabByIndex(0).props('titleLinkClass')).toBe('');
|
||||
expect(findTabByIndex(1).props('titleLinkClass')).toBe('gl-shadow-inner-b-2-theme-accent');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kubernetes overview tab', () => {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ describe('LabelsSelect', () => {
|
|||
|
||||
it('generated label item template has correct title for tooltip', () => {
|
||||
expect($labelEl.find('a').attr('title')).toBe(
|
||||
"<span class='font-weight-bold scoped-label-tooltip-title'>Scoped label</span><br>Foobar",
|
||||
"<span class='font-weight-bold'>Scoped label</span><br>Foobar",
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
import { pickProperties, searchInItemsProperties } from '~/lib/utils/search_utils';
|
||||
|
||||
const items = [1, 2].map((id) => ({
|
||||
id,
|
||||
name: `name ${id}`,
|
||||
text: `text ${id}`,
|
||||
title: `title ${id}`,
|
||||
}));
|
||||
|
||||
describe('pickProperties', () => {
|
||||
it.each`
|
||||
source | properties | outcome
|
||||
${undefined} | ${[]} | ${{}}
|
||||
${null} | ${[]} | ${{}}
|
||||
${{}} | ${[]} | ${{}}
|
||||
${items[0]} | ${[]} | ${items[0]}
|
||||
${items[0]} | ${undefined} | ${items[0]}
|
||||
${items[0]} | ${null} | ${items[0]}
|
||||
${items[0]} | ${['name']} | ${{ name: 'name 1' }}
|
||||
${items[0]} | ${['name', 'text', 'id']} | ${{ name: 'name 1', text: 'text 1', id: 1 }}
|
||||
`('picks specific properties from source object', ({ source, properties, outcome }) => {
|
||||
expect(pickProperties(source, properties)).toEqual(outcome);
|
||||
});
|
||||
|
||||
it('throws an error if property does not exist on source object', () => {
|
||||
try {
|
||||
pickProperties(items[0], ['name', 'text1']);
|
||||
} catch (error) {
|
||||
expect(error).toEqual(
|
||||
new Error('text1 does not exist on object. Please provide valid property list.'),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('searchInItemsProperties', () => {
|
||||
it.each`
|
||||
items | properties | searchQuery | outcome
|
||||
${undefined} | ${[]} | ${''} | ${[]}
|
||||
${null} | ${[]} | ${''} | ${[]}
|
||||
${[]} | ${[]} | ${''} | ${[]}
|
||||
${items} | ${[]} | ${''} | ${items}
|
||||
${items} | ${[]} | ${'name 1'} | ${[items[0]]}
|
||||
${items} | ${['text']} | ${'name 1'} | ${[]}
|
||||
${items} | ${['text']} | ${'text 1'} | ${[items[0]]}
|
||||
${items} | ${['text', 'name']} | ${'text 2'} | ${[items[1]]}
|
||||
${items} | ${['text', 'name', 'title']} | ${'text 2'} | ${[items[1]]}
|
||||
${items} | ${['name', 'title']} | ${'text 2'} | ${[]}
|
||||
`(
|
||||
'filters items based on search query and picked properties',
|
||||
({ items: mockedItems, properties, searchQuery, outcome }) => {
|
||||
expect(searchInItemsProperties({ items: mockedItems, properties, searchQuery })).toEqual(
|
||||
outcome,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it('throws an error if property does not exist on source objects when searched', () => {
|
||||
try {
|
||||
searchInItemsProperties({ items, properties: ['name', 'text1'], searchQuery: 'text 1' });
|
||||
} catch (error) {
|
||||
expect(error).toEqual(
|
||||
new Error('text1 does not exist on object. Please provide valid property list.'),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue