Commit 0357dce1 authored by Paul Slaughter's avatar Paul Slaughter

Merge branch '36854-webide-use-gl-alert' into 'master'

Refactor WebIDE error message to use GlAlert

Closes #36852 and #36854

See merge request gitlab-org/gitlab!23300
parents 883c82d9 c8bf1bc0
<script>
import { mapActions } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
GlAlert,
GlLoadingIcon,
},
props: {
......@@ -17,9 +18,14 @@ export default {
isLoading: false,
};
},
computed: {
canDismiss() {
return !this.message.action;
},
},
methods: {
...mapActions(['setErrorMessage']),
clickAction() {
doAction() {
if (this.isLoading) return;
this.isLoading = true;
......@@ -33,28 +39,23 @@ export default {
this.isLoading = false;
});
},
clickFlash() {
if (!this.message.action) {
this.setErrorMessage(null);
}
dismiss() {
this.setErrorMessage(null);
},
},
};
</script>
<template>
<div class="flash-container flash-container-page" @click="clickFlash">
<div class="flash-alert" data-qa-selector="flash_alert">
<span v-html="message.text"> </span>
<button
v-if="message.action"
type="button"
class="flash-action text-white p-0 border-top-0 border-right-0 border-left-0 bg-transparent"
@click.stop.prevent="clickAction"
>
{{ message.actionText }}
<gl-loading-icon v-show="isLoading" inline />
</button>
</div>
</div>
<gl-alert
data-qa-selector="flash_alert"
variant="danger"
:dismissible="canDismiss"
:primary-button-text="message.actionText"
@dismiss="dismiss"
@primaryAction="doAction"
>
<span v-html="message.text"></span>
<gl-loading-icon v-show="isLoading" inline class="vertical-align-middle ml-1" />
</gl-alert>
</template>
---
title: Fix Web IDE alert message look and feel
merge_request: 23300
author: Sean Nichols
type: fixed
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import ErrorMessage from '~/ide/components/error_message.vue';
......@@ -15,7 +15,7 @@ describe('IDE error message component', () => {
actions: { setErrorMessage: setErrorMessageMock },
});
wrapper = shallowMount(ErrorMessage, {
wrapper = mount(ErrorMessage, {
propsData: {
message: {
text: 'some text',
......@@ -38,15 +38,18 @@ describe('IDE error message component', () => {
wrapper = null;
});
const findDismissButton = () => wrapper.find('button[aria-label=Dismiss]');
const findActionButton = () => wrapper.find('button.gl-alert-action');
it('renders error message', () => {
const text = 'error message';
createComponent({ text });
expect(wrapper.text()).toContain(text);
});
it('clears error message on click', () => {
it('clears error message on dismiss click', () => {
createComponent();
wrapper.trigger('click');
findDismissButton().trigger('click');
expect(setErrorMessageMock).toHaveBeenCalledWith(expect.any(Object), null, undefined);
});
......@@ -68,29 +71,27 @@ describe('IDE error message component', () => {
});
it('renders action button', () => {
const button = wrapper.find('button');
const button = findActionButton();
expect(button.exists()).toBe(true);
expect(button.text()).toContain(message.actionText);
});
it('does not clear error message on click', () => {
wrapper.trigger('click');
expect(setErrorMessageMock).not.toHaveBeenCalled();
it('does not show dismiss button', () => {
expect(findDismissButton().exists()).toBe(false);
});
it('dispatches action', () => {
wrapper.find('button').trigger('click');
findActionButton().trigger('click');
expect(actionMock).toHaveBeenCalledWith(message.actionPayload);
});
it('does not dispatch action when already loading', () => {
wrapper.find('button').trigger('click');
findActionButton().trigger('click');
actionMock.mockReset();
return wrapper.vm.$nextTick(() => {
wrapper.find('button').trigger('click');
findActionButton().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(actionMock).not.toHaveBeenCalled();
......@@ -106,7 +107,7 @@ describe('IDE error message component', () => {
resolveAction = resolve;
}),
);
wrapper.find('button').trigger('click');
findActionButton().trigger('click');
return wrapper.vm.$nextTick(() => {
expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
......@@ -115,7 +116,7 @@ describe('IDE error message component', () => {
});
it('hides loading icon when operation finishes', () => {
wrapper.find('button').trigger('click');
findActionButton().trigger('click');
return actionMock()
.then(() => wrapper.vm.$nextTick())
.then(() => {
......
......@@ -61,14 +61,14 @@ describe('ide component, non-empty repo', () => {
});
it('shows error message when set', done => {
expect(vm.$el.querySelector('.flash-container')).toBe(null);
expect(vm.$el.querySelector('.gl-alert')).toBe(null);
vm.$store.state.errorMessage = {
text: 'error',
};
vm.$nextTick(() => {
expect(vm.$el.querySelector('.flash-container')).not.toBe(null);
expect(vm.$el.querySelector('.gl-alert')).not.toBe(null);
done();
});
......
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