Commit 1d97dc0d authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch '347237-move-erase-job-log-button' into 'master'

Re-position the job log erase button

See merge request gitlab-org/gitlab!81049
parents a32cb47b 54003d98
...@@ -288,7 +288,6 @@ export default { ...@@ -288,7 +288,6 @@ export default {
'sidebar-collapsed': !isSidebarOpen, 'sidebar-collapsed': !isSidebarOpen,
'has-archived-block': job.archived, 'has-archived-block': job.archived,
}" }"
:erase-path="job.erase_path"
:size="jobLogSize" :size="jobLogSize"
:raw-path="job.raw_path" :raw-path="job.raw_path"
:is-scroll-bottom-disabled="isScrollBottomDisabled" :is-scroll-bottom-disabled="isScrollBottomDisabled"
...@@ -325,6 +324,7 @@ export default { ...@@ -325,6 +324,7 @@ export default {
'right-sidebar-expanded': isSidebarOpen, 'right-sidebar-expanded': isSidebarOpen,
'right-sidebar-collapsed': !isSidebarOpen, 'right-sidebar-collapsed': !isSidebarOpen,
}" }"
:erase-path="job.erase_path"
:artifact-help-url="artifactHelpUrl" :artifact-help-url="artifactHelpUrl"
data-testid="job-sidebar" data-testid="job-sidebar"
/> />
......
...@@ -5,7 +5,6 @@ import { __, s__, sprintf } from '~/locale'; ...@@ -5,7 +5,6 @@ import { __, s__, sprintf } from '~/locale';
export default { export default {
i18n: { i18n: {
eraseLogButtonLabel: s__('Job|Erase job log and artifacts'),
scrollToBottomButtonLabel: s__('Job|Scroll to bottom'), scrollToBottomButtonLabel: s__('Job|Scroll to bottom'),
scrollToTopButtonLabel: s__('Job|Scroll to top'), scrollToTopButtonLabel: s__('Job|Scroll to top'),
showRawButtonLabel: s__('Job|Show complete raw'), showRawButtonLabel: s__('Job|Show complete raw'),
...@@ -18,11 +17,6 @@ export default { ...@@ -18,11 +17,6 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
props: { props: {
erasePath: {
type: String,
required: false,
default: null,
},
size: { size: {
type: Number, type: Number,
required: true, required: true,
...@@ -97,20 +91,6 @@ export default { ...@@ -97,20 +91,6 @@ export default {
data-testid="job-raw-link-controller" data-testid="job-raw-link-controller"
icon="doc-text" icon="doc-text"
/> />
<gl-button
v-if="erasePath"
v-gl-tooltip.body
:title="$options.i18n.eraseLogButtonLabel"
:aria-label="$options.i18n.eraseLogButtonLabel"
:href="erasePath"
:data-confirm="__('Are you sure you want to erase this build?')"
class="gl-ml-3"
data-testid="job-log-erase-link"
data-confirm-btn-variant="danger"
data-method="post"
icon="remove"
/>
<!-- eo links --> <!-- eo links -->
<!-- scroll buttons --> <!-- scroll buttons -->
......
<script> <script>
import { GlButton, GlLink, GlModalDirective } from '@gitlab/ui'; import { GlButton, GlModalDirective } from '@gitlab/ui';
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { JOB_SIDEBAR } from '../constants'; import { JOB_SIDEBAR } from '../constants';
...@@ -10,7 +10,6 @@ export default { ...@@ -10,7 +10,6 @@ export default {
}, },
components: { components: {
GlButton, GlButton,
GlLink,
}, },
directives: { directives: {
GlModal: GlModalDirective, GlModal: GlModalDirective,
...@@ -37,9 +36,18 @@ export default { ...@@ -37,9 +36,18 @@ export default {
:aria-label="$options.i18n.retryLabel" :aria-label="$options.i18n.retryLabel"
category="primary" category="primary"
variant="confirm" variant="confirm"
>{{ $options.i18n.retryLabel }}</gl-button icon="retry"
> data-testid="retry-job-button"
<gl-link v-else :href="href" class="btn gl-button btn-confirm" data-method="post" rel="nofollow" />
>{{ $options.i18n.retryLabel }}
</gl-link> <gl-button
v-else
:href="href"
:aria-label="$options.i18n.retryLabel"
category="primary"
variant="confirm"
icon="retry"
data-method="post"
data-testid="retry-job-link"
/>
</template> </template>
<script> <script>
import { GlButton, GlIcon } from '@gitlab/ui'; import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { JOB_SIDEBAR } from '../constants'; import { JOB_SIDEBAR } from '../constants';
import ArtifactsBlock from './artifacts_block.vue'; import ArtifactsBlock from './artifacts_block.vue';
...@@ -18,10 +19,17 @@ export const forwardDeploymentFailureModalId = 'forward-deployment-failure'; ...@@ -18,10 +19,17 @@ export const forwardDeploymentFailureModalId = 'forward-deployment-failure';
export default { export default {
name: 'JobSidebar', name: 'JobSidebar',
i18n: { i18n: {
eraseLogButtonLabel: s__('Job|Erase job log and artifacts'),
eraseLogConfirmText: s__('Job|Are you sure you want to erase this job log and artifacts?'),
cancelJobButtonLabel: s__('Job|Cancel'),
retryJobButtonLabel: s__('Job|Retry'),
...JOB_SIDEBAR, ...JOB_SIDEBAR,
}, },
borderTopClass: ['gl-border-t-solid', 'gl-border-t-1', 'gl-border-t-gray-100'], borderTopClass: ['gl-border-t-solid', 'gl-border-t-1', 'gl-border-t-gray-100'],
forwardDeploymentFailureModalId, forwardDeploymentFailureModalId,
directives: {
GlTooltip: GlTooltipDirective,
},
components: { components: {
ArtifactsBlock, ArtifactsBlock,
CommitBlock, CommitBlock,
...@@ -41,6 +49,11 @@ export default { ...@@ -41,6 +49,11 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
erasePath: {
type: String,
required: false,
default: null,
},
}, },
computed: { computed: {
...mapGetters(['hasForwardDeploymentFailure']), ...mapGetters(['hasForwardDeploymentFailure']),
...@@ -81,8 +94,24 @@ export default { ...@@ -81,8 +94,24 @@ export default {
</h4> </h4>
</tooltip-on-truncate> </tooltip-on-truncate>
<div class="gl-flex-grow-1 gl-flex-shrink-0 gl-text-right"> <div class="gl-flex-grow-1 gl-flex-shrink-0 gl-text-right">
<gl-button
v-if="erasePath"
v-gl-tooltip.left
:title="$options.i18n.eraseLogButtonLabel"
:aria-label="$options.i18n.eraseLogButtonLabel"
:href="erasePath"
:data-confirm="$options.i18n.eraseLogConfirmText"
class="gl-mr-2"
data-testid="job-log-erase-link"
data-confirm-btn-variant="danger"
data-method="post"
icon="remove"
/>
<job-sidebar-retry-button <job-sidebar-retry-button
v-if="job.retry_path" v-if="job.retry_path"
v-gl-tooltip.left
:title="$options.i18n.retryJobButtonLabel"
:aria-label="$options.i18n.retryJobButtonLabel"
:category="retryButtonCategory" :category="retryButtonCategory"
:href="job.retry_path" :href="job.retry_path"
:modal-id="$options.forwardDeploymentFailureModalId" :modal-id="$options.forwardDeploymentFailureModalId"
...@@ -92,12 +121,15 @@ export default { ...@@ -92,12 +121,15 @@ export default {
/> />
<gl-button <gl-button
v-if="job.cancel_path" v-if="job.cancel_path"
v-gl-tooltip.left
:title="$options.i18n.cancelJobButtonLabel"
:aria-label="$options.i18n.cancelJobButtonLabel"
:href="job.cancel_path" :href="job.cancel_path"
icon="cancel"
data-method="post" data-method="post"
data-testid="cancel-button" data-testid="cancel-button"
rel="nofollow" rel="nofollow"
>{{ $options.i18n.cancel }} />
</gl-button>
</div> </div>
<gl-button <gl-button
......
...@@ -4738,9 +4738,6 @@ msgstr "" ...@@ -4738,9 +4738,6 @@ msgstr ""
msgid "Are you sure you want to discard your changes?" msgid "Are you sure you want to discard your changes?"
msgstr "" msgstr ""
msgid "Are you sure you want to erase this build?"
msgstr ""
msgid "Are you sure you want to import %d repository?" msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?" msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] "" msgstr[0] ""
...@@ -21031,9 +21028,15 @@ msgstr "" ...@@ -21031,9 +21028,15 @@ msgstr ""
msgid "Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment. Retrying this job could result in overwriting the environment with the older source code." msgid "Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment. Retrying this job could result in overwriting the environment with the older source code."
msgstr "" msgstr ""
msgid "Job|Are you sure you want to erase this job log and artifacts?"
msgstr ""
msgid "Job|Browse" msgid "Job|Browse"
msgstr "" msgstr ""
msgid "Job|Cancel"
msgstr ""
msgid "Job|Complete Raw" msgid "Job|Complete Raw"
msgstr "" msgstr ""
...@@ -21061,6 +21064,9 @@ msgstr "" ...@@ -21061,6 +21064,9 @@ msgstr ""
msgid "Job|Pipeline" msgid "Job|Pipeline"
msgstr "" msgstr ""
msgid "Job|Retry"
msgstr ""
msgid "Job|Scroll to bottom" msgid "Job|Scroll to bottom"
msgstr "" msgstr ""
......
...@@ -313,7 +313,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -313,7 +313,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'job is cancelable' do context 'job is cancelable' do
it 'shows cancel button' do it 'shows cancel button' do
click_link 'Cancel' find('[data-testid="cancel-button"]').click
expect(page.current_path).to eq(job_url) expect(page.current_path).to eq(job_url)
end end
...@@ -1031,7 +1031,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -1031,7 +1031,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
end end
it 'loads the page and shows all needed controls' do it 'loads the page and shows all needed controls' do
expect(page).to have_content 'Retry' expect(page).to have_selector('[data-testid="retry-button"')
end end
end end
end end
...@@ -1049,7 +1049,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -1049,7 +1049,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows the right status and buttons' do it 'shows the right status and buttons' do
page.within('aside.right-sidebar') do page.within('aside.right-sidebar') do
expect(page).to have_content 'Cancel' expect(page).to have_selector('[data-testid="cancel-button"')
end end
end end
end end
......
...@@ -8,7 +8,6 @@ describe('Job log controllers', () => { ...@@ -8,7 +8,6 @@ describe('Job log controllers', () => {
afterEach(() => { afterEach(() => {
if (wrapper?.destroy) { if (wrapper?.destroy) {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
} }
}); });
...@@ -34,7 +33,6 @@ describe('Job log controllers', () => { ...@@ -34,7 +33,6 @@ describe('Job log controllers', () => {
const findTruncatedInfo = () => wrapper.find('[data-testid="log-truncated-info"]'); const findTruncatedInfo = () => wrapper.find('[data-testid="log-truncated-info"]');
const findRawLink = () => wrapper.find('[data-testid="raw-link"]'); const findRawLink = () => wrapper.find('[data-testid="raw-link"]');
const findRawLinkController = () => wrapper.find('[data-testid="job-raw-link-controller"]'); const findRawLinkController = () => wrapper.find('[data-testid="job-raw-link-controller"]');
const findEraseLink = () => wrapper.find('[data-testid="job-log-erase-link"]');
const findScrollTop = () => wrapper.find('[data-testid="job-controller-scroll-top"]'); const findScrollTop = () => wrapper.find('[data-testid="job-controller-scroll-top"]');
const findScrollBottom = () => wrapper.find('[data-testid="job-controller-scroll-bottom"]'); const findScrollBottom = () => wrapper.find('[data-testid="job-controller-scroll-bottom"]');
...@@ -76,28 +74,6 @@ describe('Job log controllers', () => { ...@@ -76,28 +74,6 @@ describe('Job log controllers', () => {
expect(findRawLinkController().exists()).toBe(false); expect(findRawLinkController().exists()).toBe(false);
}); });
}); });
describe('when is erasable', () => {
beforeEach(() => {
createWrapper();
});
it('renders erase job link', () => {
expect(findEraseLink().exists()).toBe(true);
});
});
describe('when it is not erasable', () => {
beforeEach(() => {
createWrapper({
erasePath: null,
});
});
it('does not render erase button', () => {
expect(findEraseLink().exists()).toBe(false);
});
});
}); });
describe('scroll buttons', () => { describe('scroll buttons', () => {
......
import { GlButton, GlLink } from '@gitlab/ui'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { shallowMount } from '@vue/test-utils';
import JobsSidebarRetryButton from '~/jobs/components/job_sidebar_retry_button.vue'; import JobsSidebarRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
import createStore from '~/jobs/store'; import createStore from '~/jobs/store';
import job from '../mock_data'; import job from '../mock_data';
...@@ -9,12 +8,12 @@ describe('Job Sidebar Retry Button', () => { ...@@ -9,12 +8,12 @@ describe('Job Sidebar Retry Button', () => {
let wrapper; let wrapper;
const forwardDeploymentFailure = 'forward_deployment_failure'; const forwardDeploymentFailure = 'forward_deployment_failure';
const findRetryButton = () => wrapper.find(GlButton); const findRetryButton = () => wrapper.findByTestId('retry-job-button');
const findRetryLink = () => wrapper.find(GlLink); const findRetryLink = () => wrapper.findByTestId('retry-job-link');
const createWrapper = ({ props = {} } = {}) => { const createWrapper = ({ props = {} } = {}) => {
store = createStore(); store = createStore();
wrapper = shallowMount(JobsSidebarRetryButton, { wrapper = shallowMountExtended(JobsSidebarRetryButton, {
propsData: { propsData: {
href: job.retry_path, href: job.retry_path,
modalId: 'modal-id', modalId: 'modal-id',
...@@ -27,7 +26,6 @@ describe('Job Sidebar Retry Button', () => { ...@@ -27,7 +26,6 @@ describe('Job Sidebar Retry Button', () => {
afterEach(() => { afterEach(() => {
if (wrapper) { if (wrapper) {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
} }
}); });
...@@ -44,7 +42,6 @@ describe('Job Sidebar Retry Button', () => { ...@@ -44,7 +42,6 @@ describe('Job Sidebar Retry Button', () => {
expect(findRetryButton().exists()).toBe(buttonExists); expect(findRetryButton().exists()).toBe(buttonExists);
expect(findRetryLink().exists()).toBe(linkExists); expect(findRetryLink().exists()).toBe(linkExists);
expect(wrapper.text()).toMatch('Retry');
}, },
); );
...@@ -55,6 +52,7 @@ describe('Job Sidebar Retry Button', () => { ...@@ -55,6 +52,7 @@ describe('Job Sidebar Retry Button', () => {
expect(findRetryButton().attributes()).toMatchObject({ expect(findRetryButton().attributes()).toMatchObject({
category: 'primary', category: 'primary',
variant: 'confirm', variant: 'confirm',
icon: 'retry',
}); });
}); });
}); });
...@@ -64,6 +62,7 @@ describe('Job Sidebar Retry Button', () => { ...@@ -64,6 +62,7 @@ describe('Job Sidebar Retry Button', () => {
expect(findRetryLink().attributes()).toMatchObject({ expect(findRetryLink().attributes()).toMatchObject({
'data-method': 'post', 'data-method': 'post',
href: job.retry_path, href: job.retry_path,
icon: 'retry',
}); });
}); });
}); });
......
...@@ -21,25 +21,54 @@ describe('Sidebar details block', () => { ...@@ -21,25 +21,54 @@ describe('Sidebar details block', () => {
const findNewIssueButton = () => wrapper.findByTestId('job-new-issue'); const findNewIssueButton = () => wrapper.findByTestId('job-new-issue');
const findRetryButton = () => wrapper.find(JobRetryButton); const findRetryButton = () => wrapper.find(JobRetryButton);
const findTerminalLink = () => wrapper.findByTestId('terminal-link'); const findTerminalLink = () => wrapper.findByTestId('terminal-link');
const findEraseLink = () => wrapper.findByTestId('job-log-erase-link');
const createWrapper = ({ props = {} } = {}) => { const createWrapper = (props) => {
store = createStore(); store = createStore();
store.state.job = job; store.state.job = job;
wrapper = extendedWrapper( wrapper = extendedWrapper(
shallowMount(Sidebar, { shallowMount(Sidebar, {
propsData: {
...props, ...props,
},
store, store,
}), }),
); );
}; };
afterEach(() => { afterEach(() => {
if (wrapper) {
wrapper.destroy(); wrapper.destroy();
wrapper = null; });
}
describe('when job log is erasable', () => {
const path = '/root/ci-project/-/jobs/1447/erase';
beforeEach(() => {
createWrapper({
erasePath: path,
});
});
it('renders erase job link', () => {
expect(findEraseLink().exists()).toBe(true);
});
it('erase job link has correct path', () => {
expect(findEraseLink().attributes('href')).toBe(path);
});
});
describe('when job log is not erasable', () => {
beforeEach(() => {
createWrapper();
});
it('does not render erase button', () => {
expect(findEraseLink().exists()).toBe(false);
});
}); });
describe('when there is no retry path retry', () => { describe('when there is no retry path retry', () => {
...@@ -86,7 +115,7 @@ describe('Sidebar details block', () => { ...@@ -86,7 +115,7 @@ describe('Sidebar details block', () => {
}); });
it('should render link to cancel job', () => { it('should render link to cancel job', () => {
expect(findCancelButton().text()).toMatch('Cancel'); expect(findCancelButton().props('icon')).toBe('cancel');
expect(findCancelButton().attributes('href')).toBe(job.cancel_path); expect(findCancelButton().attributes('href')).toBe(job.cancel_path);
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment