Commit acb2207b authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '197962-move-components-into-shared' into 'master'

Move package list components into shared for upcoming work

See merge request gitlab-org/gitlab!31744
parents 356ae326 7838193e
......@@ -5,8 +5,8 @@ import Tracking from '~/tracking';
import { s__, sprintf } from '~/locale';
import { TrackingActions } from '../../shared/constants';
import { packageTypeToTrackCategory } from '../../shared/utils';
import PackagesListLoader from './packages_list_loader.vue';
import PackagesListRow from './packages_list_row.vue';
import PackagesListLoader from '../../shared/components/packages_list_loader.vue';
import PackagesListRow from '../../shared/components/package_list_row.vue';
export default {
components: {
......@@ -98,6 +98,8 @@ export default {
v-for="packageEntity in list"
:key="packageEntity.id"
:package-entity="packageEntity"
:package-link="packageEntity._links.web_path"
:is-group="isGroupPage"
@packageToDelete="setItemToBeDeleted"
/>
</div>
......
import { LIST_KEY_PROJECT } from '../constants';
import { beautifyPath } from '../../shared/utils';
export const getList = state =>
export default state =>
state.packages.map(p => ({ ...p, projectPathName: beautifyPath(p[LIST_KEY_PROJECT]) }));
export const getCommitLink = ({ config }) => ({ project_path: projectPath, pipeline = {} }) => {
if (config.isGroupPage) {
return `/${projectPath}/commit/${pipeline.sha}`;
}
return `../commit/${pipeline.sha}`;
};
import Vue from 'vue';
import Vuex from 'vuex';
import * as actions from './actions';
import * as getters from './getters';
import getList from './getters';
import mutations from './mutations';
import state from './state';
......@@ -10,7 +10,9 @@ Vue.use(Vuex);
export const createStore = () =>
new Vuex.Store({
state,
getters,
getters: {
getList,
},
actions,
mutations,
});
......
......@@ -4,10 +4,9 @@ import PublishMethod from './publish_method.vue';
import { GlButton, GlIcon, GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { getPackageTypeLabel } from '../../shared/utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { mapState } from 'vuex';
export default {
name: 'PackagesListRow',
name: 'PackageListRow',
components: {
GlButton,
GlIcon,
......@@ -25,11 +24,27 @@ export default {
type: Object,
required: true,
},
packageLink: {
type: String,
required: true,
},
disableDelete: {
type: Boolean,
default: false,
required: false,
},
isGroup: {
type: Boolean,
default: false,
required: false,
},
showPackageType: {
type: Boolean,
default: true,
required: false,
},
},
computed: {
...mapState({
isGroupPage: state => state.config.isGroupPage,
}),
packageType() {
return getPackageTypeLabel(this.packageEntity.package_type);
},
......@@ -40,7 +55,7 @@ export default {
return Boolean(this.packageEntity.project_path);
},
deleteAvailable() {
return !this.isGroupPage;
return !this.disableDelete && !this.isGroup;
},
},
};
......@@ -51,7 +66,7 @@ export default {
<div class="table-section section-50 d-flex flex-md-column justify-content-between flex-wrap">
<div class="d-flex align-items-center mr-2">
<gl-link
:href="packageEntity._links.web_path"
:href="packageLink"
data-qa-selector="package_link"
class="text-dark font-weight-bold mb-md-1"
>
......@@ -80,25 +95,25 @@ export default {
<gl-icon name="review-list" class="text-secondary ml-2 mr-1" />
<gl-link
ref="packages-row-project"
data-testid="packages-row-project"
:href="`/${packageEntity.project_path}`"
class="text-secondary"
>{{ packageEntity.projectPathName }}</gl-link
>
</div>
<div class="d-flex align-items-center">
<div v-if="showPackageType" class="d-flex align-items-center" data-testid="package-type">
<gl-icon name="package" class="text-secondary ml-2 mr-1" />
<span ref="package-type">{{ packageType }}</span>
<span>{{ packageType }}</span>
</div>
</div>
</div>
<div
class="table-section d-flex flex-md-column justify-content-between align-items-md-end"
:class="isGroupPage ? 'section-50' : 'section-40'"
:class="!deleteAvailable ? 'section-50' : 'section-40'"
>
<publish-method :package-entity="packageEntity" />
<publish-method :package-entity="packageEntity" :is-group="isGroup" />
<div class="text-secondary order-0 order-md-1 mt-md-2">
<gl-sprintf :message="__('Created %{timestamp}')">
......@@ -113,7 +128,7 @@ export default {
<div v-if="deleteAvailable" class="table-section section-10 d-flex justify-content-end">
<gl-button
ref="action-delete"
data-testid="action-delete"
icon="remove"
category="primary"
variant="danger"
......
<script>
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { GlIcon, GlLink } from '@gitlab/ui';
import { mapGetters } from 'vuex';
import { getCommitLink } from '../utils';
export default {
name: 'PublishMethod',
......@@ -15,9 +15,13 @@ export default {
type: Object,
required: true,
},
isGroup: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
...mapGetters(['getCommitLink']),
hasPipeline() {
return Boolean(this.packageEntity.pipeline);
},
......@@ -25,7 +29,7 @@ export default {
return this.packageEntity.pipeline?.sha.substring(0, 8);
},
linkToCommit() {
return this.getCommitLink(this.packageEntity);
return getCommitLink(this.packageEntity, this.isGroup);
},
},
};
......
......@@ -24,3 +24,11 @@ export const getPackageTypeLabel = packageType => {
return null;
}
};
export const getCommitLink = ({ project_path: projectPath, pipeline = {} }, isGroup = false) => {
if (isGroup) {
return `/${projectPath}/commit/${pipeline.sha}`;
}
return `../commit/${pipeline.sha}`;
};
......@@ -4,8 +4,8 @@ import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
import Tracking from '~/tracking';
import { mount, createLocalVue } from '@vue/test-utils';
import PackagesList from 'ee/packages/list/components/packages_list.vue';
import PackagesListLoader from 'ee/packages/list/components/packages_list_loader.vue';
import PackagesListRow from 'ee/packages/list/components/packages_list_row.vue';
import PackagesListLoader from 'ee/packages/shared/components/packages_list_loader.vue';
import PackagesListRow from 'ee/packages/shared/components/package_list_row.vue';
import * as SharedUtils from 'ee/packages/shared/utils';
import { TrackingActions } from 'ee/packages/shared/constants';
import stubChildren from 'helpers/stub_children';
......
import * as getters from 'ee/packages/list/stores/getters';
import getList from 'ee/packages/list/stores/getters';
import { packageList } from '../../mock_data';
describe('Getters registry list store', () => {
......@@ -21,35 +21,16 @@ describe('Getters registry list store', () => {
describe('getList', () => {
it('returns a list of packages', () => {
const result = getters.getList(state);
const result = getList(state);
expect(result).toHaveLength(packageList.length);
expect(result[0].name).toBe('Test package');
});
it('adds projectPathName', () => {
const result = getters.getList(state);
const result = getList(state);
expect(result[0].projectPathName).toMatchInlineSnapshot(`"foo / bar / baz"`);
});
});
describe('getCommitLink', () => {
it('returns a relative link when isGroupPage is false', () => {
const link = getters.getCommitLink(state)(packageList[0]);
expect(link).toContain('../commit');
});
describe('when isGroupPage is true', () => {
beforeEach(() => setState({ isGroupPage: true }));
it('returns an absolute link matching project path', () => {
const mavenPackage = packageList[0];
const link = getters.getCommitLink(state)(mavenPackage);
expect(link).toContain(`/${mavenPackage.project_path}/commit`);
});
});
});
});
......@@ -44,6 +44,7 @@ exports[`packages_list_row renders 1`] = `
<gl-link-stub
class="text-secondary"
data-testid="packages-row-project"
href="/foo/bar/baz"
>
......@@ -52,6 +53,7 @@ exports[`packages_list_row renders 1`] = `
<div
class="d-flex align-items-center"
data-testid="package-type"
>
<gl-icon-stub
class="text-secondary ml-2 mr-1"
......@@ -88,6 +90,7 @@ exports[`packages_list_row renders 1`] = `
<gl-button-stub
aria-label="Remove package"
category="primary"
data-testid="action-delete"
icon="remove"
size="medium"
title="Remove package"
......
......@@ -24,7 +24,7 @@ exports[`publish_method renders 1`] = `
<gl-link-stub
class="mr-1"
href="commit-link"
href="../commit/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
>
xxxxxxxx
</gl-link-stub>
......
import Vuex from 'vuex';
import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
import PackagesListRow from 'ee/packages/list/components/packages_list_row.vue';
import { mount, shallowMount } from '@vue/test-utils';
import PackagesListRow from 'ee/packages/shared/components/package_list_row.vue';
import PackageTags from 'ee/packages/shared/components/package_tags.vue';
import { packageList } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('packages_list_row', () => {
let wrapper;
let store;
......@@ -14,36 +10,27 @@ describe('packages_list_row', () => {
const [packageWithoutTags, packageWithTags] = packageList;
const findPackageTags = () => wrapper.find(PackageTags);
const findProjectLink = () => wrapper.find({ ref: 'packages-row-project' });
const findDeleteButton = () => wrapper.find({ ref: 'action-delete' });
const findProjectLink = () => wrapper.find('[data-testid="packages-row-project"]');
const findDeleteButton = () => wrapper.find('[data-testid="action-delete"]');
const findPackageType = () => wrapper.find('[data-testid="package-type"]');
const mountComponent = (
isGroupPage = false,
const mountComponent = ({
isGroup = false,
packageEntity = packageWithoutTags,
shallow = true,
) => {
showPackageType = true,
disableDelete = false,
} = {}) => {
const mountFunc = shallow ? shallowMount : mount;
const state = {
config: {
isGroupPage,
},
};
store = new Vuex.Store({
state,
getters: {
getCommitLink: () => () => {
return 'commit-link';
},
},
});
wrapper = mountFunc(PackagesListRow, {
localVue,
store,
propsData: {
packageLink: 'foo',
packageEntity,
isGroup,
showPackageType,
disableDelete,
},
});
};
......@@ -60,7 +47,7 @@ describe('packages_list_row', () => {
describe('tags', () => {
it('renders package tags when a package has tags', () => {
mountComponent(false, packageWithTags);
mountComponent({ isGroup: false, packageEntity: packageWithTags });
expect(findPackageTags().exists()).toBe(true);
});
......@@ -72,9 +59,9 @@ describe('packages_list_row', () => {
});
});
describe('when is isGroupPage', () => {
describe('when is is group', () => {
beforeEach(() => {
mountComponent(true);
mountComponent({ isGroup: true });
});
it('has project field', () => {
......@@ -86,8 +73,32 @@ describe('packages_list_row', () => {
});
});
describe('showPackageType', () => {
it('shows the type when set', () => {
mountComponent();
expect(findPackageType().exists()).toBe(true);
});
it('does not show the type when not set', () => {
mountComponent({ showPackageType: false });
expect(findPackageType().exists()).toBe(false);
});
});
describe('deleteAvailable', () => {
it('does not show when not set', () => {
mountComponent({ disableDelete: true });
expect(findDeleteButton().exists()).toBe(false);
});
});
describe('delete event', () => {
beforeEach(() => mountComponent(false, packageWithoutTags, false));
beforeEach(() =>
mountComponent({ isGroup: false, packageEntity: packageWithoutTags, shallow: false }),
);
it('emits the packageToDelete event when the delete button is clicked', () => {
findDeleteButton().trigger('click');
......
import { mount } from '@vue/test-utils';
import PackagesListLoader from 'ee/packages/list/components/packages_list_loader.vue';
import PackagesListLoader from 'ee/packages/shared/components/packages_list_loader.vue';
describe('PackagesListLoader', () => {
let wrapper;
......
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import PublishMethod from 'ee/packages/list/components/publish_method.vue';
import { shallowMount } from '@vue/test-utils';
import PublishMethod from 'ee/packages/shared/components/publish_method.vue';
import { packageList } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('publish_method', () => {
let wrapper;
let store;
const [packageWithoutPipeline, packageWithPipeline] = packageList;
......@@ -16,20 +11,11 @@ describe('publish_method', () => {
const findPipelineSha = () => wrapper.find({ ref: 'pipeline-sha' });
const findManualPublish = () => wrapper.find({ ref: 'manual-ref' });
const mountComponent = packageEntity => {
store = new Vuex.Store({
getters: {
getCommitLink: () => () => {
return 'commit-link';
},
},
});
const mountComponent = (packageEntity = {}, isGroup = false) => {
wrapper = shallowMount(PublishMethod, {
localVue,
store,
propsData: {
packageEntity,
isGroup,
},
});
};
......
......@@ -2,8 +2,10 @@ import {
packageTypeToTrackCategory,
beautifyPath,
getPackageTypeLabel,
getCommitLink,
} from 'ee/packages/shared/utils';
import { PackageType, TrackingCategories } from 'ee/packages/shared/constants';
import { packageList } from '../mock_data';
describe('Packages shared utils', () => {
describe('packageTypeToTrackCategory', () => {
......@@ -43,4 +45,21 @@ describe('Packages shared utils', () => {
});
});
});
describe('getCommitLink', () => {
it('returns a relative link when isGroup is false', () => {
const link = getCommitLink(packageList[0], false);
expect(link).toContain('../commit');
});
describe('when isGroup is true', () => {
it('returns an absolute link matching project path', () => {
const mavenPackage = packageList[0];
const link = getCommitLink(mavenPackage, true);
expect(link).toContain(`/${mavenPackage.project_path}/commit`);
});
});
});
});
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