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
d19f0b9b
Commit
d19f0b9b
authored
Jan 22, 2021
by
Nicolò Maria Mezzopera
Committed by
Scott Hampton
Jan 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add delete image renderless component
- source - test
parent
e09c35bb
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
351 additions
and
70 deletions
+351
-70
app/assets/javascripts/registry/explorer/components/delete_image.vue
...javascripts/registry/explorer/components/delete_image.vue
+77
-0
app/assets/javascripts/registry/explorer/constants/details.js
...assets/javascripts/registry/explorer/constants/details.js
+49
-0
app/assets/javascripts/registry/explorer/pages/list.vue
app/assets/javascripts/registry/explorer/pages/list.vue
+31
-41
locale/gitlab.pot
locale/gitlab.pot
+21
-0
spec/frontend/registry/explorer/components/delete_image_spec.js
...rontend/registry/explorer/components/delete_image_spec.js
+153
-0
spec/frontend/registry/explorer/pages/list_spec.js
spec/frontend/registry/explorer/pages/list_spec.js
+20
-29
No files found.
app/assets/javascripts/registry/explorer/components/delete_image.vue
0 → 100644
View file @
d19f0b9b
<
script
>
import
{
produce
}
from
'
immer
'
;
import
deleteContainerRepositoryMutation
from
'
../graphql/mutations/delete_container_repository.mutation.graphql
'
;
import
getContainerRepositoryDetailsQuery
from
'
../graphql/queries/get_container_repository_details.query.graphql
'
;
import
{
GRAPHQL_PAGE_SIZE
}
from
'
../constants/index
'
;
export
default
{
props
:
{
id
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
useUpdateFn
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
methods
:
{
updateImageStatus
(
store
,
{
data
:
{
destroyContainerRepository
}
})
{
const
variables
=
{
id
:
this
.
id
,
first
:
GRAPHQL_PAGE_SIZE
,
};
const
sourceData
=
store
.
readQuery
({
query
:
getContainerRepositoryDetailsQuery
,
variables
,
});
const
data
=
produce
(
sourceData
,
(
draftState
)
=>
{
// eslint-disable-next-line no-param-reassign
draftState
.
containerRepository
.
status
=
destroyContainerRepository
.
containerRepository
.
status
;
});
store
.
writeQuery
({
query
:
getContainerRepositoryDetailsQuery
,
variables
,
data
,
});
},
doDelete
()
{
this
.
$emit
(
'
start
'
);
return
this
.
$apollo
.
mutate
({
mutation
:
deleteContainerRepositoryMutation
,
variables
:
{
id
:
this
.
id
,
},
update
:
this
.
useUpdateFn
?
this
.
updateImageStatus
:
undefined
,
})
.
then
(({
data
})
=>
{
if
(
data
?.
destroyContainerRepository
?.
errors
[
0
])
{
this
.
$emit
(
'
error
'
,
data
?.
destroyContainerRepository
?.
errors
);
return
;
}
this
.
$emit
(
'
success
'
);
})
.
catch
((
e
)
=>
{
// note: we are adding an array to follow the same format of the error raised above
this
.
$emit
(
'
error
'
,
[
e
]);
})
.
finally
(()
=>
{
this
.
$emit
(
'
end
'
);
});
},
},
render
()
{
if
(
this
.
$scopedSlots
?.
default
)
{
return
this
.
$scopedSlots
.
default
({
doDelete
:
this
.
doDelete
});
}
return
null
;
},
};
</
script
>
app/assets/javascripts/registry/explorer/constants/details.js
View file @
d19f0b9b
import
{
s__
,
__
}
from
'
~/locale
'
;
import
{
helpPagePath
}
from
'
~/helpers/help_page_helper
'
;
// Translations strings
export
const
DETAILS_PAGE_TITLE
=
s__
(
'
ContainerRegistry|%{imageName} tags
'
);
...
...
@@ -32,6 +33,7 @@ export const CONFIGURATION_DETAILS_ROW_TEST = s__(
export
const
REMOVE_TAG_BUTTON_TITLE
=
s__
(
'
ContainerRegistry|Remove tag
'
);
export
const
REMOVE_TAGS_BUTTON_TITLE
=
s__
(
'
ContainerRegistry|Delete selected
'
);
export
const
REMOVE_TAG_CONFIRMATION_TEXT
=
s__
(
`ContainerRegistry|You are about to remove %{item}. Are you sure?`
,
);
...
...
@@ -76,6 +78,29 @@ export const CLEANUP_DISABLED_TOOLTIP = s__(
'
ContainerRegistry|Cleanup is disabled for this project
'
,
);
export
const
DETAILS_DELETE_IMAGE_ERROR_MESSAGE
=
s__
(
'
ContainerRegistry|Something went wrong while scheduling the image for deletion.
'
,
);
export
const
DELETE_IMAGE_CONFIRMATION_TITLE
=
s__
(
'
ContainerRegistry|Delete image repository?
'
);
export
const
DELETE_IMAGE_CONFIRMATION_TEXT
=
s__
(
'
ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone.
'
,
);
export
const
SCHEDULED_FOR_DELETION_STATUS_TITLE
=
s__
(
'
ContainerRegistry|Image repository will be deleted
'
,
);
export
const
SCHEDULED_FOR_DELETION_STATUS_MESSAGE
=
s__
(
'
ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}
'
,
);
export
const
FAILED_DELETION_STATUS_TITLE
=
s__
(
'
ContainerRegistry|Image repository deletion failed
'
,
);
export
const
FAILED_DELETION_STATUS_MESSAGE
=
s__
(
'
ContainerRegistry|This image repository has failed to be deleted
'
,
);
// Parameters
export
const
DEFAULT_PAGE
=
1
;
...
...
@@ -85,15 +110,39 @@ export const ALERT_SUCCESS_TAG = 'success_tag';
export
const
ALERT_DANGER_TAG
=
'
danger_tag
'
;
export
const
ALERT_SUCCESS_TAGS
=
'
success_tags
'
;
export
const
ALERT_DANGER_TAGS
=
'
danger_tags
'
;
export
const
ALERT_DANGER_IMAGE
=
'
danger_image
'
;
export
const
DELETE_SCHEDULED
=
'
DELETE_SCHEDULED
'
;
export
const
DELETE_FAILED
=
'
DELETE_FAILED
'
;
export
const
ALERT_MESSAGES
=
{
[
ALERT_SUCCESS_TAG
]:
DELETE_TAG_SUCCESS_MESSAGE
,
[
ALERT_DANGER_TAG
]:
DELETE_TAG_ERROR_MESSAGE
,
[
ALERT_SUCCESS_TAGS
]:
DELETE_TAGS_SUCCESS_MESSAGE
,
[
ALERT_DANGER_TAGS
]:
DELETE_TAGS_ERROR_MESSAGE
,
[
ALERT_DANGER_IMAGE
]:
DETAILS_DELETE_IMAGE_ERROR_MESSAGE
,
};
export
const
UNFINISHED_STATUS
=
'
UNFINISHED
'
;
export
const
UNSCHEDULED_STATUS
=
'
UNSCHEDULED
'
;
export
const
SCHEDULED_STATUS
=
'
SCHEDULED
'
;
export
const
ONGOING_STATUS
=
'
ONGOING
'
;
export
const
IMAGE_STATUS_TITLES
=
{
[
DELETE_SCHEDULED
]:
SCHEDULED_FOR_DELETION_STATUS_TITLE
,
[
DELETE_FAILED
]:
FAILED_DELETION_STATUS_TITLE
,
};
export
const
IMAGE_STATUS_MESSAGES
=
{
[
DELETE_SCHEDULED
]:
SCHEDULED_FOR_DELETION_STATUS_MESSAGE
,
[
DELETE_FAILED
]:
FAILED_DELETION_STATUS_MESSAGE
,
};
export
const
IMAGE_STATUS_ALERT_TYPE
=
{
[
DELETE_SCHEDULED
]:
'
info
'
,
[
DELETE_FAILED
]:
'
warning
'
,
};
export
const
PACKAGE_DELETE_HELP_PAGE_PATH
=
helpPagePath
(
'
user/packages/container_registry
'
,
{
anchor
:
'
delete-images
'
,
});
app/assets/javascripts/registry/explorer/pages/list.vue
View file @
d19f0b9b
...
...
@@ -14,9 +14,9 @@ import getContainerRepositoriesQuery from 'shared_queries/container_registry/get
import
Tracking
from
'
~/tracking
'
;
import
createFlash
from
'
~/flash
'
;
import
RegistryHeader
from
'
../components/list_page/registry_header.vue
'
;
import
DeleteImage
from
'
../components/delete_image.vue
'
;
import
getContainerRepositoriesDetails
from
'
../graphql/queries/get_container_repositories_details.query.graphql
'
;
import
deleteContainerRepositoryMutation
from
'
../graphql/mutations/delete_container_repository.mutation.graphql
'
;
import
{
DELETE_IMAGE_SUCCESS_MESSAGE
,
...
...
@@ -60,6 +60,7 @@ export default {
GlSkeletonLoader
,
GlSearchBoxByClick
,
RegistryHeader
,
DeleteImage
,
},
directives
:
{
GlTooltip
:
GlTooltipDirective
,
...
...
@@ -179,30 +180,6 @@ export default {
this
.
itemToDelete
=
item
;
this
.
$refs
.
deleteModal
.
show
();
},
handleDeleteImage
()
{
this
.
track
(
'
confirm_delete
'
);
this
.
mutationLoading
=
true
;
return
this
.
$apollo
.
mutate
({
mutation
:
deleteContainerRepositoryMutation
,
variables
:
{
id
:
this
.
itemToDelete
.
id
,
},
})
.
then
(({
data
})
=>
{
if
(
data
?.
destroyContainerRepository
?.
errors
[
0
])
{
this
.
deleteAlertType
=
'
danger
'
;
}
else
{
this
.
deleteAlertType
=
'
success
'
;
}
})
.
catch
(()
=>
{
this
.
deleteAlertType
=
'
danger
'
;
})
.
finally
(()
=>
{
this
.
mutationLoading
=
false
;
});
},
dismissDeleteAlert
()
{
this
.
deleteAlertType
=
null
;
this
.
itemToDelete
=
{};
...
...
@@ -250,6 +227,10 @@ export default {
});
}
},
startDelete
()
{
this
.
track
(
'
confirm_delete
'
);
this
.
mutationLoading
=
true
;
},
},
};
</
script
>
...
...
@@ -358,23 +339,32 @@ export default {
</
template
>
</template>
<
gl-modal
ref=
"deleteModal
"
modal-id=
"delete-image-modal
"
ok-variant=
"danger
"
@
ok=
"handleDeleteImage
"
@
cancel=
"track('cancel_delete')
"
<
delete-image
:id=
"itemToDelete.id
"
@
start=
"startDelete
"
@
error=
"deleteAlertType = 'danger'
"
@
success=
"deleteAlertType = 'success'
"
@
end=
"mutationLoading = false
"
>
<
template
#modal-title
>
{{
$options
.
i18n
.
REMOVE_REPOSITORY_LABEL
}}
</
template
>
<p>
<gl-sprintf
:message=
"$options.i18n.REMOVE_REPOSITORY_MODAL_TEXT"
>
<
template
#title
>
<b>
{{
itemToDelete
.
path
}}
</b>
</
template
>
</gl-sprintf>
</p>
<
template
#modal-ok
>
{{
__
(
'
Remove
'
)
}}
</
template
>
</gl-modal>
<
template
#default=
"{ doDelete }"
>
<gl-modal
ref=
"deleteModal"
modal-id=
"delete-image-modal"
:action-primary=
"
{ text: __('Remove'), attributes: { variant: 'danger' } }"
@primary="doDelete"
@cancel="track('cancel_delete')"
>
<template
#modal-title
>
{{
$options
.
i18n
.
REMOVE_REPOSITORY_LABEL
}}
</
template
>
<p>
<gl-sprintf
:message=
"$options.i18n.REMOVE_REPOSITORY_MODAL_TEXT"
>
<
template
#title
>
<b>
{{
itemToDelete
.
path
}}
</b>
</
template
>
</gl-sprintf>
</p>
</gl-modal>
</template>
</delete-image>
</template>
</div>
</template>
locale/gitlab.pot
View file @
d19f0b9b
...
...
@@ -7585,9 +7585,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
msgid "ContainerRegistry|Delete image repository?"
msgstr ""
msgid "ContainerRegistry|Delete selected"
msgstr ""
msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
msgstr ""
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
...
...
@@ -7615,6 +7621,12 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
msgstr ""
msgid "ContainerRegistry|Image repository deletion failed"
msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
msgid "ContainerRegistry|Image tags"
msgstr ""
...
...
@@ -7707,6 +7719,9 @@ msgstr ""
msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
msgstr ""
msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
msgstr ""
msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
msgstr ""
...
...
@@ -7752,9 +7767,15 @@ msgstr ""
msgid "ContainerRegistry|This image has no active tags"
msgstr ""
msgid "ContainerRegistry|This image repository has failed to be deleted"
msgstr ""
msgid "ContainerRegistry|This image repository is scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
msgstr ""
...
...
spec/frontend/registry/explorer/components/delete_image_spec.js
0 → 100644
View file @
d19f0b9b
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
component
from
'
~/registry/explorer/components/delete_image.vue
'
;
import
deleteContainerRepositoryMutation
from
'
~/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql
'
;
import
getContainerRepositoryDetailsQuery
from
'
~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
'
;
import
{
GRAPHQL_PAGE_SIZE
}
from
'
~/registry/explorer/constants/index
'
;
describe
(
'
Delete Image
'
,
()
=>
{
let
wrapper
;
const
id
=
'
1
'
;
const
storeMock
=
{
readQuery
:
jest
.
fn
().
mockReturnValue
({
containerRepository
:
{
status
:
'
foo
'
,
},
}),
writeQuery
:
jest
.
fn
(),
};
const
updatePayload
=
{
data
:
{
destroyContainerRepository
:
{
containerRepository
:
{
status
:
'
baz
'
,
},
},
},
};
const
findButton
=
()
=>
wrapper
.
find
(
'
button
'
);
const
mountComponent
=
({
propsData
=
{
id
},
mutate
=
jest
.
fn
().
mockResolvedValue
({}),
}
=
{})
=>
{
wrapper
=
shallowMount
(
component
,
{
propsData
,
mocks
:
{
$apollo
:
{
mutate
,
},
},
scopedSlots
:
{
default
:
'
<button @click="props.doDelete">test</button>
'
,
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
executes apollo mutate on doDelete
'
,
()
=>
{
const
mutate
=
jest
.
fn
().
mockResolvedValue
({});
mountComponent
({
mutate
});
wrapper
.
vm
.
doDelete
();
expect
(
mutate
).
toHaveBeenCalledWith
({
mutation
:
deleteContainerRepositoryMutation
,
variables
:
{
id
,
},
update
:
undefined
,
});
});
it
(
'
on success emits the correct events
'
,
async
()
=>
{
const
mutate
=
jest
.
fn
().
mockResolvedValue
({});
mountComponent
({
mutate
});
wrapper
.
vm
.
doDelete
();
await
waitForPromises
();
expect
(
wrapper
.
emitted
(
'
start
'
)).
toEqual
([[]]);
expect
(
wrapper
.
emitted
(
'
success
'
)).
toEqual
([[]]);
expect
(
wrapper
.
emitted
(
'
end
'
)).
toEqual
([[]]);
});
it
(
'
when a payload contains an error emits an error event
'
,
async
()
=>
{
const
mutate
=
jest
.
fn
()
.
mockResolvedValue
({
data
:
{
destroyContainerRepository
:
{
errors
:
[
'
foo
'
]
}
}
});
mountComponent
({
mutate
});
wrapper
.
vm
.
doDelete
();
await
waitForPromises
();
expect
(
wrapper
.
emitted
(
'
error
'
)).
toEqual
([[[
'
foo
'
]]]);
});
it
(
'
when the api call errors emits an error event
'
,
async
()
=>
{
const
mutate
=
jest
.
fn
().
mockRejectedValue
(
'
error
'
);
mountComponent
({
mutate
});
wrapper
.
vm
.
doDelete
();
await
waitForPromises
();
expect
(
wrapper
.
emitted
(
'
error
'
)).
toEqual
([[[
'
error
'
]]]);
});
it
(
'
uses the update function, when the prop is set to true
'
,
()
=>
{
const
mutate
=
jest
.
fn
().
mockResolvedValue
({});
mountComponent
({
mutate
,
propsData
:
{
id
,
useUpdateFn
:
true
}
});
wrapper
.
vm
.
doDelete
();
expect
(
mutate
).
toHaveBeenCalledWith
({
mutation
:
deleteContainerRepositoryMutation
,
variables
:
{
id
,
},
update
:
wrapper
.
vm
.
updateImageStatus
,
});
});
it
(
'
updateImage status reads and write to the cache
'
,
()
=>
{
mountComponent
();
const
variables
=
{
id
,
first
:
GRAPHQL_PAGE_SIZE
,
};
wrapper
.
vm
.
updateImageStatus
(
storeMock
,
updatePayload
);
expect
(
storeMock
.
readQuery
).
toHaveBeenCalledWith
({
query
:
getContainerRepositoryDetailsQuery
,
variables
,
});
expect
(
storeMock
.
writeQuery
).
toHaveBeenCalledWith
({
query
:
getContainerRepositoryDetailsQuery
,
variables
,
data
:
{
containerRepository
:
{
status
:
updatePayload
.
data
.
destroyContainerRepository
.
containerRepository
.
status
,
},
},
});
});
it
(
'
binds the doDelete function to the default scoped slot
'
,
()
=>
{
const
mutate
=
jest
.
fn
().
mockResolvedValue
({});
mountComponent
({
mutate
});
findButton
().
trigger
(
'
click
'
);
expect
(
mutate
).
toHaveBeenCalled
();
});
});
spec/frontend/registry/explorer/pages/list_spec.js
View file @
d19f0b9b
...
...
@@ -11,6 +11,7 @@ import GroupEmptyState from '~/registry/explorer/components/list_page/group_empt
import
ProjectEmptyState
from
'
~/registry/explorer/components/list_page/project_empty_state.vue
'
;
import
RegistryHeader
from
'
~/registry/explorer/components/list_page/registry_header.vue
'
;
import
ImageList
from
'
~/registry/explorer/components/list_page/image_list.vue
'
;
import
DeleteImage
from
'
~/registry/explorer/components/delete_image.vue
'
;
import
TitleArea
from
'
~/vue_shared/components/registry/title_area.vue
'
;
import
{
...
...
@@ -27,7 +28,6 @@ import {
graphQLImageListMock
,
graphQLImageDeleteMock
,
deletedContainerRepository
,
graphQLImageDeleteMockError
,
graphQLEmptyImageListMock
,
graphQLEmptyGroupImageListMock
,
pageInfo
,
...
...
@@ -58,6 +58,7 @@ describe('List Page', () => {
const
findListHeader
=
()
=>
wrapper
.
find
(
'
[data-testid="listHeader"]
'
);
const
findSearchBox
=
()
=>
wrapper
.
find
(
GlSearchBoxByClick
);
const
findEmptySearchMessage
=
()
=>
wrapper
.
find
(
'
[data-testid="emptySearch"]
'
);
const
findDeleteImage
=
()
=>
wrapper
.
find
(
DeleteImage
);
const
waitForApolloRequestRender
=
async
()
=>
{
jest
.
runOnlyPendingTimers
();
...
...
@@ -91,6 +92,7 @@ describe('List Page', () => {
GlSprintf
,
RegistryHeader
,
TitleArea
,
DeleteImage
,
},
mocks
:
{
$toast
,
...
...
@@ -300,23 +302,22 @@ describe('List Page', () => {
});
describe
(
'
delete image
'
,
()
=>
{
const
deleteImage
=
async
()
=>
{
await
w
rapper
.
vm
.
$nextTick
();
const
selectImageForDeletion
=
async
()
=>
{
await
w
aitForApolloRequestRender
();
findImageList
().
vm
.
$emit
(
'
delete
'
,
deletedContainerRepository
);
findDeleteModal
().
vm
.
$emit
(
'
ok
'
);
await
waitForApolloRequestRender
();
};
it
(
'
should call deleteItem when confirming deletion
'
,
async
()
=>
{
const
mutationResolver
=
jest
.
fn
().
mockResolvedValue
(
graphQLImageDeleteMock
);
mountComponent
({
mutationResolver
});
await
deleteImage
();
await
selectImageForDeletion
();
findDeleteModal
().
vm
.
$emit
(
'
primary
'
);
await
waitForApolloRequestRender
();
expect
(
wrapper
.
vm
.
itemToDelete
).
toEqual
(
deletedContainerRepository
);
expect
(
mutationResolver
).
toHaveBeenCalledWith
({
id
:
deletedContainerRepository
.
id
});
const
updatedImage
=
findImageList
()
.
props
(
'
images
'
)
...
...
@@ -326,10 +327,12 @@ describe('List Page', () => {
});
it
(
'
should show a success alert when delete request is successful
'
,
async
()
=>
{
const
mutationResolver
=
jest
.
fn
().
mockResolvedValue
(
graphQLImageDeleteMock
);
mountComponent
({
mutationResolver
});
mountComponent
();
await
deleteImage
();
await
selectImageForDeletion
();
findDeleteImage
().
vm
.
$emit
(
'
success
'
);
await
wrapper
.
vm
.
$nextTick
();
const
alert
=
findDeleteAlert
();
expect
(
alert
.
exists
()).
toBe
(
true
);
...
...
@@ -340,23 +343,12 @@ describe('List Page', () => {
describe
(
'
when delete request fails it shows an alert
'
,
()
=>
{
it
(
'
user recoverable error
'
,
async
()
=>
{
const
mutationResolver
=
jest
.
fn
().
mockResolvedValue
(
graphQLImageDeleteMockError
);
mountComponent
({
mutationResolver
});
mountComponent
();
await
deleteImage
();
await
selectImageForDeletion
();
const
alert
=
findDeleteAlert
();
expect
(
alert
.
exists
()).
toBe
(
true
);
expect
(
alert
.
text
().
replace
(
/
\s\s
+/gm
,
'
'
)).
toBe
(
DELETE_IMAGE_ERROR_MESSAGE
.
replace
(
'
%{title}
'
,
wrapper
.
vm
.
itemToDelete
.
path
),
);
});
it
(
'
network error
'
,
async
()
=>
{
const
mutationResolver
=
jest
.
fn
().
mockRejectedValue
();
mountComponent
({
mutationResolver
});
await
deleteImage
();
findDeleteImage
().
vm
.
$emit
(
'
error
'
);
await
wrapper
.
vm
.
$nextTick
();
const
alert
=
findDeleteAlert
();
expect
(
alert
.
exists
()).
toBe
(
true
);
...
...
@@ -499,9 +491,8 @@ describe('List Page', () => {
testTrackingCall
(
'
cancel_delete
'
);
});
it
(
'
send an event when confirm is clicked on modal
'
,
()
=>
{
const
deleteModal
=
findDeleteModal
();
deleteModal
.
vm
.
$emit
(
'
ok
'
);
it
(
'
send an event when the deletion starts
'
,
()
=>
{
findDeleteImage
().
vm
.
$emit
(
'
start
'
);
testTrackingCall
(
'
confirm_delete
'
);
});
});
...
...
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