Commit c75dfb40 authored by Paul Gascou-Vaillancourt's avatar Paul Gascou-Vaillancourt Committed by David O'Regan

Integrate GlModal close button change

GlModal was updated to use a Pajamas-compliant close button. This is
done by overriding the modal-header slot to display a custom close
button, and by re-exposing the title prop as well as the modal-title
slot.
Those are drop-in changes as it still possible to set a modal's title
either by providing a modal-header slot, a modal-title slot, or by
passing the title prop.
However, the specs needed to be updated to reflect those API changes.
parent c1af21fb
...@@ -5,6 +5,7 @@ exports[`dashboard should match the snapshot 1`] = ` ...@@ -5,6 +5,7 @@ exports[`dashboard should match the snapshot 1`] = `
class="environments-dashboard" class="environments-dashboard"
> >
<gl-modal-stub <gl-modal-stub
dismisslabel="Close"
modalclass="" modalclass=""
modalid="add-projects-modal" modalid="add-projects-modal"
ok-disabled="true" ok-disabled="true"
......
import { createLocalVue, mount } from '@vue/test-utils'; import { createLocalVue, mount } from '@vue/test-utils';
import { getByRole, getByAltText } from '@testing-library/dom'; import { getByRole } from '@testing-library/dom';
import Vuex from 'vuex'; import Vuex from 'vuex';
import GeoReplicableEmptyState from 'ee/geo_replicable/components/geo_replicable_empty_state.vue'; import GeoReplicableEmptyState from 'ee/geo_replicable/components/geo_replicable_empty_state.vue';
import createStore from 'ee/geo_replicable/store'; import createStore from 'ee/geo_replicable/store';
...@@ -45,11 +45,9 @@ describe('GeoReplicableEmptyState', () => { ...@@ -45,11 +45,9 @@ describe('GeoReplicableEmptyState', () => {
}); });
it('sets correct svg', () => { it('sets correct svg', () => {
expect( expect(getByRole(wrapper.element, 'img').getAttribute('src')).toBe(
getByAltText(wrapper.element, `There are no ${MOCK_REPLICABLE_TYPE} to show`).getAttribute( MOCK_GEO_REPLICATION_SVG_PATH,
'src', );
),
).toBe(MOCK_GEO_REPLICATION_SVG_PATH);
}); });
}); });
}); });
...@@ -5,6 +5,7 @@ exports[`DeleteScheduleModal renders delete schedule modal layout 1`] = ` ...@@ -5,6 +5,7 @@ exports[`DeleteScheduleModal renders delete schedule modal layout 1`] = `
actioncancel="[object Object]" actioncancel="[object Object]"
actionprimary="[object Object]" actionprimary="[object Object]"
data-testid="delete-schedule-modal-37" data-testid="delete-schedule-modal-37"
dismisslabel="Close"
modalclass="" modalclass=""
modalid="deleteScheduleModal" modalid="deleteScheduleModal"
size="sm" size="sm"
......
...@@ -4,6 +4,7 @@ exports[`AddEditRotationModal renders rotation modal layout 1`] = ` ...@@ -4,6 +4,7 @@ exports[`AddEditRotationModal renders rotation modal layout 1`] = `
<gl-modal-stub <gl-modal-stub
actioncancel="[object Object]" actioncancel="[object Object]"
actionprimary="[object Object]" actionprimary="[object Object]"
dismisslabel="Close"
modalclass="" modalclass=""
modalid="addRotationModal" modalid="addRotationModal"
size="sm" size="sm"
......
...@@ -5,6 +5,7 @@ exports[`DeleteRotationModal renders delete rotation modal layout 1`] = ` ...@@ -5,6 +5,7 @@ exports[`DeleteRotationModal renders delete rotation modal layout 1`] = `
actioncancel="[object Object]" actioncancel="[object Object]"
actionprimary="[object Object]" actionprimary="[object Object]"
data-testid="delete-rotation-modal-gid://gitlab/IncidentManagement::OncallRotation/2" data-testid="delete-rotation-modal-gid://gitlab/IncidentManagement::OncallRotation/2"
dismisslabel="Close"
modalclass="" modalclass=""
modalid="deleteRotationModal" modalid="deleteRotationModal"
size="sm" size="sm"
......
...@@ -31,6 +31,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = ` ...@@ -31,6 +31,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
<gl-modal-stub <gl-modal-stub
actioncancel="[object Object]" actioncancel="[object Object]"
actionprimary="[object Object]" actionprimary="[object Object]"
dismisslabel="Close"
footer-class="gl-bg-gray-10 gl-p-5" footer-class="gl-bg-gray-10 gl-p-5"
modalclass="" modalclass=""
modalid="fakeUniqueId" modalid="fakeUniqueId"
......
...@@ -97,9 +97,6 @@ describe('RequirementsEmptyState', () => { ...@@ -97,9 +97,6 @@ describe('RequirementsEmptyState', () => {
const emptyStateEl = wrapper.find('.empty-state .svg-content img'); const emptyStateEl = wrapper.find('.empty-state .svg-content img');
expect(emptyStateEl.exists()).toBe(true); expect(emptyStateEl.exists()).toBe(true);
expect(emptyStateEl.attributes('alt')).toBe(
'With requirements, you can set criteria to check your products against.',
);
expect(emptyStateEl.attributes('src')).toBe( expect(emptyStateEl.attributes('src')).toBe(
'/assets/illustrations/empty-state/requirements.svg', '/assets/illustrations/empty-state/requirements.svg',
); );
......
...@@ -247,6 +247,7 @@ spec: ...@@ -247,6 +247,7 @@ spec:
<gl-modal-stub <gl-modal-stub
actioncancel="[object Object]" actioncancel="[object Object]"
actionsecondary="[object Object]" actionsecondary="[object Object]"
dismisslabel="Close"
modalclass="" modalclass=""
modalid="delete-modal" modalid="delete-modal"
size="md" size="md"
......
...@@ -45,7 +45,7 @@ describe('DAST Modal', () => { ...@@ -45,7 +45,7 @@ describe('DAST Modal', () => {
it('should contain the dynamic title', () => { it('should contain the dynamic title', () => {
createWrapper({ scannedResourcesCount: 20 }); createWrapper({ scannedResourcesCount: 20 });
expect(wrapper.attributes('title')).toBe('20 Scanned URLs'); expect(wrapper.find(GlModal).props('title')).toBe('20 Scanned URLs');
}); });
it('should not show download button when link is not present', () => { it('should not show download button when link is not present', () => {
......
...@@ -12,7 +12,7 @@ exports[`Vulnerability Report error states has unavailable pages 1`] = ` ...@@ -12,7 +12,7 @@ exports[`Vulnerability Report error states has unavailable pages 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="Oops, something doesn't seem right." alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="/test/empty_state.svg" src="/test/empty_state.svg"
/> />
......
...@@ -58,7 +58,7 @@ exports[`Security Charts error states has unavailable pages 1`] = ` ...@@ -58,7 +58,7 @@ exports[`Security Charts error states has unavailable pages 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="Oops, something doesn't seem right." alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="/test/empty_state.svg" src="/test/empty_state.svg"
/> />
......
...@@ -4,6 +4,7 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = ` ...@@ -4,6 +4,7 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = `
<gl-modal-stub <gl-modal-stub
body-class="add-review-item pt-0" body-class="add-review-item pt-0"
cancel-variant="light" cancel-variant="light"
dismisslabel="Close"
modalclass="" modalclass=""
modalid="add-review-item" modalid="add-review-item"
ok-disabled="true" ok-disabled="true"
......
...@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { GlSprintf, GlModal, GlLink } from '@gitlab/ui'; import { GlSprintf, GlModal, GlLink } from '@gitlab/ui';
import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper'; import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
import { stubComponent } from 'helpers/stub_component';
import pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue'; import pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue';
import modalProps from './pipeline_tour_success_mock_data'; import modalProps from './pipeline_tour_success_mock_data';
...@@ -15,7 +16,14 @@ describe('PipelineTourSuccessModal', () => { ...@@ -15,7 +16,14 @@ describe('PipelineTourSuccessModal', () => {
wrapper = shallowMount(pipelineTourSuccess, { wrapper = shallowMount(pipelineTourSuccess, {
propsData: modalProps, propsData: modalProps,
stubs: { stubs: {
GlModal, GlModal: stubComponent(GlModal, {
template: `
<div>
<slot name="modal-title"></slot>
<slot></slot>
<slot name="modal-footer"></slot>
</div>`,
}),
GlSprintf, GlSprintf,
GlEmoji, GlEmoji,
}, },
......
...@@ -52,6 +52,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] = ...@@ -52,6 +52,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
</gl-button-stub> </gl-button-stub>
<gl-modal-stub <gl-modal-stub
dismisslabel="Close"
modalclass="" modalclass=""
modalid="resetWebhookModal" modalid="resetWebhookModal"
ok-title="Reset webhook URL" ok-title="Reset webhook URL"
......
...@@ -68,7 +68,7 @@ describe('InviteMembersModal', () => { ...@@ -68,7 +68,7 @@ describe('InviteMembersModal', () => {
}); });
it('renders the modal with the correct title', () => { it('renders the modal with the correct title', () => {
expect(wrapper.attributes('title')).toBe('Invite team members'); expect(wrapper.find(GlModal).props('title')).toBe('Invite team members');
}); });
it('renders the Cancel button text correctly', () => { it('renders the Cancel button text correctly', () => {
......
...@@ -34,7 +34,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -34,7 +34,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
...@@ -95,7 +95,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -95,7 +95,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no Composer packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
...@@ -156,7 +156,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -156,7 +156,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no Conan packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
...@@ -217,7 +217,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -217,7 +217,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no Generic packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
...@@ -278,7 +278,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -278,7 +278,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no Maven packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
...@@ -339,7 +339,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -339,7 +339,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no NPM packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
...@@ -400,7 +400,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -400,7 +400,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no NuGet packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
...@@ -461,7 +461,7 @@ exports[`packages_list_app renders 1`] = ` ...@@ -461,7 +461,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content" class="svg-250 svg-content"
> >
<img <img
alt="There are no PyPI packages yet" alt=""
class="gl-max-w-full" class="gl-max-w-full"
src="helpSvg" src="helpSvg"
/> />
......
...@@ -44,7 +44,7 @@ describe('Test case details', () => { ...@@ -44,7 +44,7 @@ describe('Test case details', () => {
}); });
it('renders the test case classname as modal title', () => { it('renders the test case classname as modal title', () => {
expect(findModal().attributes('title')).toBe(defaultTestCase.classname); expect(findModal().props('title')).toBe(defaultTestCase.classname);
}); });
it('renders the test case name', () => { it('renders the test case name', () => {
......
...@@ -84,7 +84,7 @@ describe('UpdateUsername component', () => { ...@@ -84,7 +84,7 @@ describe('UpdateUsername component', () => {
it('confirmation modal contains proper header and body', async () => { it('confirmation modal contains proper header and body', async () => {
const { modal } = findElements(); const { modal } = findElements();
expect(modal.attributes('title')).toBe('Change username?'); expect(modal.props('title')).toBe('Change username?');
expect(modal.text()).toContain( expect(modal.text()).toContain(
`You are going to change the username ${defaultProps.initialUsername} to ${newUsername}`, `You are going to change the username ${defaultProps.initialUsername} to ${newUsername}`,
); );
......
...@@ -31,6 +31,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = ` ...@@ -31,6 +31,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
<gl-modal-stub <gl-modal-stub
actioncancel="[object Object]" actioncancel="[object Object]"
actionprimary="[object Object]" actionprimary="[object Object]"
dismisslabel="Close"
footer-class="gl-bg-gray-10 gl-p-5" footer-class="gl-bg-gray-10 gl-p-5"
modalclass="" modalclass=""
modalid="fakeUniqueId" modalid="fakeUniqueId"
......
...@@ -29,24 +29,12 @@ exports[`Project remove modal intialized matches the snapshot 1`] = ` ...@@ -29,24 +29,12 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
Delete project Delete project
</gl-button-stub> </gl-button-stub>
<b-modal-stub <div
canceltitle="Cancel" footer-class="gl-bg-gray-10 gl-p-5"
cancelvariant="secondary" ok-variant="danger"
footerclass="gl-bg-gray-10 gl-p-5" title-class="gl-text-red-500"
headerclosecontent="&times;"
headercloselabel="Close"
id="delete-project-modal-2"
ignoreenforcefocusselector=""
lazy="true"
modalclass="gl-modal,"
oktitle="OK"
okvariant="danger"
size="sm"
title=""
titleclass="gl-text-red-500"
titletag="h4"
> >
Delete project. Are you ABSOLUTELY SURE?
<div> <div>
<p <p
...@@ -70,49 +58,6 @@ exports[`Project remove modal intialized matches the snapshot 1`] = ` ...@@ -70,49 +58,6 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
/> />
</div> </div>
</div>
<template />
<template>
Delete project. Are you ABSOLUTELY SURE?
</template>
<template />
<template />
<template />
<template>
<gl-button-stub
buttontextclasses=""
category="primary"
class="js-modal-action-cancel"
icon=""
size="medium"
variant="default"
>
Cancel, keep project
</gl-button-stub>
<!---->
<gl-button-stub
buttontextclasses=""
category="primary"
class="js-modal-action-primary"
disabled="true"
icon=""
size="medium"
variant="danger"
>
Yes, delete project
</gl-button-stub>
</template>
</b-modal-stub>
</form> </form>
`; `;
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui'; import { GlModal } from '@gitlab/ui';
import { stubComponent } from 'helpers/stub_component';
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue'; import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' })); jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' }));
...@@ -17,12 +18,19 @@ describe('Project remove modal', () => { ...@@ -17,12 +18,19 @@ describe('Project remove modal', () => {
formPath: 'some/path', formPath: 'some/path',
}; };
const createComponent = (data = {}) => { const createComponent = (data = {}, stubs = {}) => {
wrapper = shallowMount(SharedDeleteButton, { wrapper = shallowMount(SharedDeleteButton, {
propsData: defaultProps, propsData: defaultProps,
data: () => data, data: () => data,
stubs: { stubs: {
GlModal, GlModal: stubComponent(GlModal, {
template: `
<div>
<slot name="modal-title"></slot>
<slot></slot>
</div>`,
}),
...stubs,
}, },
}); });
}; };
...@@ -52,7 +60,7 @@ describe('Project remove modal', () => { ...@@ -52,7 +60,7 @@ describe('Project remove modal', () => {
describe('when the user input does not match the confirmPhrase', () => { describe('when the user input does not match the confirmPhrase', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ userInput: 'bar' }); createComponent({ userInput: 'bar' }, { GlModal });
}); });
it('the confirm button is disabled', () => { it('the confirm button is disabled', () => {
...@@ -62,7 +70,7 @@ describe('Project remove modal', () => { ...@@ -62,7 +70,7 @@ describe('Project remove modal', () => {
describe('when the user input matches the confirmPhrase', () => { describe('when the user input matches the confirmPhrase', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ userInput: defaultProps.confirmPhrase }); createComponent({ userInput: defaultProps.confirmPhrase }, { GlModal });
}); });
it('the confirm button is not disabled', () => { it('the confirm button is not disabled', () => {
......
...@@ -60,6 +60,7 @@ exports[`self monitor component When the self monitor project has not been creat ...@@ -60,6 +60,7 @@ exports[`self monitor component When the self monitor project has not been creat
<gl-modal-stub <gl-modal-stub
cancel-title="Cancel" cancel-title="Cancel"
category="primary" category="primary"
dismisslabel="Close"
modalclass="" modalclass=""
modalid="delete-self-monitor-modal" modalid="delete-self-monitor-modal"
ok-title="Delete project" ok-title="Delete project"
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
exports[`EmptyStateComponent should render content 1`] = ` exports[`EmptyStateComponent should render content 1`] = `
"<section class=\\"row empty-state text-center\\"> "<section class=\\"row empty-state text-center\\">
<div class=\\"col-12\\"> <div class=\\"col-12\\">
<div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"Getting started with serverless\\" class=\\"gl-max-w-full\\"></div> <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"\\" class=\\"gl-max-w-full\\"></div>
</div> </div>
<div class=\\"col-12\\"> <div class=\\"col-12\\">
<div class=\\"text-content gl-mx-auto gl-my-0 gl-p-5\\"> <div class=\\"text-content gl-mx-auto gl-my-0 gl-p-5\\">
......
...@@ -876,10 +876,10 @@ ...@@ -876,10 +876,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
"@gitlab/ui@25.4.0": "@gitlab/ui@25.7.2":
version "25.4.0" version "25.7.2"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.4.0.tgz#67bfd2a905097fc4cec0272665c36c722b3475c9" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.7.2.tgz#50271f99818645f9bc7ef675c08f9bf1bae54293"
integrity sha512-/dffpdyDcX102wWTbzDQOmOGfAEyDitRWCBOk2U+WRKPJIsWYtZuw40putwNA/gUUE1U08TPHf3sGSLzwIKZPA== integrity sha512-hgM9JHesIqnDujjJ16BHFQWYwzWd9php8xElhkGUdKWGV+PVw9TVdYcKfkIAb3TXtb9551uXN0Jv6wH5DRJyXw==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0" "@gitlab/vue-toasted" "^1.3.0"
......
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