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
750cca34
Commit
750cca34
authored
Jun 02, 2021
by
Nicolò Maria Mezzopera
Committed by
Olena Horal-Koretska
Jun 02, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow users to delete items from the package file list
Changelog: added
parent
174bbef0
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
394 additions
and
69 deletions
+394
-69
app/assets/javascripts/api.js
app/assets/javascripts/api.js
+11
-0
app/assets/javascripts/packages/details/components/app.vue
app/assets/javascripts/packages/details/components/app.vue
+64
-22
app/assets/javascripts/packages/details/components/package_files.vue
...javascripts/packages/details/components/package_files.vue
+32
-4
app/assets/javascripts/packages/details/store/actions.js
app/assets/javascripts/packages/details/store/actions.js
+29
-4
app/assets/javascripts/packages/details/store/mutation_types.js
...sets/javascripts/packages/details/store/mutation_types.js
+1
-0
app/assets/javascripts/packages/details/store/mutations.js
app/assets/javascripts/packages/details/store/mutations.js
+3
-0
app/assets/javascripts/packages/shared/constants.js
app/assets/javascripts/packages/shared/constants.js
+13
-2
app/presenters/packages/detail/package_presenter.rb
app/presenters/packages/detail/package_presenter.rb
+2
-2
locale/gitlab.pot
locale/gitlab.pot
+18
-3
spec/frontend/api_spec.js
spec/frontend/api_spec.js
+18
-0
spec/frontend/packages/details/components/app_spec.js
spec/frontend/packages/details/components/app_spec.js
+85
-19
spec/frontend/packages/details/components/package_files_spec.js
...rontend/packages/details/components/package_files_spec.js
+50
-7
spec/frontend/packages/details/store/actions_spec.js
spec/frontend/packages/details/store/actions_spec.js
+57
-5
spec/frontend/packages/details/store/mutations_spec.js
spec/frontend/packages/details/store/mutations_spec.js
+9
-0
spec/presenters/packages/detail/package_presenter_spec.rb
spec/presenters/packages/detail/package_presenter_spec.rb
+2
-1
No files found.
app/assets/javascripts/api.js
View file @
750cca34
...
...
@@ -23,6 +23,8 @@ const Api = {
groupPackagesPath
:
'
/api/:version/groups/:id/packages
'
,
projectPackagesPath
:
'
/api/:version/projects/:id/packages
'
,
projectPackagePath
:
'
/api/:version/projects/:id/packages/:package_id
'
,
projectPackageFilePath
:
'
/api/:version/projects/:id/packages/:package_id/package_files/:package_file_id
'
,
groupProjectsPath
:
'
/api/:version/groups/:id/projects.json
'
,
groupSharePath
:
'
/api/:version/groups/:id/share
'
,
projectsPath
:
'
/api/:version/projects.json
'
,
...
...
@@ -124,6 +126,15 @@ const Api = {
return
axios
.
delete
(
url
);
},
deleteProjectPackageFile
(
projectId
,
packageId
,
fileId
)
{
const
url
=
Api
.
buildUrl
(
this
.
projectPackageFilePath
)
.
replace
(
'
:id
'
,
projectId
)
.
replace
(
'
:package_id
'
,
packageId
)
.
replace
(
'
:package_file_id
'
,
fileId
);
return
axios
.
delete
(
url
);
},
containerRegistryDetails
(
registryId
,
options
=
{})
{
const
url
=
Api
.
buildUrl
(
this
.
containerRegistryDetailsPath
).
replace
(
'
:id
'
,
registryId
);
return
axios
.
get
(
url
,
options
);
...
...
app/assets/javascripts/packages/details/components/app.vue
View file @
750cca34
...
...
@@ -13,7 +13,7 @@ import {
import
{
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
objectToQueryString
}
from
'
~/lib/utils/common_utils
'
;
import
{
numberToHumanSize
}
from
'
~/lib/utils/number_utils
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
Tracking
from
'
~/tracking
'
;
import
PackageListRow
from
'
../../shared/components/package_list_row.vue
'
;
import
PackagesListLoader
from
'
../../shared/components/packages_list_loader.vue
'
;
...
...
@@ -51,6 +51,11 @@ export default {
},
mixins
:
[
Tracking
.
mixin
()],
trackingActions
:
{
...
TrackingActions
},
data
()
{
return
{
fileToDelete
:
null
,
};
},
computed
:
{
...
mapState
([
'
projectName
'
,
...
...
@@ -86,13 +91,10 @@ export default {
},
},
methods
:
{
...
mapActions
([
'
deletePackage
'
,
'
fetchPackageVersions
'
]),
...
mapActions
([
'
deletePackage
'
,
'
fetchPackageVersions
'
,
'
deletePackageFile
'
]),
formatSize
(
size
)
{
return
numberToHumanSize
(
size
);
},
cancelDelete
()
{
this
.
$refs
.
deleteModal
.
hide
();
},
getPackageVersions
()
{
if
(
!
this
.
packageEntity
.
versions
)
{
this
.
fetchPackageVersions
();
...
...
@@ -108,12 +110,43 @@ export default {
const
modalQuery
=
objectToQueryString
({
[
SHOW_DELETE_SUCCESS_ALERT
]:
true
});
window
.
location
.
replace
(
`
${
returnTo
}
?
${
modalQuery
}
`
);
},
handleFileDelete
(
file
)
{
this
.
track
(
TrackingActions
.
REQUEST_DELETE_PACKAGE_FILE
);
this
.
fileToDelete
=
{
...
file
};
this
.
$refs
.
deleteFileModal
.
show
();
},
confirmFileDelete
()
{
this
.
track
(
TrackingActions
.
DELETE_PACKAGE_FILE
);
this
.
deletePackageFile
(
this
.
fileToDelete
.
id
);
this
.
fileToDelete
=
null
;
},
},
i18n
:
{
deleteModalTitle
:
s__
(
`PackageRegistry|Delete Package Version`
),
deleteModalContent
:
s__
(
`PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?`
,
),
deleteFileModalTitle
:
s__
(
`PackageRegistry|Delete Package File`
),
deleteFileModalContent
:
s__
(
`PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?`
,
),
},
modal
:
{
packageDeletePrimaryAction
:
{
text
:
__
(
'
Delete
'
),
attributes
:
[
{
variant
:
'
danger
'
},
{
category
:
'
primary
'
},
{
'
data-qa-selector
'
:
'
delete_modal_button
'
},
],
},
fileDeletePrimaryAction
:
{
text
:
__
(
'
Delete
'
),
attributes
:
[{
variant
:
'
danger
'
},
{
category
:
'
primary
'
}],
},
cancelAction
:
{
text
:
__
(
'
Cancel
'
),
},
},
};
</
script
>
...
...
@@ -159,7 +192,9 @@ export default {
<package-files
v-if=
"showFiles"
:package-files=
"packageFiles"
:can-delete=
"canDelete"
@
download-file=
"track($options.trackingActions.PULL_PACKAGE)"
@
delete-file=
"handleFileDelete"
/>
</gl-tab>
...
...
@@ -210,7 +245,15 @@ export default {
</gl-tab>
</gl-tabs>
<gl-modal
ref=
"deleteModal"
class=
"js-delete-modal"
modal-id=
"delete-modal"
>
<gl-modal
ref=
"deleteModal"
class=
"js-delete-modal"
modal-id=
"delete-modal"
:action-primary=
"$options.modal.packageDeletePrimaryAction"
:action-cancel=
"$options.modal.cancelAction"
@
primary=
"confirmPackageDeletion"
@
canceled=
"track($options.trackingActions.CANCEL_DELETE_PACKAGE)"
>
<
template
#modal-title
>
{{
$options
.
i18n
.
deleteModalTitle
}}
</
template
>
<gl-sprintf
:message=
"$options.i18n.deleteModalContent"
>
<
template
#version
>
...
...
@@ -221,23 +264,22 @@ export default {
<strong>
{{
packageEntity
.
name
}}
</strong>
</
template
>
</gl-sprintf>
</gl-modal>
<
template
#modal-footer
>
<div
class=
"gl-w-full"
>
<div
class=
"float-right"
>
<gl-button
@
click=
"cancelDelete"
>
{{
__
(
'
Cancel
'
)
}}
</gl-button>
<gl-button
ref=
"modal-delete-button"
variant=
"danger"
category=
"primary"
data-qa-selector=
"delete_modal_button"
@
click=
"confirmPackageDeletion"
<gl-modal
ref=
"deleteFileModal"
modal-id=
"delete-file-modal"
:action-primary=
"$options.modal.fileDeletePrimaryAction"
:action-cancel=
"$options.modal.cancelAction"
@
primary=
"confirmFileDelete"
@
canceled=
"track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
>
{{
__
(
'
Delete
'
)
}}
</gl-button
>
</div
>
</div
>
<
template
#modal-title
>
{{
$options
.
i18n
.
deleteFileModalTitle
}}
</
template
>
<gl-sprintf
v-if=
"fileToDelete"
:message=
"$options.i18n.deleteFileModalContent"
>
<
template
#filename
>
<strong>
{{
fileToDelete
.
file_name
}}
</strong
>
</
template
>
</gl-sprintf>
</gl-modal>
</div>
</template>
app/assets/javascripts/packages/details/components/package_files.vue
View file @
750cca34
<
script
>
import
{
GlLink
,
GlTable
}
from
'
@gitlab/ui
'
;
import
{
GlLink
,
GlTable
,
GlDropdownItem
,
GlDropdown
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
last
}
from
'
lodash
'
;
import
{
numberToHumanSize
}
from
'
~/lib/utils/number_utils
'
;
import
{
__
}
from
'
~/locale
'
;
...
...
@@ -12,6 +12,9 @@ export default {
components
:
{
GlLink
,
GlTable
,
GlIcon
,
GlDropdown
,
GlDropdownItem
,
FileIcon
,
TimeAgoTooltip
,
},
...
...
@@ -22,6 +25,11 @@ export default {
required
:
false
,
default
:
()
=>
[],
},
canDelete
:
{
type
:
Boolean
,
default
:
false
,
required
:
false
,
},
},
computed
:
{
filesTableRows
()
{
...
...
@@ -39,7 +47,6 @@ export default {
{
key
:
'
name
'
,
label
:
__
(
'
Name
'
),
tdClass
:
'
gl-display-flex gl-align-items-center
'
,
},
{
key
:
'
commit
'
,
...
...
@@ -55,6 +62,13 @@ export default {
label
:
__
(
'
Created
'
),
class
:
'
gl-text-right
'
,
},
{
key
:
'
actions
'
,
label
:
''
,
hide
:
!
this
.
canDelete
,
class
:
'
gl-text-right
'
,
tdClass
:
'
gl-w-4
'
,
},
].
filter
((
c
)
=>
!
c
.
hide
);
},
},
...
...
@@ -63,6 +77,9 @@ export default {
return
numberToHumanSize
(
size
);
},
},
i18n
:
{
deleteFile
:
__
(
'
Delete file
'
),
},
};
</
script
>
...
...
@@ -77,7 +94,7 @@ export default {
<template
#cell(name)=
"
{ item }">
<gl-link
:href=
"item.download_path"
class=
"gl-
relative gl-
text-gray-500"
class=
"gl-text-gray-500"
data-testid=
"download-link"
@
click=
"$emit('download-file')"
>
...
...
@@ -86,7 +103,7 @@ export default {
css-classes=
"gl-relative file-icon"
class=
"gl-mr-1 gl-relative"
/>
<span
class=
"gl-relative"
>
{{
item
.
file_name
}}
</span>
<span>
{{
item
.
file_name
}}
</span>
</gl-link>
</
template
>
...
...
@@ -103,6 +120,17 @@ export default {
<
template
#cell(created)=
"{ item }"
>
<time-ago-tooltip
:time=
"item.created_at"
/>
</
template
>
<
template
#cell(actions)=
"{ item }"
>
<gl-dropdown
category=
"tertiary"
right
>
<template
#button-content
>
<gl-icon
name=
"ellipsis_v"
/>
</
template
>
<gl-dropdown-item
data-testid=
"delete-file"
@
click=
"$emit('delete-file', item)"
>
{{ $options.i18n.deleteFile }}
</gl-dropdown-item>
</gl-dropdown>
</template>
</gl-table>
</div>
</template>
app/assets/javascripts/packages/details/store/actions.js
View file @
750cca34
import
Api
from
'
~/api
'
;
import
{
deprecatedCreateFlash
as
createFlash
}
from
'
~/flash
'
;
import
{
DELETE_PACKAGE_ERROR_MESSAGE
}
from
'
~/packages/shared/constants
'
;
import
createFlash
from
'
~/flash
'
;
import
{
DELETE_PACKAGE_ERROR_MESSAGE
,
DELETE_PACKAGE_FILE_ERROR_MESSAGE
,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
,
}
from
'
~/packages/shared/constants
'
;
import
{
FETCH_PACKAGE_VERSIONS_ERROR
}
from
'
../constants
'
;
import
*
as
types
from
'
./mutation_types
'
;
...
...
@@ -16,7 +20,7 @@ export const fetchPackageVersions = ({ commit, state }) => {
}
})
.
catch
(()
=>
{
createFlash
(
FETCH_PACKAGE_VERSIONS_ERROR
);
createFlash
(
{
message
:
FETCH_PACKAGE_VERSIONS_ERROR
,
type
:
'
warning
'
}
);
})
.
finally
(()
=>
{
commit
(
types
.
SET_LOADING
,
false
);
...
...
@@ -29,6 +33,27 @@ export const deletePackage = ({
},
})
=>
{
return
Api
.
deleteProjectPackage
(
project_id
,
id
).
catch
(()
=>
{
createFlash
(
DELETE_PACKAGE_ERROR_MESSAGE
);
createFlash
({
message
:
DELETE_PACKAGE_ERROR_MESSAGE
,
type
:
'
warning
'
});
});
};
export
const
deletePackageFile
=
(
{
state
:
{
packageEntity
:
{
project_id
,
id
},
packageFiles
,
},
commit
,
},
fileId
,
)
=>
{
return
Api
.
deleteProjectPackageFile
(
project_id
,
id
,
fileId
)
.
then
(()
=>
{
const
filtered
=
packageFiles
.
filter
((
f
)
=>
f
.
id
!==
fileId
);
commit
(
types
.
UPDATE_PACKAGE_FILES
,
filtered
);
createFlash
({
message
:
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
,
type
:
'
success
'
});
})
.
catch
(()
=>
{
createFlash
({
message
:
DELETE_PACKAGE_FILE_ERROR_MESSAGE
,
type
:
'
warning
'
});
});
};
app/assets/javascripts/packages/details/store/mutation_types.js
View file @
750cca34
export
const
SET_LOADING
=
'
SET_LOADING
'
;
export
const
SET_PACKAGE_VERSIONS
=
'
SET_PACKAGE_VERSIONS
'
;
export
const
UPDATE_PACKAGE_FILES
=
'
UPDATE_PACKAGE_FILES
'
;
app/assets/javascripts/packages/details/store/mutations.js
View file @
750cca34
...
...
@@ -11,4 +11,7 @@ export default {
versions
,
};
},
[
types
.
UPDATE_PACKAGE_FILES
](
state
,
files
)
{
state
.
packageFiles
=
files
;
},
};
app/assets/javascripts/packages/shared/constants.js
View file @
750cca34
import
{
__
}
from
'
~/locale
'
;
import
{
__
,
s__
}
from
'
~/locale
'
;
export
const
PackageType
=
{
CONAN
:
'
conan
'
,
...
...
@@ -16,6 +16,9 @@ export const TrackingActions = {
REQUEST_DELETE_PACKAGE
:
'
request_delete_package
'
,
CANCEL_DELETE_PACKAGE
:
'
cancel_delete_package
'
,
PULL_PACKAGE
:
'
pull_package
'
,
DELETE_PACKAGE_FILE
:
'
delete_package_file
'
,
REQUEST_DELETE_PACKAGE_FILE
:
'
request_delete_package_file
'
,
CANCEL_DELETE_PACKAGE_FILE
:
'
cancel_delete_package_file
'
,
};
export
const
TrackingCategories
=
{
...
...
@@ -25,7 +28,15 @@ export const TrackingCategories = {
};
export
const
SHOW_DELETE_SUCCESS_ALERT
=
'
showSuccessDeleteAlert
'
;
export
const
DELETE_PACKAGE_ERROR_MESSAGE
=
__
(
'
Something went wrong while deleting the package.
'
);
export
const
DELETE_PACKAGE_ERROR_MESSAGE
=
s__
(
'
PackageRegistry|Something went wrong while deleting the package.
'
,
);
export
const
DELETE_PACKAGE_FILE_ERROR_MESSAGE
=
s__
(
__
(
'
PackageRegistry|Something went wrong while deleting the package file.
'
),
);
export
const
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
=
s__
(
'
PackageRegistry|Package file deleted successfully
'
,
);
export
const
PACKAGE_ERROR_STATUS
=
'
error
'
;
export
const
PACKAGE_DEFAULT_STATUS
=
'
default
'
;
...
...
app/presenters/packages/detail/package_presenter.rb
View file @
750cca34
...
...
@@ -46,8 +46,8 @@ module Packages
size:
package_file
.
size
,
file_md5:
package_file
.
file_md5
,
file_sha1:
package_file
.
file_sha1
,
file_sha256:
package_file
.
file_sha256
file_sha256:
package_file
.
file_sha256
,
id:
package_file
.
id
}
file_view
[
:pipelines
]
=
build_pipeline_infos
(
package_file
.
pipelines
)
if
package_file
.
pipelines
.
present?
...
...
locale/gitlab.pot
View file @
750cca34
...
...
@@ -10620,6 +10620,9 @@ msgstr ""
msgid "Delete domain"
msgstr ""
msgid "Delete file"
msgstr ""
msgid "Delete image repository"
msgstr ""
...
...
@@ -23537,6 +23540,9 @@ msgstr ""
msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
msgstr ""
msgid "PackageRegistry|Delete Package File"
msgstr ""
msgid "PackageRegistry|Delete Package Version"
msgstr ""
...
...
@@ -23615,6 +23621,9 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
msgid "PackageRegistry|Package has %{number} archived update"
msgstr ""
...
...
@@ -23678,6 +23687,12 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
msgstr ""
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
...
...
@@ -23708,6 +23723,9 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
msgstr ""
...
...
@@ -30474,9 +30492,6 @@ msgstr ""
msgid "Something went wrong while deleting description changes. Please try again."
msgstr ""
msgid "Something went wrong while deleting the package."
msgstr ""
msgid "Something went wrong while deleting the source branch. Please try again."
msgstr ""
...
...
spec/frontend/api_spec.js
View file @
750cca34
...
...
@@ -116,6 +116,24 @@ describe('Api', () => {
});
});
});
describe
(
'
deleteProjectPackageFile
'
,
()
=>
{
const
packageFileId
=
'
package_file_id
'
;
it
(
'
delete a package
'
,
()
=>
{
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects/
${
projectId
}
/packages/
${
packageId
}
/package_files/
${
packageFileId
}
`
;
jest
.
spyOn
(
axios
,
'
delete
'
);
mock
.
onDelete
(
expectedUrl
).
replyOnce
(
httpStatus
.
OK
,
true
);
return
Api
.
deleteProjectPackageFile
(
projectId
,
packageId
,
packageFileId
).
then
(
({
data
})
=>
{
expect
(
data
).
toEqual
(
true
);
expect
(
axios
.
delete
).
toHaveBeenCalledWith
(
expectedUrl
);
},
);
});
});
});
describe
(
'
container registry
'
,
()
=>
{
...
...
spec/frontend/packages/details/components/app_spec.js
View file @
750cca34
import
{
GlEmptyState
,
GlModal
}
from
'
@gitlab/ui
'
;
import
{
GlEmptyState
}
from
'
@gitlab/ui
'
;
import
{
mount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
stubChildren
from
'
helpers/stub_children
'
;
...
...
@@ -34,6 +34,7 @@ describe('PackagesApp', () => {
let
store
;
const
fetchPackageVersions
=
jest
.
fn
();
const
deletePackage
=
jest
.
fn
();
const
deletePackageFile
=
jest
.
fn
();
const
defaultProjectName
=
'
bar
'
;
const
{
location
}
=
window
;
...
...
@@ -59,6 +60,7 @@ describe('PackagesApp', () => {
actions
:
{
deletePackage
,
fetchPackageVersions
,
deletePackageFile
,
},
getters
,
});
...
...
@@ -82,8 +84,8 @@ describe('PackagesApp', () => {
const
packageTitle
=
()
=>
wrapper
.
find
(
PackageTitle
);
const
emptyState
=
()
=>
wrapper
.
find
(
GlEmptyState
);
const
deleteButton
=
()
=>
wrapper
.
find
(
'
.js-delete-button
'
);
const
deleteModal
=
()
=>
wrapper
.
find
(
GlModal
);
const
modalDeleteButton
=
()
=>
wrapper
.
find
({
ref
:
'
modal-delete-button
'
});
const
findDeleteModal
=
()
=>
wrapper
.
find
({
ref
:
'
deleteModal
'
}
);
const
findDeleteFileModal
=
()
=>
wrapper
.
find
({
ref
:
'
deleteFileModal
'
});
const
versionsTab
=
()
=>
wrapper
.
find
(
'
.js-versions-tab > a
'
);
const
packagesLoader
=
()
=>
wrapper
.
find
(
PackagesListLoader
);
const
packagesVersionRows
=
()
=>
wrapper
.
findAll
(
PackageListRow
);
...
...
@@ -110,7 +112,7 @@ describe('PackagesApp', () => {
it
(
'
renders the app and displays the package title
'
,
()
=>
{
createComponent
();
expect
(
packageTitle
()
).
toExist
(
);
expect
(
packageTitle
()
.
exists
()).
toBe
(
true
);
});
it
(
'
renders an empty state component when no an invalid package is passed as a prop
'
,
()
=>
{
...
...
@@ -118,7 +120,7 @@ describe('PackagesApp', () => {
packageEntity
:
{},
});
expect
(
emptyState
()
).
toExist
(
);
expect
(
emptyState
()
.
exists
()).
toBe
(
true
);
});
it
(
'
package history has the right props
'
,
()
=>
{
...
...
@@ -152,7 +154,16 @@ describe('PackagesApp', () => {
});
it
(
'
shows the delete confirmation modal when delete is clicked
'
,
()
=>
{
expect
(
deleteModal
()).
toExist
();
expect
(
findDeleteModal
().
exists
()).
toBe
(
true
);
});
});
describe
(
'
deleting package files
'
,
()
=>
{
it
(
'
shows the delete confirmation modal when delete is clicked
'
,
()
=>
{
createComponent
();
findPackageFiles
().
vm
.
$emit
(
'
delete-file
'
,
mavenFiles
[
0
]);
expect
(
findDeleteFileModal
().
exists
()).
toBe
(
true
);
});
});
...
...
@@ -228,13 +239,7 @@ describe('PackagesApp', () => {
});
describe
(
'
tracking and delete
'
,
()
=>
{
const
doDelete
=
async
()
=>
{
deleteButton
().
trigger
(
'
click
'
);
await
wrapper
.
vm
.
$nextTick
();
modalDeleteButton
().
trigger
(
'
click
'
);
};
describe
(
'
delete
'
,
()
=>
{
describe
(
'
delete package
'
,
()
=>
{
const
originalReferrer
=
document
.
referrer
;
const
setReferrer
=
(
value
=
defaultProjectName
)
=>
{
Object
.
defineProperty
(
document
,
'
referrer
'
,
{
...
...
@@ -250,9 +255,9 @@ describe('PackagesApp', () => {
});
});
it
(
'
calls the proper vuex action
'
,
async
()
=>
{
it
(
'
calls the proper vuex action
'
,
()
=>
{
createComponent
({
packageEntity
:
npmPackage
});
await
doDelete
(
);
findDeleteModal
().
vm
.
$emit
(
'
primary
'
);
expect
(
deletePackage
).
toHaveBeenCalled
();
});
...
...
@@ -260,7 +265,7 @@ describe('PackagesApp', () => {
setReferrer
();
deletePackage
.
mockResolvedValue
();
createComponent
({
packageEntity
:
npmPackage
});
await
doDelete
(
);
findDeleteModal
().
vm
.
$emit
(
'
primary
'
);
await
deletePackage
();
expect
(
window
.
location
.
replace
).
toHaveBeenCalledWith
(
'
project_url?showSuccessDeleteAlert=true
'
,
...
...
@@ -271,7 +276,7 @@ describe('PackagesApp', () => {
setReferrer
(
'
baz
'
);
deletePackage
.
mockResolvedValue
();
createComponent
({
packageEntity
:
npmPackage
});
await
doDelete
(
);
findDeleteModal
().
vm
.
$emit
(
'
primary
'
);
await
deletePackage
();
expect
(
window
.
location
.
replace
).
toHaveBeenCalledWith
(
'
group_url?showSuccessDeleteAlert=true
'
,
...
...
@@ -279,6 +284,17 @@ describe('PackagesApp', () => {
});
});
describe
(
'
delete file
'
,
()
=>
{
it
(
'
calls the proper vuex action
'
,
()
=>
{
createComponent
({
packageEntity
:
npmPackage
});
findPackageFiles
().
vm
.
$emit
(
'
delete-file
'
,
mavenFiles
[
0
]);
findDeleteFileModal
().
vm
.
$emit
(
'
primary
'
);
expect
(
deletePackageFile
).
toHaveBeenCalled
();
});
});
describe
(
'
tracking
'
,
()
=>
{
let
eventSpy
;
let
utilSpy
;
...
...
@@ -295,9 +311,9 @@ describe('PackagesApp', () => {
expect
(
utilSpy
).
toHaveBeenCalledWith
(
'
conan
'
);
});
it
(
`delete button on delete modal call event with
${
TrackingActions
.
DELETE_PACKAGE
}
`
,
async
()
=>
{
it
(
`delete button on delete modal call event with
${
TrackingActions
.
DELETE_PACKAGE
}
`
,
()
=>
{
createComponent
({
packageEntity
:
npmPackage
});
await
doDelete
(
);
findDeleteModal
().
vm
.
$emit
(
'
primary
'
);
expect
(
eventSpy
).
toHaveBeenCalledWith
(
category
,
TrackingActions
.
DELETE_PACKAGE
,
...
...
@@ -305,6 +321,56 @@ describe('PackagesApp', () => {
);
});
it
(
`canceling a package deletion tracks
${
TrackingActions
.
CANCEL_DELETE_PACKAGE
}
`
,
()
=>
{
createComponent
({
packageEntity
:
npmPackage
});
findDeleteModal
().
vm
.
$emit
(
'
canceled
'
);
expect
(
eventSpy
).
toHaveBeenCalledWith
(
category
,
TrackingActions
.
CANCEL_DELETE_PACKAGE
,
expect
.
any
(
Object
),
);
});
it
(
`request a file deletion tracks
${
TrackingActions
.
REQUEST_DELETE_PACKAGE_FILE
}
`
,
()
=>
{
createComponent
({
packageEntity
:
npmPackage
});
findPackageFiles
().
vm
.
$emit
(
'
delete-file
'
,
mavenFiles
[
0
]);
expect
(
eventSpy
).
toHaveBeenCalledWith
(
category
,
TrackingActions
.
REQUEST_DELETE_PACKAGE_FILE
,
expect
.
any
(
Object
),
);
});
it
(
`confirming a file deletion tracks
${
TrackingActions
.
DELETE_PACKAGE_FILE
}
`
,
()
=>
{
createComponent
({
packageEntity
:
npmPackage
});
findPackageFiles
().
vm
.
$emit
(
'
delete-file
'
,
npmPackage
);
findDeleteFileModal
().
vm
.
$emit
(
'
primary
'
);
expect
(
eventSpy
).
toHaveBeenCalledWith
(
category
,
TrackingActions
.
REQUEST_DELETE_PACKAGE_FILE
,
expect
.
any
(
Object
),
);
});
it
(
`canceling a file deletion tracks
${
TrackingActions
.
CANCEL_DELETE_PACKAGE_FILE
}
`
,
()
=>
{
createComponent
({
packageEntity
:
npmPackage
});
findPackageFiles
().
vm
.
$emit
(
'
delete-file
'
,
npmPackage
);
findDeleteFileModal
().
vm
.
$emit
(
'
canceled
'
);
expect
(
eventSpy
).
toHaveBeenCalledWith
(
category
,
TrackingActions
.
CANCEL_DELETE_PACKAGE_FILE
,
expect
.
any
(
Object
),
);
});
it
(
`file download link call event with
${
TrackingActions
.
PULL_PACKAGE
}
`
,
()
=>
{
createComponent
({
packageEntity
:
conanPackage
});
...
...
spec/frontend/packages/details/components/package_files_spec.js
View file @
750cca34
import
{
GlDropdown
}
from
'
@gitlab/ui
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
stubChildren
from
'
helpers/stub_children
'
;
import
component
from
'
~/packages/details/components/package_files.vue
'
;
...
...
@@ -12,16 +13,19 @@ describe('Package Files', () => {
const
findAllRows
=
()
=>
wrapper
.
findAll
(
'
[data-testid="file-row"
'
);
const
findFirstRow
=
()
=>
findAllRows
().
at
(
0
);
const
findSecondRow
=
()
=>
findAllRows
().
at
(
1
);
const
findFirstRowDownloadLink
=
()
=>
findFirstRow
().
find
(
'
[data-testid="download-link"
'
);
const
findFirstRowCommitLink
=
()
=>
findFirstRow
().
find
(
'
[data-testid="commit-link"
'
);
const
findSecondRowCommitLink
=
()
=>
findSecondRow
().
find
(
'
[data-testid="commit-link"
'
);
const
findFirstRowDownloadLink
=
()
=>
findFirstRow
().
find
(
'
[data-testid="download-link"
]
'
);
const
findFirstRowCommitLink
=
()
=>
findFirstRow
().
find
(
'
[data-testid="commit-link"
]
'
);
const
findSecondRowCommitLink
=
()
=>
findSecondRow
().
find
(
'
[data-testid="commit-link"
]
'
);
const
findFirstRowFileIcon
=
()
=>
findFirstRow
().
find
(
FileIcon
);
const
findFirstRowCreatedAt
=
()
=>
findFirstRow
().
find
(
TimeAgoTooltip
);
const
findFirstActionMenu
=
()
=>
findFirstRow
().
findComponent
(
GlDropdown
);
const
findActionMenuDelete
=
()
=>
findFirstActionMenu
().
find
(
'
[data-testid="delete-file"]
'
);
const
createComponent
=
(
packageFiles
=
npmFiles
)
=>
{
const
createComponent
=
(
{
packageFiles
=
npmFiles
,
canDelete
=
true
}
=
{}
)
=>
{
wrapper
=
mount
(
component
,
{
propsData
:
{
packageFiles
,
canDelete
,
},
stubs
:
{
...
stubChildren
(
component
),
...
...
@@ -43,7 +47,7 @@ describe('Package Files', () => {
});
it
(
'
renders multiple files for a package that contains more than one file
'
,
()
=>
{
createComponent
(
mavenFiles
);
createComponent
(
{
packageFiles
:
mavenFiles
}
);
expect
(
findAllRows
()).
toHaveLength
(
2
);
});
...
...
@@ -123,7 +127,7 @@ describe('Package Files', () => {
});
describe
(
'
when package file has no pipeline associated
'
,
()
=>
{
it
(
'
does not exist
'
,
()
=>
{
createComponent
(
mavenFiles
);
createComponent
(
{
packageFiles
:
mavenFiles
}
);
expect
(
findFirstRowCommitLink
().
exists
()).
toBe
(
false
);
});
...
...
@@ -131,11 +135,50 @@ describe('Package Files', () => {
describe
(
'
when only one file lacks an associated pipeline
'
,
()
=>
{
it
(
'
renders the commit when it exists and not otherwise
'
,
()
=>
{
createComponent
(
[
npmFiles
[
0
],
mavenFiles
[
0
]]
);
createComponent
(
{
packageFiles
:
[
npmFiles
[
0
],
mavenFiles
[
0
]]
}
);
expect
(
findFirstRowCommitLink
().
exists
()).
toBe
(
true
);
expect
(
findSecondRowCommitLink
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
action menu
'
,
()
=>
{
describe
(
'
when the user can delete
'
,
()
=>
{
it
(
'
exists
'
,
()
=>
{
createComponent
();
expect
(
findFirstActionMenu
().
exists
()).
toBe
(
true
);
});
describe
(
'
menu items
'
,
()
=>
{
describe
(
'
delete file
'
,
()
=>
{
it
(
'
exists
'
,
()
=>
{
createComponent
();
expect
(
findActionMenuDelete
().
exists
()).
toBe
(
true
);
});
it
(
'
emits a delete event when clicked
'
,
()
=>
{
createComponent
();
findActionMenuDelete
().
vm
.
$emit
(
'
click
'
);
const
[[{
id
}]]
=
wrapper
.
emitted
(
'
delete-file
'
);
expect
(
id
).
toBe
(
npmFiles
[
0
].
id
);
});
});
});
});
describe
(
'
when the user can not delete
'
,
()
=>
{
const
canDelete
=
false
;
it
(
'
does not exist
'
,
()
=>
{
createComponent
({
canDelete
});
expect
(
findFirstActionMenu
().
exists
()).
toBe
(
false
);
});
});
});
});
});
spec/frontend/packages/details/store/actions_spec.js
View file @
750cca34
import
testAction
from
'
helpers/vuex_action_helper
'
;
import
Api
from
'
~/api
'
;
import
{
deprecatedCreateFlash
as
createFlash
}
from
'
~/flash
'
;
import
createFlash
from
'
~/flash
'
;
import
{
FETCH_PACKAGE_VERSIONS_ERROR
}
from
'
~/packages/details/constants
'
;
import
{
fetchPackageVersions
,
deletePackage
}
from
'
~/packages/details/store/actions
'
;
import
{
fetchPackageVersions
,
deletePackage
,
deletePackageFile
,
}
from
'
~/packages/details/store/actions
'
;
import
*
as
types
from
'
~/packages/details/store/mutation_types
'
;
import
{
DELETE_PACKAGE_ERROR_MESSAGE
}
from
'
~/packages/shared/constants
'
;
import
{
DELETE_PACKAGE_ERROR_MESSAGE
,
DELETE_PACKAGE_FILE_ERROR_MESSAGE
,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
,
}
from
'
~/packages/shared/constants
'
;
import
{
npmPackage
as
packageEntity
}
from
'
../../mock_data
'
;
jest
.
mock
(
'
~/flash.js
'
);
...
...
@@ -74,7 +82,10 @@ describe('Actions Package details store', () => {
packageEntity
.
project_id
,
packageEntity
.
id
,
);
expect
(
createFlash
).
toHaveBeenCalledWith
(
FETCH_PACKAGE_VERSIONS_ERROR
);
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
FETCH_PACKAGE_VERSIONS_ERROR
,
type
:
'
warning
'
,
});
done
();
},
);
...
...
@@ -96,7 +107,48 @@ describe('Actions Package details store', () => {
Api
.
deleteProjectPackage
=
jest
.
fn
().
mockRejectedValue
();
testAction
(
deletePackage
,
undefined
,
{
packageEntity
},
[],
[],
()
=>
{
expect
(
createFlash
).
toHaveBeenCalledWith
(
DELETE_PACKAGE_ERROR_MESSAGE
);
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
DELETE_PACKAGE_ERROR_MESSAGE
,
type
:
'
warning
'
,
});
done
();
});
});
});
describe
(
'
deletePackageFile
'
,
()
=>
{
const
fileId
=
'
a_file_id
'
;
it
(
'
should call Api.deleteProjectPackageFile and commit the right data
'
,
(
done
)
=>
{
const
packageFiles
=
[{
id
:
'
foo
'
},
{
id
:
fileId
}];
Api
.
deleteProjectPackageFile
=
jest
.
fn
().
mockResolvedValue
();
testAction
(
deletePackageFile
,
fileId
,
{
packageEntity
,
packageFiles
},
[{
type
:
types
.
UPDATE_PACKAGE_FILES
,
payload
:
[{
id
:
'
foo
'
}]
}],
[],
()
=>
{
expect
(
Api
.
deleteProjectPackageFile
).
toHaveBeenCalledWith
(
packageEntity
.
project_id
,
packageEntity
.
id
,
fileId
,
);
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
,
type
:
'
success
'
,
});
done
();
},
);
});
it
(
'
should create flash on API error
'
,
(
done
)
=>
{
Api
.
deleteProjectPackageFile
=
jest
.
fn
().
mockRejectedValue
();
testAction
(
deletePackageFile
,
fileId
,
{
packageEntity
},
[],
[],
()
=>
{
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
DELETE_PACKAGE_FILE_ERROR_MESSAGE
,
type
:
'
warning
'
,
});
done
();
});
});
...
...
spec/frontend/packages/details/store/mutations_spec.js
View file @
750cca34
...
...
@@ -28,4 +28,13 @@ describe('Mutations package details Store', () => {
expect
(
mockState
.
packageEntity
.
versions
).
toEqual
(
fakeVersions
);
});
});
describe
(
'
UPDATE_PACKAGE_FILES
'
,
()
=>
{
it
(
'
should update the packageFiles
'
,
()
=>
{
const
files
=
[
1
,
2
,
3
];
mutations
[
types
.
UPDATE_PACKAGE_FILES
](
mockState
,
files
);
expect
(
mockState
.
packageFiles
).
toEqual
(
files
);
});
});
});
spec/presenters/packages/detail/package_presenter_spec.rb
View file @
750cca34
...
...
@@ -19,7 +19,8 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
size:
file
.
size
,
file_md5:
file
.
file_md5
,
file_sha1:
file
.
file_sha1
,
file_sha256:
file
.
file_sha256
file_sha256:
file
.
file_sha256
,
id:
file
.
id
}
end
end
...
...
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