From e13331735e2290bb270b35a32755fc4246a9efc6 Mon Sep 17 00:00:00 2001 From: Sascha Eggenberger <seggenberger@gitlab.com> Date: Wed, 6 Dec 2023 13:12:28 +0000 Subject: [PATCH] Test case layout update Changelog: changed EE: true --- .../show/components/issuable_body.vue | 9 +- .../show/components/issuable_edit_form.vue | 5 +- .../show/components/issuable_header.vue | 2 +- .../show/components/issuable_show_root.vue | 9 ++ .../show/components/issuable_title.vue | 6 +- .../components/issuable_sidebar_root.vue | 55 +++++--- .../stylesheets/components/detail_page.scss | 6 +- app/assets/stylesheets/framework/sidebar.scss | 9 ++ .../components/test_case_show_root.vue | 50 ++++++-- .../components/test_case_sidebar.vue | 54 +------- .../components/test_case_sidebar_todo.vue | 82 ++++++++++++ .../projects/quality/test_case_show_spec.rb | 6 +- .../components/test_case_show_root_spec.js | 16 ++- .../components/test_case_sidebar_spec.js | 55 +------- .../components/test_case_sidebar_todo_spec.js | 121 ++++++++++++++++++ locale/gitlab.pot | 6 - .../components/issuable_sidebar_root_spec.js | 16 ++- 17 files changed, 344 insertions(+), 163 deletions(-) create mode 100644 ee/app/assets/javascripts/test_case_show/components/test_case_sidebar_todo.vue create mode 100644 ee/spec/frontend/test_case_show/components/test_case_sidebar_todo_spec.js diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_body.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_body.vue index dae3ddfe01632..bac71c1eda211 100644 --- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_body.vue +++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_body.vue @@ -31,6 +31,10 @@ export default { type: Boolean, required: true, }, + hideEditButton: { + type: Boolean, + required: false, + }, enableAutocomplete: { type: Boolean, required: true, @@ -166,6 +170,7 @@ export default { :issuable="issuable" :status-icon="statusIcon" :enable-edit="enableEdit" + :hide-edit-button="hideEditButton" :workspace-type="workspaceType" @edit-issuable="$emit('edit-issuable', $event)" > @@ -181,12 +186,12 @@ export default { :task-list-update-path="taskListUpdatePath" /> <slot name="secondary-content"></slot> - <small v-if="isUpdated" class="edited-text gl-font-sm!"> + <small v-if="isUpdated" class="edited-text gl-font-sm! gl-text-secondary"> {{ __('Edited') }} <time-ago-tooltip :time="issuable.updatedAt" tooltip-placement="bottom" /> <span v-if="updatedBy"> {{ __('by') }} - <gl-link :href="updatedBy.webUrl" class="author-link gl-font-sm!"> + <gl-link :href="updatedBy.webUrl" class="author-link gl-font-sm! gl-text-secondary"> <span>{{ updatedBy.name }}</span> </gl-link> </span> diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_edit_form.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_edit_form.vue index 7c3dd5c3623d6..3353374310fc8 100644 --- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_edit_form.vue +++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_edit_form.vue @@ -153,7 +153,10 @@ export default { </template> </markdown-field> </gl-form-group> - <div data-testid="actions" class="col-12 gl-mt-3 gl-mb-3 gl-px-0 clearfix"> + <div + data-testid="actions" + class="col-12 gl-mt-3 gl-mb-3 gl-px-0 clearfix gl-display-flex gl-gap-3" + > <slot name="edit-form-actions" :issuable-title="title" diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue index 760a3e01d6f37..1b95a2abdf991 100644 --- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue +++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue @@ -221,7 +221,7 @@ export default { @click="handleRightSidebarToggleClick" /> </div> - <div class="detail-page-header-actions gl-align-self-center gl-display-flex"> + <div class="detail-page-header-actions gl-align-self-center gl-display-flex gl-gap-3"> <slot name="header-actions"></slot> </div> </div> diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue index 040f49c7c25d5..1d44c4a1c1461 100644 --- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue +++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue @@ -32,6 +32,11 @@ export default { required: false, default: false, }, + hideEditButton: { + type: Boolean, + required: false, + default: false, + }, enableAutocomplete: { type: Boolean, required: false, @@ -137,6 +142,7 @@ export default { :status-icon="statusIcon" :status-icon-class="statusIconClass" :enable-edit="enableEdit" + :hide-edit-button="hideEditButton" :enable-autocomplete="enableAutocomplete" :enable-autosave="enableAutosave" :enable-zen-mode="enableZenMode" @@ -169,6 +175,9 @@ export default { </issuable-discussion> <issuable-sidebar> + <template #right-sidebar-top-items="{ sidebarExpanded, toggleSidebar }"> + <slot name="right-sidebar-top-items" v-bind="{ sidebarExpanded, toggleSidebar }"></slot> + </template> <template #right-sidebar-items="{ sidebarExpanded, toggleSidebar }"> <slot name="right-sidebar-items" v-bind="{ sidebarExpanded, toggleSidebar }"></slot> </template> diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue index 5387e39e3eb15..3dae894b1276c 100644 --- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue +++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue @@ -33,6 +33,10 @@ export default { type: Boolean, required: true, }, + hideEditButton: { + type: Boolean, + required: false, + }, workspaceType: { type: String, required: false, @@ -70,7 +74,7 @@ export default { data-testid="issuable-title" ></h1> <gl-button - v-if="enableEdit" + v-if="enableEdit && !hideEditButton" v-gl-tooltip.bottom :title="$options.i18n.editTitleAndDescription" :aria-label="$options.i18n.editTitleAndDescription" diff --git a/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue b/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue index 774267639fc1f..cb9ad6418a471 100644 --- a/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue +++ b/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue @@ -1,13 +1,17 @@ <script> -import { GlIcon } from '@gitlab/ui'; +import { GlButton, GlTooltipDirective } from '@gitlab/ui'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils'; +import { __ } from '~/locale'; import { USER_COLLAPSED_GUTTER_COOKIE } from '../constants'; export default { components: { - GlIcon, + GlButton, + }, + directives: { + GlTooltip: GlTooltipDirective, }, data() { const userExpanded = !parseBoolean(getCookie(USER_COLLAPSED_GUTTER_COOKIE)); @@ -20,6 +24,20 @@ export default { isExpanded: userExpanded ? bp.isDesktop() : userExpanded, }; }, + computed: { + toggleLabel() { + return this.isExpanded ? __('Collapse sidebar') : __('Expand sidebar'); + }, + toggleIcon() { + return this.isExpanded ? 'chevron-double-lg-right' : 'chevron-double-lg-left'; + }, + expandedToggleClass() { + return this.isExpanded ? 'block' : ''; + }, + collapsedToggleClass() { + return !this.isExpanded ? 'block' : ''; + }, + }, mounted() { window.addEventListener('resize', this.handleWindowResize); this.updatePageContainerClass(); @@ -59,23 +77,24 @@ export default { class="right-sidebar" aria-live="polite" > - <button - class="toggle-right-sidebar-button js-toggle-right-sidebar-button w-100 gl-text-decoration-none! gl-display-flex gl-outline-0!" - data-testid="toggle-right-sidebar-button" - :title="__('Toggle sidebar')" - @click="toggleSidebar" - > - <span v-if="isExpanded" class="collapse-text gl-flex-grow-1 gl-text-left">{{ - __('Collapse sidebar') - }}</span> - <gl-icon v-show="isExpanded" data-testid="icon-collapse" name="chevron-double-lg-right" /> - <gl-icon - v-show="!isExpanded" - data-testid="icon-expand" - name="chevron-double-lg-left" - class="gl-ml-2" + <div class="right-sidebar-header" :class="expandedToggleClass"> + <gl-button + v-gl-tooltip.hover.left + category="tertiary" + size="small" + class="gl-float-right gutter-toggle toggle-right-sidebar-button js-toggle-right-sidebar-button gl-shadow-none!" + :class="collapsedToggleClass" + data-testid="toggle-right-sidebar-button" + :icon="toggleIcon" + :title="toggleLabel" + :aria-label="toggleLabel" + @click="toggleSidebar" /> - </button> + <slot + name="right-sidebar-top-items" + v-bind="{ sidebarExpanded: isExpanded, toggleSidebar }" + ></slot> + </div> <div data-testid="sidebar-items" class="issuable-sidebar"> <slot name="right-sidebar-items" diff --git a/app/assets/stylesheets/components/detail_page.scss b/app/assets/stylesheets/components/detail_page.scss index 56214040fddf6..98ed7f590ea52 100644 --- a/app/assets/stylesheets/components/detail_page.scss +++ b/app/assets/stylesheets/components/detail_page.scss @@ -53,13 +53,17 @@ margin: 0 0 $gl-spacing-scale-4; color: $gl-text-color; padding: 0 0 0.3em; - border-bottom: 1px solid $white-dark; } .description { @include clearfix; margin-top: 6px; + + + .edited-text { + display: inline-block; + margin-top: $gl-spacing-scale-4; + } } .author-link { diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 168aa704a69da..30f6d39f70bba 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -53,12 +53,21 @@ height: $gl-padding; } } + + .right-sidebar-header { + flex-wrap: wrap; + } } .right-sidebar-expanded { padding-right: 0; z-index: $zindex-dropdown-menu; + .right-sidebar-header { + padding-block: $gl-spacing-scale-4; + margin-left: 20px; + } + .inline-block { @include gl-display-inline-block; } diff --git a/ee/app/assets/javascripts/test_case_show/components/test_case_show_root.vue b/ee/app/assets/javascripts/test_case_show/components/test_case_show_root.vue index 34d4810f4fe3a..cfa2e2f3b7222 100644 --- a/ee/app/assets/javascripts/test_case_show/components/test_case_show_root.vue +++ b/ee/app/assets/javascripts/test_case_show/components/test_case_show_root.vue @@ -18,6 +18,7 @@ import { s__, __ } from '~/locale'; import TestCaseGraphQL from '../mixins/test_case_graphql'; import TestCaseSidebar from './test_case_sidebar.vue'; +import TestCaseSidebarTodo from './test_case_sidebar_todo.vue'; const stateEvent = { Close: 'CLOSE', @@ -34,6 +35,7 @@ export default { GlAlert, IssuableShow, TestCaseSidebar, + TestCaseSidebarTodo, GlDisclosureDropdown, GlDisclosureDropdownGroup, GlDisclosureDropdownItem, @@ -70,7 +72,13 @@ export default { return this.isTestCaseOpen ? __('Open') : __('Archived'); }, testCaseActionTitle() { - return this.isTestCaseOpen ? __('Archive test case') : __('Reopen test case'); + return this.isTestCaseOpen ? __('Archive') : __('Reopen'); + }, + editCaseActionTitle() { + return __('Edit'); + }, + editCaseActionAriaLabel() { + return __('Edit title and description'); }, todo() { const todos = this.testCase.currentUserTodos.nodes; @@ -83,6 +91,15 @@ export default { id: getIdFromGraphQLId(label.id), })); }, + editTestCaseItem() { + return { + text: this.editCaseActionTitle, + action: this.handleEditTestCase, + extraAttrs: { + 'data-testid': 'edit-test-case', + }, + }; + }, toggleTestCaseStateItem() { return { text: this.testCaseActionTitle, action: this.handleTestCaseStateChange }; }, @@ -159,6 +176,7 @@ export default { :issuable="testCase" :status-icon="statusIcon" :enable-edit="canEditTestCase" + hide-edit-button :enable-autocomplete="true" :enable-task-list="true" :edit-form-visible="editTestCaseFormVisible" @@ -168,9 +186,7 @@ export default { :task-list-update-path="updatePath" :task-list-lock-version="lockVersion" :workspace-type="$options.WORKSPACE_PROJECT" - status-icon-class="gl-sm-display-none" show-work-item-type-icon - @edit-issuable="handleEditTestCase" @task-list-update-success="handleTaskListUpdateSuccess" @task-list-update-failure="handleTaskListUpdateFailure" > @@ -196,6 +212,7 @@ export default { category="secondary" :toggle-text="__('Options')" > + <gl-disclosure-dropdown-item :item="editTestCaseItem" /> <gl-disclosure-dropdown-item :item="toggleTestCaseStateItem" data-testid="toggle-state-dropdown-item" @@ -204,10 +221,20 @@ export default { <gl-disclosure-dropdown-item :item="newTestCaseItem" /> </gl-disclosure-dropdown-group> </gl-disclosure-dropdown> + <gl-button + v-if="canEditTestCase" + data-testid="edit-test-case" + class="gl-display-none gl-md-display-inline-block" + :loading="testCaseStateChangeInProgress" + :title="editCaseActionAriaLabel" + :aria-label="editCaseActionAriaLabel" + @click="handleEditTestCase" + >{{ editCaseActionTitle }}</gl-button + > <gl-button v-if="canEditTestCase" data-testid="archive-test-case" - class="gl-display-none gl-md-display-inline-block gl-mr-2" + class="gl-display-none gl-md-display-inline-block" :loading="testCaseStateChangeInProgress" @click="handleTestCaseStateChange" >{{ testCaseActionTitle }}</gl-button @@ -233,19 +260,22 @@ export default { @click.prevent="handleSaveTestCase(issuableMeta)" >{{ __('Save changes') }}</gl-button > - <gl-button - data-testid="cancel-test-case-edit" - class="gl-float-right" - @click="handleCancelClick" - > + <gl-button data-testid="cancel-test-case-edit" @click="handleCancelClick"> {{ __('Cancel') }} </gl-button> </template> + <template #right-sidebar-top-items="{ sidebarExpanded, toggleSidebar }"> + <test-case-sidebar-todo + :sidebar-expanded="sidebarExpanded" + :todo="todo" + @test-case-updated="handleTestCaseUpdated" + @sidebar-toggle="toggleSidebar" + /> + </template> <template #right-sidebar-items="{ sidebarExpanded, toggleSidebar }"> <test-case-sidebar :sidebar-expanded="sidebarExpanded" :selected-labels="selectedLabels" - :todo="todo" :moved="testCase.moved" @test-case-updated="handleTestCaseUpdated" @sidebar-toggle="toggleSidebar" diff --git a/ee/app/assets/javascripts/test_case_show/components/test_case_sidebar.vue b/ee/app/assets/javascripts/test_case_show/components/test_case_sidebar.vue index 519e51da1de2d..2d767bed52ffe 100644 --- a/ee/app/assets/javascripts/test_case_show/components/test_case_sidebar.vue +++ b/ee/app/assets/javascripts/test_case_show/components/test_case_sidebar.vue @@ -1,6 +1,5 @@ <script> -import { GlTooltipDirective as GlTooltip, GlButton, GlIcon, GlLoadingIcon } from '@gitlab/ui'; -import { s__, __ } from '~/locale'; +import { s__ } from '~/locale'; import ProjectSelect from '~/sidebar/components/move/issuable_move_dropdown.vue'; import LabelsSelectWidget from '~/sidebar/components/labels/labels_select_widget/labels_select_root.vue'; import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue'; @@ -11,16 +10,10 @@ export default { TYPE_TEST_CASE, WORKSPACE_PROJECT, components: { - GlButton, - GlIcon, - GlLoadingIcon, ProjectSelect, LabelsSelectWidget, SidebarConfidentialityWidget, }, - directives: { - GlTooltip, - }, mixins: [TestCaseGraphQL], inject: [ 'projectFullPath', @@ -37,11 +30,6 @@ export default { type: Boolean, required: true, }, - todo: { - type: Object, - required: false, - default: null, - }, selectedLabels: { type: Array, required: true, @@ -59,18 +47,6 @@ export default { }; }, computed: { - isTodoPending() { - return this.todo?.state === 'pending'; - }, - todoUpdateInProgress() { - return this.$apollo.queries.testCase.loading || this.testCaseTodoUpdateInProgress; - }, - todoActionText() { - return this.isTodoPending ? __('Mark as done') : __('Add a to do'); - }, - todoIcon() { - return this.isTodoPending ? 'todo-done' : 'todo-add'; - }, selectProjectDropdownButtonTitle() { return this.testCaseMoveInProgress ? s__('TestCases|Moving test case') @@ -81,13 +57,6 @@ export default { this.sidebarEl = document.querySelector('aside.right-sidebar'); }, methods: { - handleTodoButtonClick() { - if (this.isTodoPending) { - this.markTestCaseTodoDone(); - } else { - this.addTestCaseAsTodo(); - } - }, toggleSidebar() { this.$emit('sidebar-toggle'); }, @@ -175,27 +144,6 @@ export default { <template> <div class="test-case-sidebar-items"> - <template v-if="canEditTestCase"> - <div v-if="sidebarExpanded" data-testid="todo" class="block todo gl-display-flex"> - <span class="gl-flex-grow-1">{{ __('To Do') }}</span> - <gl-button :loading="todoUpdateInProgress" size="small" @click="handleTodoButtonClick">{{ - todoActionText - }}</gl-button> - </div> - <div v-else class="block todo"> - <gl-button - v-gl-tooltip:body.viewport.left - :title="todoActionText" - class="sidebar-collapsed-icon" - category="tertiary" - data-testid="collapsed-button" - @click="handleTodoButtonClick" - > - <gl-loading-icon v-if="todoUpdateInProgress" size="sm" /> - <gl-icon v-else :name="todoIcon" :class="{ 'todo-undone': isTodoPending }" /> - </gl-button> - </div> - </template> <labels-select-widget :iid="String(testCaseId)" :full-path="projectFullPath" diff --git a/ee/app/assets/javascripts/test_case_show/components/test_case_sidebar_todo.vue b/ee/app/assets/javascripts/test_case_show/components/test_case_sidebar_todo.vue new file mode 100644 index 0000000000000..a215d7f241d0a --- /dev/null +++ b/ee/app/assets/javascripts/test_case_show/components/test_case_sidebar_todo.vue @@ -0,0 +1,82 @@ +<script> +import { GlTooltipDirective as GlTooltip, GlButton, GlIcon, GlLoadingIcon } from '@gitlab/ui'; +import { __ } from '~/locale'; +import { TYPE_TEST_CASE, WORKSPACE_PROJECT } from '~/issues/constants'; +import TestCaseGraphQL from '../mixins/test_case_graphql'; + +export default { + TYPE_TEST_CASE, + WORKSPACE_PROJECT, + components: { + GlButton, + GlIcon, + GlLoadingIcon, + }, + directives: { + GlTooltip, + }, + mixins: [TestCaseGraphQL], + inject: ['projectFullPath', 'testCaseId', 'canEditTestCase'], + props: { + sidebarExpanded: { + type: Boolean, + required: true, + }, + todo: { + type: Object, + required: false, + default: null, + }, + }, + computed: { + isTodoPending() { + return this.todo?.state === 'pending'; + }, + todoUpdateInProgress() { + return this.$apollo.queries.testCase.loading || this.testCaseTodoUpdateInProgress; + }, + todoActionText() { + return this.isTodoPending ? __('Mark as done') : __('Add a to do'); + }, + todoIcon() { + return this.isTodoPending ? 'todo-done' : 'todo-add'; + }, + }, + methods: { + handleTodoButtonClick() { + if (this.isTodoPending) { + this.markTestCaseTodoDone(); + } else { + this.addTestCaseAsTodo(); + } + }, + }, +}; +</script> + +<template> + <div v-if="canEditTestCase" class="gl-order-n1"> + <div v-if="sidebarExpanded" data-testid="todo" class="todo gl-display-flex"> + <gl-button + :loading="todoUpdateInProgress" + size="small" + data-testid="expanded-button" + @click="handleTodoButtonClick" + >{{ todoActionText }}</gl-button + > + </div> + <div v-else class="block todo"> + <gl-button + v-gl-tooltip:body.viewport.left + :title="todoActionText" + class="sidebar-collapsed-icon" + category="tertiary" + data-testid="collapsed-button" + @click="handleTodoButtonClick" + > + <gl-loading-icon v-if="todoUpdateInProgress" size="sm" /> + <gl-icon v-else :name="todoIcon" :class="{ 'todo-undone': isTodoPending }" /> + </gl-button> + </div> + </div> +</template> diff --git a/ee/spec/features/projects/quality/test_case_show_spec.rb b/ee/spec/features/projects/quality/test_case_show_spec.rb index 3ff8e8dfaa92d..2128447e9bf53 100644 --- a/ee/spec/features/projects/quality/test_case_show_spec.rb +++ b/ee/spec/features/projects/quality/test_case_show_spec.rb @@ -39,16 +39,16 @@ end it 'shows action buttons' do - expect(page).to have_button('Archive test case') + expect(page).to have_button('Archive') expect(page).to have_link('New test case', href: new_project_quality_test_case_path(project)) expect(page).not_to have_button('Options') end it 'archives test case' do - click_button('Archive test case') + click_button('Archive') expect(page).to have_css('.gl-badge', text: 'Archived') - expect(page).to have_button('Reopen test case') + expect(page).to have_button('Reopen') end end diff --git a/ee/spec/frontend/test_case_show/components/test_case_show_root_spec.js b/ee/spec/frontend/test_case_show/components/test_case_show_root_spec.js index 76fd056f0a9ed..cec3c3aa33e7a 100644 --- a/ee/spec/frontend/test_case_show/components/test_case_show_root_spec.js +++ b/ee/spec/frontend/test_case_show/components/test_case_show_root_spec.js @@ -13,6 +13,7 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import TestCaseShowRoot from 'ee/test_case_show/components/test_case_show_root.vue'; import TestCaseSidebar from 'ee/test_case_show/components/test_case_sidebar.vue'; +import TestCaseSidebarTodo from 'ee/test_case_show/components/test_case_sidebar_todo.vue'; import projectTestCase from 'ee/test_case_show/queries/project_test_case.query.graphql'; import projectTestCaseTaskList from 'ee/test_case_show/queries/test_case_tasklist.query.graphql'; import { mockCurrentUserTodo } from 'jest/vue_shared/issuable/list/mock_data'; @@ -45,7 +46,9 @@ describe('TestCaseShowRoot', () => { const findBadge = () => wrapper.findComponent(GlBadge); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findIssuableShow = () => wrapper.findComponent(IssuableShow); + const findIssuableEditButton = () => wrapper.findByTestId('edit-test-case'); const findTestCaseSidebar = () => wrapper.findComponent(TestCaseSidebar); + const findTestCaseSidebarTodo = () => wrapper.findComponent(TestCaseSidebarTodo); const findToggleStateButton = () => wrapper.findByTestId('archive-test-case'); const findToggleStateDropdownItem = () => wrapper.findByTestId('toggle-state-dropdown-item'); @@ -86,8 +89,8 @@ describe('TestCaseShowRoot', () => { describe('computed', () => { describe.each` state | isTestCaseOpen | statusIcon | statusBadgeText | testCaseActionTitle - ${'opened'} | ${true} | ${'issue-open-m'} | ${'Open'} | ${'Archive test case'} - ${'closed'} | ${false} | ${'mobile-issue-close'} | ${'Archived'} | ${'Reopen test case'} + ${'opened'} | ${true} | ${'issue-open-m'} | ${'Open'} | ${'Archive'} + ${'closed'} | ${false} | ${'mobile-issue-close'} | ${'Archived'} | ${'Reopen'} `( 'when `testCase.state` is $state', ({ state, isTestCaseOpen, statusIcon, statusBadgeText, testCaseActionTitle }) => { @@ -292,7 +295,6 @@ describe('TestCaseShowRoot', () => { it('renders IssuableShow', () => { const { - canEditTestCase, descriptionPreviewPath, descriptionHelpPath, updatePath, @@ -308,8 +310,8 @@ describe('TestCaseShowRoot', () => { enableAutocomplete: true, enableTaskList: true, issuable: mockTestCase, - enableEdit: canEditTestCase, - taskCompletionStatus: {}, + enableEdit: true, + taskCompletionStatus: null, taskListUpdatePath: updatePath, taskListLockVersion: lockVersion, workspaceType: 'project', @@ -318,7 +320,7 @@ describe('TestCaseShowRoot', () => { describe('when IssuableShow emits `edit-issuable`', () => { beforeEach(() => { - findIssuableShow().vm.$emit('edit-issuable'); + findIssuableEditButton().trigger('click'); }); it('renders edit-form-actions slot contents', () => { @@ -389,7 +391,7 @@ describe('TestCaseShowRoot', () => { it('renders test-case-sidebar', () => { expect(findTestCaseSidebar().exists()).toBe(true); - expect(findTestCaseSidebar().props('todo')).toEqual(mockCurrentUserTodo); + expect(findTestCaseSidebarTodo().props('todo')).toEqual(mockCurrentUserTodo); }); it('updates `sidebarExpanded` prop on `sidebar-toggle` event', async () => { diff --git a/ee/spec/frontend/test_case_show/components/test_case_sidebar_spec.js b/ee/spec/frontend/test_case_show/components/test_case_sidebar_spec.js index 6bebe8dacbe38..fd4a236ca509a 100644 --- a/ee/spec/frontend/test_case_show/components/test_case_sidebar_spec.js +++ b/ee/spec/frontend/test_case_show/components/test_case_sidebar_spec.js @@ -1,9 +1,7 @@ -import { GlButton, GlIcon, GlLoadingIcon } from '@gitlab/ui'; - import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import TestCaseSidebar from 'ee/test_case_show/components/test_case_sidebar.vue'; -import { mockCurrentUserTodo, mockLabels } from 'jest/vue_shared/issuable/list/mock_data'; +import { mockLabels } from 'jest/vue_shared/issuable/list/mock_data'; import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import ProjectSelect from '~/sidebar/components/move/issuable_move_dropdown.vue'; import LabelsSelectWidget from '~/sidebar/components/labels/labels_select_widget/labels_select_root.vue'; @@ -13,7 +11,6 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import projectTestCase from 'ee/test_case_show/queries/project_test_case.query.graphql'; import { TYPE_TEST_CASE, WORKSPACE_PROJECT } from '~/issues/constants'; -import waitForPromises from 'helpers/wait_for_promises'; import { mockProvide, mockTaskCompletionResponse } from '../mock_data'; Vue.use(VueApollo); @@ -24,7 +21,6 @@ describe('TestCaseSidebar', () => { const createComponent = ({ provide = {}, sidebarExpanded = true, - todo = mockCurrentUserTodo, selectedLabels = mockLabels, moved = false, } = {}) => { @@ -38,7 +34,6 @@ describe('TestCaseSidebar', () => { apolloProvider, propsData: { sidebarExpanded, - todo, selectedLabels, moved, }, @@ -49,8 +44,6 @@ describe('TestCaseSidebar', () => { const findSidebarConfidentialityWidget = () => wrapper.findComponent(SidebarConfidentialityWidget); const findProjectSelect = () => wrapper.findComponent(ProjectSelect); - const findCollapsedTodoButton = () => wrapper.findByTestId('collapsed-button'); - const findExpandedTodoEl = () => wrapper.findByTestId('todo'); beforeEach(() => { setHTMLFixture('<aside class="right-sidebar"></aside>'); @@ -60,52 +53,6 @@ describe('TestCaseSidebar', () => { resetHTMLFixture(); }); - describe('To Do section', () => { - it('does not render', () => { - createComponent({ - provide: { - canEditTestCase: false, - }, - }); - - expect(findExpandedTodoEl().exists()).toBe(false); - expect(findCollapsedTodoButton().exists()).toBe(false); - }); - - describe('when expanded', () => { - it('renders expanded todo button', () => { - createComponent(); - - const todoEl = findExpandedTodoEl(); - - expect(todoEl.text()).toContain('To Do'); - expect(todoEl.findComponent(GlButton).text()).toBe('Add a to do'); - }); - }); - - describe('when collapsed', () => { - it('renders collapsed todo button', async () => { - createComponent({ - sidebarExpanded: false, - }); - await waitForPromises(); - - const todoButton = findCollapsedTodoButton(); - - expect(todoButton.attributes('title')).toBe('Add a to do'); - expect(todoButton.findComponent(GlIcon).exists()).toBe(true); - }); - - it('display loading icon', () => { - createComponent({ - sidebarExpanded: false, - }); - - expect(findCollapsedTodoButton().findComponent(GlLoadingIcon).exists()).toBe(true); - }); - }); - }); - describe('Label select widget', () => { it('renders label-select', () => { createComponent(); diff --git a/ee/spec/frontend/test_case_show/components/test_case_sidebar_todo_spec.js b/ee/spec/frontend/test_case_show/components/test_case_sidebar_todo_spec.js new file mode 100644 index 0000000000000..8b967451fa310 --- /dev/null +++ b/ee/spec/frontend/test_case_show/components/test_case_sidebar_todo_spec.js @@ -0,0 +1,121 @@ +import { GlButton, GlLoadingIcon } from '@gitlab/ui'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import TestCaseSidebarTodo from 'ee/test_case_show/components/test_case_sidebar_todo.vue'; +import { mockCurrentUserTodo } from 'jest/vue_shared/issuable/list/mock_data'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import projectTestCase from 'ee/test_case_show/queries/project_test_case.query.graphql'; +import waitForPromises from 'helpers/wait_for_promises'; +import { mockProvide, mockTaskCompletionResponse } from '../mock_data'; + +Vue.use(VueApollo); + +describe('TestCaseSidebarTodo', () => { + let wrapper; + + const createComponent = ({ + provide = {}, + sidebarExpanded = true, + todo = mockCurrentUserTodo, + } = {}) => { + const apolloProvider = createMockApollo([[projectTestCase, mockTaskCompletionResponse]]); + + wrapper = shallowMountExtended(TestCaseSidebarTodo, { + provide: { + ...mockProvide, + ...provide, + }, + apolloProvider, + propsData: { + sidebarExpanded, + todo, + }, + stubs: { + GlButton, + }, + }); + }; + + const findCollapsedTodoButton = () => wrapper.findByTestId('collapsed-button'); + const findExpandedTodoButton = () => wrapper.findByTestId('expanded-button'); + const findExpandedTodoEl = () => wrapper.findByTestId('todo'); + + beforeEach(() => { + setHTMLFixture('<aside class="right-sidebar"></aside>'); + }); + + afterEach(() => { + resetHTMLFixture(); + }); + + describe('To Do section', () => { + it('does not render when the test case can not be edited', () => { + createComponent({ + provide: { + canEditTestCase: false, + }, + }); + + expect(findExpandedTodoEl().exists()).toBe(false); + expect(findCollapsedTodoButton().exists()).toBe(false); + }); + + describe('when expanded', () => { + it('sidebarExpanded set to `true` renders expanded todo button', () => { + createComponent({ + sidebarExpanded: true, + }); + + expect(findCollapsedTodoButton().exists()).toBe(false); + expect(findExpandedTodoButton().exists()).toBe(true); + }); + + it('renders expanded todo button', () => { + createComponent(); + + const todoEl = findExpandedTodoEl(); + expect(todoEl.findComponent(GlButton).text()).toBe('Add a to do'); + }); + + it('display loading icon', () => { + createComponent({ + sidebarExpanded: true, + }); + + expect(findExpandedTodoButton().findComponent(GlLoadingIcon).exists()).toBe(true); + }); + }); + + describe('when collapsed', () => { + it('sidebarExpanded set to `false` renders collapsed todo button', () => { + createComponent({ + sidebarExpanded: false, + }); + + expect(findCollapsedTodoButton().exists()).toBe(true); + expect(findExpandedTodoButton().exists()).toBe(false); + }); + + it('renders collapsed todo button', async () => { + createComponent({ + sidebarExpanded: false, + }); + await waitForPromises(); + + const todoButton = findCollapsedTodoButton(); + + expect(todoButton.attributes('title')).toBe('Add a to do'); + }); + + it('display loading icon', () => { + createComponent({ + sidebarExpanded: false, + }); + + expect(findCollapsedTodoButton().findComponent(GlLoadingIcon).exists()).toBe(true); + }); + }); + }); +}); diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 66468232633e2..13130f93e2696 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6398,9 +6398,6 @@ msgstr "" msgid "Archive project" msgstr "" -msgid "Archive test case" -msgstr "" - msgid "Archived" msgstr "" @@ -40184,9 +40181,6 @@ msgstr "" msgid "Reopen milestone" msgstr "" -msgid "Reopen test case" -msgstr "" - msgid "Reopen this %{quick_action_target}" msgstr "" diff --git a/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js b/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js index f2509aead776c..d5c6ece8cb5a4 100644 --- a/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js +++ b/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js @@ -1,3 +1,4 @@ +import { GlButton, GlIcon } from '@gitlab/ui'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { nextTick } from 'vue'; import Cookies from '~/lib/utils/cookies'; @@ -18,6 +19,10 @@ const createComponent = () => { <button class="js-todo">Todo</button> `, }, + stubs: { + GlButton, + GlIcon, + }, }); }; @@ -62,9 +67,8 @@ describe('IssuableSidebarRoot', () => { const buttonEl = findToggleSidebarButton(); expect(buttonEl.exists()).toBe(true); - expect(buttonEl.attributes('title')).toBe('Toggle sidebar'); - expect(buttonEl.find('span').text()).toBe('Collapse sidebar'); - expect(wrapper.findByTestId('icon-collapse').isVisible()).toBe(true); + expect(buttonEl.attributes('title')).toBe('Collapse sidebar'); + expect(wrapper.findByTestId('chevron-double-lg-right-icon').isVisible()).toBe(true); }); describe('when collapsing the sidebar', () => { @@ -116,12 +120,12 @@ describe('IssuableSidebarRoot', () => { assertPageLayoutClasses({ isExpanded: false }); }); - it('renders sidebar toggle button with text and icon', () => { + it('renders sidebar toggle button with title and icon', () => { const buttonEl = findToggleSidebarButton(); expect(buttonEl.exists()).toBe(true); - expect(buttonEl.attributes('title')).toBe('Toggle sidebar'); - expect(wrapper.findByTestId('icon-expand').isVisible()).toBe(true); + expect(buttonEl.attributes('title')).toBe('Expand sidebar'); + expect(wrapper.findByTestId('chevron-double-lg-left-icon').isVisible()).toBe(true); }); }); -- GitLab