diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2018-08-16 10:45:14 +0000 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2018-08-16 10:45:14 +0000 |
commit | 8369ea8972f1c244bf1fe37f1128f824be25f69b (patch) | |
tree | 67965359679011e71c10a87451429a5557b8e61e | |
parent | a7045bd3dc3380f9f4d0a6230aa98ddd48152503 (diff) | |
download | gitlab-ce-8369ea8972f1c244bf1fe37f1128f824be25f69b.tar.gz |
Creates empty state component for job log view
-rw-r--r-- | app/assets/javascripts/jobs/components/empty_state.vue | 76 | ||||
-rw-r--r-- | changelogs/unreleased/50101-empty-state-component.yml | 5 | ||||
-rw-r--r-- | spec/javascripts/jobs/empty_state_spec.js | 90 |
3 files changed, 171 insertions, 0 deletions
diff --git a/app/assets/javascripts/jobs/components/empty_state.vue b/app/assets/javascripts/jobs/components/empty_state.vue new file mode 100644 index 00000000000..4faf08387fb --- /dev/null +++ b/app/assets/javascripts/jobs/components/empty_state.vue @@ -0,0 +1,76 @@ +<script> + export default { + props: { + illustrationPath: { + type: String, + required: true, + }, + illustrationSizeClass: { + type: String, + required: true, + }, + title: { + type: String, + required: true, + }, + content: { + type: String, + required: false, + default: null, + }, + action: { + type: Object, + required: false, + default: null, + validator(value) { + return ( + value === null || + (Object.prototype.hasOwnProperty.call(value, 'link') && + Object.prototype.hasOwnProperty.call(value, 'method') && + Object.prototype.hasOwnProperty.call(value, 'title')) + ); + }, + }, + }, + }; +</script> +<template> + <div class="row empty-state"> + <div class="col-12"> + <div + :class="illustrationSizeClass" + class="svg-content" + > + <img :src="illustrationPath" /> + </div> + </div> + + <div class="col-12"> + <div class="text-content"> + <h4 class="js-job-empty-state-title text-center"> + {{ title }} + </h4> + + <p + v-if="content" + class="js-job-empty-state-content" + > + {{ content }} + </p> + + <div + v-if="action" + class="text-center" + > + <a + :href="action.link" + :data-method="action.method" + class="js-job-empty-state-action btn btn-primary" + > + {{ action.title }} + </a> + </div> + </div> + </div> + </div> +</template> diff --git a/changelogs/unreleased/50101-empty-state-component.yml b/changelogs/unreleased/50101-empty-state-component.yml new file mode 100644 index 00000000000..ee99b65d964 --- /dev/null +++ b/changelogs/unreleased/50101-empty-state-component.yml @@ -0,0 +1,5 @@ +--- +title: Creates empty state vue component for job view +merge_request: +author: +type: other diff --git a/spec/javascripts/jobs/empty_state_spec.js b/spec/javascripts/jobs/empty_state_spec.js new file mode 100644 index 00000000000..f8feb069fe0 --- /dev/null +++ b/spec/javascripts/jobs/empty_state_spec.js @@ -0,0 +1,90 @@ +import Vue from 'vue'; +import component from '~/jobs/components/empty_state.vue'; +import mountComponent from '../helpers/vue_mount_component_helper'; + +describe('Empty State', () => { + const Component = Vue.extend(component); + let vm; + + const props = { + illustrationPath: 'illustrations/pending_job_empty.svg', + illustrationSizeClass: 'svg-430', + title: 'This job has not started yet', + }; + + const content = 'This job is in pending state and is waiting to be picked by a runner'; + + afterEach(() => { + vm.$destroy(); + }); + + describe('renders image and title', () => { + beforeEach(() => { + vm = mountComponent(Component, { + ...props, + content, + }); + }); + + it('renders img with provided path and size', () => { + expect(vm.$el.querySelector('img').getAttribute('src')).toEqual(props.illustrationPath); + expect(vm.$el.querySelector('.svg-content').classList).toContain(props.illustrationSizeClass); + }); + + it('renders provided title', () => { + expect(vm.$el.querySelector('.js-job-empty-state-title').textContent.trim()).toEqual( + props.title, + ); + }); + }); + + describe('with content', () => { + it('renders content', () => { + vm = mountComponent(Component, { + ...props, + content, + }); + + expect(vm.$el.querySelector('.js-job-empty-state-content').textContent.trim()).toEqual( + content, + ); + }); + }); + + describe('without content', () => { + it('does not render content', () => { + vm = mountComponent(Component, { + ...props, + }); + expect(vm.$el.querySelector('.js-job-empty-state-content')).toBeNull(); + }); + }); + + describe('with action', () => { + it('renders action', () => { + vm = mountComponent(Component, { + ...props, + content, + action: { + link: 'runner', + title: 'Check runner', + method: 'post', + }, + }); + + expect(vm.$el.querySelector('.js-job-empty-state-action').getAttribute('href')).toEqual( + 'runner', + ); + }); + }); + + describe('without action', () => { + it('does not render action', () => { + vm = mountComponent(Component, { + ...props, + content, + }); + expect(vm.$el.querySelector('.js-job-empty-state-action')).toBeNull(); + }); + }); +}); |