Commit 14fb668e authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

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

Refactor package metadata to apollo aproach

See merge request gitlab-org/gitlab!67122
parents c63d8bdb fce54015
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import { PackageType } from '~/packages/shared/constants';
import {
PACKAGE_TYPE_NUGET,
PACKAGE_TYPE_CONAN,
PACKAGE_TYPE_MAVEN,
} from '~/packages_and_registries/package_registry/constants';
import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
export default {
......@@ -25,12 +29,18 @@ export default {
},
computed: {
showMetadata() {
const visibilityConditions = {
[PackageType.NUGET]: this.packageEntity.nuget_metadatum,
[PackageType.CONAN]: this.packageEntity.conan_metadatum,
[PackageType.MAVEN]: this.packageEntity.maven_metadatum,
};
return visibilityConditions[this.packageEntity.package_type];
return [PACKAGE_TYPE_NUGET, PACKAGE_TYPE_CONAN, PACKAGE_TYPE_MAVEN].includes(
this.packageEntity.packageType,
);
},
showNugetMetadata() {
return this.packageEntity.packageType === PACKAGE_TYPE_NUGET;
},
showConanMetadata() {
return this.packageEntity.packageType === PACKAGE_TYPE_CONAN;
},
showMavenMetadata() {
return this.packageEntity.packageType === PACKAGE_TYPE_MAVEN;
},
},
};
......@@ -41,12 +51,12 @@ export default {
<h3 class="gl-font-lg" data-testid="title">{{ __('Additional Metadata') }}</h3>
<div class="gl-bg-gray-50 gl-inset-border-1-gray-100 gl-rounded-base" data-testid="main">
<template v-if="packageEntity.nuget_metadatum">
<template v-if="showNugetMetadata">
<details-row icon="project" padding="gl-p-4" dashed data-testid="nuget-source">
<gl-sprintf :message="$options.i18n.sourceText">
<template #link>
<gl-link :href="packageEntity.nuget_metadatum.project_url" target="_blank">{{
packageEntity.nuget_metadatum.project_url
<gl-link :href="packageEntity.metadata.projectUrl" target="_blank">{{
packageEntity.metadata.projectUrl
}}</gl-link>
</template>
</gl-sprintf>
......@@ -54,8 +64,8 @@ export default {
<details-row icon="license" padding="gl-p-4" data-testid="nuget-license">
<gl-sprintf :message="$options.i18n.licenseText">
<template #link>
<gl-link :href="packageEntity.nuget_metadatum.license_url" target="_blank">{{
packageEntity.nuget_metadatum.license_url
<gl-link :href="packageEntity.metadata.licenseUrl" target="_blank">{{
packageEntity.metadata.licenseUrl
}}</gl-link>
</template>
</gl-sprintf>
......@@ -63,28 +73,28 @@ export default {
</template>
<details-row
v-else-if="packageEntity.conan_metadatum"
v-else-if="showConanMetadata"
icon="information-o"
padding="gl-p-4"
data-testid="conan-recipe"
>
<gl-sprintf :message="$options.i18n.recipeText">
<template #recipe>{{ packageEntity.name }}</template>
<template #recipe>{{ packageEntity.metadata.recipe }}</template>
</gl-sprintf>
</details-row>
<template v-else-if="packageEntity.maven_metadatum">
<template v-else-if="showMavenMetadata">
<details-row icon="information-o" padding="gl-p-4" dashed data-testid="maven-app">
<gl-sprintf :message="$options.i18n.appName">
<template #name>
<strong>{{ packageEntity.maven_metadatum.app_name }}</strong>
<strong>{{ packageEntity.metadata.appName }}</strong>
</template>
</gl-sprintf>
</details-row>
<details-row icon="information-o" padding="gl-p-4" data-testid="maven-group">
<gl-sprintf :message="$options.i18n.appGroup">
<template #group>
<strong>{{ packageEntity.maven_metadatum.app_group }}</strong>
<strong>{{ packageEntity.metadata.appGroup }}</strong>
</template>
</gl-sprintf>
</details-row>
......
......@@ -19,13 +19,13 @@ import { convertToGraphQLId } from '~/graphql_shared/utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { objectToQuery } from '~/lib/utils/url_utility';
import { s__, __ } from '~/locale';
// import AdditionalMetadata from '~/packages/details/components/additional_metadata.vue';
// 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 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 AdditionalMetadata from '~/packages_and_registries/package_registry/components/details/additional_metadata.vue';
import PackageHistory from '~/packages_and_registries/package_registry/components/details/package_history.vue';
import {
PACKAGE_TYPE_NUGET,
......@@ -61,7 +61,7 @@ export default {
// PackageListRow,
// DependencyRow,
PackageHistory,
// AdditionalMetadata,
AdditionalMetadata,
// InstallationCommands,
// PackageFiles,
},
......@@ -244,9 +244,9 @@ export default {
:package-entity="packageEntity"
:npm-path="npmPath"
:npm-help-path="npmHelpPath"
/>
/> -->
<additional-metadata :package-entity="packageEntity" /> -->
<additional-metadata :package-entity="packageEntity" />
</div>
<!-- <package-files
......
{
"__schema": {
"types": [
{
"kind": "UNION",
"name": "PackageMetadata",
"possibleTypes": [
{ "name": "ComposerMetadata" },
{ "name": "ConanMetadata" },
{ "name": "MavenMetadata" },
{ "name": "NugetMetadata" },
{ "name": "PypiMetadata" }
]
}
]
}
}
import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import introspectionQueryResultData from './fragmentTypes.json';
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData,
});
Vue.use(VueApollo);
......@@ -8,6 +14,9 @@ export const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
{},
{
cacheConfig: {
fragmentMatcher,
},
assumeImmutableResults: true,
},
),
......
......@@ -40,5 +40,35 @@ query getPackageDetails($id: ID!) {
size
}
}
metadata {
... on ComposerMetadata {
targetSha
composerJson {
license
version
}
}
... on PypiMetadata {
requiredPython
}
... on ConanMetadata {
packageChannel
packageUsername
recipe
recipePath
}
... on MavenMetadata {
appName
appGroup
appVersion
path
}
... on NugetMetadata {
iconUrl
licenseUrl
projectUrl
}
}
}
}
import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { mavenPackage, conanPackage, nugetPackage, npmPackage } from 'jest/packages/mock_data';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
conanMetadata,
mavenMetadata,
nugetMetadata,
packageData,
} from 'jest/packages_and_registries/package_registry/mock_data';
import component from '~/packages_and_registries/package_registry/components/details/additional_metadata.vue';
import {
PACKAGE_TYPE_NUGET,
PACKAGE_TYPE_CONAN,
PACKAGE_TYPE_MAVEN,
PACKAGE_TYPE_NPM,
} from '~/packages_and_registries/package_registry/constants';
import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
const mavenPackage = { packageType: PACKAGE_TYPE_MAVEN, metadata: mavenMetadata() };
const conanPackage = { packageType: PACKAGE_TYPE_CONAN, metadata: conanMetadata() };
const nugetPackage = { packageType: PACKAGE_TYPE_NUGET, metadata: nugetMetadata() };
const npmPackage = { packageType: PACKAGE_TYPE_NPM, metadata: {} };
describe('Package Additional Metadata', () => {
let wrapper;
const defaultProps = {
packageEntity: { ...mavenPackage },
packageEntity: {
...packageData(mavenPackage),
},
};
const mountComponent = (props) => {
wrapper = shallowMount(component, {
wrapper = shallowMountExtended(component, {
propsData: { ...defaultProps, ...props },
stubs: {
DetailsRow,
......@@ -25,14 +43,14 @@ describe('Package Additional Metadata', () => {
wrapper = null;
});
const findTitle = () => wrapper.find('[data-testid="title"]');
const findMainArea = () => wrapper.find('[data-testid="main"]');
const findNugetSource = () => wrapper.find('[data-testid="nuget-source"]');
const findNugetLicense = () => wrapper.find('[data-testid="nuget-license"]');
const findConanRecipe = () => wrapper.find('[data-testid="conan-recipe"]');
const findMavenApp = () => wrapper.find('[data-testid="maven-app"]');
const findMavenGroup = () => wrapper.find('[data-testid="maven-group"]');
const findElementLink = (container) => container.find(GlLink);
const findTitle = () => wrapper.findByTestId('title');
const findMainArea = () => wrapper.findByTestId('main');
const findNugetSource = () => wrapper.findByTestId('nuget-source');
const findNugetLicense = () => wrapper.findByTestId('nuget-license');
const findConanRecipe = () => wrapper.findByTestId('conan-recipe');
const findMavenApp = () => wrapper.findByTestId('maven-app');
const findMavenGroup = () => wrapper.findByTestId('maven-group');
const findElementLink = (container) => container.findComponent(GlLink);
it('has the correct title', () => {
mountComponent();
......@@ -43,27 +61,21 @@ describe('Package Additional Metadata', () => {
expect(title.text()).toBe('Additional Metadata');
});
describe.each`
packageEntity | visible | metadata
${mavenPackage} | ${true} | ${'maven_metadatum'}
${conanPackage} | ${true} | ${'conan_metadatum'}
${nugetPackage} | ${true} | ${'nuget_metadatum'}
${npmPackage} | ${false} | ${null}
`('Component visibility', ({ packageEntity, visible, metadata }) => {
it(`Is ${visible} that the component markup is visible when the package is ${packageEntity.package_type}`, () => {
it.each`
packageEntity | visible | packageType
${mavenPackage} | ${true} | ${PACKAGE_TYPE_MAVEN}
${conanPackage} | ${true} | ${PACKAGE_TYPE_CONAN}
${nugetPackage} | ${true} | ${PACKAGE_TYPE_NUGET}
${npmPackage} | ${false} | ${PACKAGE_TYPE_NPM}
`(
`It is $visible that the component is visible when the package is $packageType`,
({ packageEntity, visible }) => {
mountComponent({ packageEntity });
expect(findTitle().exists()).toBe(visible);
expect(findMainArea().exists()).toBe(visible);
});
it(`The component is hidden if ${metadata} is missing`, () => {
mountComponent({ packageEntity: { ...packageEntity, [metadata]: null } });
expect(findTitle().exists()).toBe(false);
expect(findMainArea().exists()).toBe(false);
});
});
},
);
describe('nuget metadata', () => {
beforeEach(() => {
......@@ -71,15 +83,15 @@ describe('Package Additional Metadata', () => {
});
it.each`
name | finderFunction | text | link | icon
${'source'} | ${findNugetSource} | ${'Source project located at project-foo-url'} | ${'project_url'} | ${'project'}
${'license'} | ${findNugetLicense} | ${'License information located at license-foo-url'} | ${'license_url'} | ${'license'}
name | finderFunction | text | link | icon
${'source'} | ${findNugetSource} | ${'Source project located at projectUrl'} | ${'projectUrl'} | ${'project'}
${'license'} | ${findNugetLicense} | ${'License information located at licenseUrl'} | ${'licenseUrl'} | ${'license'}
`('$name element', ({ finderFunction, text, link, icon }) => {
const element = finderFunction();
expect(element.exists()).toBe(true);
expect(element.text()).toBe(text);
expect(element.props('icon')).toBe(icon);
expect(findElementLink(element).attributes('href')).toBe(nugetPackage.nuget_metadatum[link]);
expect(findElementLink(element).attributes('href')).toBe(nugetPackage.metadata[link]);
});
});
......@@ -89,8 +101,8 @@ describe('Package Additional Metadata', () => {
});
it.each`
name | finderFunction | text | icon
${'recipe'} | ${findConanRecipe} | ${'Recipe: conan-package/1.0.0@conan+conan-package/stable'} | ${'information-o'}
name | finderFunction | text | icon
${'recipe'} | ${findConanRecipe} | ${'Recipe: package-8/1.0.0@gitlab-org+gitlab-test/stable'} | ${'information-o'}
`('$name element', ({ finderFunction, text, icon }) => {
const element = finderFunction();
expect(element.exists()).toBe(true);
......@@ -105,9 +117,9 @@ describe('Package Additional Metadata', () => {
});
it.each`
name | finderFunction | text | icon
${'app'} | ${findMavenApp} | ${'App name: test-app'} | ${'information-o'}
${'group'} | ${findMavenGroup} | ${'App group: com.test.app'} | ${'information-o'}
name | finderFunction | text | icon
${'app'} | ${findMavenApp} | ${'App name: appName'} | ${'information-o'}
${'group'} | ${findMavenGroup} | ${'App group: appGroup'} | ${'information-o'}
`('$name element', ({ finderFunction, text, icon }) => {
const element = finderFunction();
expect(element.exists()).toBe(true);
......
......@@ -5,6 +5,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import AdditionalMetadata from '~/packages_and_registries/package_registry/components/details/additional_metadata.vue';
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';
......@@ -48,6 +49,7 @@ describe('PackagesApp', () => {
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findPackageTitle = () => wrapper.findComponent(PackageTitle);
const findPackageHistory = () => wrapper.findComponent(PackageHistory);
const findAdditionalMetadata = () => wrapper.findComponent(AdditionalMetadata);
afterEach(() => {
wrapper.destroy();
......@@ -95,4 +97,15 @@ describe('PackagesApp', () => {
projectName: provide.projectName,
});
});
it('renders additional metadata and has the right props', async () => {
createComponent();
await waitForPromises();
expect(findAdditionalMetadata().exists()).toBe(true);
expect(findAdditionalMetadata().props()).toMatchObject({
packageEntity: expect.objectContaining(packageData()),
});
});
});
......@@ -58,10 +58,49 @@ export const packageData = (extend) => ({
...extend,
});
export const conanMetadata = () => ({
packageChannel: 'stable',
packageUsername: 'gitlab-org+gitlab-test',
recipe: 'package-8/1.0.0@gitlab-org+gitlab-test/stable',
recipePath: 'package-8/1.0.0/gitlab-org+gitlab-test/stable',
});
export const composerMetadata = () => ({
targetSha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0',
composerJson: {
license: 'MIT',
version: '1.0.0',
},
});
export const pypyMetadata = () => ({
requiredPython: '1.0.0',
});
export const mavenMetadata = () => ({
appName: 'appName',
appGroup: 'appGroup',
appVersion: 'appVersion',
path: 'path',
});
export const nugetMetadata = () => ({
iconUrl: 'iconUrl',
licenseUrl: 'licenseUrl',
projectUrl: 'projectUrl',
});
export const packageDetailsQuery = () => ({
data: {
package: {
...packageData(),
metadata: {
...conanMetadata(),
...composerMetadata(),
...pypyMetadata(),
...mavenMetadata(),
...nugetMetadata(),
},
tags: {
nodes: packageTags(),
__typename: 'PackageTagConnection',
......
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