Commit 12e0fc1e authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '354473-pipeline-filter-default-branch-name' into 'master'

Add default branch to Pipelines page filter if no search term provided

See merge request gitlab-org/gitlab!82245
parents b3c7c3d6 039b1145
...@@ -98,6 +98,11 @@ export default { ...@@ -98,6 +98,11 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
defaultBranchName: {
type: String,
required: false,
default: null,
},
params: { params: {
type: Object, type: Object,
required: true, required: true,
...@@ -347,6 +352,7 @@ export default { ...@@ -347,6 +352,7 @@ export default {
<pipelines-filtered-search <pipelines-filtered-search
class="gl-display-flex gl-flex-grow-1 gl-mr-4" class="gl-display-flex gl-flex-grow-1 gl-mr-4"
:project-id="projectId" :project-id="projectId"
:default-branch-name="defaultBranchName"
:params="validatedParams" :params="validatedParams"
@filterPipelines="filterPipelines" @filterPipelines="filterPipelines"
/> />
......
...@@ -24,6 +24,11 @@ export default { ...@@ -24,6 +24,11 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
defaultBranchName: {
type: String,
required: false,
default: null,
},
params: { params: {
type: Object, type: Object,
required: true, required: true,
...@@ -57,6 +62,7 @@ export default { ...@@ -57,6 +62,7 @@ export default {
token: PipelineBranchNameToken, token: PipelineBranchNameToken,
operators: OPERATOR_IS_ONLY, operators: OPERATOR_IS_ONLY,
projectId: this.projectId, projectId: this.projectId,
defaultBranchName: this.defaultBranchName,
disabled: this.selectedTypes.includes(this.$options.tagType), disabled: this.selectedTypes.includes(this.$options.tagType),
}, },
{ {
......
...@@ -35,6 +35,13 @@ export default { ...@@ -35,6 +35,13 @@ export default {
Api.branches(this.config.projectId, searchterm) Api.branches(this.config.projectId, searchterm)
.then(({ data }) => { .then(({ data }) => {
this.branches = data.map((branch) => branch.name); this.branches = data.map((branch) => branch.name);
if (!searchterm && this.config.defaultBranchName) {
// Shift the default branch to the top of the list
this.branches = this.branches.filter(
(branch) => branch !== this.config.defaultBranchName,
);
this.branches.unshift(this.config.defaultBranchName);
}
this.loading = false; this.loading = false;
}) })
.catch((err) => { .catch((err) => {
......
...@@ -36,6 +36,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => { ...@@ -36,6 +36,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
ciLintPath, ciLintPath,
resetCachePath, resetCachePath,
projectId, projectId,
defaultBranchName,
params, params,
ciRunnerSettingsPath, ciRunnerSettingsPath,
anyRunnersAvailable, anyRunnersAvailable,
...@@ -75,6 +76,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => { ...@@ -75,6 +76,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
ciLintPath, ciLintPath,
resetCachePath, resetCachePath,
projectId, projectId,
defaultBranchName,
params: JSON.parse(params), params: JSON.parse(params),
ciRunnerSettingsPath, ciRunnerSettingsPath,
anyRunnersAvailable: parseBoolean(anyRunnersAvailable), anyRunnersAvailable: parseBoolean(anyRunnersAvailable),
......
...@@ -84,6 +84,7 @@ module Ci ...@@ -84,6 +84,7 @@ module Ci
data = { data = {
endpoint: list_url, endpoint: list_url,
project_id: project.id, project_id: project.id,
default_branch_name: project.default_branch,
params: params.to_json, params: params.to_json,
artifacts_endpoint: downloadable_artifacts_project_pipeline_path(project, artifacts_endpoint_placeholder, format: :json), artifacts_endpoint: downloadable_artifacts_project_pipeline_path(project, artifacts_endpoint_placeholder, format: :json),
artifacts_endpoint_placeholder: artifacts_endpoint_placeholder, artifacts_endpoint_placeholder: artifacts_endpoint_placeholder,
......
...@@ -27,6 +27,7 @@ describe('Pipelines filtered search', () => { ...@@ -27,6 +27,7 @@ describe('Pipelines filtered search', () => {
wrapper = mount(PipelinesFilteredSearch, { wrapper = mount(PipelinesFilteredSearch, {
propsData: { propsData: {
projectId: '21', projectId: '21',
defaultBranchName: 'main',
params, params,
}, },
attachTo: document.body, attachTo: document.body,
...@@ -69,6 +70,7 @@ describe('Pipelines filtered search', () => { ...@@ -69,6 +70,7 @@ describe('Pipelines filtered search', () => {
title: 'Branch name', title: 'Branch name',
unique: true, unique: true,
projectId: '21', projectId: '21',
defaultBranchName: 'main',
operators: OPERATOR_IS_ONLY, operators: OPERATOR_IS_ONLY,
}); });
......
...@@ -27,6 +27,7 @@ jest.mock('~/flash'); ...@@ -27,6 +27,7 @@ jest.mock('~/flash');
const mockProjectPath = 'twitter/flight'; const mockProjectPath = 'twitter/flight';
const mockProjectId = '21'; const mockProjectId = '21';
const mockDefaultBranchName = 'main';
const mockPipelinesEndpoint = `/${mockProjectPath}/pipelines.json`; const mockPipelinesEndpoint = `/${mockProjectPath}/pipelines.json`;
const mockPipelinesIds = mockPipelinesResponse.pipelines.map(({ id }) => id); const mockPipelinesIds = mockPipelinesResponse.pipelines.map(({ id }) => id);
const mockPipelineWithStages = mockPipelinesResponse.pipelines.find( const mockPipelineWithStages = mockPipelinesResponse.pipelines.find(
...@@ -85,6 +86,7 @@ describe('Pipelines', () => { ...@@ -85,6 +86,7 @@ describe('Pipelines', () => {
propsData: { propsData: {
store: new Store(), store: new Store(),
projectId: mockProjectId, projectId: mockProjectId,
defaultBranchName: mockDefaultBranchName,
endpoint: mockPipelinesEndpoint, endpoint: mockPipelinesEndpoint,
params: {}, params: {},
...props, ...props,
......
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui'; import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api'; import Api from '~/api';
import PipelineBranchNameToken from '~/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue'; import PipelineBranchNameToken from '~/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue';
import { branches, mockBranchesAfterMap } from '../mock_data'; import { branches, mockBranchesAfterMap } from '../mock_data';
...@@ -10,6 +12,8 @@ describe('Pipeline Branch Name Token', () => { ...@@ -10,6 +12,8 @@ describe('Pipeline Branch Name Token', () => {
const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken); const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken);
const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon); const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const getBranchSuggestions = () =>
findAllFilteredSearchSuggestions().wrappers.map((w) => w.text());
const stubs = { const stubs = {
GlFilteredSearchToken: { GlFilteredSearchToken: {
...@@ -24,6 +28,7 @@ describe('Pipeline Branch Name Token', () => { ...@@ -24,6 +28,7 @@ describe('Pipeline Branch Name Token', () => {
title: 'Branch name', title: 'Branch name',
unique: true, unique: true,
projectId: '21', projectId: '21',
defaultBranchName: null,
disabled: false, disabled: false,
}, },
value: { value: {
...@@ -31,6 +36,19 @@ describe('Pipeline Branch Name Token', () => { ...@@ -31,6 +36,19 @@ describe('Pipeline Branch Name Token', () => {
}, },
}; };
const optionsWithDefaultBranchName = (options) => {
return {
propsData: {
...defaultProps,
config: {
...defaultProps.config,
defaultBranchName: 'main',
},
},
...options,
};
};
const createComponent = (options, data) => { const createComponent = (options, data) => {
wrapper = shallowMount(PipelineBranchNameToken, { wrapper = shallowMount(PipelineBranchNameToken, {
propsData: { propsData: {
...@@ -94,5 +112,34 @@ describe('Pipeline Branch Name Token', () => { ...@@ -94,5 +112,34 @@ describe('Pipeline Branch Name Token', () => {
expect(findAllFilteredSearchSuggestions()).toHaveLength(mockBranches.length); expect(findAllFilteredSearchSuggestions()).toHaveLength(mockBranches.length);
}); });
it('shows the default branch first if no branch was searched for', async () => {
const mockBranches = [{ name: 'branch-1' }];
jest.spyOn(Api, 'branches').mockResolvedValue({ data: mockBranches });
createComponent(optionsWithDefaultBranchName({ stubs }), { loading: false });
await nextTick();
expect(getBranchSuggestions()).toEqual(['main', 'branch-1']);
});
it('does not show the default branch if a search term was provided', async () => {
const mockBranches = [{ name: 'branch-1' }];
jest.spyOn(Api, 'branches').mockResolvedValue({ data: mockBranches });
createComponent(optionsWithDefaultBranchName(), { loading: false });
findFilteredSearchToken().vm.$emit('input', { data: 'branch-1' });
await waitForPromises();
expect(getBranchSuggestions()).toEqual(['branch-1']);
});
it('shows the default branch only once if it appears in the results', async () => {
const mockBranches = [{ name: 'main' }];
jest.spyOn(Api, 'branches').mockResolvedValue({ data: mockBranches });
createComponent(optionsWithDefaultBranchName({ stubs }), { loading: false });
await nextTick();
expect(getBranchSuggestions()).toEqual(['main']);
});
}); });
}); });
...@@ -106,6 +106,7 @@ RSpec.describe Ci::PipelinesHelper do ...@@ -106,6 +106,7 @@ RSpec.describe Ci::PipelinesHelper do
it 'has the expected keys' do it 'has the expected keys' do
expect(subject.keys).to match_array([:endpoint, expect(subject.keys).to match_array([:endpoint,
:project_id, :project_id,
:default_branch_name,
:params, :params,
:artifacts_endpoint, :artifacts_endpoint,
:artifacts_endpoint_placeholder, :artifacts_endpoint_placeholder,
......
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