Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
abc0c2c770
commit
a46fed716c
|
|
@ -7,7 +7,9 @@ const twoFactorNode = document.querySelector('.js-two-factor-auth');
|
|||
const skippable = twoFactorNode ? parseBoolean(twoFactorNode.dataset.twoFactorSkippable) : false;
|
||||
|
||||
if (skippable) {
|
||||
const button = `<br/><a class="btn gl-button btn-sm btn-confirm gl-mt-3" data-qa-selector="configure_it_later_button" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`;
|
||||
const button = `<div class="gl-alert-actions">
|
||||
<a class="btn gl-button btn-md btn-confirm gl-alert-action" data-qa-selector="configure_it_later_button" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>
|
||||
</div>`;
|
||||
const flashAlert = document.querySelector('.flash-alert');
|
||||
if (flashAlert) {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
|
|
@ -17,7 +19,5 @@ if (skippable) {
|
|||
|
||||
mount2faRegistration();
|
||||
initWebAuthnRegistration();
|
||||
|
||||
initRecoveryCodes();
|
||||
|
||||
initManageTwoFactorForm();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
<script>
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import {
|
||||
sprintfWorkItem,
|
||||
WIDGET_TYPE_ASSIGNEES,
|
||||
WIDGET_TYPE_HEALTH_STATUS,
|
||||
WIDGET_TYPE_ITERATION,
|
||||
WIDGET_TYPE_LABELS,
|
||||
WIDGET_TYPE_MILESTONE,
|
||||
WIDGET_TYPE_PROGRESS,
|
||||
WIDGET_TYPE_START_AND_DUE_DATE,
|
||||
WIDGET_TYPE_WEIGHT,
|
||||
} from '../constants';
|
||||
import WorkItemState from './work_item_state.vue';
|
||||
import WorkItemDueDate from './work_item_due_date.vue';
|
||||
import WorkItemAssignees from './work_item_assignees.vue';
|
||||
import WorkItemLabels from './work_item_labels.vue';
|
||||
import WorkItemMilestone from './work_item_milestone.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WorkItemLabels,
|
||||
WorkItemMilestone,
|
||||
WorkItemAssignees,
|
||||
WorkItemDueDate,
|
||||
WorkItemState,
|
||||
WorkItemWeight: () => import('ee_component/work_items/components/work_item_weight.vue'),
|
||||
WorkItemProgress: () => import('ee_component/work_items/components/work_item_progress.vue'),
|
||||
WorkItemIteration: () => import('ee_component/work_items/components/work_item_iteration.vue'),
|
||||
WorkItemHealthStatus: () =>
|
||||
import('ee_component/work_items/components/work_item_health_status.vue'),
|
||||
},
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
inject: ['fullPath'],
|
||||
props: {
|
||||
workItem: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
workItemParentId: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
workItemType() {
|
||||
return this.workItem.workItemType?.name;
|
||||
},
|
||||
canUpdate() {
|
||||
return this.workItem?.userPermissions?.updateWorkItem;
|
||||
},
|
||||
canDelete() {
|
||||
return this.workItem?.userPermissions?.deleteWorkItem;
|
||||
},
|
||||
canSetWorkItemMetadata() {
|
||||
return this.workItem?.userPermissions?.setWorkItemMetadata;
|
||||
},
|
||||
canAssignUnassignUser() {
|
||||
return this.workItemAssignees && this.canSetWorkItemMetadata;
|
||||
},
|
||||
confidentialTooltip() {
|
||||
return sprintfWorkItem(this.$options.i18n.confidentialTooltip, this.workItemType);
|
||||
},
|
||||
workItemAssignees() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_ASSIGNEES);
|
||||
},
|
||||
workItemLabels() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_LABELS);
|
||||
},
|
||||
workItemDueDate() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_START_AND_DUE_DATE);
|
||||
},
|
||||
workItemWeight() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_WEIGHT);
|
||||
},
|
||||
workItemProgress() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_PROGRESS);
|
||||
},
|
||||
workItemIteration() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_ITERATION);
|
||||
},
|
||||
workItemHealthStatus() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_HEALTH_STATUS);
|
||||
},
|
||||
workItemMilestone() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_MILESTONE);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isWidgetPresent(type) {
|
||||
return this.workItem?.widgets?.find((widget) => widget.type === type);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<work-item-state
|
||||
:work-item="workItem"
|
||||
:work-item-parent-id="workItemParentId"
|
||||
:can-update="canUpdate"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-assignees
|
||||
v-if="workItemAssignees"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:assignees="workItemAssignees.assignees.nodes"
|
||||
:allows-multiple-assignees="workItemAssignees.allowsMultipleAssignees"
|
||||
:work-item-type="workItemType"
|
||||
:can-invite-members="workItemAssignees.canInviteMembers"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-labels
|
||||
v-if="workItemLabels"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-due-date
|
||||
v-if="workItemDueDate"
|
||||
:can-update="canUpdate"
|
||||
:due-date="workItemDueDate.dueDate"
|
||||
:start-date="workItemDueDate.startDate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-type="workItemType"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-milestone
|
||||
v-if="workItemMilestone"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-milestone="workItemMilestone.milestone"
|
||||
:work-item-type="workItemType"
|
||||
:can-update="canUpdate"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-weight
|
||||
v-if="workItemWeight"
|
||||
class="gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:weight="workItemWeight.weight"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
:work-item-type="workItemType"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-progress
|
||||
v-if="workItemProgress"
|
||||
class="gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:progress="workItemProgress.progress"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-type="workItemType"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-iteration
|
||||
v-if="workItemIteration"
|
||||
class="gl-mb-5"
|
||||
:iteration="workItemIteration.iteration"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
:work-item-type="workItemType"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-health-status
|
||||
v-if="workItemHealthStatus"
|
||||
class="gl-mb-5"
|
||||
:health-status="workItemHealthStatus.healthStatus"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
:work-item-type="workItemType"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
|
@ -22,18 +22,11 @@ import {
|
|||
sprintfWorkItem,
|
||||
i18n,
|
||||
WIDGET_TYPE_ASSIGNEES,
|
||||
WIDGET_TYPE_LABELS,
|
||||
WIDGET_TYPE_NOTIFICATIONS,
|
||||
WIDGET_TYPE_CURRENT_USER_TODOS,
|
||||
WIDGET_TYPE_DESCRIPTION,
|
||||
WIDGET_TYPE_AWARD_EMOJI,
|
||||
WIDGET_TYPE_START_AND_DUE_DATE,
|
||||
WIDGET_TYPE_WEIGHT,
|
||||
WIDGET_TYPE_PROGRESS,
|
||||
WIDGET_TYPE_HIERARCHY,
|
||||
WIDGET_TYPE_MILESTONE,
|
||||
WIDGET_TYPE_ITERATION,
|
||||
WIDGET_TYPE_HEALTH_STATUS,
|
||||
WORK_ITEM_TYPE_VALUE_ISSUE,
|
||||
WORK_ITEM_TYPE_VALUE_OBJECTIVE,
|
||||
WIDGET_TYPE_NOTES,
|
||||
|
|
@ -48,17 +41,13 @@ import { findHierarchyWidgetChildren } from '../utils';
|
|||
import WorkItemTree from './work_item_links/work_item_tree.vue';
|
||||
import WorkItemActions from './work_item_actions.vue';
|
||||
import WorkItemTodos from './work_item_todos.vue';
|
||||
import WorkItemState from './work_item_state.vue';
|
||||
import WorkItemTitle from './work_item_title.vue';
|
||||
import WorkItemAttributesWrapper from './work_item_attributes_wrapper.vue';
|
||||
import WorkItemCreatedUpdated from './work_item_created_updated.vue';
|
||||
import WorkItemDescription from './work_item_description.vue';
|
||||
import WorkItemAwardEmoji from './work_item_award_emoji.vue';
|
||||
import WorkItemDueDate from './work_item_due_date.vue';
|
||||
import WorkItemAssignees from './work_item_assignees.vue';
|
||||
import WorkItemLabels from './work_item_labels.vue';
|
||||
import WorkItemMilestone from './work_item_milestone.vue';
|
||||
import WorkItemNotes from './work_item_notes.vue';
|
||||
import WorkItemDetailModal from './work_item_detail_modal.vue';
|
||||
import WorkItemAwardEmoji from './work_item_award_emoji.vue';
|
||||
|
||||
export default {
|
||||
i18n,
|
||||
|
|
@ -74,23 +63,14 @@ export default {
|
|||
GlSkeletonLoader,
|
||||
GlIcon,
|
||||
GlEmptyState,
|
||||
WorkItemAssignees,
|
||||
WorkItemActions,
|
||||
WorkItemTodos,
|
||||
WorkItemCreatedUpdated,
|
||||
WorkItemDescription,
|
||||
WorkItemAwardEmoji,
|
||||
WorkItemDueDate,
|
||||
WorkItemLabels,
|
||||
WorkItemTitle,
|
||||
WorkItemState,
|
||||
WorkItemWeight: () => import('ee_component/work_items/components/work_item_weight.vue'),
|
||||
WorkItemProgress: () => import('ee_component/work_items/components/work_item_progress.vue'),
|
||||
WorkItemAttributesWrapper,
|
||||
WorkItemTypeIcon,
|
||||
WorkItemIteration: () => import('ee_component/work_items/components/work_item_iteration.vue'),
|
||||
WorkItemHealthStatus: () =>
|
||||
import('ee_component/work_items/components/work_item_health_status.vue'),
|
||||
WorkItemMilestone,
|
||||
WorkItemTree,
|
||||
WorkItemNotes,
|
||||
WorkItemDetailModal,
|
||||
|
|
@ -256,33 +236,12 @@ export default {
|
|||
workItemAssignees() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_ASSIGNEES);
|
||||
},
|
||||
workItemLabels() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_LABELS);
|
||||
},
|
||||
workItemDueDate() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_START_AND_DUE_DATE);
|
||||
},
|
||||
workItemWeight() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_WEIGHT);
|
||||
},
|
||||
workItemProgress() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_PROGRESS);
|
||||
},
|
||||
workItemAwardEmoji() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_AWARD_EMOJI);
|
||||
},
|
||||
workItemHierarchy() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_HIERARCHY);
|
||||
},
|
||||
workItemIteration() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_ITERATION);
|
||||
},
|
||||
workItemHealthStatus() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_HEALTH_STATUS);
|
||||
},
|
||||
workItemMilestone() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_MILESTONE);
|
||||
},
|
||||
workItemNotes() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_NOTES);
|
||||
},
|
||||
|
|
@ -511,83 +470,9 @@ export default {
|
|||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-created-updated :work-item-iid="workItemIid" />
|
||||
<work-item-state
|
||||
<work-item-attributes-wrapper
|
||||
:work-item="workItem"
|
||||
:work-item-parent-id="workItemParentId"
|
||||
:can-update="canUpdate"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-assignees
|
||||
v-if="workItemAssignees"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:assignees="workItemAssignees.assignees.nodes"
|
||||
:allows-multiple-assignees="workItemAssignees.allowsMultipleAssignees"
|
||||
:work-item-type="workItemType"
|
||||
:can-invite-members="workItemAssignees.canInviteMembers"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-labels
|
||||
v-if="workItemLabels"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-due-date
|
||||
v-if="workItemDueDate"
|
||||
:can-update="canUpdate"
|
||||
:due-date="workItemDueDate.dueDate"
|
||||
:start-date="workItemDueDate.startDate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-type="workItemType"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-milestone
|
||||
v-if="workItemMilestone"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-milestone="workItemMilestone.milestone"
|
||||
:work-item-type="workItemType"
|
||||
:can-update="canUpdate"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-weight
|
||||
v-if="workItemWeight"
|
||||
class="gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:weight="workItemWeight.weight"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
:work-item-type="workItemType"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-progress
|
||||
v-if="workItemProgress"
|
||||
class="gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:progress="workItemProgress.progress"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-type="workItemType"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-iteration
|
||||
v-if="workItemIteration"
|
||||
class="gl-mb-5"
|
||||
:iteration="workItemIteration.iteration"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
:work-item-type="workItemType"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-health-status
|
||||
v-if="workItemHealthStatus"
|
||||
class="gl-mb-5"
|
||||
:health-status="workItemHealthStatus.healthStatus"
|
||||
:can-update="canUpdate"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
:work-item-type="workItemType"
|
||||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-description
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
- else
|
||||
= _("(removed)")
|
||||
|
||||
.todo-body.gl-mb-2.gl-px-2.gl-display-flex.gl-align-items-flex-start.gl-lg-align-items-center
|
||||
.todo-body.gl-mb-2.gl-px-2.gl-display-flex.gl-align-items-flex-start
|
||||
.todo-avatar.gl-display-none.gl-sm-display-inline-block
|
||||
= author_avatar(todo, size: 24)
|
||||
.todo-note
|
||||
|
|
@ -47,6 +47,8 @@
|
|||
%span.action-description<
|
||||
= first_line_in_markdown(todo, :body, 125, is_todo: true, project: todo.project, group: todo.group)
|
||||
|
||||
= render_if_exists "dashboard/todos/diff_summary", local_assigns: { todo: todo }
|
||||
|
||||
.todo-timestamp.gl-white-space-nowrap.gl-sm-ml-3.gl-mt-2.gl-mb-2.gl-sm-my-0.gl-px-2.gl-sm-px-0
|
||||
%span.todo-timestamp.gl-font-sm.gl-text-secondary
|
||||
= todo_due_date(todo)
|
||||
|
|
|
|||
|
|
@ -28,4 +28,4 @@
|
|||
= clipboard_button(target: '#domain_verification', class: 'btn-default d-none d-sm-block')
|
||||
%p.form-text.text-muted
|
||||
- link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
|
||||
= _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration.").html_safe % { link_to_help: link_to_help }
|
||||
= _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration within seven days.").html_safe % { link_to_help: link_to_help }
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ feature_categories:
|
|||
description: Define ownership of namespaces, projects, and users by organizations
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119421
|
||||
milestone: '16.0'
|
||||
gitlab_schema: gitlab_main
|
||||
gitlab_schema: gitlab_main_clusterwide
|
||||
|
|
|
|||
|
|
@ -5239,7 +5239,7 @@ msgstr ""
|
|||
msgid "Analytics"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Add to Dashboard"
|
||||
msgid "Analytics|A visualization with that name already exists."
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Add visualizations"
|
||||
|
|
@ -5311,9 +5311,15 @@ msgstr ""
|
|||
msgid "Analytics|Edit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Enter a visualization name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Error while saving dashboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Error while saving visualization."
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Host"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -5323,7 +5329,7 @@ msgstr ""
|
|||
msgid "Analytics|Line Chart"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|New Analytics Visualization Title"
|
||||
msgid "Analytics|New analytics visualization name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|New dashboard"
|
||||
|
|
@ -5362,6 +5368,18 @@ msgstr ""
|
|||
msgid "Analytics|Save"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Save and add to Dashboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Save new visualization"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Select a measurement"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Select a visualization type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Single Statistic"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -5374,6 +5392,9 @@ msgstr ""
|
|||
msgid "Analytics|Updating dashboard %{dashboardId}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Updating visualization %{visualizationName}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Users"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -5392,6 +5413,9 @@ msgstr ""
|
|||
msgid "Analytics|Visualization Type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Visualization was saved successfully"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analyze your dependencies for known vulnerabilities."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -16424,7 +16448,7 @@ msgstr ""
|
|||
msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
|
||||
msgstr ""
|
||||
|
||||
msgid "DomainVerification|To verify ownership of your domain, add the above key to a TXT record within your DNS configuration. %{link_to_help}"
|
||||
msgid "DomainVerification|To verify ownership of your domain, add the above key to a TXT record within your DNS configuration within seven days. %{link_to_help}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Don't have a group?"
|
||||
|
|
@ -44775,6 +44799,9 @@ msgstr ""
|
|||
msgid "Summary comment (optional)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Summary generated by AI"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sun"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -47737,7 +47764,7 @@ msgstr ""
|
|||
msgid "To"
|
||||
msgstr ""
|
||||
|
||||
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
|
||||
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration within seven days."
|
||||
msgstr ""
|
||||
|
||||
msgid "To Do"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
|
||||
import WorkItemDueDate from '~/work_items/components/work_item_due_date.vue';
|
||||
import WorkItemState from '~/work_items/components/work_item_state.vue';
|
||||
import WorkItemLabels from '~/work_items/components/work_item_labels.vue';
|
||||
import WorkItemMilestone from '~/work_items/components/work_item_milestone.vue';
|
||||
|
||||
import WorkItemAttributesWrapper from '~/work_items/components/work_item_attributes_wrapper.vue';
|
||||
import { workItemResponseFactory } from '../mock_data';
|
||||
|
||||
describe('WorkItemAttributesWrapper component', () => {
|
||||
let wrapper;
|
||||
|
||||
const workItemQueryResponse = workItemResponseFactory({ canUpdate: true, canDelete: true });
|
||||
|
||||
const findWorkItemState = () => wrapper.findComponent(WorkItemState);
|
||||
const findWorkItemDueDate = () => wrapper.findComponent(WorkItemDueDate);
|
||||
const findWorkItemAssignees = () => wrapper.findComponent(WorkItemAssignees);
|
||||
const findWorkItemLabels = () => wrapper.findComponent(WorkItemLabels);
|
||||
const findWorkItemMilestone = () => wrapper.findComponent(WorkItemMilestone);
|
||||
|
||||
const createComponent = ({ workItem = workItemQueryResponse.data.workItem } = {}) => {
|
||||
wrapper = shallowMount(WorkItemAttributesWrapper, {
|
||||
propsData: {
|
||||
workItem,
|
||||
},
|
||||
provide: {
|
||||
hasIssueWeightsFeature: true,
|
||||
hasIterationsFeature: true,
|
||||
hasOkrsFeature: true,
|
||||
hasIssuableHealthStatusFeature: true,
|
||||
projectNamespace: 'namespace',
|
||||
fullPath: 'group/project',
|
||||
},
|
||||
stubs: {
|
||||
WorkItemWeight: true,
|
||||
WorkItemIteration: true,
|
||||
WorkItemHealthStatus: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
describe('work item state', () => {
|
||||
it('renders the work item state', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findWorkItemState().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('assignees widget', () => {
|
||||
it('renders assignees component when widget is returned from the API', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findWorkItemAssignees().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render assignees component when widget is not returned from the API', () => {
|
||||
createComponent({
|
||||
workItem: workItemResponseFactory({ assigneesWidgetPresent: false }).data.workItem,
|
||||
});
|
||||
|
||||
expect(findWorkItemAssignees().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('labels widget', () => {
|
||||
it.each`
|
||||
description | labelsWidgetPresent | exists
|
||||
${'renders when widget is returned from API'} | ${true} | ${true}
|
||||
${'does not render when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ labelsWidgetPresent, exists }) => {
|
||||
const response = workItemResponseFactory({ labelsWidgetPresent });
|
||||
createComponent({ workItem: response.data.workItem });
|
||||
|
||||
expect(findWorkItemLabels().exists()).toBe(exists);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dates widget', () => {
|
||||
describe.each`
|
||||
description | datesWidgetPresent | exists
|
||||
${'when widget is returned from API'} | ${true} | ${true}
|
||||
${'when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ datesWidgetPresent, exists }) => {
|
||||
it(`${datesWidgetPresent ? 'renders' : 'does not render'} due date component`, () => {
|
||||
const response = workItemResponseFactory({ datesWidgetPresent });
|
||||
createComponent({ workItem: response.data.workItem });
|
||||
|
||||
expect(findWorkItemDueDate().exists()).toBe(exists);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('milestone widget', () => {
|
||||
it.each`
|
||||
description | milestoneWidgetPresent | exists
|
||||
${'renders when widget is returned from API'} | ${true} | ${true}
|
||||
${'does not render when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ milestoneWidgetPresent, exists }) => {
|
||||
const response = workItemResponseFactory({ milestoneWidgetPresent });
|
||||
createComponent({ workItem: response.data.workItem });
|
||||
|
||||
expect(findWorkItemMilestone().exists()).toBe(exists);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -18,12 +18,8 @@ import WorkItemDetail from '~/work_items/components/work_item_detail.vue';
|
|||
import WorkItemActions from '~/work_items/components/work_item_actions.vue';
|
||||
import WorkItemDescription from '~/work_items/components/work_item_description.vue';
|
||||
import WorkItemCreatedUpdated from '~/work_items/components/work_item_created_updated.vue';
|
||||
import WorkItemDueDate from '~/work_items/components/work_item_due_date.vue';
|
||||
import WorkItemState from '~/work_items/components/work_item_state.vue';
|
||||
import WorkItemAttributesWrapper from '~/work_items/components/work_item_attributes_wrapper.vue';
|
||||
import WorkItemTitle from '~/work_items/components/work_item_title.vue';
|
||||
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
|
||||
import WorkItemLabels from '~/work_items/components/work_item_labels.vue';
|
||||
import WorkItemMilestone from '~/work_items/components/work_item_milestone.vue';
|
||||
import WorkItemTree from '~/work_items/components/work_item_links/work_item_tree.vue';
|
||||
import WorkItemNotes from '~/work_items/components/work_item_notes.vue';
|
||||
import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
|
||||
|
|
@ -69,12 +65,8 @@ describe('WorkItemDetail component', () => {
|
|||
const findWorkItemActions = () => wrapper.findComponent(WorkItemActions);
|
||||
const findWorkItemTitle = () => wrapper.findComponent(WorkItemTitle);
|
||||
const findCreatedUpdated = () => wrapper.findComponent(WorkItemCreatedUpdated);
|
||||
const findWorkItemState = () => wrapper.findComponent(WorkItemState);
|
||||
const findWorkItemDescription = () => wrapper.findComponent(WorkItemDescription);
|
||||
const findWorkItemDueDate = () => wrapper.findComponent(WorkItemDueDate);
|
||||
const findWorkItemAssignees = () => wrapper.findComponent(WorkItemAssignees);
|
||||
const findWorkItemLabels = () => wrapper.findComponent(WorkItemLabels);
|
||||
const findWorkItemMilestone = () => wrapper.findComponent(WorkItemMilestone);
|
||||
const findWorkItemAttributesWrapper = () => wrapper.findComponent(WorkItemAttributesWrapper);
|
||||
const findParent = () => wrapper.find('[data-testid="work-item-parent"]');
|
||||
const findParentButton = () => findParent().findComponent(GlButton);
|
||||
const findCloseButton = () => wrapper.find('[data-testid="work-item-close"]');
|
||||
|
|
@ -168,7 +160,6 @@ describe('WorkItemDetail component', () => {
|
|||
|
||||
it('renders skeleton loader', () => {
|
||||
expect(findSkeleton().exists()).toBe(true);
|
||||
expect(findWorkItemState().exists()).toBe(false);
|
||||
expect(findWorkItemTitle().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -181,7 +172,6 @@ describe('WorkItemDetail component', () => {
|
|||
|
||||
it('does not render skeleton', () => {
|
||||
expect(findSkeleton().exists()).toBe(false);
|
||||
expect(findWorkItemState().exists()).toBe(true);
|
||||
expect(findWorkItemTitle().exists()).toBe(true);
|
||||
});
|
||||
|
||||
|
|
@ -480,83 +470,6 @@ describe('WorkItemDetail component', () => {
|
|||
|
||||
expect(findAlert().text()).toBe(updateError);
|
||||
});
|
||||
describe('assignees widget', () => {
|
||||
it('renders assignees component when widget is returned from the API', async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkItemAssignees().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render assignees component when widget is not returned from the API', async () => {
|
||||
createComponent({
|
||||
handler: jest
|
||||
.fn()
|
||||
.mockResolvedValue(workItemByIidResponseFactory({ assigneesWidgetPresent: false })),
|
||||
});
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkItemAssignees().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('labels widget', () => {
|
||||
it.each`
|
||||
description | labelsWidgetPresent | exists
|
||||
${'renders when widget is returned from API'} | ${true} | ${true}
|
||||
${'does not render when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', async ({ labelsWidgetPresent, exists }) => {
|
||||
const response = workItemByIidResponseFactory({ labelsWidgetPresent });
|
||||
const handler = jest.fn().mockResolvedValue(response);
|
||||
createComponent({ handler });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkItemLabels().exists()).toBe(exists);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dates widget', () => {
|
||||
describe.each`
|
||||
description | datesWidgetPresent | exists
|
||||
${'when widget is returned from API'} | ${true} | ${true}
|
||||
${'when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ datesWidgetPresent, exists }) => {
|
||||
it(`${datesWidgetPresent ? 'renders' : 'does not render'} due date component`, async () => {
|
||||
const response = workItemByIidResponseFactory({ datesWidgetPresent });
|
||||
const handler = jest.fn().mockResolvedValue(response);
|
||||
createComponent({ handler });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkItemDueDate().exists()).toBe(exists);
|
||||
});
|
||||
});
|
||||
|
||||
it('shows an error message when it emits an `error` event', async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
const updateError = 'Failed to update';
|
||||
|
||||
findWorkItemDueDate().vm.$emit('error', updateError);
|
||||
await waitForPromises();
|
||||
|
||||
expect(findAlert().text()).toBe(updateError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('milestone widget', () => {
|
||||
it.each`
|
||||
description | milestoneWidgetPresent | exists
|
||||
${'renders when widget is returned from API'} | ${true} | ${true}
|
||||
${'does not render when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', async ({ milestoneWidgetPresent, exists }) => {
|
||||
const response = workItemByIidResponseFactory({ milestoneWidgetPresent });
|
||||
const handler = jest.fn().mockResolvedValue(response);
|
||||
createComponent({ handler });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkItemMilestone().exists()).toBe(exists);
|
||||
});
|
||||
});
|
||||
|
||||
it('calls the work item query', async () => {
|
||||
createComponent();
|
||||
|
|
@ -713,4 +626,24 @@ describe('WorkItemDetail component', () => {
|
|||
expect(findWorkItemTodos().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('work item attributes wrapper', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('renders the work item attributes wrapper', () => {
|
||||
expect(findWorkItemAttributesWrapper().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('shows an error message when it emits an `error` event', async () => {
|
||||
const updateError = 'Failed to update';
|
||||
|
||||
findWorkItemAttributesWrapper().vm.$emit('error', updateError);
|
||||
await waitForPromises();
|
||||
|
||||
expect(findAlert().text()).toBe(updateError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue