Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-07-24 09:09:41 +00:00
parent fe9cb6b25a
commit ff83f24eac
28 changed files with 250 additions and 183 deletions

View File

@ -1 +1 @@
d483d0d4cb972dd54d23919523ddc296f0dd9590
43e8389d447f471e889dd4521a13037f36d8a230

View File

@ -27,7 +27,7 @@ export default {
<template>
<div class="block gl-display-flex gl-justify-content-space-between">
<span class="issuable-header-text hide-collapsed">
{{ __('To Do') }}
{{ __('To-Do') }}
</span>
<sidebar-todo
v-if="!sidebarCollapsed"

View File

@ -7,7 +7,7 @@ import createAlertTodo from '../../graphql/mutations/alert_todo_create.graphql';
export default {
i18n: {
UPDATE_ALERT_TODO_ERROR: s__(
'AlertManagement|There was an error while updating the To Do of the alert.',
'AlertManagement|There was an error while updating the To-Do of the alert.',
),
},
components: {

View File

@ -97,10 +97,10 @@ export default {
data-testid="dropzone-area"
>
<gl-icon name="upload" :size="iconStyles.size" :class="iconStyles.class" />
<p class="gl-font-weight-bold gl-mb-0">
<gl-sprintf :message="__('Drop or %{linkStart}upload%{linkEnd} Designs to attach')">
<p class="gl-mb-0">
<gl-sprintf :message="__('Drop or %{linkStart}upload%{linkEnd} designs to attach')">
<template #link="{ content }">
<gl-link class="gl-font-weight-normal" @click.stop="openFileUpload">
<gl-link @click.stop="openFileUpload">
{{ content }}
</gl-link>
</template>

View File

@ -1,28 +0,0 @@
<script>
import { mapState } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
Icon,
},
computed: {
...mapState({
confidential: ({ noteableData }) => noteableData.confidential,
dicussionLocked: ({ noteableData }) => noteableData.discussion_locked,
}),
},
};
</script>
<template>
<div class="gl-display-inline-block">
<div v-if="confidential" class="issuable-warning-icon inline">
<icon class="icon" name="eye-slash" data-testid="confidential" />
</div>
<div v-if="dicussionLocked" class="issuable-warning-icon inline">
<icon class="icon" name="lock" data-testid="locked" />
</div>
</div>
</template>

View File

@ -1,8 +1,6 @@
import Vue from 'vue';
import issuableApp from './components/app.vue';
import IssuableHeaderWarnings from './components/issuable_header_warnings.vue';
import { parseIssuableData } from './utils/parse_data';
import { store } from '~/notes/stores';
export default function initIssueableApp() {
return new Vue({
@ -17,13 +15,3 @@ export default function initIssueableApp() {
},
});
}
export function issuableHeaderWarnings() {
return new Vue({
el: document.getElementById('js-issuable-header-warnings'),
store,
render(createElement) {
return createElement(IssuableHeaderWarnings);
},
});
}

View File

@ -5,6 +5,7 @@ import store from '~/mr_notes/stores';
import notesApp from '../notes/components/notes_app.vue';
import discussionKeyboardNavigator from '../notes/components/discussion_keyboard_navigator.vue';
import initWidget from '../vue_merge_request_widget';
import { parseBoolean } from '~/lib/utils/common_utils';
export default () => {
// eslint-disable-next-line no-new
@ -20,6 +21,7 @@ export default () => {
const noteableData = JSON.parse(notesDataset.noteableData);
noteableData.noteableType = notesDataset.noteableType;
noteableData.targetType = notesDataset.targetType;
noteableData.discussion_locked = parseBoolean(notesDataset.isLocked);
return {
noteableData,

View File

@ -1,3 +1,8 @@
// Note: this getter is important because
// `noteableData` is namespaced under `notes` for `~/mr_notes/stores`
// while `noteableData` is directly available as `state.noteableData` for `~/notes/stores`
export const getNoteableData = state => state.notes.noteableData;
export default {
isLoggedIn(state, getters) {
return Boolean(getters.getUserData.id);

View File

@ -3,16 +3,18 @@ import Issue from '~/issue';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import ZenMode from '~/zen_mode';
import '~/notes/index';
import initIssueableApp, { issuableHeaderWarnings } from '~/issue_show';
import { store } from '~/notes/stores';
import initIssueableApp from '~/issue_show';
import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace';
import initRelatedMergeRequestsApp from '~/related_merge_requests';
import initVueIssuableSidebarApp from '~/issuable_sidebar/sidebar_bundle';
export default function() {
initIssueableApp();
initIssuableHeaderWarning(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
issuableHeaderWarnings();
import(/* webpackChunkName: 'design_management' */ '~/design_management')
.then(module => module.default())

View File

@ -2,6 +2,8 @@ import initMrNotes from '~/mr_notes';
import { initReviewBar } from '~/batch_comments';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initShow from '../init_merge_request_show';
import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
import store from '~/mr_notes/stores';
document.addEventListener('DOMContentLoaded', () => {
initShow();
@ -10,4 +12,5 @@ document.addEventListener('DOMContentLoaded', () => {
}
initMrNotes();
initReviewBar();
initIssuableHeaderWarning(store);
});

View File

@ -13,7 +13,6 @@ export default {
if (value === 0) {
this.containerRegistryEnabled = false;
this.lfsEnabled = false;
}
} else if (oldValue === 0) {
this.mergeRequestsAccessLevel = value;

View File

@ -6,7 +6,7 @@ import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
const MARK_TEXT = __('Mark as done');
const TODO_TEXT = __('Add a To Do');
const TODO_TEXT = __('Add a To-Do');
export default {
directives: {

View File

@ -0,0 +1,12 @@
import Vue from 'vue';
import IssuableHeaderWarnings from './issuable_header_warnings.vue';
export default function issuableHeaderWarnings(store) {
return new Vue({
el: document.getElementById('js-issuable-header-warnings'),
store,
render(createElement) {
return createElement(IssuableHeaderWarnings);
},
});
}

View File

@ -0,0 +1,43 @@
<script>
import { mapGetters } from 'vuex';
import { GlIcon } from '@gitlab/ui';
export default {
components: {
GlIcon,
},
computed: {
...mapGetters(['getNoteableData']),
isLocked() {
return this.getNoteableData.discussion_locked;
},
isConfidential() {
return this.getNoteableData.confidential;
},
warningIconsMeta() {
return [
{
iconName: 'lock',
visible: this.isLocked,
dataTestId: 'locked',
},
{
iconName: 'eye-slash',
visible: this.isConfidential,
dataTestId: 'confidential',
},
];
},
},
};
</script>
<template>
<div class="gl-display-inline-block">
<template v-for="meta in warningIconsMeta">
<div v-if="meta.visible" :key="meta.iconName" class="issuable-warning-icon inline">
<gl-icon :name="meta.iconName" :data-testid="meta.dataTestId" class="icon" />
</div>
</template>
</div>
</template>

View File

@ -15,8 +15,7 @@
= state_human_name
.issuable-meta
- if @merge_request.discussion_locked?
.issuable-warning-icon.inline= sprite_icon('lock', size: 16, css_class: 'icon')
#js-issuable-header-warnings
= issuable_meta(@merge_request, @project, "Merge request")
%a.btn.btn-default.float-right.d-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }

View File

@ -70,7 +70,8 @@
noteable_type: 'MergeRequest',
target_type: 'merge_request',
help_page_path: suggest_changes_help_path,
current_user_data: @current_user_data} }
current_user_data: @current_user_data,
is_locked: @merge_request.discussion_locked.to_s } }
= render "projects/merge_requests/tabs/pane", name: "commits", id: "commits", class: "commits" do
-# This tab is always loaded via AJAX

View File

@ -0,0 +1,5 @@
---
title: Consolidate issuable_header_warning for both MR and issue
merge_request: 37043
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Use normal font weight for Design Management dropzone text
merge_request: 37787
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Allow LFS to be enabled in project settings even when Repository is disabled
merge_request: 37401
author:
type: fixed

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1402,6 +1402,9 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
msgid "Add a To-Do"
msgstr ""
msgid "Add a bullet list"
msgstr ""
@ -1429,6 +1432,9 @@ msgstr ""
msgid "Add a numbered list"
msgstr ""
msgid "Add a related issue"
msgstr ""
msgid "Add a table"
msgstr ""
@ -1447,9 +1453,6 @@ msgstr ""
msgid "Add an impersonation token"
msgstr ""
msgid "Add an issue"
msgstr ""
msgid "Add another link"
msgstr ""
@ -2118,7 +2121,7 @@ msgstr ""
msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
msgid "AlertManagement|There was an error while updating the To Do of the alert."
msgid "AlertManagement|There was an error while updating the To-Do of the alert."
msgstr ""
msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
@ -8557,7 +8560,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} Designs to attach"
msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
msgstr ""
msgid "Drop your designs to start your upload."
@ -20901,6 +20904,9 @@ msgstr ""
msgid "SecurityConfiguration|Configure"
msgstr ""
msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
msgstr ""
@ -25017,6 +25023,9 @@ msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
msgid "To-Do"
msgstr ""
msgid "To-Do List"
msgstr ""

View File

@ -52,9 +52,9 @@ describe('Alert Details Sidebar To Do', () => {
});
});
it('renders a button for adding a To Do', () => {
it('renders a button for adding a To-Do', () => {
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find('[data-testid="alert-todo-button"]').text()).toBe('Add a To Do');
expect(wrapper.find('[data-testid="alert-todo-button"]').text()).toBe('Add a To-Do');
});
});

View File

@ -18,10 +18,10 @@ exports[`Design management dropzone component when dragging renders correct temp
/>
<p
class="gl-font-weight-bold gl-mb-0"
class="gl-mb-0"
>
<gl-sprintf-stub
message="Drop or %{linkStart}upload%{linkEnd} Designs to attach"
message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
/>
</p>
</div>
@ -94,10 +94,10 @@ exports[`Design management dropzone component when dragging renders correct temp
/>
<p
class="gl-font-weight-bold gl-mb-0"
class="gl-mb-0"
>
<gl-sprintf-stub
message="Drop or %{linkStart}upload%{linkEnd} Designs to attach"
message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
/>
</p>
</div>
@ -170,10 +170,10 @@ exports[`Design management dropzone component when dragging renders correct temp
/>
<p
class="gl-font-weight-bold gl-mb-0"
class="gl-mb-0"
>
<gl-sprintf-stub
message="Drop or %{linkStart}upload%{linkEnd} Designs to attach"
message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
/>
</p>
</div>
@ -245,10 +245,10 @@ exports[`Design management dropzone component when dragging renders correct temp
/>
<p
class="gl-font-weight-bold gl-mb-0"
class="gl-mb-0"
>
<gl-sprintf-stub
message="Drop or %{linkStart}upload%{linkEnd} Designs to attach"
message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
/>
</p>
</div>
@ -320,10 +320,10 @@ exports[`Design management dropzone component when dragging renders correct temp
/>
<p
class="gl-font-weight-bold gl-mb-0"
class="gl-mb-0"
>
<gl-sprintf-stub
message="Drop or %{linkStart}upload%{linkEnd} Designs to attach"
message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
/>
</p>
</div>
@ -395,10 +395,10 @@ exports[`Design management dropzone component when no slot provided renders defa
/>
<p
class="gl-font-weight-bold gl-mb-0"
class="gl-mb-0"
>
<gl-sprintf-stub
message="Drop or %{linkStart}upload%{linkEnd} Designs to attach"
message="Drop or %{linkStart}upload%{linkEnd} designs to attach"
/>
</p>
</div>

View File

@ -22,6 +22,7 @@ export default function initVueMRPage() {
mrDiscussionsEl.setAttribute('data-noteable-data', JSON.stringify(noteableDataMock));
mrDiscussionsEl.setAttribute('data-notes-data', JSON.stringify(notesDataMock));
mrDiscussionsEl.setAttribute('data-noteable-type', 'merge-request');
mrDiscussionsEl.setAttribute('data-is-locked', 'false');
mrTestEl.appendChild(mrDiscussionsEl);
const discussionCounterEl = document.createElement('div');

View File

@ -1,79 +0,0 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import IssuableHeaderWarnings from '~/issue_show/components/issuable_header_warnings.vue';
import createStore from '~/notes/stores';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('IssuableHeaderWarnings', () => {
let wrapper;
let store;
const findConfidential = () => wrapper.find('[data-testid="confidential"]');
const findLocked = () => wrapper.find('[data-testid="locked"]');
const confidentialIconName = () => findConfidential().attributes('name');
const lockedIconName = () => findLocked().attributes('name');
const createComponent = () => {
wrapper = shallowMount(IssuableHeaderWarnings, { store, localVue });
};
beforeEach(() => {
store = createStore();
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
store = null;
});
describe('when confidential is on', () => {
beforeEach(() => {
store.state.noteableData.confidential = true;
createComponent();
});
it('renders the confidential icon', () => {
expect(confidentialIconName()).toBe('eye-slash');
});
});
describe('when confidential is off', () => {
beforeEach(() => {
store.state.noteableData.confidential = false;
createComponent();
});
it('does not find the component', () => {
expect(findConfidential().exists()).toBe(false);
});
});
describe('when discussion locked is on', () => {
beforeEach(() => {
store.state.noteableData.discussion_locked = true;
createComponent();
});
it('renders the locked icon', () => {
expect(lockedIconName()).toBe('lock');
});
});
describe('when discussion locked is off', () => {
beforeEach(() => {
store.state.noteableData.discussion_locked = false;
createComponent();
});
it('does not find the component', () => {
expect(findLocked().exists()).toBe(false);
});
});
});

View File

@ -6,6 +6,8 @@ import {
visibilityLevelDescriptions,
visibilityOptions,
} from '~/pages/projects/shared/permissions/constants';
import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
const defaultProps = {
currentSettings: {
@ -65,7 +67,13 @@ describe('Settings Panel', () => {
return mountComponent({ ...extraProps, currentSettings: currentSettingsProps });
};
const findLFSSettingsMessage = () => wrapper.find({ ref: 'git-lfs-settings' }).find('p');
const findLFSSettingsRow = () => wrapper.find({ ref: 'git-lfs-settings' });
const findLFSSettingsMessage = () => findLFSSettingsRow().find('p');
const findLFSFeatureToggle = () => findLFSSettingsRow().find(projectFeatureToggle);
const findRepositoryFeatureProjectRow = () => wrapper.find({ ref: 'repository-settings' });
const findRepositoryFeatureSetting = () =>
findRepositoryFeatureProjectRow().find(projectFeatureSetting);
beforeEach(() => {
wrapper = mountComponent();
@ -154,7 +162,7 @@ describe('Settings Panel', () => {
it('should set the repository help text when the visibility level is set to private', () => {
wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.PRIVATE });
expect(wrapper.find({ ref: 'repository-settings' }).props().helpText).toEqual(
expect(findRepositoryFeatureProjectRow().props().helpText).toBe(
'View and edit files in this project',
);
});
@ -162,7 +170,7 @@ describe('Settings Panel', () => {
it('should set the repository help text with a read access warning when the visibility level is set to non-private', () => {
wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.PUBLIC });
expect(wrapper.find({ ref: 'repository-settings' }).props().helpText).toEqual(
expect(findRepositoryFeatureProjectRow().props().helpText).toBe(
'View and edit files in this project. Non-project members will only have read access',
);
});
@ -176,7 +184,7 @@ describe('Settings Panel', () => {
wrapper
.find('[name="project[project_feature_attributes][merge_requests_access_level]"]')
.props().disabledInput,
).toEqual(false);
).toBe(false);
});
it('should disable the merge requests access level input when the repository is disabled', () => {
@ -186,7 +194,7 @@ describe('Settings Panel', () => {
wrapper
.find('[name="project[project_feature_attributes][merge_requests_access_level]"]')
.props().disabledInput,
).toEqual(true);
).toBe(true);
});
});
@ -197,7 +205,7 @@ describe('Settings Panel', () => {
expect(
wrapper.find('[name="project[project_feature_attributes][forking_access_level]"]').props()
.disabledInput,
).toEqual(false);
).toBe(false);
});
it('should disable the forking access level input when the repository is disabled', () => {
@ -206,7 +214,7 @@ describe('Settings Panel', () => {
expect(
wrapper.find('[name="project[project_feature_attributes][forking_access_level]"]').props()
.disabledInput,
).toEqual(true);
).toBe(true);
});
});
@ -217,7 +225,7 @@ describe('Settings Panel', () => {
expect(
wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]').props()
.disabledInput,
).toEqual(false);
).toBe(false);
});
it('should disable the builds access level input when the repository is disabled', () => {
@ -226,7 +234,7 @@ describe('Settings Panel', () => {
expect(
wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]').props()
.disabledInput,
).toEqual(true);
).toBe(true);
});
});
@ -287,7 +295,7 @@ describe('Settings Panel', () => {
expect(
wrapper.find('[name="project[container_registry_enabled]"]').props().disabledInput,
).toEqual(false);
).toBe(false);
});
it('should disable the container registry input when the repository is disabled', () => {
@ -298,7 +306,7 @@ describe('Settings Panel', () => {
expect(
wrapper.find('[name="project[container_registry_enabled]"]').props().disabledInput,
).toEqual(true);
).toBe(true);
});
});
@ -307,7 +315,7 @@ describe('Settings Panel', () => {
wrapper.setProps({ lfsAvailable: true });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find({ ref: 'git-lfs-settings' }).exists()).toEqual(true);
expect(findLFSSettingsRow().exists()).toBe(true);
});
});
@ -315,14 +323,12 @@ describe('Settings Panel', () => {
wrapper.setProps({ lfsAvailable: false });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find({ ref: 'git-lfs-settings' }).exists()).toEqual(false);
expect(findLFSSettingsRow().exists()).toBe(false);
});
});
it('should set the LFS settings help path', () => {
expect(wrapper.find({ ref: 'git-lfs-settings' }).props().helpPath).toBe(
defaultProps.lfsHelpPath,
);
expect(findLFSSettingsRow().props().helpPath).toBe(defaultProps.lfsHelpPath);
});
it('should enable the LFS input when the repository is enabled', () => {
@ -331,7 +337,7 @@ describe('Settings Panel', () => {
{ lfsAvailable: true },
);
expect(wrapper.find('[name="project[lfs_enabled]"]').props().disabledInput).toEqual(false);
expect(findLFSFeatureToggle().props().disabledInput).toBe(false);
});
it('should disable the LFS input when the repository is disabled', () => {
@ -340,7 +346,27 @@ describe('Settings Panel', () => {
{ lfsAvailable: true },
);
expect(wrapper.find('[name="project[lfs_enabled]"]').props().disabledInput).toEqual(true);
expect(findLFSFeatureToggle().props().disabledInput).toBe(true);
});
it('should not change lfsEnabled when disabling the repository', async () => {
// mount over shallowMount, because we are aiming to test rendered state of toggle
wrapper = mountComponent({ currentSettings: { lfsEnabled: true } }, mount);
const repositoryFeatureToggleButton = findRepositoryFeatureSetting().find('button');
const lfsFeatureToggleButton = findLFSFeatureToggle().find('button');
const isToggleButtonChecked = toggleButton => toggleButton.classes('is-checked');
// assert the initial state
expect(isToggleButtonChecked(lfsFeatureToggleButton)).toBe(true);
expect(isToggleButtonChecked(repositoryFeatureToggleButton)).toBe(true);
repositoryFeatureToggleButton.trigger('click');
await wrapper.vm.$nextTick();
expect(isToggleButtonChecked(repositoryFeatureToggleButton)).toBe(false);
// LFS toggle should still be checked
expect(isToggleButtonChecked(lfsFeatureToggleButton)).toBe(true);
});
describe.each`
@ -364,14 +390,14 @@ describe('Settings Panel', () => {
expect(message.text()).toContain(
'LFS objects from this repository are still available to forks',
);
expect(link.text()).toEqual('How do I remove them?');
expect(link.attributes('href')).toEqual(
expect(link.text()).toBe('How do I remove them?');
expect(link.attributes('href')).toBe(
'/help/topics/git/lfs/index#removing-objects-from-lfs',
);
});
} else {
it('does not show warning message', () => {
expect(findLFSSettingsMessage().exists()).toEqual(false);
expect(findLFSSettingsMessage().exists()).toBe(false);
});
}
},
@ -383,7 +409,7 @@ describe('Settings Panel', () => {
wrapper.setProps({ packagesAvailable: true });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find({ ref: 'package-settings' }).exists()).toEqual(true);
expect(wrapper.find({ ref: 'package-settings' }).exists()).toBe(true);
});
});
@ -391,7 +417,7 @@ describe('Settings Panel', () => {
wrapper.setProps({ packagesAvailable: false });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find({ ref: 'package-settings' }).exists()).toEqual(false);
expect(wrapper.find({ ref: 'package-settings' }).exists()).toBe(false);
});
});
@ -411,9 +437,7 @@ describe('Settings Panel', () => {
{ packagesAvailable: true },
);
expect(wrapper.find('[name="project[packages_enabled]"]').props().disabledInput).toEqual(
false,
);
expect(wrapper.find('[name="project[packages_enabled]"]').props().disabledInput).toBe(false);
});
it('should disable the packages input when the repository is disabled', () => {
@ -422,9 +446,7 @@ describe('Settings Panel', () => {
{ packagesAvailable: true },
);
expect(wrapper.find('[name="project[packages_enabled]"]').props().disabledInput).toEqual(
true,
);
expect(wrapper.find('[name="project[packages_enabled]"]').props().disabledInput).toBe(true);
});
});
@ -503,7 +525,7 @@ describe('Settings Panel', () => {
});
it('should contain help text', () => {
expect(wrapper.find({ ref: 'metrics-visibility-settings' }).props().helpText).toEqual(
expect(wrapper.find({ ref: 'metrics-visibility-settings' }).props().helpText).toBe(
'With Metrics Dashboard you can visualize this project performance metrics',
);
});
@ -514,7 +536,7 @@ describe('Settings Panel', () => {
const metricsSettingsRow = wrapper.find({ ref: 'metrics-visibility-settings' });
expect(wrapper.vm.metricsOptionsDropdownEnabled).toBe(true);
expect(metricsSettingsRow.find('select').attributes('disabled')).toEqual('disabled');
expect(metricsSettingsRow.find('select').attributes('disabled')).toBe('disabled');
});
});
});

View File

@ -36,7 +36,7 @@ describe('SidebarTodo', () => {
it.each`
isTodo | iconClass | label | icon
${false} | ${''} | ${'Add a To Do'} | ${'todo-add'}
${false} | ${''} | ${'Add a To-Do'} | ${'todo-add'}
${true} | ${'todo-undone'} | ${'Mark as done'} | ${'todo-done'}
`(
'renders proper button when `isTodo` prop is `$isTodo`',

View File

@ -0,0 +1,73 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import IssuableHeaderWarnings from '~/vue_shared/components/issuable/issuable_header_warnings.vue';
import createIssueStore from '~/notes/stores';
import { createStore as createMrStore } from '~/mr_notes/stores';
const ISSUABLE_TYPE_ISSUE = 'issue';
const ISSUABLE_TYPE_MR = 'merge request';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('IssuableHeaderWarnings', () => {
let wrapper;
let store;
const findConfidentialIcon = () => wrapper.find('[data-testid="confidential"]');
const findLockedIcon = () => wrapper.find('[data-testid="locked"]');
const renderTestMessage = renders => (renders ? 'renders' : 'does not render');
const setLock = locked => {
store.getters.getNoteableData.discussion_locked = locked;
};
const setConfidential = confidential => {
store.getters.getNoteableData.confidential = confidential;
};
const createComponent = () => {
wrapper = shallowMount(IssuableHeaderWarnings, { store, localVue });
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
store = null;
});
describe.each`
issuableType
${ISSUABLE_TYPE_ISSUE} | ${ISSUABLE_TYPE_MR}
`(`when issuableType=$issuableType`, ({ issuableType }) => {
beforeEach(() => {
store = issuableType === ISSUABLE_TYPE_ISSUE ? createIssueStore() : createMrStore();
createComponent();
});
describe.each`
lockStatus | confidentialStatus
${true} | ${true}
${true} | ${false}
${false} | ${true}
${false} | ${false}
`(
`when locked=$lockStatus and confidential=$confidentialStatus`,
({ lockStatus, confidentialStatus }) => {
beforeEach(() => {
setLock(lockStatus);
setConfidential(confidentialStatus);
});
it(`${renderTestMessage(lockStatus)} the locked icon`, () => {
expect(findLockedIcon().exists()).toBe(lockStatus);
});
it(`${renderTestMessage(confidentialStatus)} the confidential icon`, () => {
expect(findConfidentialIcon().exists()).toBe(confidentialStatus);
});
},
);
});
});