Commit b8592751 authored by Sarah Groff Hennigh-Palermo's avatar Sarah Groff Hennigh-Palermo

Merge branch 'integrate-graphql-with-pipeline-status' into 'master'

Integrate new pipeline query for pipeline editor

See merge request gitlab-org/gitlab!54888
parents da037a99 2087e3e2
<script> <script>
import { GlIcon, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui'; import { GlIcon, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import getCommitSha from '~/pipeline_editor/graphql/queries/client/commit_sha.graphql'; import getCommitSha from '~/pipeline_editor/graphql/queries/client/commit_sha.graphql';
import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql'; import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
import { toggleQueryPollingByVisibility } from '~/pipelines/components/graph/utils';
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
const POLL_INTERVAL = 10000; const POLL_INTERVAL = 10000;
...@@ -38,13 +40,11 @@ export default { ...@@ -38,13 +40,11 @@ export default {
}; };
}, },
update: (data) => { update: (data) => {
const { id, commitPath = '', shortSha = '', detailedStatus = {} } = const { id, commitPath = '', detailedStatus = {} } = data.project?.pipeline || {};
data.project?.pipeline || {};
return { return {
id, id,
commitPath, commitPath,
shortSha,
detailedStatus, detailedStatus,
}; };
}, },
...@@ -61,24 +61,34 @@ export default { ...@@ -61,24 +61,34 @@ export default {
}, },
computed: { computed: {
hasPipelineData() { hasPipelineData() {
return Boolean(this.$apollo.queries.pipeline?.id); return Boolean(this.pipeline?.id);
}, },
isQueryLoading() { pipelineId() {
return this.$apollo.queries.pipeline.loading && !this.hasPipelineData; return getIdFromGraphQLId(this.pipeline.id);
},
showLoadingState() {
// the query is set to poll regularly, so if there is no pipeline data
// (e.g. pipeline is null during fetch when the pipeline hasn't been
// triggered yet), we can just show the loading state until the pipeline
// details are ready to be fetched
return this.$apollo.queries.pipeline.loading || (!this.hasPipelineData && !this.hasError);
},
shortSha() {
return truncateSha(this.commitSha);
}, },
status() { status() {
return this.pipeline.detailedStatus; return this.pipeline.detailedStatus;
}, },
pipelineId() {
return getIdFromGraphQLId(this.pipeline.id);
}, },
mounted() {
toggleQueryPollingByVisibility(this.$apollo.queries.pipeline, POLL_INTERVAL);
}, },
}; };
</script> </script>
<template> <template>
<div class="gl-white-space-nowrap gl-max-w-full"> <div class="gl-white-space-nowrap gl-max-w-full">
<template v-if="isQueryLoading"> <template v-if="showLoadingState">
<gl-loading-icon class="gl-mr-auto gl-display-inline-block" size="sm" /> <gl-loading-icon class="gl-mr-auto gl-display-inline-block" size="sm" />
<span data-testid="pipeline-loading-msg">{{ $options.i18n.fetchLoading }}</span> <span data-testid="pipeline-loading-msg">{{ $options.i18n.fetchLoading }}</span>
</template> </template>
...@@ -110,7 +120,7 @@ export default { ...@@ -110,7 +120,7 @@ export default {
target="_blank" target="_blank"
data-testid="pipeline-commit" data-testid="pipeline-commit"
> >
{{ pipeline.shortSha }} {{ shortSha }}
</gl-link> </gl-link>
</template> </template>
</gl-sprintf> </gl-sprintf>
......
query getPipeline($fullPath: ID!, $sha: String!) { query getPipeline($fullPath: ID!, $sha: String!) {
project(fullPath: $fullPath) @client { project(fullPath: $fullPath) {
pipeline(sha: $sha) { pipeline(sha: $sha) {
commitPath commitPath
id id
iid iid
shortSha
status status
detailedStatus { detailedStatus {
detailsPath detailsPath
......
...@@ -11,29 +11,6 @@ export const resolvers = { ...@@ -11,29 +11,6 @@ export const resolvers = {
}), }),
}; };
}, },
/* eslint-disable @gitlab/require-i18n-strings */
project() {
return {
__typename: 'Project',
pipeline: {
__typename: 'Pipeline',
commitPath: `/-/commit/aabbccdd`,
id: 'gid://gitlab/Ci::Pipeline/118',
iid: '28',
shortSha: 'aabbccdd',
status: 'SUCCESS',
detailedStatus: {
__typename: 'DetailedStatus',
detailsPath: '/root/sample-ci-project/-/pipelines/118"',
group: 'success',
icon: 'status_success',
text: 'passed',
},
},
};
},
/* eslint-enable @gitlab/require-i18n-strings */
}, },
Mutation: { Mutation: {
lintCI: (_, { endpoint, content, dry_run }) => { lintCI: (_, { endpoint, content, dry_run }) => {
......
...@@ -4,6 +4,7 @@ import VueApollo from 'vue-apollo'; ...@@ -4,6 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import PipelineStatus, { i18n } from '~/pipeline_editor/components/header/pipeline_status.vue'; import PipelineStatus, { i18n } from '~/pipeline_editor/components/header/pipeline_status.vue';
import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data'; import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data';
...@@ -19,32 +20,9 @@ describe('Pipeline Status', () => { ...@@ -19,32 +20,9 @@ describe('Pipeline Status', () => {
let mockApollo; let mockApollo;
let mockPipelineQuery; let mockPipelineQuery;
const createComponent = ({ hasPipeline = true, isQueryLoading = false }) => {
const pipeline = hasPipeline
? { loading: isQueryLoading, ...mockProjectPipeline.pipeline }
: { loading: isQueryLoading };
wrapper = shallowMount(PipelineStatus, {
provide: mockProvide,
stubs: { GlLink, GlSprintf },
data: () => (hasPipeline ? { pipeline } : {}),
mocks: {
$apollo: {
queries: {
pipeline,
},
},
},
});
};
const createComponentWithApollo = () => { const createComponentWithApollo = () => {
const resolvers = { const handlers = [[getPipelineQuery, mockPipelineQuery]];
Query: { mockApollo = createMockApollo(handlers);
project: mockPipelineQuery,
},
};
mockApollo = createMockApollo([], resolvers);
wrapper = shallowMount(PipelineStatus, { wrapper = shallowMount(PipelineStatus, {
localVue, localVue,
...@@ -78,16 +56,17 @@ describe('Pipeline Status', () => { ...@@ -78,16 +56,17 @@ describe('Pipeline Status', () => {
wrapper = null; wrapper = null;
}); });
describe('while querying', () => { describe('loading icon', () => {
it('renders loading icon', () => { it('renders while query is being fetched', () => {
createComponent({ isQueryLoading: true, hasPipeline: false }); createComponentWithApollo();
expect(findLoadingIcon().exists()).toBe(true); expect(findLoadingIcon().exists()).toBe(true);
expect(findPipelineLoadingMsg().text()).toBe(i18n.fetchLoading); expect(findPipelineLoadingMsg().text()).toBe(i18n.fetchLoading);
}); });
it('does not render loading icon if pipeline data is already set', () => { it('does not render if query is no longer loading', async () => {
createComponent({ isQueryLoading: true }); createComponentWithApollo();
await waitForPromises();
expect(findLoadingIcon().exists()).toBe(false); expect(findLoadingIcon().exists()).toBe(false);
}); });
...@@ -96,7 +75,9 @@ describe('Pipeline Status', () => { ...@@ -96,7 +75,9 @@ describe('Pipeline Status', () => {
describe('when querying data', () => { describe('when querying data', () => {
describe('when data is set', () => { describe('when data is set', () => {
beforeEach(async () => { beforeEach(async () => {
mockPipelineQuery.mockResolvedValue(mockProjectPipeline); mockPipelineQuery.mockResolvedValue({
data: { project: mockProjectPipeline },
});
createComponentWithApollo(); createComponentWithApollo();
await waitForPromises(); await waitForPromises();
...@@ -104,14 +85,10 @@ describe('Pipeline Status', () => { ...@@ -104,14 +85,10 @@ describe('Pipeline Status', () => {
it('query is called with correct variables', async () => { it('query is called with correct variables', async () => {
expect(mockPipelineQuery).toHaveBeenCalledTimes(1); expect(mockPipelineQuery).toHaveBeenCalledTimes(1);
expect(mockPipelineQuery).toHaveBeenCalledWith( expect(mockPipelineQuery).toHaveBeenCalledWith({
expect.anything(),
{
fullPath: mockProjectFullPath, fullPath: mockProjectFullPath,
}, sha: mockCommitSha,
expect.anything(), });
expect.anything(),
);
}); });
it('does not render error', () => { it('does not render error', () => {
......
...@@ -46,24 +46,6 @@ describe('~/pipeline_editor/graphql/resolvers', () => { ...@@ -46,24 +46,6 @@ describe('~/pipeline_editor/graphql/resolvers', () => {
await expect(result.rawData).resolves.toBe(mockCiYml); await expect(result.rawData).resolves.toBe(mockCiYml);
}); });
}); });
describe('pipeline', () => {
it('resolves pipeline data with type names', async () => {
const result = await resolvers.Query.project(null);
// eslint-disable-next-line no-underscore-dangle
expect(result.__typename).toBe('Project');
});
it('resolves pipeline data with necessary data', async () => {
const result = await resolvers.Query.project(null);
const pipelineKeys = Object.keys(result.pipeline);
const statusKeys = Object.keys(result.pipeline.detailedStatus);
expect(pipelineKeys).toContain('id', 'commitPath', 'detailedStatus', 'shortSha');
expect(statusKeys).toContain('detailsPath', 'text');
});
});
}); });
describe('Mutation', () => { describe('Mutation', () => {
......
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