Commit 7c85f127 authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '330847-convert-package-details-page-to-use-graphql' into 'master'

Refactor history component to new apollo aproach

See merge request gitlab-org/gitlab!66749
parents 15cf698b 869367a4
......@@ -23,10 +23,10 @@ import { s__, __ } from '~/locale';
// import DependencyRow from '~/packages/details/components/dependency_row.vue';
// import InstallationCommands from '~/packages/details/components/installation_commands.vue';
// import PackageFiles from '~/packages/details/components/package_files.vue';
// import PackageHistory from '~/packages/details/components/package_history.vue';
// import PackageListRow from '~/packages/shared/components/package_list_row.vue';
import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
import { packageTypeToTrackCategory } from '~/packages/shared/utils';
import PackageHistory from '~/packages_and_registries/package_registry/components/details/package_history.vue';
import {
PACKAGE_TYPE_NUGET,
PACKAGE_TYPE_COMPOSER,
......@@ -60,7 +60,7 @@ export default {
PackagesListLoader,
// PackageListRow,
// DependencyRow,
// PackageHistory,
PackageHistory,
// AdditionalMetadata,
// InstallationCommands,
// PackageFiles,
......@@ -124,10 +124,10 @@ export default {
return this.packageEntity.packageFiles;
},
isLoading() {
return this.$apollo.queries.package;
return this.$apollo.queries.packageEntity.loading;
},
isValidPackage() {
return Boolean(this.packageEntity?.name);
return this.isLoading || Boolean(this.packageEntity?.name);
},
tracking() {
return {
......@@ -237,10 +237,10 @@ export default {
<gl-tabs>
<gl-tab :title="__('Detail')">
<div data-qa-selector="package_information_content">
<!-- <package-history :package-entity="packageEntity" :project-name="projectName" />
<div v-if="!isLoading" data-qa-selector="package_information_content">
<package-history :package-entity="packageEntity" :project-name="projectName" />
<installation-commands
<!-- <installation-commands
:package-entity="packageEntity"
:npm-path="npmPath"
:npm-help-path="npmHelpPath"
......
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { first } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { s__, n__ } from '~/locale';
import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
......@@ -45,7 +46,7 @@ export default {
},
computed: {
pipelines() {
return this.packageEntity.pipelines || [];
return this.packageEntity?.pipelines?.nodes || [];
},
firstPipeline() {
return first(this.pipelines);
......@@ -71,6 +72,9 @@ export default {
truncate(value) {
return truncateSha(value);
},
convertToBaseId(value) {
return getIdFromGraphQLId(value);
},
},
};
</script>
......@@ -88,7 +92,7 @@ export default {
<strong>{{ packageEntity.version }}</strong>
</template>
<template #datetime>
<time-ago-tooltip :time="packageEntity.created_at" />
<time-ago-tooltip :time="packageEntity.createdAt" />
</template>
</gl-sprintf>
</history-item>
......@@ -98,9 +102,7 @@ export default {
<history-item icon="commit" data-testid="first-pipeline-commit">
<gl-sprintf :message="$options.i18n.createdByCommitText">
<template #link>
<gl-link :href="firstPipeline.project.commit_url"
>#{{ truncate(firstPipeline.sha) }}</gl-link
>
<gl-link :href="firstPipeline.commitPath">#{{ truncate(firstPipeline.sha) }}</gl-link>
</template>
<template #branch>
<strong>{{ firstPipeline.ref }}</strong>
......@@ -110,10 +112,10 @@ export default {
<history-item icon="pipeline" data-testid="first-pipeline-pipeline">
<gl-sprintf :message="$options.i18n.createdByPipelineText">
<template #link>
<gl-link :href="firstPipeline.project.pipeline_url">#{{ firstPipeline.id }}</gl-link>
<gl-link :href="firstPipeline.path">#{{ convertToBaseId(firstPipeline.id) }}</gl-link>
</template>
<template #datetime>
<time-ago-tooltip :time="firstPipeline.created_at" />
<time-ago-tooltip :time="firstPipeline.createdAt" />
</template>
<template #author>{{ firstPipeline.user.name }}</template>
</gl-sprintf>
......@@ -127,7 +129,7 @@ export default {
<strong>{{ projectName }}</strong>
</template>
<template #datetime>
<time-ago-tooltip :time="packageEntity.created_at" />
<time-ago-tooltip :time="packageEntity.createdAt" />
</template>
</gl-sprintf>
</history-item>
......@@ -149,16 +151,16 @@ export default {
>
<gl-sprintf :message="$options.i18n.combinedUpdateText">
<template #link>
<gl-link :href="pipeline.project.commit_url">#{{ truncate(pipeline.sha) }}</gl-link>
<gl-link :href="pipeline.commitPath">#{{ truncate(pipeline.sha) }}</gl-link>
</template>
<template #branch>
<strong>{{ pipeline.ref }}</strong>
</template>
<template #pipeline>
<gl-link :href="pipeline.project.pipeline_url">#{{ pipeline.id }}</gl-link>
<gl-link :href="pipeline.path">#{{ convertToBaseId(pipeline.id) }}</gl-link>
</template>
<template #datetime>
<time-ago-tooltip :time="pipeline.created_at" />
<time-ago-tooltip :time="pipeline.createdAt" />
</template>
</gl-sprintf>
</history-item>
......
......@@ -15,13 +15,22 @@ query getPackageDetails($id: ID!) {
}
pipelines(first: 3) {
nodes {
ref
id
sha
createdAt
commitPath
path
user {
name
}
project {
name
webUrl
}
}
}
packageFiles(first: 1000) {
packageFiles(first: 100) {
nodes {
id
fileMd5
......
......@@ -6,10 +6,11 @@ import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import PackagesApp from '~/packages_and_registries/package_registry/components/details/app.vue';
import PackageHistory from '~/packages_and_registries/package_registry/components/details/package_history.vue';
import PackageTitle from '~/packages_and_registries/package_registry/components/details/package_title.vue';
import { FETCH_PACKAGE_DETAILS_ERROR_MESSAGE } from '~/packages_and_registries/package_registry/constants';
import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql';
import { packageDetailsQuery, packageData } from '../../mock_data';
import { packageDetailsQuery, packageData, emptyPackageDetailsQuery } from '../../mock_data';
jest.mock('~/flash');
......@@ -19,6 +20,18 @@ describe('PackagesApp', () => {
let wrapper;
let apolloProvider;
const provide = {
packageId: '111',
titleComponent: 'PackageTitle',
projectName: 'projectName',
canDelete: 'canDelete',
svgPath: 'svgPath',
npmPath: 'npmPath',
npmHelpPath: 'npmHelpPath',
projectListUrl: 'projectListUrl',
groupListUrl: 'groupListUrl',
};
function createComponent({ resolver = jest.fn().mockResolvedValue(packageDetailsQuery()) } = {}) {
localVue.use(VueApollo);
......@@ -28,29 +41,22 @@ describe('PackagesApp', () => {
wrapper = shallowMount(PackagesApp, {
localVue,
apolloProvider,
provide: {
packageId: '111',
titleComponent: 'PackageTitle',
projectName: 'projectName',
canDelete: 'canDelete',
svgPath: 'svgPath',
npmPath: 'npmPath',
npmHelpPath: 'npmHelpPath',
projectListUrl: 'projectListUrl',
groupListUrl: 'groupListUrl',
},
provide,
});
}
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findPackageTitle = () => wrapper.findComponent(PackageTitle);
const findPackageHistory = () => wrapper.findComponent(PackageHistory);
afterEach(() => {
wrapper.destroy();
});
it('renders an empty state component', () => {
createComponent();
it('renders an empty state component', async () => {
createComponent({ resolver: jest.fn().mockResolvedValue(emptyPackageDetailsQuery) });
await waitForPromises();
expect(findEmptyState().exists()).toBe(true);
});
......@@ -77,4 +83,16 @@ describe('PackagesApp', () => {
}),
);
});
it('renders history and has the right props', async () => {
createComponent();
await waitForPromises();
expect(findPackageHistory().exists()).toBe(true);
expect(findPackageHistory().props()).toMatchObject({
packageEntity: expect.objectContaining(packageData()),
projectName: provide.projectName,
});
});
});
import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
import { mavenPackage, mockPipelineInfo } from 'jest/packages/mock_data';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
packageData,
packagePipelines,
} from 'jest/packages_and_registries/package_registry/mock_data';
import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
import component from '~/packages_and_registries/package_registry/components/details/package_history.vue';
import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
......@@ -11,14 +14,16 @@ describe('Package History', () => {
let wrapper;
const defaultProps = {
projectName: 'baz project',
packageEntity: { ...mavenPackage },
packageEntity: { ...packageData() },
};
const [onePipeline] = packagePipelines();
const createPipelines = (amount) =>
[...Array(amount)].map((x, index) => ({ ...mockPipelineInfo, id: index + 1 }));
[...Array(amount)].map((x, index) => packagePipelines({ id: index + 1 })[0]);
const mountComponent = (props) => {
wrapper = shallowMount(component, {
wrapper = shallowMountExtended(component, {
propsData: { ...defaultProps, ...props },
stubs: {
HistoryItem: stubComponent(HistoryItem, {
......@@ -31,14 +36,13 @@ describe('Package History', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
const findHistoryElement = (testId) => wrapper.find(`[data-testid="${testId}"]`);
const findElementLink = (container) => container.find(GlLink);
const findElementTimeAgo = (container) => container.find(TimeAgoTooltip);
const findTitle = () => wrapper.find('[data-testid="title"]');
const findTimeline = () => wrapper.find('[data-testid="timeline"]');
const findHistoryElement = (testId) => wrapper.findByTestId(testId);
const findElementLink = (container) => container.findComponent(GlLink);
const findElementTimeAgo = (container) => container.findComponent(TimeAgoTooltip);
const findTitle = () => wrapper.findByTestId('title');
const findTimeline = () => wrapper.findByTestId('timeline');
it('has the correct title', () => {
mountComponent();
......@@ -59,23 +63,25 @@ describe('Package History', () => {
expect.arrayContaining(['timeline', 'main-notes-list', 'notes']),
);
});
describe.each`
name | amount | icon | text | timeAgoTooltip | link
${'created-on'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'clock'} | ${'Test package version 1.0.0 was first created'} | ${mavenPackage.created_at} | ${null}
${'first-pipeline-commit'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'commit'} | ${'Created by commit #sha-baz on branch branch-name'} | ${null} | ${mockPipelineInfo.project.commit_url}
${'first-pipeline-pipeline'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'pipeline'} | ${'Built by pipeline #1 triggered by foo'} | ${mockPipelineInfo.created_at} | ${mockPipelineInfo.project.pipeline_url}
${'published'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'package'} | ${'Published to the baz project Package Registry'} | ${mavenPackage.created_at} | ${null}
${'archived'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'history'} | ${'Package has 1 archived update'} | ${null} | ${null}
${'archived'} | ${HISTORY_PIPELINES_LIMIT + 3} | ${'history'} | ${'Package has 2 archived updates'} | ${null} | ${null}
${'pipeline-entry'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'pencil'} | ${'Package updated by commit #sha-baz on branch branch-name, built by pipeline #3, and published to the registry'} | ${mavenPackage.created_at} | ${mockPipelineInfo.project.commit_url}
name | amount | icon | text | timeAgoTooltip | link
${'created-on'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'clock'} | ${'@gitlab-org/package-15 version 1.0.0 was first created'} | ${packageData().createdAt} | ${null}
${'first-pipeline-commit'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'commit'} | ${'Created by commit #b83d6e39 on branch master'} | ${null} | ${onePipeline.commitPath}
${'first-pipeline-pipeline'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'pipeline'} | ${'Built by pipeline #1 triggered by Administrator'} | ${onePipeline.createdAt} | ${onePipeline.path}
${'published'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'package'} | ${'Published to the baz project Package Registry'} | ${packageData().createdAt} | ${null}
${'archived'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'history'} | ${'Package has 1 archived update'} | ${null} | ${null}
${'archived'} | ${HISTORY_PIPELINES_LIMIT + 3} | ${'history'} | ${'Package has 2 archived updates'} | ${null} | ${null}
${'pipeline-entry'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'pencil'} | ${'Package updated by commit #b83d6e39 on branch master, built by pipeline #3, and published to the registry'} | ${packageData().createdAt} | ${onePipeline.commitPath}
`(
'with $amount pipelines history element $name',
({ name, icon, text, timeAgoTooltip, link, amount }) => {
let element;
beforeEach(() => {
const packageEntity = { ...packageData(), pipelines: { nodes: createPipelines(amount) } };
mountComponent({
packageEntity: { ...mavenPackage, pipelines: createPipelines(amount) },
packageEntity,
});
element = findHistoryElement(name);
});
......
......@@ -6,11 +6,21 @@ export const packageTags = () => [
export const packagePipelines = (extend) => [
{
commitPath: '/namespace14/project14/-/commit/b83d6e391c22777fca1ed3012fce84f633d7fed0',
createdAt: '2020-08-17T14:23:32Z',
id: 'gid://gitlab/Ci::Pipeline/36',
path: '/namespace14/project14/-/pipelines/36',
name: 'project14',
ref: 'master',
sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0',
project: {
name: 'project14',
webUrl: 'http://gdk.test:3000/namespace14/project14',
__typename: 'Project',
},
user: {
name: 'Administrator',
},
...extend,
__typename: 'Pipeline',
},
......@@ -68,3 +78,11 @@ export const packageDetailsQuery = () => ({
},
},
});
export const emptyPackageDetailsQuery = () => ({
data: {
package: {
__typename: 'PackageDetailsType',
},
},
});
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