Commit e40c0224 authored by Donald Cook's avatar Donald Cook Committed by Simon Knox

Unmocking create new task

Use real mutations for creating
parent 2bcf8074
......@@ -34,7 +34,10 @@ export default {
};
},
update(data) {
return data.localWorkItem;
return data.workItem;
},
skip() {
return !this.workItemId;
},
error() {
this.$emit(
......@@ -46,10 +49,7 @@ export default {
},
computed: {
workItemTitle() {
return this.workItem?.widgets?.nodes.find(
// eslint-disable-next-line no-underscore-dangle
(widget) => widget.__typename === 'LocalTitleWidget',
)?.contentText;
return this.workItem?.title;
},
},
};
......
#import './widget.fragment.graphql'
mutation createWorkItem($input: LocalCreateWorkItemInput) {
localCreateWorkItem(input: $input) @client {
mutation createWorkItem($input: WorkItemCreateInput!) {
workItemCreate(input: $input) {
workItem {
id
type
widgets {
title
workItemType {
id
}
widgets @client {
nodes {
...WidgetBase
... on LocalTitleWidget {
contentText
}
}
}
}
......
......@@ -20,24 +20,18 @@ export function createApolloProvider() {
defaultClient.cache.writeQuery({
query: workItemQuery,
variables: {
id: '1',
id: 'gid://gitlab/WorkItem/1',
},
data: {
localWorkItem: {
__typename: 'LocalWorkItem',
id: '1',
id: 'gid://gitlab/WorkItem/1',
type: 'FEATURE',
// eslint-disable-next-line @gitlab/require-i18n-strings
title: 'Test Work Item',
widgets: {
__typename: 'LocalWorkItemWidgetConnection',
nodes: [
{
__typename: 'LocalTitleWidget',
type: 'TITLE',
enabled: true,
// eslint-disable-next-line @gitlab/require-i18n-strings
contentText: 'Test Work Item Title',
},
],
nodes: [],
},
},
},
......
import { uuids } from '~/lib/utils/uuids';
import workItemQuery from './work_item.query.graphql';
export const resolvers = {
Mutation: {
localCreateWorkItem(_, { input }, { cache }) {
const id = uuids()[0];
const workItem = {
__typename: 'LocalWorkItem',
type: 'FEATURE',
id,
widgets: {
__typename: 'LocalWorkItemWidgetConnection',
nodes: [
{
__typename: 'LocalTitleWidget',
type: 'TITLE',
enabled: true,
contentText: input.title,
},
],
},
};
cache.writeQuery({
query: workItemQuery,
variables: { id },
data: { localWorkItem: workItem },
});
return {
__typename: 'LocalCreateWorkItemPayload',
workItem,
};
},
localUpdateWorkItem(_, { input }, { cache }) {
const workItemTitle = {
__typename: 'LocalTitleWidget',
type: 'TITLE',
enabled: true,
contentText: input.title,
};
const workItem = {
__typename: 'LocalWorkItem',
type: 'FEATURE',
id: input.id,
title: input.title,
widgets: {
__typename: 'LocalWorkItemWidgetConnection',
nodes: [workItemTitle],
nodes: [],
},
};
......
......@@ -22,14 +22,10 @@ type LocalWorkItemWidgetConnection {
pageInfo: PageInfo!
}
type LocalTitleWidget implements LocalWorkItemWidget {
type: LocalWidgetType!
contentText: String!
}
type LocalWorkItem {
id: ID!
type: LocalWorkItemType!
title: String!
widgets: [LocalWorkItemWidgetConnection]
}
......
#import './widget.fragment.graphql'
mutation updateWorkItem($input: LocalUpdateWorkItemInput) {
localUpdateWorkItem(input: $input) @client {
mutation workItemUpdate($input: WorkItemUpdateInput!) {
workItemUpdate(input: $input) {
workItem {
id
type
widgets {
title
workItemType {
id
}
widgets @client {
nodes {
...WidgetBase
... on LocalTitleWidget {
contentText
}
}
}
}
......
#import './widget.fragment.graphql'
query WorkItem($id: ID!) {
localWorkItem(id: $id) @client {
workItem(id: $id) {
id
type
widgets {
title
workItemType {
id
}
widgets @client {
nodes {
...WidgetBase
... on LocalTitleWidget {
contentText
}
}
}
}
......
<script>
import { GlButton, GlAlert, GlLoadingIcon, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { s__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import workItemQuery from '../graphql/work_item.query.graphql';
import createWorkItemMutation from '../graphql/create_work_item.mutation.graphql';
import projectWorkItemTypesQuery from '../graphql/project_work_item_types.query.graphql';
......@@ -67,19 +69,43 @@ export default {
variables: {
input: {
title: this.title,
projectPath: this.fullPath,
workItemTypeId: this.selectedWorkItemType?.id,
},
},
update(store, { data: { workItemCreate } }) {
const { id, title, workItemType } = workItemCreate.workItem;
store.writeQuery({
query: workItemQuery,
variables: {
id,
},
data: {
workItem: {
__typename: 'WorkItem',
id,
title,
workItemType,
widgets: {
__typename: 'LocalWorkItemWidgetConnection',
nodes: [],
},
},
},
});
},
});
const {
data: {
localCreateWorkItem: {
workItemCreate: {
workItem: { id, type },
},
},
} = response;
if (!this.isModal) {
this.$router.push({ name: 'workItem', params: { id } });
this.$router.push({ name: 'workItem', params: { id: `${getIdFromGraphQLId(id)}` } });
} else {
this.$emit('onCreate', { id, title: this.title, type });
}
......
<script>
import { GlAlert } from '@gitlab/ui';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import Tracking from '~/tracking';
import workItemQuery from '../graphql/work_item.query.graphql';
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
import { widgetTypes, WI_TITLE_TRACK_LABEL } from '../constants';
import { WI_TITLE_TRACK_LABEL } from '../constants';
import ItemTitle from '../components/item_title.vue';
......@@ -14,6 +15,7 @@ export default {
components: {
ItemTitle,
GlAlert,
GlLoadingIcon,
},
mixins: [trackingMixin],
props: {
......@@ -24,7 +26,7 @@ export default {
},
data() {
return {
workItem: null,
workItem: {},
error: false,
};
},
......@@ -33,12 +35,9 @@ export default {
query: workItemQuery,
variables() {
return {
id: this.id,
id: this.gid,
};
},
update(data) {
return data.localWorkItem;
},
},
},
computed: {
......@@ -50,19 +49,19 @@ export default {
property: '[type_work_item]',
};
},
titleWidgetData() {
return this.workItem?.widgets?.nodes?.find((widget) => widget.type === widgetTypes.title);
gid() {
return convertToGraphQLId('WorkItem', this.id);
},
},
methods: {
async updateWorkItem(title) {
async updateWorkItem(updatedTitle) {
try {
await this.$apollo.mutate({
mutation: updateWorkItemMutation,
variables: {
input: {
id: this.id,
title,
id: this.gid,
title: updatedTitle,
},
},
});
......@@ -82,12 +81,18 @@ export default {
}}</gl-alert>
<!-- Title widget placeholder -->
<div>
<item-title
v-if="titleWidgetData"
:initial-title="titleWidgetData.contentText"
data-testid="title"
@title-changed="updateWorkItem"
<gl-loading-icon
v-if="$apollo.queries.workItem.loading"
size="md"
data-testid="loading-types"
/>
<template v-else>
<item-title
:initial-title="workItem.title"
data-testid="title"
@title-changed="updateWorkItem"
/>
</template>
</div>
</section>
</template>
export const workItemQueryResponse = {
localWorkItem: {
__typename: 'LocalWorkItem',
workItem: {
__typename: 'WorkItem',
id: '1',
type: 'FEATURE',
title: 'Test',
workItemType: {
__typename: 'WorkItemType',
id: 'work-item-type-1',
},
widgets: {
__typename: 'LocalWorkItemWidgetConnection',
nodes: [
......@@ -17,20 +21,29 @@ export const workItemQueryResponse = {
};
export const updateWorkItemMutationResponse = {
__typename: 'LocalUpdateWorkItemPayload',
workItem: {
__typename: 'LocalWorkItem',
id: '1',
widgets: {
__typename: 'LocalWorkItemWidgetConnection',
nodes: [
{
__typename: 'LocalTitleWidget',
type: 'TITLE',
enabled: true,
contentText: 'Updated title',
data: {
workItemUpdate: {
__typename: 'LocalUpdateWorkItemPayload',
workItem: {
__typename: 'LocalWorkItem',
id: '1',
title: 'Updated title',
workItemType: {
__typename: 'WorkItemType',
id: 'work-item-type-1',
},
],
widgets: {
__typename: 'LocalWorkItemWidgetConnection',
nodes: [
{
__typename: 'LocalTitleWidget',
type: 'TITLE',
enabled: true,
contentText: 'Updated title',
},
],
},
},
},
},
};
......@@ -48,3 +61,20 @@ export const projectWorkItemTypesQueryResponse = {
},
},
};
export const createWorkItemMutationResponse = {
data: {
workItemCreate: {
__typename: 'WorkItemCreatePayload',
workItem: {
__typename: 'WorkItem',
id: '1',
title: 'Updated title',
workItemType: {
__typename: 'WorkItemType',
id: 'work-item-type-1',
},
},
},
},
};
......@@ -8,7 +8,8 @@ import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
import ItemTitle from '~/work_items/components/item_title.vue';
import { resolvers } from '~/work_items/graphql/resolvers';
import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql';
import { projectWorkItemTypesQueryResponse } from '../mock_data';
import createWorkItemMutation from '~/work_items/graphql/create_work_item.mutation.graphql';
import { projectWorkItemTypesQueryResponse, createWorkItemMutationResponse } from '../mock_data';
jest.mock('~/lib/utils/uuids', () => ({ uuids: () => ['testuuid'] }));
......@@ -19,6 +20,7 @@ describe('Create work item component', () => {
let fakeApollo;
const querySuccessHandler = jest.fn().mockResolvedValue(projectWorkItemTypesQueryResponse);
const mutationSuccessHandler = jest.fn().mockResolvedValue(createWorkItemMutationResponse);
const findAlert = () => wrapper.findComponent(GlAlert);
const findTitleInput = () => wrapper.findComponent(ItemTitle);
......@@ -30,8 +32,19 @@ describe('Create work item component', () => {
const findContent = () => wrapper.find('[data-testid="content"]');
const findLoadingTypesIcon = () => wrapper.find('[data-testid="loading-types"]');
const createComponent = ({ data = {}, props = {}, queryHandler = querySuccessHandler } = {}) => {
fakeApollo = createMockApollo([[projectWorkItemTypesQuery, queryHandler]], resolvers);
const createComponent = ({
data = {},
props = {},
queryHandler = querySuccessHandler,
mutationHandler = mutationSuccessHandler,
} = {}) => {
fakeApollo = createMockApollo(
[
[projectWorkItemTypesQuery, queryHandler],
[createWorkItemMutation, mutationHandler],
],
resolvers,
);
wrapper = shallowMount(CreateWorkItem, {
apolloProvider: fakeApollo,
data() {
......@@ -126,7 +139,7 @@ describe('Create work item component', () => {
wrapper.find('form').trigger('submit');
await waitForPromises();
const expected = { id: 'testuuid', title: mockTitle, type: 'FEATURE' };
const expected = { id: '1', title: mockTitle };
expect(wrapper.emitted('onCreate')).toEqual([[expected]]);
});
......
......@@ -9,11 +9,12 @@ import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutati
import WorkItemsRoot from '~/work_items/pages/work_item_root.vue';
import ItemTitle from '~/work_items/components/item_title.vue';
import { resolvers } from '~/work_items/graphql/resolvers';
import { workItemQueryResponse } from '../mock_data';
import { workItemQueryResponse, updateWorkItemMutationResponse } from '../mock_data';
Vue.use(VueApollo);
const WORK_ITEM_ID = '1';
const WORK_ITEM_GID = `gid://gitlab/WorkItem/${WORK_ITEM_ID}`;
describe('Work items root component', () => {
const mockUpdatedTitle = 'Updated title';
......@@ -23,15 +24,19 @@ describe('Work items root component', () => {
const findTitle = () => wrapper.findComponent(ItemTitle);
const createComponent = ({ queryResponse = workItemQueryResponse } = {}) => {
fakeApollo = createMockApollo([], resolvers, {
possibleTypes: {
LocalWorkItemWidget: ['LocalTitleWidget'],
fakeApollo = createMockApollo(
[[updateWorkItemMutation, jest.fn().mockResolvedValue(updateWorkItemMutationResponse)]],
resolvers,
{
possibleTypes: {
LocalWorkItemWidget: ['LocalTitleWidget'],
},
},
});
);
fakeApollo.clients.defaultClient.cache.writeQuery({
query: workItemQuery,
variables: {
id: WORK_ITEM_ID,
id: WORK_ITEM_GID,
},
data: queryResponse,
});
......@@ -49,7 +54,7 @@ describe('Work items root component', () => {
fakeApollo = null;
});
it('renders the title if title is in the widgets list', () => {
it('renders the title', () => {
createComponent();
expect(findTitle().exists()).toBe(true);
......@@ -66,35 +71,11 @@ describe('Work items root component', () => {
mutation: updateWorkItemMutation,
variables: {
input: {
id: WORK_ITEM_ID,
id: WORK_ITEM_GID,
title: mockUpdatedTitle,
},
},
});
await waitForPromises();
expect(findTitle().props('initialTitle')).toBe(mockUpdatedTitle);
});
it('does not render the title if title is not in the widgets list', () => {
const queryResponse = {
workItem: {
...workItemQueryResponse.workItem,
widgets: {
__typename: 'WorkItemWidgetConnection',
nodes: [
{
__typename: 'SomeOtherWidget',
type: 'OTHER',
contentText: 'Test',
},
],
},
},
};
createComponent({ queryResponse });
expect(findTitle().exists()).toBe(false);
});
describe('tracking', () => {
......
......@@ -21,6 +21,7 @@ describe('Work items router', () => {
mocks: {
$apollo: {
queries: {
workItem: {},
workItemTypes: {},
},
},
......
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