Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
e40c0224
Commit
e40c0224
authored
Feb 18, 2022
by
Donald Cook
Committed by
Simon Knox
Mar 10, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Unmocking create new task
Use real mutations for creating
parent
2bcf8074
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
160 additions
and
151 deletions
+160
-151
app/assets/javascripts/work_items/components/work_item_detail_modal.vue
...ascripts/work_items/components/work_item_detail_modal.vue
+5
-5
app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql
...ipts/work_items/graphql/create_work_item.mutation.graphql
+7
-7
app/assets/javascripts/work_items/graphql/provider.js
app/assets/javascripts/work_items/graphql/provider.js
+5
-11
app/assets/javascripts/work_items/graphql/resolvers.js
app/assets/javascripts/work_items/graphql/resolvers.js
+2
-39
app/assets/javascripts/work_items/graphql/typedefs.graphql
app/assets/javascripts/work_items/graphql/typedefs.graphql
+1
-5
app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql
...ipts/work_items/graphql/update_work_item.mutation.graphql
+7
-7
app/assets/javascripts/work_items/graphql/work_item.query.graphql
...ts/javascripts/work_items/graphql/work_item.query.graphql
+6
-6
app/assets/javascripts/work_items/pages/create_work_item.vue
app/assets/javascripts/work_items/pages/create_work_item.vue
+28
-2
app/assets/javascripts/work_items/pages/work_item_root.vue
app/assets/javascripts/work_items/pages/work_item_root.vue
+22
-17
spec/frontend/work_items/mock_data.js
spec/frontend/work_items/mock_data.js
+46
-16
spec/frontend/work_items/pages/create_work_item_spec.js
spec/frontend/work_items/pages/create_work_item_spec.js
+17
-4
spec/frontend/work_items/pages/work_item_root_spec.js
spec/frontend/work_items/pages/work_item_root_spec.js
+13
-32
spec/frontend/work_items/router_spec.js
spec/frontend/work_items/router_spec.js
+1
-0
No files found.
app/assets/javascripts/work_items/components/work_item_detail_modal.vue
View file @
e40c0224
...
...
@@ -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
;
},
},
};
...
...
app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql
View file @
e40c0224
#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
}
}
}
}
...
...
app/assets/javascripts/work_items/graphql/provider.js
View file @
e40c0224
...
...
@@ -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
:
[],
},
},
},
...
...
app/assets/javascripts/work_items/graphql/resolvers.js
View file @
e40c0224
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
:
[],
},
};
...
...
app/assets/javascripts/work_items/graphql/typedefs.graphql
View file @
e40c0224
...
...
@@ -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
]
}
...
...
app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql
View file @
e40c0224
#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
}
}
}
}
...
...
app/assets/javascripts/work_items/graphql/work_item.query.graphql
View file @
e40c0224
#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
}
}
}
}
...
...
app/assets/javascripts/work_items/pages/create_work_item.vue
View file @
e40c0224
<
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
});
}
...
...
app/assets/javascripts/work_items/pages/work_item_root.vue
View file @
e40c0224
<
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
.
g
id
,
};
},
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
(
t
itle
)
{
async
updateWorkItem
(
updatedT
itle
)
{
try
{
await
this
.
$apollo
.
mutate
({
mutation
:
updateWorkItemMutation
,
variables
:
{
input
:
{
id
:
this
.
id
,
title
,
id
:
this
.
g
id
,
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>
spec/frontend/work_items/mock_data.js
View file @
e40c0224
export
const
workItemQueryResponse
=
{
localW
orkItem
:
{
__typename
:
'
Local
WorkItem
'
,
w
orkItem
:
{
__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
'
,
},
},
},
},
};
spec/frontend/work_items/pages/create_work_item_spec.js
View file @
e40c0224
...
...
@@ -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
]]);
});
...
...
spec/frontend/work_items/pages/work_item_root_spec.js
View file @
e40c0224
...
...
@@ -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_
G
ID
,
},
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_
G
ID
,
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
'
,
()
=>
{
...
...
spec/frontend/work_items/router_spec.js
View file @
e40c0224
...
...
@@ -21,6 +21,7 @@ describe('Work items router', () => {
mocks
:
{
$apollo
:
{
queries
:
{
workItem
:
{},
workItemTypes
:
{},
},
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment