Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1db4510841
commit
433ee53e3e
26 changed files with 853 additions and 373 deletions
|
@ -1,13 +1,13 @@
|
|||
<script>
|
||||
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
|
||||
import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import allVersionsMixin from '../../mixins/all_versions';
|
||||
import { findVersionId } from '../../utils/design_management_utils';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlDeprecatedDropdown,
|
||||
GlDeprecatedDropdownItem,
|
||||
},
|
||||
mixins: [allVersionsMixin],
|
||||
computed: {
|
||||
|
@ -50,8 +50,8 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<gl-dropdown :text="dropdownText" variant="link" class="design-version-dropdown">
|
||||
<gl-dropdown-item v-for="(version, index) in allVersions" :key="version.node.id">
|
||||
<gl-deprecated-dropdown :text="dropdownText" variant="link" class="design-version-dropdown">
|
||||
<gl-deprecated-dropdown-item v-for="(version, index) in allVersions" :key="version.node.id">
|
||||
<router-link
|
||||
class="d-flex js-version-link"
|
||||
:to="{ path: $route.path, query: { version: findVersionId(version.node.id) } }"
|
||||
|
@ -71,6 +71,6 @@ export default {
|
|||
class="fa fa-check float-right gl-mr-2"
|
||||
></i>
|
||||
</router-link>
|
||||
</gl-dropdown-item>
|
||||
</gl-dropdown>
|
||||
</gl-deprecated-dropdown-item>
|
||||
</gl-deprecated-dropdown>
|
||||
</template>
|
||||
|
|
|
@ -7,7 +7,7 @@ import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
|
|||
import initFilePickers from '~/file_pickers';
|
||||
import initProjectLoadingSpinner from '../shared/save_project_loader';
|
||||
import initProjectPermissionsSettings from '../shared/permissions';
|
||||
import initProjectRemoveModal from '~/projects/project_remove_modal';
|
||||
import initProjectDeleteButton from '~/projects/project_delete_button';
|
||||
import UserCallout from '~/user_callout';
|
||||
import initServiceDesk from '~/projects/settings_service_desk';
|
||||
|
||||
|
@ -15,7 +15,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
initFilePickers();
|
||||
initConfirmDangerModal();
|
||||
initSettingsPanels();
|
||||
initProjectRemoveModal();
|
||||
initProjectDeleteButton();
|
||||
mountBadgeSettings(PROJECT_BADGE);
|
||||
|
||||
new UserCallout({ className: 'js-service-desk-callout' }); // eslint-disable-line no-new
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<script>
|
||||
import { GlAlert, GlSprintf } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import SharedDeleteButton from './shared/delete_button.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlSprintf,
|
||||
GlAlert,
|
||||
SharedDeleteButton,
|
||||
},
|
||||
props: {
|
||||
confirmPhrase: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
formPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
strings: {
|
||||
alertTitle: __('You are about to permanently delete this project'),
|
||||
alertBody: __(
|
||||
'Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc.',
|
||||
),
|
||||
modalBody: __(
|
||||
"This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc.",
|
||||
),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<shared-delete-button v-bind="{ confirmPhrase, formPath }">
|
||||
<template #modal-body>
|
||||
<gl-alert
|
||||
class="gl-mb-5"
|
||||
variant="danger"
|
||||
:title="$options.strings.alertTitle"
|
||||
:dismissible="false"
|
||||
>
|
||||
<gl-sprintf :message="$options.strings.alertBody">
|
||||
<template #strong="{ content }">
|
||||
<strong>{{ content }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</gl-alert>
|
||||
<p>{{ $options.strings.modalBody }}</p>
|
||||
</template>
|
||||
</shared-delete-button>
|
||||
</template>
|
|
@ -1,108 +0,0 @@
|
|||
<script>
|
||||
import { GlModal, GlModalDirective, GlSprintf, GlFormInput, GlButton } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import { rstrip } from '~/lib/utils/common_utils';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlModal,
|
||||
GlSprintf,
|
||||
GlFormInput,
|
||||
GlButton,
|
||||
},
|
||||
directives: {
|
||||
GlModal: GlModalDirective,
|
||||
},
|
||||
props: {
|
||||
confirmPhrase: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
warningMessage: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
formPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userInput: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
buttonDisabled() {
|
||||
return rstrip(this.userInput) !== this.confirmPhrase;
|
||||
},
|
||||
csrfToken() {
|
||||
return csrf.token;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
submitForm() {
|
||||
this.$refs.form.submit();
|
||||
},
|
||||
},
|
||||
strings: {
|
||||
removeProject: __('Remove project'),
|
||||
title: __('Confirmation required'),
|
||||
confirm: __('Confirm'),
|
||||
dataLoss: __(
|
||||
'This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention.',
|
||||
),
|
||||
confirmText: __('Please type %{phrase_code} to proceed or close this modal to cancel.'),
|
||||
},
|
||||
modalId: 'remove-project-modal',
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form ref="form" :action="formPath" method="post">
|
||||
<input type="hidden" name="_method" value="delete" />
|
||||
<input :value="csrfToken" type="hidden" name="authenticity_token" />
|
||||
<gl-button v-gl-modal="$options.modalId" category="primary" variant="danger">{{
|
||||
$options.strings.removeProject
|
||||
}}</gl-button>
|
||||
<gl-modal
|
||||
ref="removeModal"
|
||||
:modal-id="$options.modalId"
|
||||
size="sm"
|
||||
ok-variant="danger"
|
||||
footer-class="bg-gray-light gl-p-5"
|
||||
>
|
||||
<template #modal-title>{{ $options.strings.title }}</template>
|
||||
<template #modal-footer>
|
||||
<div class="gl-w-full gl-display-flex gl-just-content-start gl-m-0">
|
||||
<gl-button
|
||||
:disabled="buttonDisabled"
|
||||
category="primary"
|
||||
variant="danger"
|
||||
@click="submitForm"
|
||||
>
|
||||
{{ $options.strings.confirm }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<p class="gl-text-red-500 gl-font-weight-bold">{{ warningMessage }}</p>
|
||||
<p class="gl-mb-0">{{ $options.strings.dataLoss }}</p>
|
||||
<p>
|
||||
<gl-sprintf :message="$options.strings.confirmText">
|
||||
<template #phrase_code>
|
||||
<code>{{ confirmPhrase }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<gl-form-input
|
||||
id="confirm_name_input"
|
||||
v-model="userInput"
|
||||
name="confirm_name_input"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
</gl-modal>
|
||||
</form>
|
||||
</template>
|
|
@ -0,0 +1,101 @@
|
|||
<script>
|
||||
import { uniqueId } from 'lodash';
|
||||
import { GlModal, GlModalDirective, GlFormInput, GlButton } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlModal,
|
||||
GlFormInput,
|
||||
GlButton,
|
||||
},
|
||||
directives: {
|
||||
GlModal: GlModalDirective,
|
||||
},
|
||||
props: {
|
||||
confirmPhrase: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
formPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userInput: null,
|
||||
modalId: uniqueId('delete-project-modal-'),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
confirmDisabled() {
|
||||
return this.userInput !== this.confirmPhrase;
|
||||
},
|
||||
csrfToken() {
|
||||
return csrf.token;
|
||||
},
|
||||
modalActionProps() {
|
||||
return {
|
||||
primary: {
|
||||
text: __('Yes, delete project'),
|
||||
attributes: [{ variant: 'danger' }, { disabled: this.confirmDisabled }],
|
||||
},
|
||||
cancel: {
|
||||
text: __('Cancel, keep project'),
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
submitForm() {
|
||||
this.$refs.form.submit();
|
||||
},
|
||||
},
|
||||
strings: {
|
||||
deleteProject: __('Remove project'),
|
||||
title: __('Delete project. Are you ABSOLUTELY SURE?'),
|
||||
confirmText: __('Please type the following to confirm:'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form ref="form" :action="formPath" method="post">
|
||||
<input type="hidden" name="_method" value="delete" />
|
||||
<input :value="csrfToken" type="hidden" name="authenticity_token" />
|
||||
|
||||
<gl-button v-gl-modal="modalId" category="primary" variant="danger">{{
|
||||
$options.strings.deleteProject
|
||||
}}</gl-button>
|
||||
|
||||
<gl-modal
|
||||
ref="removeModal"
|
||||
:modal-id="modalId"
|
||||
size="sm"
|
||||
ok-variant="danger"
|
||||
footer-class="gl-bg-gray-10 gl-p-5"
|
||||
title-class="gl-text-red-500"
|
||||
:action-primary="modalActionProps.primary"
|
||||
:action-cancel="modalActionProps.cancel"
|
||||
@ok="submitForm"
|
||||
>
|
||||
<template #modal-title>{{ $options.strings.title }}</template>
|
||||
<div>
|
||||
<slot name="modal-body"></slot>
|
||||
<p class="gl-mb-1">{{ $options.strings.confirmText }}</p>
|
||||
<p>
|
||||
<code>{{ confirmPhrase }}</code>
|
||||
</p>
|
||||
<gl-form-input
|
||||
id="confirm_name_input"
|
||||
v-model="userInput"
|
||||
name="confirm_name_input"
|
||||
type="text"
|
||||
/>
|
||||
<slot name="modal-footer"></slot>
|
||||
</div>
|
||||
</gl-modal>
|
||||
</form>
|
||||
</template>
|
|
@ -1,21 +1,20 @@
|
|||
import Vue from 'vue';
|
||||
import RemoveProjectModal from './components/remove_modal.vue';
|
||||
import ProjectDeleteButton from './components/project_delete_button.vue';
|
||||
|
||||
export default (selector = '#js-confirm-project-remove') => {
|
||||
export default (selector = '#js-project-delete-button') => {
|
||||
const el = document.querySelector(selector);
|
||||
|
||||
if (!el) return;
|
||||
|
||||
const { formPath, confirmPhrase, warningMessage } = el.dataset;
|
||||
const { confirmPhrase, formPath } = el.dataset;
|
||||
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el,
|
||||
render(createElement) {
|
||||
return createElement(RemoveProjectModal, {
|
||||
return createElement(ProjectDeleteButton, {
|
||||
props: {
|
||||
confirmPhrase,
|
||||
warningMessage,
|
||||
formPath,
|
||||
},
|
||||
});
|
|
@ -6,4 +6,4 @@
|
|||
%strong= _('Removing the project will delete its repository and all related resources including issues, merge requests etc.')
|
||||
%p
|
||||
%strong= _('Removed projects cannot be restored!')
|
||||
#js-confirm-project-remove{ data: { form_path: project_path(project), confirm_phrase: project.path, warning_message: remove_project_message(project) } }
|
||||
#js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: project.path } }
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update project remove modal to add additional warnings
|
||||
merge_request: 36962
|
||||
author:
|
||||
type: changed
|
6
changelogs/unreleased/remove-redis-3-references.yml
Normal file
6
changelogs/unreleased/remove-redis-3-references.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Set minimum Redis version to 4 and recommended version to 5 in Redis check
|
||||
task
|
||||
merge_request: 38475
|
||||
author:
|
||||
type: changed
|
|
@ -23,32 +23,39 @@ Example output:
|
|||
|
||||
```plaintext
|
||||
System information
|
||||
System: Debian 7.8
|
||||
Current User: git
|
||||
Using RVM: no
|
||||
Ruby Version: 2.1.5p273
|
||||
Gem Version: 2.4.3
|
||||
Bundler Version: 1.7.6
|
||||
Rake Version: 10.3.2
|
||||
Redis Version: 3.2.5
|
||||
Sidekiq Version: 2.17.8
|
||||
System: Ubuntu 20.04
|
||||
Proxy: no
|
||||
Current User: git
|
||||
Using RVM: no
|
||||
Ruby Version: 2.6.6p146
|
||||
Gem Version: 2.7.10
|
||||
Bundler Version:1.17.3
|
||||
Rake Version: 12.3.3
|
||||
Redis Version: 5.0.9
|
||||
Git Version: 2.27.0
|
||||
Sidekiq Version:5.2.9
|
||||
Go Version: unknown
|
||||
|
||||
GitLab information
|
||||
Version: 7.7.1
|
||||
Revision: 41ab9e1
|
||||
Directory: /home/git/gitlab
|
||||
DB Adapter: postgresql
|
||||
URL: https://gitlab.example.com
|
||||
HTTP Clone URL: https://gitlab.example.com/some-project.git
|
||||
SSH Clone URL: git@gitlab.example.com:some-project.git
|
||||
Using LDAP: no
|
||||
Using Omniauth: no
|
||||
Version: 13.2.2-ee
|
||||
Revision: 618883a1f9d
|
||||
Directory: /opt/gitlab/embedded/service/gitlab-rails
|
||||
DB Adapter: PostgreSQL
|
||||
DB Version: 11.7
|
||||
URL: http://gitlab.example.com
|
||||
HTTP Clone URL: http://gitlab.example.com/some-group/some-project.git
|
||||
SSH Clone URL: git@gitlab.example.com:some-group/some-project.git
|
||||
Elasticsearch: no
|
||||
Geo: no
|
||||
Using LDAP: no
|
||||
Using Omniauth: yes
|
||||
Omniauth Providers:
|
||||
|
||||
GitLab Shell
|
||||
Version: 2.4.1
|
||||
Repositories: /home/git/repositories/
|
||||
Hooks: /home/git/gitlab-shell/hooks/
|
||||
Git: /usr/bin/git
|
||||
Version: 13.3.0
|
||||
Repository storage paths:
|
||||
- default: /var/opt/gitlab/git-data/repositories
|
||||
GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
|
||||
```
|
||||
|
||||
## Show GitLab license information **(STARTER ONLY)**
|
||||
|
|
|
@ -19,13 +19,7 @@ The following are the requirements for providing your own Redis instance:
|
|||
|
||||
- Redis version 5.0 or higher is recommended, as this is what ships with
|
||||
Omnibus GitLab packages starting with GitLab 12.7.
|
||||
- Support for Redis 3.2 is deprecated with GitLab 12.10 and will be completely
|
||||
removed in GitLab 13.0.
|
||||
- GitLab 12.0 and later requires Redis version 3.2 or higher. Older Redis
|
||||
versions do not support an optional count argument to SPOP which is now
|
||||
required for [Merge Trains](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md).
|
||||
- In addition, if Redis 4 or later is available, GitLab makes use of certain
|
||||
commands like `UNLINK` and `USAGE` which were introduced only in Redis 4.
|
||||
- GitLab 13.0 and later requires Redis version 4.0 or higher.
|
||||
- Standalone Redis or Redis high availability with Sentinel are supported. Redis
|
||||
Cluster is not supported.
|
||||
- Managed Redis from cloud providers such as AWS ElastiCache will work. If these
|
||||
|
|
|
@ -2359,6 +2359,46 @@ type DastSiteProfileCreatePayload {
|
|||
id: ID
|
||||
}
|
||||
|
||||
"""
|
||||
Autogenerated input type of DastSiteProfileDelete
|
||||
"""
|
||||
input DastSiteProfileDeleteInput {
|
||||
"""
|
||||
A unique identifier for the client performing the mutation.
|
||||
"""
|
||||
clientMutationId: String
|
||||
|
||||
"""
|
||||
The project the site profile belongs to.
|
||||
"""
|
||||
fullPath: ID!
|
||||
|
||||
"""
|
||||
ID of the site profile to be deleted.
|
||||
"""
|
||||
id: DastSiteProfileID!
|
||||
}
|
||||
|
||||
"""
|
||||
Autogenerated return type of DastSiteProfileDelete
|
||||
"""
|
||||
type DastSiteProfileDeletePayload {
|
||||
"""
|
||||
A unique identifier for the client performing the mutation.
|
||||
"""
|
||||
clientMutationId: String
|
||||
|
||||
"""
|
||||
Errors encountered during execution of the mutation.
|
||||
"""
|
||||
errors: [String!]!
|
||||
}
|
||||
|
||||
"""
|
||||
Identifier of DastSiteProfile
|
||||
"""
|
||||
scalar DastSiteProfileID
|
||||
|
||||
"""
|
||||
Autogenerated input type of DeleteAnnotation
|
||||
"""
|
||||
|
@ -8496,6 +8536,7 @@ type Mutation {
|
|||
dastOnDemandScanCreate(input: DastOnDemandScanCreateInput!): DastOnDemandScanCreatePayload
|
||||
dastScannerProfileCreate(input: DastScannerProfileCreateInput!): DastScannerProfileCreatePayload
|
||||
dastSiteProfileCreate(input: DastSiteProfileCreateInput!): DastSiteProfileCreatePayload
|
||||
dastSiteProfileDelete(input: DastSiteProfileDeleteInput!): DastSiteProfileDeletePayload
|
||||
deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload
|
||||
designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload
|
||||
designManagementUpload(input: DesignManagementUploadInput!): DesignManagementUploadPayload
|
||||
|
|
|
@ -6340,6 +6340,118 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "DastSiteProfileDeleteInput",
|
||||
"description": "Autogenerated input type of DastSiteProfileDelete",
|
||||
"fields": null,
|
||||
"inputFields": [
|
||||
{
|
||||
"name": "fullPath",
|
||||
"description": "The project the site profile belongs to.",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of the site profile to be deleted.",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "DastSiteProfileID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "clientMutationId",
|
||||
"description": "A unique identifier for the client performing the mutation.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"interfaces": null,
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "DastSiteProfileDeletePayload",
|
||||
"description": "Autogenerated return type of DastSiteProfileDelete",
|
||||
"fields": [
|
||||
{
|
||||
"name": "clientMutationId",
|
||||
"description": "A unique identifier for the client performing the mutation.",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "errors",
|
||||
"description": "Errors encountered during execution of the mutation.",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "SCALAR",
|
||||
"name": "DastSiteProfileID",
|
||||
"description": "Identifier of DastSiteProfile",
|
||||
"fields": null,
|
||||
"inputFields": null,
|
||||
"interfaces": null,
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "DeleteAnnotationInput",
|
||||
|
@ -24452,6 +24564,33 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "dastSiteProfileDelete",
|
||||
"description": null,
|
||||
"args": [
|
||||
{
|
||||
"name": "input",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "DastSiteProfileDeleteInput",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "DastSiteProfileDeletePayload",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "deleteAnnotation",
|
||||
"description": null,
|
||||
|
|
|
@ -412,6 +412,15 @@ Autogenerated return type of DastSiteProfileCreate
|
|||
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
|
||||
| `id` | ID | ID of the site profile. |
|
||||
|
||||
## DastSiteProfileDeletePayload
|
||||
|
||||
Autogenerated return type of DastSiteProfileDelete
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | ---- | ---------- |
|
||||
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
|
||||
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
|
||||
|
||||
## DeleteAnnotationPayload
|
||||
|
||||
Autogenerated return type of DeleteAnnotation
|
||||
|
|
|
@ -195,21 +195,59 @@ Following you'll find some general common practices you will find as part of our
|
|||
|
||||
### How to query DOM elements
|
||||
|
||||
When it comes to querying DOM elements in your tests, it is best to uniquely and semantically target the element. Sometimes this cannot be done feasibly. In these cases, adding test attributes to simplify the selectors might be the best option.
|
||||
When it comes to querying DOM elements in your tests, it is best to uniquely and semantically target
|
||||
the element.
|
||||
|
||||
Preferentially, in component testing with `@vue/test-utils`, you should query for child components using the component itself. This helps enforce that specific behavior can be covered by that component's individual unit tests. Otherwise, try to use:
|
||||
Preferentially, this is done by targeting text the user actually sees using [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro).
|
||||
When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/dom-testing-library/api-queries#byrole)
|
||||
as these enforce accessibility best practices as well. The examples below demonstrate the order of preference.
|
||||
|
||||
Sometimes this cannot be done feasibly. In these cases, adding test attributes to simplify the
|
||||
selectors might be the best option.
|
||||
|
||||
- A semantic attribute like `name` (also verifies that `name` was setup properly)
|
||||
- A `data-testid` attribute ([recommended by maintainers of `@vue/test-utils`](https://github.com/vuejs/vue-test-utils/issues/1498#issuecomment-610133465))
|
||||
- a Vue `ref` (if using `@vue/test-utils`)
|
||||
|
||||
```javascript
|
||||
// Bad
|
||||
import { mount, shallowMount } from '@vue/test-utils'
|
||||
import { getByRole, getByText } from '@testing-library/dom'
|
||||
|
||||
let wrapper
|
||||
let el
|
||||
|
||||
const createComponent = (mountFn = shallowMount) => {
|
||||
wrapper = mountFn(Component)
|
||||
el = wrapper.vm.$el // reference to the container element
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent()
|
||||
})
|
||||
|
||||
|
||||
it('exists', () => {
|
||||
wrapper.find('.js-foo');
|
||||
wrapper.find('.btn-primary');
|
||||
wrapper.find('.qa-foo-component');
|
||||
wrapper.find('[data-qa-selector="foo"]');
|
||||
// Best
|
||||
|
||||
// NOTE: both mount and shallowMount work as long as a DOM element is available
|
||||
// Finds a properly formatted link with an accessable name of "Click Me"
|
||||
getByRole(el, 'link', { name: /Click Me/i })
|
||||
getByRole(el, 'link', { name: 'Click Me' })
|
||||
// Finds any element with the text "Click Me"
|
||||
getByText(el, 'Click Me')
|
||||
// Regex is also available
|
||||
getByText(el, /Click Me/i)
|
||||
|
||||
// Good
|
||||
wrapper.find('input[name=foo]');
|
||||
wrapper.find('[data-testid="foo"]');
|
||||
wrapper.find({ ref: 'foo'});
|
||||
|
||||
// Bad
|
||||
wrapper.find('.js-foo');
|
||||
wrapper.find('.btn-primary');
|
||||
wrapper.find('.qa-foo-component');
|
||||
wrapper.find('[data-qa-selector="foo"]');
|
||||
});
|
||||
|
||||
// Good
|
||||
|
@ -225,6 +263,22 @@ It is not recommended that you add `.js-*` classes just for testing purposes. On
|
|||
|
||||
Do not use a `.qa-*` class or `data-qa-selector` attribute for any tests other than QA end-to-end testing.
|
||||
|
||||
### Querying for child components
|
||||
|
||||
When testing Vue components with `@vue/test-utils` another possible approach is querying for child
|
||||
components instead of querying for DOM nodes. This assumes that implementation details of behavior
|
||||
under test should be covered by that component's individual unit test. There is no strong preference
|
||||
in writing DOM or component queries as long as your tests reliably cover expected behavior for the
|
||||
component under test.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
it('exists', () => {
|
||||
wrapper.find(FooComponent);
|
||||
});
|
||||
```
|
||||
|
||||
### Naming unit tests
|
||||
|
||||
When writing describe test blocks to test specific functions/methods,
|
||||
|
|
|
@ -85,6 +85,10 @@ module Gitlab
|
|||
def self.job_entry_matches_all_keys?
|
||||
::Feature.enabled?(:ci_job_entry_matches_all_keys)
|
||||
end
|
||||
|
||||
def self.reset_ci_minutes_for_all_namespaces?
|
||||
::Feature.enabled?(:reset_ci_minutes_for_all_namespaces, default_enabled: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,8 +5,8 @@ require 'redis'
|
|||
module SystemCheck
|
||||
module App
|
||||
class RedisVersionCheck < SystemCheck::BaseCheck
|
||||
MIN_REDIS_VERSION = '3.2.0'
|
||||
RECOMMENDED_REDIS_VERSION = '4.0.0'
|
||||
MIN_REDIS_VERSION = '4.0.0'
|
||||
RECOMMENDED_REDIS_VERSION = '4.0.0' # In future we may deprecate but still support Redis 4
|
||||
set_name "Redis version >= #{RECOMMENDED_REDIS_VERSION}?"
|
||||
|
||||
@custom_error_message = ''
|
||||
|
|
|
@ -3083,6 +3083,9 @@ msgstr ""
|
|||
msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Are you setting up GitLab for a company?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4245,6 +4248,9 @@ msgstr ""
|
|||
msgid "Cancel this job"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel, keep project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Canceled deployment to"
|
||||
msgstr ""
|
||||
|
||||
|
@ -7283,6 +7289,9 @@ msgstr ""
|
|||
msgid "Customer Portal"
|
||||
msgstr ""
|
||||
|
||||
msgid "Customizable by an administrator."
|
||||
msgstr ""
|
||||
|
||||
msgid "Customize colors"
|
||||
msgstr ""
|
||||
|
||||
|
@ -7729,6 +7738,9 @@ msgstr ""
|
|||
msgid "Delete project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete project. Are you ABSOLUTELY SURE?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete serverless domain?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -16547,6 +16559,12 @@ msgstr ""
|
|||
msgid "OnDemandScans|Target URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
|
||||
msgstr ""
|
||||
|
||||
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
|
||||
msgstr ""
|
||||
|
||||
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
|
@ -17773,6 +17791,9 @@ msgstr ""
|
|||
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
|
||||
msgstr ""
|
||||
|
||||
msgid "Please type the following to confirm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
|
||||
msgstr ""
|
||||
|
||||
|
@ -18991,6 +19012,12 @@ msgstr ""
|
|||
msgid "Projects to index"
|
||||
msgstr ""
|
||||
|
||||
msgid "Projects will be permanently deleted after a 7-day waiting period."
|
||||
msgstr ""
|
||||
|
||||
msgid "Projects will be permanently deleted immediately."
|
||||
msgstr ""
|
||||
|
||||
msgid "Projects with critical vulnerabilities"
|
||||
msgstr ""
|
||||
|
||||
|
@ -19675,6 +19702,9 @@ msgstr ""
|
|||
msgid "Recover hidden stage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Recovering projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "Recovery Codes"
|
||||
msgstr ""
|
||||
|
||||
|
@ -20069,12 +20099,6 @@ msgstr ""
|
|||
msgid "Removes time estimate."
|
||||
msgstr ""
|
||||
|
||||
msgid "Removing a project deletes it immediately, there will be no delay before the project is permanently removed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -24392,6 +24416,15 @@ msgstr ""
|
|||
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
|
||||
msgstr ""
|
||||
|
||||
msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
|
||||
msgstr ""
|
||||
|
||||
msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
|
||||
msgstr ""
|
||||
|
||||
msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
|
||||
msgstr ""
|
||||
|
||||
msgid "This also resolves all related threads"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25851,9 +25884,6 @@ msgstr ""
|
|||
msgid "Until"
|
||||
msgstr ""
|
||||
|
||||
msgid "Until that time, the project can be restored."
|
||||
msgstr ""
|
||||
|
||||
msgid "Unverified"
|
||||
msgstr ""
|
||||
|
||||
|
@ -27315,6 +27345,9 @@ msgstr ""
|
|||
msgid "Yes, close issue"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yes, delete project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yes, let me map Google Code users to full names or GitLab users."
|
||||
msgstr ""
|
||||
|
||||
|
@ -27330,6 +27363,9 @@ msgstr ""
|
|||
msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
|
||||
msgstr ""
|
||||
|
||||
msgid "You are about to permanently delete this project"
|
||||
msgstr ""
|
||||
|
||||
msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
|
||||
msgstr ""
|
||||
|
||||
|
@ -27480,6 +27516,9 @@ msgstr ""
|
|||
msgid "You can only upload one design when dropping onto an existing design."
|
||||
msgstr ""
|
||||
|
||||
msgid "You can recover this project until %{date}"
|
||||
msgstr ""
|
||||
|
||||
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ RSpec.describe 'Project' do
|
|||
end
|
||||
|
||||
it 'removes a project', :sidekiq_might_not_need_inline do
|
||||
expect { remove_with_confirm('Remove project', project.path) }.to change { Project.count }.by(-1)
|
||||
expect { remove_with_confirm('Remove project', project.path, 'Yes, delete project') }.to change { Project.count }.by(-1)
|
||||
expect(page).to have_content "Project '#{project.full_name}' is in the process of being deleted."
|
||||
expect(Project.all.count).to be_zero
|
||||
expect(project.issues).to be_empty
|
||||
|
@ -386,9 +386,9 @@ RSpec.describe 'Project' do
|
|||
{ form: '.rspec-merge-request-settings', input: '#project_printing_merge_request_link_enabled' }]
|
||||
end
|
||||
|
||||
def remove_with_confirm(button_text, confirm_with)
|
||||
def remove_with_confirm(button_text, confirm_with, confirm_button_text = 'Confirm')
|
||||
click_button button_text
|
||||
fill_in 'confirm_name_input', with: confirm_with
|
||||
click_button 'Confirm'
|
||||
click_button confirm_button_text
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Design management design version dropdown component renders design version dropdown button 1`] = `
|
||||
<gl-dropdown-stub
|
||||
<gl-deprecated-dropdown-stub
|
||||
class="design-version-dropdown"
|
||||
issueiid=""
|
||||
projectpath=""
|
||||
text="Showing Latest Version"
|
||||
variant="link"
|
||||
>
|
||||
<gl-dropdown-item-stub>
|
||||
<gl-deprecated-dropdown-item-stub>
|
||||
<router-link-stub
|
||||
class="d-flex js-version-link"
|
||||
to="[object Object]"
|
||||
|
@ -31,8 +31,8 @@ exports[`Design management design version dropdown component renders design vers
|
|||
class="fa fa-check float-right gl-mr-2"
|
||||
/>
|
||||
</router-link-stub>
|
||||
</gl-dropdown-item-stub>
|
||||
<gl-dropdown-item-stub>
|
||||
</gl-deprecated-dropdown-item-stub>
|
||||
<gl-deprecated-dropdown-item-stub>
|
||||
<router-link-stub
|
||||
class="d-flex js-version-link"
|
||||
to="[object Object]"
|
||||
|
@ -51,19 +51,19 @@ exports[`Design management design version dropdown component renders design vers
|
|||
|
||||
<!---->
|
||||
</router-link-stub>
|
||||
</gl-dropdown-item-stub>
|
||||
</gl-dropdown-stub>
|
||||
</gl-deprecated-dropdown-item-stub>
|
||||
</gl-deprecated-dropdown-stub>
|
||||
`;
|
||||
|
||||
exports[`Design management design version dropdown component renders design version list 1`] = `
|
||||
<gl-dropdown-stub
|
||||
<gl-deprecated-dropdown-stub
|
||||
class="design-version-dropdown"
|
||||
issueiid=""
|
||||
projectpath=""
|
||||
text="Showing Latest Version"
|
||||
variant="link"
|
||||
>
|
||||
<gl-dropdown-item-stub>
|
||||
<gl-deprecated-dropdown-item-stub>
|
||||
<router-link-stub
|
||||
class="d-flex js-version-link"
|
||||
to="[object Object]"
|
||||
|
@ -86,8 +86,8 @@ exports[`Design management design version dropdown component renders design vers
|
|||
class="fa fa-check float-right gl-mr-2"
|
||||
/>
|
||||
</router-link-stub>
|
||||
</gl-dropdown-item-stub>
|
||||
<gl-dropdown-item-stub>
|
||||
</gl-deprecated-dropdown-item-stub>
|
||||
<gl-deprecated-dropdown-item-stub>
|
||||
<router-link-stub
|
||||
class="d-flex js-version-link"
|
||||
to="[object Object]"
|
||||
|
@ -106,6 +106,6 @@ exports[`Design management design version dropdown component renders design vers
|
|||
|
||||
<!---->
|
||||
</router-link-stub>
|
||||
</gl-dropdown-item-stub>
|
||||
</gl-dropdown-stub>
|
||||
</gl-deprecated-dropdown-item-stub>
|
||||
</gl-deprecated-dropdown-stub>
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Project remove modal initialized matches the snapshot 1`] = `
|
||||
<form
|
||||
action="some/path"
|
||||
method="post"
|
||||
>
|
||||
<input
|
||||
name="_method"
|
||||
type="hidden"
|
||||
value="delete"
|
||||
/>
|
||||
|
||||
<input
|
||||
name="authenticity_token"
|
||||
type="hidden"
|
||||
/>
|
||||
|
||||
<gl-button-stub
|
||||
category="primary"
|
||||
icon=""
|
||||
role="button"
|
||||
size="medium"
|
||||
tabindex="0"
|
||||
variant="danger"
|
||||
>
|
||||
Remove project
|
||||
</gl-button-stub>
|
||||
|
||||
<gl-modal-stub
|
||||
actioncancel="[object Object]"
|
||||
actionprimary="[object Object]"
|
||||
footer-class="gl-bg-gray-10 gl-p-5"
|
||||
modalclass=""
|
||||
modalid="fakeUniqueId"
|
||||
ok-variant="danger"
|
||||
size="sm"
|
||||
title-class="gl-text-red-500"
|
||||
titletag="h4"
|
||||
>
|
||||
|
||||
<div>
|
||||
<gl-alert-stub
|
||||
class="gl-mb-5"
|
||||
dismisslabel="Dismiss"
|
||||
primarybuttonlink=""
|
||||
primarybuttontext=""
|
||||
secondarybuttonlink=""
|
||||
secondarybuttontext=""
|
||||
title="You are about to permanently delete this project"
|
||||
variant="danger"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
|
||||
/>
|
||||
</gl-alert-stub>
|
||||
|
||||
<p>
|
||||
This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc.
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="gl-mb-1"
|
||||
>
|
||||
Please type the following to confirm:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>
|
||||
foo
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<gl-form-input-stub
|
||||
id="confirm_name_input"
|
||||
name="confirm_name_input"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</gl-modal-stub>
|
||||
</form>
|
||||
`;
|
|
@ -1,126 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Project remove modal initialized matches the snapshot 1`] = `
|
||||
<form
|
||||
action="some/path"
|
||||
method="post"
|
||||
>
|
||||
<input
|
||||
name="_method"
|
||||
type="hidden"
|
||||
value="delete"
|
||||
/>
|
||||
|
||||
<input
|
||||
name="authenticity_token"
|
||||
type="hidden"
|
||||
/>
|
||||
|
||||
<b-button-stub
|
||||
class="[object Object]"
|
||||
event="click"
|
||||
role="button"
|
||||
routertag="a"
|
||||
size="md"
|
||||
tabindex="0"
|
||||
tag="button"
|
||||
type="button"
|
||||
variant="danger"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<span
|
||||
class="gl-button-text"
|
||||
>
|
||||
Remove project
|
||||
</span>
|
||||
</b-button-stub>
|
||||
|
||||
<b-modal-stub
|
||||
canceltitle="Cancel"
|
||||
cancelvariant="secondary"
|
||||
footerclass="bg-gray-light gl-p-5"
|
||||
headerclosecontent="×"
|
||||
headercloselabel="Close"
|
||||
id="remove-project-modal"
|
||||
ignoreenforcefocusselector=""
|
||||
lazy="true"
|
||||
modalclass="gl-modal,"
|
||||
oktitle="OK"
|
||||
okvariant="danger"
|
||||
size="sm"
|
||||
title=""
|
||||
titletag="h4"
|
||||
>
|
||||
|
||||
<div>
|
||||
<p
|
||||
class="gl-text-red-500 gl-font-weight-bold"
|
||||
>
|
||||
This can lead to data loss.
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="gl-mb-0"
|
||||
>
|
||||
This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<gl-sprintf-stub
|
||||
message="Please type %{phrase_code} to proceed or close this modal to cancel."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<gl-form-input-stub
|
||||
id="confirm_name_input"
|
||||
name="confirm_name_input"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template />
|
||||
|
||||
<template>
|
||||
Confirmation required
|
||||
</template>
|
||||
|
||||
<template />
|
||||
|
||||
<template />
|
||||
|
||||
<template />
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="gl-w-full gl-display-flex gl-just-content-start gl-m-0"
|
||||
>
|
||||
<b-button-stub
|
||||
class="[object Object]"
|
||||
disabled="true"
|
||||
event="click"
|
||||
routertag="a"
|
||||
size="md"
|
||||
tag="button"
|
||||
type="button"
|
||||
variant="danger"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<span
|
||||
class="gl-button-text"
|
||||
>
|
||||
|
||||
Confirm
|
||||
|
||||
</span>
|
||||
</b-button-stub>
|
||||
</div>
|
||||
</template>
|
||||
</b-modal-stub>
|
||||
</form>
|
||||
`;
|
|
@ -0,0 +1,47 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import ProjectDeleteButton from '~/projects/components/project_delete_button.vue';
|
||||
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
|
||||
|
||||
jest.mock('lodash/uniqueId', () => () => 'fakeUniqueId');
|
||||
|
||||
describe('Project remove modal', () => {
|
||||
let wrapper;
|
||||
|
||||
const findSharedDeleteButton = () => wrapper.find(SharedDeleteButton);
|
||||
|
||||
const defaultProps = {
|
||||
confirmPhrase: 'foo',
|
||||
formPath: 'some/path',
|
||||
};
|
||||
|
||||
const createComponent = (props = {}) => {
|
||||
wrapper = shallowMount(ProjectDeleteButton, {
|
||||
propsData: {
|
||||
...defaultProps,
|
||||
...props,
|
||||
},
|
||||
stubs: {
|
||||
SharedDeleteButton,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
describe('initialized', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('matches the snapshot', () => {
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('passes confirmPhrase and formPath props to the shared delete button', () => {
|
||||
expect(findSharedDeleteButton().props()).toEqual(defaultProps);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,62 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlButton, GlModal } from '@gitlab/ui';
|
||||
import ProjectRemoveModal from '~/projects/components/remove_modal.vue';
|
||||
|
||||
describe('Project remove modal', () => {
|
||||
let wrapper;
|
||||
|
||||
const findFormElement = () => wrapper.find('form').element;
|
||||
const findConfirmButton = () => wrapper.find(GlModal).find(GlButton);
|
||||
|
||||
const defaultProps = {
|
||||
formPath: 'some/path',
|
||||
confirmPhrase: 'foo',
|
||||
warningMessage: 'This can lead to data loss.',
|
||||
};
|
||||
|
||||
const createComponent = (data = {}) => {
|
||||
wrapper = shallowMount(ProjectRemoveModal, {
|
||||
propsData: defaultProps,
|
||||
data: () => data,
|
||||
stubs: {
|
||||
GlButton,
|
||||
GlModal,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
describe('initialized', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('matches the snapshot', () => {
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('user input matches the confirmPhrase', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ userInput: defaultProps.confirmPhrase });
|
||||
});
|
||||
|
||||
it('the confirm button is not dislabled', () => {
|
||||
expect(findConfirmButton().attributes('disabled')).toBe(undefined);
|
||||
});
|
||||
|
||||
describe('and when the confirmation button is clicked', () => {
|
||||
beforeEach(() => {
|
||||
findConfirmButton().vm.$emit('click');
|
||||
});
|
||||
|
||||
it('submits the form element', () => {
|
||||
expect(findFormElement().submit).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,113 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Project remove modal intialized matches the snapshot 1`] = `
|
||||
<form
|
||||
action="some/path"
|
||||
method="post"
|
||||
>
|
||||
<input
|
||||
name="_method"
|
||||
type="hidden"
|
||||
value="delete"
|
||||
/>
|
||||
|
||||
<input
|
||||
name="authenticity_token"
|
||||
type="hidden"
|
||||
value="test-csrf-token"
|
||||
/>
|
||||
|
||||
<gl-button-stub
|
||||
category="primary"
|
||||
icon=""
|
||||
role="button"
|
||||
size="medium"
|
||||
tabindex="0"
|
||||
variant="danger"
|
||||
>
|
||||
Remove project
|
||||
</gl-button-stub>
|
||||
|
||||
<b-modal-stub
|
||||
canceltitle="Cancel"
|
||||
cancelvariant="secondary"
|
||||
footerclass="gl-bg-gray-10 gl-p-5"
|
||||
headerclosecontent="×"
|
||||
headercloselabel="Close"
|
||||
id="delete-project-modal-2"
|
||||
ignoreenforcefocusselector=""
|
||||
lazy="true"
|
||||
modalclass="gl-modal,"
|
||||
oktitle="OK"
|
||||
okvariant="danger"
|
||||
size="sm"
|
||||
title=""
|
||||
titleclass="gl-text-red-500"
|
||||
titletag="h4"
|
||||
>
|
||||
|
||||
<div>
|
||||
|
||||
<p
|
||||
class="gl-mb-1"
|
||||
>
|
||||
Please type the following to confirm:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>
|
||||
foo
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<gl-form-input-stub
|
||||
id="confirm_name_input"
|
||||
name="confirm_name_input"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<template />
|
||||
|
||||
<template>
|
||||
Delete project. Are you ABSOLUTELY SURE?
|
||||
</template>
|
||||
|
||||
<template />
|
||||
|
||||
<template />
|
||||
|
||||
<template />
|
||||
|
||||
<template>
|
||||
<gl-button-stub
|
||||
category="tertiary"
|
||||
class="js-modal-action-cancel"
|
||||
icon=""
|
||||
size="medium"
|
||||
variant="default"
|
||||
>
|
||||
|
||||
Cancel, keep project
|
||||
|
||||
</gl-button-stub>
|
||||
|
||||
<!---->
|
||||
|
||||
<gl-button-stub
|
||||
category="tertiary"
|
||||
class="js-modal-action-primary"
|
||||
disabled="true"
|
||||
icon=""
|
||||
size="medium"
|
||||
variant="danger"
|
||||
>
|
||||
|
||||
Yes, delete project
|
||||
|
||||
</gl-button-stub>
|
||||
</template>
|
||||
</b-modal-stub>
|
||||
</form>
|
||||
`;
|
|
@ -0,0 +1,83 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlModal } from '@gitlab/ui';
|
||||
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
|
||||
|
||||
jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' }));
|
||||
|
||||
describe('Project remove modal', () => {
|
||||
let wrapper;
|
||||
|
||||
const findFormElement = () => wrapper.find('form');
|
||||
const findConfirmButton = () => wrapper.find('.js-modal-action-primary');
|
||||
const findAuthenticityTokenInput = () => findFormElement().find('input[name=authenticity_token]');
|
||||
const findModal = () => wrapper.find(GlModal);
|
||||
|
||||
const defaultProps = {
|
||||
confirmPhrase: 'foo',
|
||||
formPath: 'some/path',
|
||||
};
|
||||
|
||||
const createComponent = (data = {}) => {
|
||||
wrapper = shallowMount(SharedDeleteButton, {
|
||||
propsData: defaultProps,
|
||||
data: () => data,
|
||||
stubs: {
|
||||
GlModal,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
describe('intialized', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('matches the snapshot', () => {
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('sets a csrf token on the authenticity form input', () => {
|
||||
expect(findAuthenticityTokenInput().element.value).toEqual('test-csrf-token');
|
||||
});
|
||||
|
||||
it('sets the form action to the provided path', () => {
|
||||
expect(findFormElement().attributes('action')).toEqual(defaultProps.formPath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user input does not match the confirmPhrase', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ userInput: 'bar' });
|
||||
});
|
||||
|
||||
it('the confirm button is disabled', () => {
|
||||
expect(findConfirmButton().attributes('disabled')).toBe('true');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user input matches the confirmPhrase', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ userInput: defaultProps.confirmPhrase });
|
||||
});
|
||||
|
||||
it('the confirm button is not disabled', () => {
|
||||
expect(findConfirmButton().attributes('disabled')).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the modal is confirmed', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
findModal().vm.$emit('ok');
|
||||
});
|
||||
|
||||
it('submits the form element', () => {
|
||||
expect(findFormElement().element.submit).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue