summaryrefslogtreecommitdiff
path: root/spec/frontend/vue_shared
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 09:55:51 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 09:55:51 +0000
commite8d2c2579383897a1dd7f9debd359abe8ae8373d (patch)
treec42be41678c2586d49a75cabce89322082698334 /spec/frontend/vue_shared
parentfc845b37ec3a90aaa719975f607740c22ba6a113 (diff)
downloadgitlab-ce-e8d2c2579383897a1dd7f9debd359abe8ae8373d.tar.gz
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'spec/frontend/vue_shared')
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap14
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap (renamed from spec/frontend/vue_shared/components/__snapshots__/editor_lite_spec.js.snap)4
-rw-r--r--spec/frontend/vue_shared/components/awards_list_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/dismissible_alert_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/file_finder/index_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js20
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js34
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap2
-rw-r--r--spec/frontend/vue_shared/components/paginated_list_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/project_avatar/default_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/project_avatar_spec.js67
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/resizable_chart/__snapshots__/resizable_chart_container_spec.js.snap30
-rw-r--r--spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js19
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js29
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js113
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/actions_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js29
-rw-r--r--spec/frontend/vue_shared/components/sidebar/todo_button_spec.js (renamed from spec/frontend/vue_shared/components/todo_button_spec.js)22
-rw-r--r--spec/frontend/vue_shared/components/source_editor_spec.js (renamed from spec/frontend/vue_shared/components/editor_lite_spec.js)16
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js20
-rw-r--r--spec/frontend/vue_shared/components/user_select_spec.js44
-rw-r--r--spec/frontend/vue_shared/components/web_ide_link_spec.js8
-rw-r--r--spec/frontend/vue_shared/new_namespace/components/welcome_spec.js26
-rw-r--r--spec/frontend/vue_shared/new_namespace/new_namespace_page_spec.js7
-rw-r--r--spec/frontend/vue_shared/oncall_schedules_list_spec.js2
-rw-r--r--spec/frontend/vue_shared/plugins/global_toast_spec.js9
-rw-r--r--spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js24
-rw-r--r--spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js37
-rw-r--r--spec/frontend/vue_shared/security_reports/mock_data.js11
-rw-r--r--spec/frontend/vue_shared/security_reports/security_reports_app_spec.js10
43 files changed, 492 insertions, 301 deletions
diff --git a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
index 3f91591f5cd..c14cf0db370 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
@@ -7,7 +7,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button"
- title="Ada, Leonardo, and Marie"
+ title="Ada, Leonardo, and Marie reacted with :thumbsup:"
type="button"
>
<!---->
@@ -37,7 +37,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
- title="You, Ada, and Marie"
+ title="You, Ada, and Marie reacted with :thumbsdown:"
type="button"
>
<!---->
@@ -67,7 +67,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button"
- title="Ada and Jane"
+ title="Ada and Jane reacted with :smile:"
type="button"
>
<!---->
@@ -97,7 +97,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
- title="You, Ada, Jane, and Leonardo"
+ title="You, Ada, Jane, and Leonardo reacted with :ok_hand:"
type="button"
>
<!---->
@@ -127,7 +127,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
- title="You"
+ title="You reacted with :cactus:"
type="button"
>
<!---->
@@ -157,7 +157,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button"
- title="Marie"
+ title="Marie reacted with :a:"
type="button"
>
<!---->
@@ -187,7 +187,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
- title="You"
+ title="You reacted with :b:"
type="button"
>
<!---->
diff --git a/spec/frontend/vue_shared/components/__snapshots__/editor_lite_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap
index 26785855369..7ce155f6a5d 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/editor_lite_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Editor Lite component rendering matches the snapshot 1`] = `
+exports[`Source Editor component rendering matches the snapshot 1`] = `
<div
data-editor-loading=""
- id="editor-lite-snippet_777"
+ id="source-editor-snippet_777"
>
<pre
class="editor-loading-content"
diff --git a/spec/frontend/vue_shared/components/awards_list_spec.js b/spec/frontend/vue_shared/components/awards_list_spec.js
index 55f9eedc169..95e9760c181 100644
--- a/spec/frontend/vue_shared/components/awards_list_spec.js
+++ b/spec/frontend/vue_shared/components/awards_list_spec.js
@@ -98,43 +98,43 @@ describe('vue_shared/components/awards_list', () => {
classes: REACTION_CONTROL_CLASSES,
count: 3,
html: matchingEmojiTag(EMOJI_THUMBSUP),
- title: 'Ada, Leonardo, and Marie',
+ title: `Ada, Leonardo, and Marie reacted with :${EMOJI_THUMBSUP}:`,
},
{
classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 3,
html: matchingEmojiTag(EMOJI_THUMBSDOWN),
- title: 'You, Ada, and Marie',
+ title: `You, Ada, and Marie reacted with :${EMOJI_THUMBSDOWN}:`,
},
{
classes: REACTION_CONTROL_CLASSES,
count: 2,
html: matchingEmojiTag(EMOJI_SMILE),
- title: 'Ada and Jane',
+ title: `Ada and Jane reacted with :${EMOJI_SMILE}:`,
},
{
classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 4,
html: matchingEmojiTag(EMOJI_OK),
- title: 'You, Ada, Jane, and Leonardo',
+ title: `You, Ada, Jane, and Leonardo reacted with :${EMOJI_OK}:`,
},
{
classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 1,
html: matchingEmojiTag(EMOJI_CACTUS),
- title: 'You',
+ title: `You reacted with :${EMOJI_CACTUS}:`,
},
{
classes: REACTION_CONTROL_CLASSES,
count: 1,
html: matchingEmojiTag(EMOJI_A),
- title: 'Marie',
+ title: `Marie reacted with :${EMOJI_A}:`,
},
{
classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 1,
html: matchingEmojiTag(EMOJI_B),
- title: 'You',
+ title: `You reacted with :${EMOJI_B}:`,
},
]);
});
@@ -246,13 +246,13 @@ describe('vue_shared/components/awards_list', () => {
classes: REACTION_CONTROL_CLASSES,
count: 1,
html: matchingEmojiTag(EMOJI_100),
- title: 'Marie',
+ title: `Marie reacted with :${EMOJI_100}:`,
},
{
classes: REACTION_CONTROL_CLASSES,
count: 1,
html: matchingEmojiTag(EMOJI_SMILE),
- title: 'Marie',
+ title: `Marie reacted with :${EMOJI_SMILE}:`,
},
]);
});
diff --git a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
index f592db935ec..d14f3e5559f 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
@@ -10,9 +10,10 @@ describe('Blob Rich Viewer component', () => {
const content = '<h1 id="markdown">Foo Bar</h1>';
const defaultType = 'markdown';
- function createComponent(type = defaultType) {
+ function createComponent(type = defaultType, richViewer) {
wrapper = shallowMount(RichViewer, {
propsData: {
+ richViewer,
content,
type,
},
@@ -31,6 +32,12 @@ describe('Blob Rich Viewer component', () => {
expect(wrapper.html()).toContain(content);
});
+ it('renders the richViewer if one is present', () => {
+ const richViewer = '<div class="js-pdf-viewer"></div>';
+ createComponent('pdf', richViewer);
+ expect(wrapper.html()).toContain(richViewer);
+ });
+
it('queries for advanced viewer', () => {
expect(handleBlobRichViewer).toHaveBeenCalledWith(expect.anything(), defaultType);
});
diff --git a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
index 46d4edad891..c6c351a7f3f 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import { HIGHLIGHT_CLASS_NAME } from '~/vue_shared/components/blob_viewers/constants';
import SimpleViewer from '~/vue_shared/components/blob_viewers/simple_viewer.vue';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import SourceEditor from '~/vue_shared/components/source_editor.vue';
describe('Blob Simple Viewer component', () => {
let wrapper;
@@ -96,7 +96,7 @@ describe('Blob Simple Viewer component', () => {
});
describe('Vue refactoring to use Source Editor', () => {
- const findEditorLite = () => wrapper.find(EditorLite);
+ const findSourceEditor = () => wrapper.find(SourceEditor);
it.each`
doesRender | condition | isRawContent | isRefactorFlagEnabled
@@ -105,19 +105,19 @@ describe('Blob Simple Viewer component', () => {
${'Does not'} | ${'both, the FF and rawContent are not specified'} | ${false} | ${false}
${'Does'} | ${'both, the FF and rawContent are specified'} | ${true} | ${true}
`(
- '$doesRender render Editor Lite component in readonly mode when $condition',
+ '$doesRender render Source Editor component in readonly mode when $condition',
async ({ isRawContent, isRefactorFlagEnabled } = {}) => {
createComponent('raw content', isRawContent, isRefactorFlagEnabled);
await waitForPromises();
if (isRawContent && isRefactorFlagEnabled) {
- expect(findEditorLite().exists()).toBe(true);
+ expect(findSourceEditor().exists()).toBe(true);
- expect(findEditorLite().props('value')).toBe('raw content');
- expect(findEditorLite().props('fileName')).toBe('test.js');
- expect(findEditorLite().props('editorOptions')).toEqual({ readOnly: true });
+ expect(findSourceEditor().props('value')).toBe('raw content');
+ expect(findSourceEditor().props('fileName')).toBe('test.js');
+ expect(findSourceEditor().props('editorOptions')).toEqual({ readOnly: true });
} else {
- expect(findEditorLite().exists()).toBe(false);
+ expect(findSourceEditor().exists()).toBe(false);
}
},
);
diff --git a/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js b/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
index eacc41ccdad..8deb466b33c 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
@@ -109,9 +109,11 @@ describe('ImageDiffViewer', () => {
components: {
imageDiffViewer,
},
- data: {
- ...allProps,
- diffMode: 'renamed',
+ data() {
+ return {
+ ...allProps,
+ diffMode: 'renamed',
+ };
},
...compileToFunctions(`
<image-diff-viewer
@@ -121,7 +123,9 @@ describe('ImageDiffViewer', () => {
:new-size="newSize"
:old-size="oldSize"
>
- <span slot="image-overlay" class="overlay">test</span>
+ <template #image-overlay>
+ <span class="overlay">test</span>
+ </template>
</image-diff-viewer>
`),
}).$mount();
diff --git a/spec/frontend/vue_shared/components/dismissible_alert_spec.js b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
index cfa6d1064e5..fcd004d35a7 100644
--- a/spec/frontend/vue_shared/components/dismissible_alert_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
@@ -5,18 +5,12 @@ import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue';
const TEST_HTML = 'Hello World! <strong>Foo</strong>';
describe('vue_shared/components/dismissible_alert', () => {
- const testAlertProps = {
- primaryButtonText: 'Lorem ipsum',
- primaryButtonLink: '/lorem/ipsum',
- };
-
let wrapper;
const createComponent = (props = {}) => {
wrapper = shallowMount(DismissibleAlert, {
propsData: {
html: TEST_HTML,
- ...testAlertProps,
...props,
},
});
@@ -28,16 +22,13 @@ describe('vue_shared/components/dismissible_alert', () => {
const findAlert = () => wrapper.find(GlAlert);
- describe('with default', () => {
+ describe('default', () => {
beforeEach(() => {
createComponent();
});
it('shows alert', () => {
- const alert = findAlert();
-
- expect(alert.exists()).toBe(true);
- expect(alert.props()).toEqual(expect.objectContaining(testAlertProps));
+ expect(findAlert().exists()).toBe(true);
});
it('shows given HTML', () => {
@@ -54,4 +45,32 @@ describe('vue_shared/components/dismissible_alert', () => {
});
});
});
+
+ describe('with additional props', () => {
+ const testAlertProps = {
+ dismissible: true,
+ title: 'Mock Title',
+ primaryButtonText: 'Lorem ipsum',
+ primaryButtonLink: '/lorem/ipsum',
+ variant: 'warning',
+ };
+
+ beforeEach(() => {
+ createComponent(testAlertProps);
+ });
+
+ it('passes other props', () => {
+ expect(findAlert().props()).toEqual(expect.objectContaining(testAlertProps));
+ });
+ });
+
+ describe('with unsafe HTML', () => {
+ beforeEach(() => {
+ createComponent({ html: '<a onclick="alert("XSS")">Link</a>' });
+ });
+
+ it('removes unsafe HTML', () => {
+ expect(findAlert().html()).toContain('<a>Link</a>');
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/file_finder/index_spec.js b/spec/frontend/vue_shared/components/file_finder/index_spec.js
index d757b7fac72..181fc4017a3 100644
--- a/spec/frontend/vue_shared/components/file_finder/index_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/index_spec.js
@@ -154,6 +154,16 @@ describe('File finder item spec', () => {
});
});
+ describe('DOM Performance', () => {
+ it('renders less DOM nodes if not visible by utilizing v-if', async () => {
+ vm.visible = false;
+
+ await waitForPromises();
+
+ expect(vm.$el).toBeInstanceOf(Comment);
+ });
+ });
+
describe('watches', () => {
describe('searchText', () => {
it('resets focusedIndex when updated', (done) => {
@@ -169,7 +179,7 @@ describe('File finder item spec', () => {
});
describe('visible', () => {
- it('returns searchText when false', (done) => {
+ it('resets searchText when changed to false', (done) => {
vm.searchText = 'test';
vm.visible = true;
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
index 93cddff8421..1b97011bf7f 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
@@ -11,7 +11,7 @@ import {
processFilters,
filterToQueryObject,
urlQueryToFilter,
- getRecentlyUsedTokenValues,
+ getRecentlyUsedSuggestions,
setTokenValueToRecentlyUsed,
} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
@@ -328,32 +328,32 @@ describe('urlQueryToFilter', () => {
);
});
-describe('getRecentlyUsedTokenValues', () => {
+describe('getRecentlyUsedSuggestions', () => {
useLocalStorageSpy();
beforeEach(() => {
localStorage.removeItem(mockStorageKey);
});
- it('returns array containing recently used token values from provided recentTokenValuesStorageKey', () => {
+ it('returns array containing recently used token values from provided recentSuggestionsStorageKey', () => {
setLocalStorageAvailability(true);
const mockExpectedArray = [{ foo: 'bar' }];
localStorage.setItem(mockStorageKey, JSON.stringify(mockExpectedArray));
- expect(getRecentlyUsedTokenValues(mockStorageKey)).toEqual(mockExpectedArray);
+ expect(getRecentlyUsedSuggestions(mockStorageKey)).toEqual(mockExpectedArray);
});
- it('returns empty array when provided recentTokenValuesStorageKey does not have anything in localStorage', () => {
+ it('returns empty array when provided recentSuggestionsStorageKey does not have anything in localStorage', () => {
setLocalStorageAvailability(true);
- expect(getRecentlyUsedTokenValues(mockStorageKey)).toEqual([]);
+ expect(getRecentlyUsedSuggestions(mockStorageKey)).toEqual([]);
});
it('returns empty array when when access to localStorage is not available', () => {
setLocalStorageAvailability(false);
- expect(getRecentlyUsedTokenValues(mockStorageKey)).toEqual([]);
+ expect(getRecentlyUsedSuggestions(mockStorageKey)).toEqual([]);
});
});
@@ -366,7 +366,7 @@ describe('setTokenValueToRecentlyUsed', () => {
localStorage.removeItem(mockStorageKey);
});
- it('adds provided tokenValue to localStorage for recentTokenValuesStorageKey', () => {
+ it('adds provided tokenValue to localStorage for recentSuggestionsStorageKey', () => {
setLocalStorageAvailability(true);
setTokenValueToRecentlyUsed(mockStorageKey, mockTokenValue1);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
index 951b050495c..74f579e77ed 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -94,7 +94,7 @@ describe('AuthorToken', () => {
it('calls `config.fetchAuthors` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchAuthors');
- getBaseToken().vm.$emit('fetch-token-values', mockAuthors[0].username);
+ getBaseToken().vm.$emit('fetch-suggestions', mockAuthors[0].username);
expect(wrapper.vm.config.fetchAuthors).toHaveBeenCalledWith(
mockAuthorToken.fetchPath,
@@ -105,17 +105,17 @@ describe('AuthorToken', () => {
it('sets response to `authors` when request is succesful', () => {
jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockResolvedValue(mockAuthors);
- getBaseToken().vm.$emit('fetch-token-values', 'root');
+ getBaseToken().vm.$emit('fetch-suggestions', 'root');
return waitForPromises().then(() => {
- expect(getBaseToken().props('tokenValues')).toEqual(mockAuthors);
+ expect(getBaseToken().props('suggestions')).toEqual(mockAuthors);
});
});
it('calls `createFlash` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
- getBaseToken().vm.$emit('fetch-token-values', 'root');
+ getBaseToken().vm.$emit('fetch-suggestions', 'root');
return waitForPromises().then(() => {
expect(createFlash).toHaveBeenCalledWith({
@@ -127,17 +127,17 @@ describe('AuthorToken', () => {
it('sets `loading` to false when request completes', async () => {
jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
- getBaseToken().vm.$emit('fetch-token-values', 'root');
+ getBaseToken().vm.$emit('fetch-suggestions', 'root');
await waitForPromises();
- expect(getBaseToken().props('tokensListLoading')).toBe(false);
+ expect(getBaseToken().props('suggestionsLoading')).toBe(false);
});
});
});
describe('template', () => {
- const activateTokenValuesList = async () => {
+ const activateSuggestionsList = async () => {
const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
@@ -154,7 +154,7 @@ describe('AuthorToken', () => {
expect(baseTokenEl.exists()).toBe(true);
expect(baseTokenEl.props()).toMatchObject({
- tokenValues: mockAuthors,
+ suggestions: mockAuthors,
fnActiveTokenValue: wrapper.vm.getActiveAuthor,
});
});
@@ -221,7 +221,7 @@ describe('AuthorToken', () => {
stubs: { Portal: true },
});
- await activateTokenValuesList();
+ await activateSuggestionsList();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
@@ -252,7 +252,7 @@ describe('AuthorToken', () => {
stubs: { Portal: true },
});
- await activateTokenValuesList();
+ await activateSuggestionsList();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
index 89c5cedc9b8..cd6ffd679d0 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
@@ -7,7 +7,7 @@ import {
import { DEFAULT_LABELS } from '~/vue_shared/components/filtered_search_bar/constants';
import {
- getRecentlyUsedTokenValues,
+ getRecentlyUsedSuggestions,
setTokenValueToRecentlyUsed,
} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
@@ -49,10 +49,10 @@ const mockProps = {
config: mockLabelToken,
value: { data: '' },
active: false,
- tokenValues: [],
- tokensListLoading: false,
- defaultTokenValues: DEFAULT_LABELS,
- recentTokenValuesStorageKey: mockStorageKey,
+ suggestions: [],
+ suggestionsLoading: false,
+ defaultSuggestions: DEFAULT_LABELS,
+ recentSuggestionsStorageKey: mockStorageKey,
fnCurrentTokenValue: jest.fn(),
};
@@ -83,7 +83,7 @@ describe('BaseToken', () => {
props: {
...mockProps,
value: { data: `"${mockRegularLabel.title}"` },
- tokenValues: mockLabels,
+ suggestions: mockLabels,
},
});
});
@@ -93,8 +93,8 @@ describe('BaseToken', () => {
});
describe('data', () => {
- it('calls `getRecentlyUsedTokenValues` to populate `recentTokenValues` when `recentTokenValuesStorageKey` is defined', () => {
- expect(getRecentlyUsedTokenValues).toHaveBeenCalledWith(mockStorageKey);
+ it('calls `getRecentlyUsedSuggestions` to populate `recentSuggestions` when `recentSuggestionsStorageKey` is defined', () => {
+ expect(getRecentlyUsedSuggestions).toHaveBeenCalledWith(mockStorageKey);
});
});
@@ -147,15 +147,15 @@ describe('BaseToken', () => {
wrapperWithTokenActive.destroy();
});
- it('emits `fetch-token-values` event on the component when value of this prop is changed to false and `tokenValues` array is empty', async () => {
+ it('emits `fetch-suggestions` event on the component when value of this prop is changed to false and `suggestions` array is empty', async () => {
wrapperWithTokenActive.setProps({
active: false,
});
await wrapperWithTokenActive.vm.$nextTick();
- expect(wrapperWithTokenActive.emitted('fetch-token-values')).toBeTruthy();
- expect(wrapperWithTokenActive.emitted('fetch-token-values')).toEqual([
+ expect(wrapperWithTokenActive.emitted('fetch-suggestions')).toBeTruthy();
+ expect(wrapperWithTokenActive.emitted('fetch-suggestions')).toEqual([
[`"${mockRegularLabel.title}"`],
]);
});
@@ -164,7 +164,7 @@ describe('BaseToken', () => {
describe('methods', () => {
describe('handleTokenValueSelected', () => {
- it('calls `setTokenValueToRecentlyUsed` when `recentTokenValuesStorageKey` is defined', () => {
+ it('calls `setTokenValueToRecentlyUsed` when `recentSuggestionsStorageKey` is defined', () => {
const mockTokenValue = {
id: 1,
title: 'Foo',
@@ -175,14 +175,14 @@ describe('BaseToken', () => {
expect(setTokenValueToRecentlyUsed).toHaveBeenCalledWith(mockStorageKey, mockTokenValue);
});
- it('does not add token from preloadedTokenValues', async () => {
+ it('does not add token from preloadedSuggestions', async () => {
const mockTokenValue = {
id: 1,
title: 'Foo',
};
wrapper.setProps({
- preloadedTokenValues: [mockTokenValue],
+ preloadedSuggestions: [mockTokenValue],
});
await wrapper.vm.$nextTick();
@@ -228,7 +228,7 @@ describe('BaseToken', () => {
wrapperWithNoStubs.destroy();
});
- it('emits `fetch-token-values` event on component after a delay when component emits `input` event', async () => {
+ it('emits `fetch-suggestions` event on component after a delay when component emits `input` event', async () => {
jest.useFakeTimers();
wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: 'foo' });
@@ -236,8 +236,8 @@ describe('BaseToken', () => {
jest.runAllTimers();
- expect(wrapperWithNoStubs.emitted('fetch-token-values')).toBeTruthy();
- expect(wrapperWithNoStubs.emitted('fetch-token-values')[2]).toEqual(['foo']);
+ expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toBeTruthy();
+ expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']);
});
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
index ca5dc984ae0..bd654c5a9cb 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
@@ -7,7 +7,7 @@ import { mockIterationToken } from '../mock_data';
jest.mock('~/flash');
describe('IterationToken', () => {
- const title = 'gitlab-org: #1';
+ const id = 123;
let wrapper;
const createComponent = ({ config = mockIterationToken, value = { data: '' } } = {}) =>
@@ -28,14 +28,14 @@ describe('IterationToken', () => {
});
it('renders iteration value', async () => {
- wrapper = createComponent({ value: { data: title } });
+ wrapper = createComponent({ value: { data: id } });
await wrapper.vm.$nextTick();
const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // `Iteration` `=` `gitlab-org: #1`
- expect(tokenSegments.at(2).text()).toBe(title);
+ expect(tokenSegments.at(2).text()).toBe(id.toString());
});
it('fetches initial values', () => {
@@ -43,10 +43,10 @@ describe('IterationToken', () => {
wrapper = createComponent({
config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy },
- value: { data: title },
+ value: { data: id },
});
- expect(fetchIterationsSpy).toHaveBeenCalledWith(title);
+ expect(fetchIterationsSpy).toHaveBeenCalledWith(id);
});
it('fetches iterations on user input', () => {
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
index cc40ff96b65..ec9458f64d2 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
@@ -159,7 +159,7 @@ describe('LabelToken', () => {
expect(baseTokenEl.exists()).toBe(true);
expect(baseTokenEl.props()).toMatchObject({
- tokenValues: mockLabels,
+ suggestions: mockLabels,
fnActiveTokenValue: wrapper.vm.getActiveLabel,
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
index 9f550ac9afc..74ceb03bb96 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
@@ -9,6 +9,7 @@ import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
import { DEFAULT_MILESTONES } from '~/vue_shared/components/filtered_search_bar/constants';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
@@ -21,6 +22,7 @@ import {
} from '../mock_data';
jest.mock('~/flash');
+jest.mock('~/milestones/milestone_utils');
const defaultStubs = {
Portal: true,
@@ -112,6 +114,7 @@ describe('MilestoneToken', () => {
return waitForPromises().then(() => {
expect(wrapper.vm.milestones).toEqual(mockMilestones);
+ expect(sortMilestonesByDueDate).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap b/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
index f3ce03796f9..5e956d66b6a 100644
--- a/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
+++ b/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
@@ -55,6 +55,8 @@ exports[`Issue placeholder note component matches snapshot 1`] = `
<p>
Foo
</p>
+
+
</div>
</div>
</div>
diff --git a/spec/frontend/vue_shared/components/paginated_list_spec.js b/spec/frontend/vue_shared/components/paginated_list_spec.js
index c0ee49f194f..9f819cc4e94 100644
--- a/spec/frontend/vue_shared/components/paginated_list_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_list_spec.js
@@ -7,9 +7,11 @@ describe('Pagination links component', () => {
let glPaginatedList;
const template = `
- <div class="slot" slot-scope="{ listItem }">
- <span class="item">Item Name: {{listItem.id}}</span>
- </div>
+ <template #default="{ listItem }">
+ <div class="slot">
+ <span class="item">Item Name: {{ listItem.id }}</span>
+ </div>
+ </template>
`;
const props = {
diff --git a/spec/frontend/vue_shared/components/project_avatar/default_spec.js b/spec/frontend/vue_shared/components/project_avatar/default_spec.js
index 0daadeebc20..84dad2374cb 100644
--- a/spec/frontend/vue_shared/components/project_avatar/default_spec.js
+++ b/spec/frontend/vue_shared/components/project_avatar/default_spec.js
@@ -3,7 +3,7 @@ import mountComponent from 'helpers/vue_mount_component_helper';
import { projectData } from 'jest/ide/mock_data';
import { TEST_HOST } from 'spec/test_constants';
import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
-import ProjectAvatarDefault from '~/vue_shared/components/project_avatar/default.vue';
+import ProjectAvatarDefault from '~/vue_shared/components/deprecated_project_avatar/default.vue';
describe('ProjectAvatarDefault component', () => {
const Component = Vue.extend(ProjectAvatarDefault);
diff --git a/spec/frontend/vue_shared/components/project_avatar_spec.js b/spec/frontend/vue_shared/components/project_avatar_spec.js
new file mode 100644
index 00000000000..d55f3127a74
--- /dev/null
+++ b/spec/frontend/vue_shared/components/project_avatar_spec.js
@@ -0,0 +1,67 @@
+import { GlAvatar } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
+
+const defaultProps = {
+ projectName: 'GitLab',
+};
+
+describe('ProjectAvatar', () => {
+ let wrapper;
+
+ const findGlAvatar = () => wrapper.findComponent(GlAvatar);
+
+ const createComponent = ({ props, attrs } = {}) => {
+ wrapper = shallowMount(ProjectAvatar, { propsData: { ...defaultProps, ...props }, attrs });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders GlAvatar with correct props', () => {
+ createComponent();
+
+ const avatar = findGlAvatar();
+ expect(avatar.exists()).toBe(true);
+ expect(avatar.props()).toMatchObject({
+ alt: defaultProps.projectName,
+ entityName: defaultProps.projectName,
+ size: 32,
+ src: '',
+ });
+ });
+
+ describe('with `size` prop', () => {
+ it('renders GlAvatar with specified `size` prop', () => {
+ const mockSize = 48;
+ createComponent({ props: { size: mockSize } });
+
+ const avatar = findGlAvatar();
+ expect(avatar.props('size')).toBe(mockSize);
+ });
+ });
+
+ describe('with `projectAvatarUrl` prop', () => {
+ it('renders GlAvatar with specified `src` prop', () => {
+ const mockProjectAvatarUrl = 'https://gitlab.com';
+ createComponent({ props: { projectAvatarUrl: mockProjectAvatarUrl } });
+
+ const avatar = findGlAvatar();
+ expect(avatar.props('src')).toBe(mockProjectAvatarUrl);
+ });
+ });
+
+ describe.each`
+ alt
+ ${''}
+ ${'custom-alt'}
+ `('when `alt` prop is "$alt"', ({ alt }) => {
+ it('renders GlAvatar with specified `alt` attribute', () => {
+ createComponent({ props: { alt } });
+
+ const avatar = findGlAvatar();
+ expect(avatar.props('alt')).toBe(alt);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
index 649eb2643f1..ab028ea52b7 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
@@ -1,5 +1,6 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
+import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
const localVue = createLocalVue();
@@ -53,7 +54,7 @@ describe('ProjectListItem component', () => {
it(`renders the project avatar`, () => {
wrapper = shallowMount(Component, options);
- expect(wrapper.find('.js-project-avatar').exists()).toBe(true);
+ expect(wrapper.findComponent(ProjectAvatar).exists()).toBe(true);
});
it(`renders a simple namespace name with a trailing slash`, () => {
diff --git a/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/resizable_chart_container_spec.js.snap b/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/resizable_chart_container_spec.js.snap
index add0c36a120..cdfe311acd9 100644
--- a/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/resizable_chart_container_spec.js.snap
+++ b/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/resizable_chart_container_spec.js.snap
@@ -2,20 +2,22 @@
exports[`Resizable Chart Container renders the component 1`] = `
<div>
- <div
- class="slot"
- >
- <span
- class="width"
+ <template>
+ <div
+ class="slot"
>
- 0
- </span>
-
- <span
- class="height"
- >
- 0
- </span>
- </div>
+ <span
+ class="width"
+ >
+ 0
+ </span>
+
+ <span
+ class="height"
+ >
+ 0
+ </span>
+ </div>
+ </template>
</div>
`;
diff --git a/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js b/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js
index 1fce3c5d0b0..40f0c0f29f2 100644
--- a/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js
+++ b/spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js
@@ -16,10 +16,12 @@ describe('Resizable Chart Container', () => {
wrapper = mount(ResizableChartContainer, {
scopedSlots: {
default: `
- <div class="slot" slot-scope="{ width, height }">
- <span class="width">{{width}}</span>
- <span class="height">{{height}}</span>
- </div>
+ <template #default="{ width, height }">
+ <div class="slot">
+ <span class="width">{{width}}</span>
+ <span class="height">{{height}}</span>
+ </div>
+ </template>
`,
},
});
diff --git a/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js b/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
index d58c87d66cb..395c74dcba6 100644
--- a/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
+++ b/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
@@ -3,7 +3,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import {
- expectedDownloadDropdownProps,
+ expectedDownloadDropdownPropsWithTitle,
securityReportMergeRequestDownloadPathsQueryResponse,
} from 'jest/vue_shared/security_reports/mock_data';
import createFlash from '~/flash';
@@ -80,7 +80,7 @@ describe('Merge request artifact Download', () => {
});
it('renders the download dropdown', () => {
- expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownPropsWithTitle);
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js b/spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js
index b99b1a66b79..3980033862e 100644
--- a/spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js
@@ -1,4 +1,4 @@
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CopyableField from '~/vue_shared/components/sidebar/copyable_field.vue';
@@ -14,6 +14,9 @@ describe('SidebarCopyableField', () => {
const createComponent = (propsData = defaultProps) => {
wrapper = shallowMount(CopyableField, {
propsData,
+ stubs: {
+ GlSprintf,
+ },
});
};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
index 60903933505..06ea88c09a0 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
@@ -54,7 +54,6 @@ describe('DropdownContentsLabelsView', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
const findDropdownContent = () => wrapper.find('[data-testid="dropdown-content"]');
@@ -381,6 +380,15 @@ describe('DropdownContentsLabelsView', () => {
expect(findDropdownFooter().exists()).toBe(false);
});
+ it('does not render footer list items when `allowLabelCreate` is false and `labelsManagePath` is null', () => {
+ createComponent({
+ ...mockConfig,
+ allowLabelCreate: false,
+ labelsManagePath: null,
+ });
+ expect(findDropdownFooter().exists()).toBe(false);
+ });
+
it('renders footer list items when `state.variant` is "embedded"', () => {
expect(findDropdownFooter().exists()).toBe(true);
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
index 3f11095cb04..46ade5d5857 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
@@ -1,11 +1,14 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/vue_shared/components/sidebar/labels_select_vue/store/actions';
import * as types from '~/vue_shared/components/sidebar/labels_select_vue/store/mutation_types';
import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/store/state';
+jest.mock('~/flash');
+
describe('LabelsSelect Actions', () => {
let state;
const mockInitialState = {
@@ -91,10 +94,6 @@ describe('LabelsSelect Actions', () => {
});
describe('receiveLabelsFailure', () => {
- beforeEach(() => {
- setFixtures('<div class="flash-container"></div>');
- });
-
it('sets value `state.labelsFetchInProgress` to `false`', (done) => {
testAction(
actions.receiveLabelsFailure,
@@ -109,9 +108,7 @@ describe('LabelsSelect Actions', () => {
it('shows flash error', () => {
actions.receiveLabelsFailure({ commit: () => {} });
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- 'Error fetching labels.',
- );
+ expect(createFlash).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
});
});
@@ -186,10 +183,6 @@ describe('LabelsSelect Actions', () => {
});
describe('receiveCreateLabelFailure', () => {
- beforeEach(() => {
- setFixtures('<div class="flash-container"></div>');
- });
-
it('sets value `state.labelCreateInProgress` to `false`', (done) => {
testAction(
actions.receiveCreateLabelFailure,
@@ -204,9 +197,7 @@ describe('LabelsSelect Actions', () => {
it('shows flash error', () => {
actions.receiveCreateLabelFailure({ commit: () => {} });
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- 'Error creating label.',
- );
+ expect(createFlash).toHaveBeenCalledWith({ message: 'Error creating label.' });
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
index ab266ac8aed..1d2a9c34599 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
@@ -153,7 +153,16 @@ describe('LabelsSelect Mutations', () => {
});
describe(`${types.UPDATE_SELECTED_LABELS}`, () => {
- const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
+ let labels;
+
+ beforeEach(() => {
+ labels = [
+ { id: 1, title: 'scoped::test', set: true },
+ { id: 2, set: false, title: 'scoped::one' },
+ { id: 3, title: '' },
+ { id: 4, title: '' },
+ ];
+ });
it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param', () => {
const updatedLabelIds = [2];
@@ -169,5 +178,23 @@ describe('LabelsSelect Mutations', () => {
}
});
});
+
+ describe('when label is scoped', () => {
+ it('unsets the currently selected scoped label and sets the current label', () => {
+ const state = {
+ labels,
+ };
+ mutations[types.UPDATE_SELECTED_LABELS](state, {
+ labels: [{ id: 2, title: 'scoped::one' }],
+ });
+
+ expect(state.labels).toEqual([
+ { id: 1, title: 'scoped::test', set: false },
+ { id: 2, set: true, title: 'scoped::one', touched: true },
+ { id: 3, title: '' },
+ { id: 4, title: '' },
+ ]);
+ });
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
index 59f3268c000..b3ffee2d020 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
@@ -1,88 +1,97 @@
import { GlLabel } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
+import { shallowMount } from '@vue/test-utils';
import DropdownValue from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue';
-import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_widget/store';
-
-import { mockConfig, mockRegularLabel, mockScopedLabel } from './mock_data';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
+import { mockRegularLabel, mockScopedLabel } from './mock_data';
describe('DropdownValue', () => {
let wrapper;
- const createComponent = (initialState = {}, slots = {}) => {
- const store = new Vuex.Store(labelsSelectModule());
-
- store.dispatch('setInitialState', { ...mockConfig, ...initialState });
+ const findAllLabels = () => wrapper.findAllComponents(GlLabel);
+ const findRegularLabel = () => findAllLabels().at(0);
+ const findScopedLabel = () => findAllLabels().at(1);
+ const findWrapper = () => wrapper.find('[data-testid="value-wrapper"]');
+ const findEmptyPlaceholder = () => wrapper.find('[data-testid="empty-placeholder"]');
+ const createComponent = (props = {}, slots = {}) => {
wrapper = shallowMount(DropdownValue, {
- localVue,
- store,
slots,
+ propsData: {
+ selectedLabels: [mockRegularLabel, mockScopedLabel],
+ allowLabelRemove: true,
+ allowScopedLabels: true,
+ labelsFilterBasePath: '/gitlab-org/my-project/issues',
+ labelsFilterParam: 'label_name',
+ ...props,
+ },
});
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
- describe('methods', () => {
- describe('labelFilterUrl', () => {
- it('returns a label filter URL based on provided label param', () => {
- createComponent();
-
- expect(wrapper.vm.labelFilterUrl(mockRegularLabel)).toBe(
- '/gitlab-org/my-project/issues?label_name[]=Foo%20Label',
- );
- });
+ describe('when there are no labels', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ selectedLabels: [],
+ },
+ {
+ default: 'None',
+ },
+ );
});
- describe('scopedLabel', () => {
- beforeEach(() => {
- createComponent();
- });
+ it('does not apply `has-labels` class to the wrapping container', () => {
+ expect(findWrapper().classes()).not.toContain('has-labels');
+ });
- it('returns `true` when provided label param is a scoped label', () => {
- expect(wrapper.vm.scopedLabel(mockScopedLabel)).toBe(true);
- });
+ it('renders an empty placeholder', () => {
+ expect(findEmptyPlaceholder().exists()).toBe(true);
+ expect(findEmptyPlaceholder().text()).toBe('None');
+ });
- it('returns `false` when provided label param is a regular label', () => {
- expect(wrapper.vm.scopedLabel(mockRegularLabel)).toBe(false);
- });
+ it('does not render any labels', () => {
+ expect(findAllLabels().length).toBe(0);
});
});
- describe('template', () => {
- it('renders class `has-labels` on component container element when `selectedLabels` is not empty', () => {
+ describe('when there are labels', () => {
+ beforeEach(() => {
createComponent();
+ });
- expect(wrapper.attributes('class')).toContain('has-labels');
+ it('applies `has-labels` class to the wrapping container', () => {
+ expect(findWrapper().classes()).toContain('has-labels');
});
- it('renders element containing `None` when `selectedLabels` is empty', () => {
- createComponent(
- {
- selectedLabels: [],
- },
- {
- default: 'None',
- },
- );
- const noneEl = wrapper.find('span.text-secondary');
+ it('does not render an empty placeholder', () => {
+ expect(findEmptyPlaceholder().exists()).toBe(false);
+ });
- expect(noneEl.exists()).toBe(true);
- expect(noneEl.text()).toBe('None');
+ it('renders a list of two labels', () => {
+ expect(findAllLabels().length).toBe(2);
});
- it('renders labels when `selectedLabels` is not empty', () => {
- createComponent();
+ it('passes correct props to the regular label', () => {
+ expect(findRegularLabel().props('target')).toBe(
+ '/gitlab-org/my-project/issues?label_name[]=Foo%20Label',
+ );
+ expect(findRegularLabel().props('scoped')).toBe(false);
+ });
+
+ it('passes correct props to the scoped label', () => {
+ expect(findScopedLabel().props('target')).toBe(
+ '/gitlab-org/my-project/issues?label_name[]=Foo%3A%3ABar',
+ );
+ expect(findScopedLabel().props('scoped')).toBe(true);
+ });
- expect(wrapper.findAll(GlLabel).length).toBe(2);
+ it('emits `onLabelRemove` event with the correct ID', () => {
+ findRegularLabel().vm.$emit('close');
+ expect(wrapper.emitted('onLabelRemove')).toEqual([[mockRegularLabel.id]]);
});
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
index ee1346c362f..66971446f47 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
@@ -34,6 +34,10 @@ describe('LabelsSelectRoot', () => {
stubs: {
'dropdown-contents': DropdownContents,
},
+ provide: {
+ iid: '1',
+ projectPath: 'test',
+ },
});
};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/actions_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/actions_spec.js
index 7ef4b769b6b..27de7de2411 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/actions_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/actions_spec.js
@@ -1,11 +1,14 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/vue_shared/components/sidebar/labels_select_widget/store/actions';
import * as types from '~/vue_shared/components/sidebar/labels_select_widget/store/mutation_types';
import defaultState from '~/vue_shared/components/sidebar/labels_select_widget/store/state';
+jest.mock('~/flash');
+
describe('LabelsSelect Actions', () => {
let state;
const mockInitialState = {
@@ -91,10 +94,6 @@ describe('LabelsSelect Actions', () => {
});
describe('receiveLabelsFailure', () => {
- beforeEach(() => {
- setFixtures('<div class="flash-container"></div>');
- });
-
it('sets value `state.labelsFetchInProgress` to `false`', (done) => {
testAction(
actions.receiveLabelsFailure,
@@ -109,9 +108,7 @@ describe('LabelsSelect Actions', () => {
it('shows flash error', () => {
actions.receiveLabelsFailure({ commit: () => {} });
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- 'Error fetching labels.',
- );
+ expect(createFlash).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js
index acb275b5d90..9e965cb33e8 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js
@@ -120,7 +120,16 @@ describe('LabelsSelect Mutations', () => {
});
describe(`${types.UPDATE_SELECTED_LABELS}`, () => {
- const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
+ let labels;
+
+ beforeEach(() => {
+ labels = [
+ { id: 1, title: 'scoped::test', set: true },
+ { id: 2, set: false, title: 'scoped::one' },
+ { id: 3, title: '' },
+ { id: 4, title: '' },
+ ];
+ });
it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param', () => {
const updatedLabelIds = [2];
@@ -136,5 +145,23 @@ describe('LabelsSelect Mutations', () => {
}
});
});
+
+ describe('when label is scoped', () => {
+ it('unsets the currently selected scoped label and sets the current label', () => {
+ const state = {
+ labels,
+ };
+ mutations[types.UPDATE_SELECTED_LABELS](state, {
+ labels: [{ id: 2, title: 'scoped::one' }],
+ });
+
+ expect(state.labels).toEqual([
+ { id: 1, title: 'scoped::test', set: false },
+ { id: 2, set: true, title: 'scoped::one', touched: true },
+ { id: 3, title: '' },
+ { id: 4, title: '' },
+ ]);
+ });
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/todo_button_spec.js b/spec/frontend/vue_shared/components/sidebar/todo_button_spec.js
index 8043bb7785b..de3e1ccfb03 100644
--- a/spec/frontend/vue_shared/components/todo_button_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/todo_button_spec.js
@@ -1,9 +1,10 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import TodoButton from '~/vue_shared/components/todo_button.vue';
+import TodoButton from '~/vue_shared/components/sidebar/todo_toggle/todo_button.vue';
describe('Todo Button', () => {
let wrapper;
+ let dispatchEventSpy;
const createComponent = (props = {}, mountFn = shallowMount) => {
wrapper = mountFn(TodoButton, {
@@ -13,8 +14,17 @@ describe('Todo Button', () => {
});
};
+ beforeEach(() => {
+ dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
+ jest.spyOn(document, 'querySelector').mockReturnValue({
+ innerText: 2,
+ });
+ });
+
afterEach(() => {
wrapper.destroy();
+ dispatchEventSpy = null;
+ jest.clearAllMocks();
});
it('renders GlButton', () => {
@@ -30,6 +40,16 @@ describe('Todo Button', () => {
expect(wrapper.emitted().click).toBeTruthy();
});
+ it('calls dispatchDocumentEvent to update global To-Do counter correctly', () => {
+ createComponent({}, mount);
+ wrapper.find(GlButton).trigger('click');
+ const dispatchedEvent = dispatchEventSpy.mock.calls[0][0];
+
+ expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
+ expect(dispatchedEvent.detail).toEqual({ count: 1 });
+ expect(dispatchedEvent.type).toBe('todo:toggle');
+ });
+
it.each`
label | isTodo
${'Mark as done'} | ${true}
diff --git a/spec/frontend/vue_shared/components/editor_lite_spec.js b/spec/frontend/vue_shared/components/source_editor_spec.js
index badd5aed0e3..dca4d60e23c 100644
--- a/spec/frontend/vue_shared/components/editor_lite_spec.js
+++ b/spec/frontend/vue_shared/components/source_editor_spec.js
@@ -1,12 +1,12 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { EDITOR_READY_EVENT } from '~/editor/constants';
-import Editor from '~/editor/editor_lite';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import Editor from '~/editor/source_editor';
+import SourceEditor from '~/vue_shared/components/source_editor.vue';
-jest.mock('~/editor/editor_lite');
+jest.mock('~/editor/source_editor');
-describe('Editor Lite component', () => {
+describe('Source Editor component', () => {
let wrapper;
let mockInstance;
@@ -30,7 +30,7 @@ describe('Editor Lite component', () => {
};
});
function createComponent(props = {}) {
- wrapper = shallowMount(EditorLite, {
+ wrapper = shallowMount(SourceEditor, {
propsData: {
value,
fileName,
@@ -73,10 +73,10 @@ describe('Editor Lite component', () => {
createComponent({ value: undefined });
expect(spy).not.toHaveBeenCalled();
- expect(wrapper.find('[id^="editor-lite-"]').exists()).toBe(true);
+ expect(wrapper.find('[id^="source-editor-"]').exists()).toBe(true);
});
- it('initialises Editor Lite instance', () => {
+ it('initialises Source Editor instance', () => {
const el = wrapper.find({ ref: 'editor' }).element;
expect(createInstanceMock).toHaveBeenCalledWith({
el,
@@ -111,7 +111,7 @@ describe('Editor Lite component', () => {
expect(wrapper.emitted().input).toEqual([[value]]);
});
- it('emits EDITOR_READY_EVENT event when the Editor Lite is ready', async () => {
+ it('emits EDITOR_READY_EVENT event when the Source Editor is ready', async () => {
const el = wrapper.find({ ref: 'editor' }).element;
expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeUndefined();
diff --git a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
index 87fe8619f28..538e67ef354 100644
--- a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
@@ -1,5 +1,5 @@
-import { GlSkeletonLoader, GlSprintf, GlIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { GlSkeletonLoader, GlIcon } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
@@ -13,6 +13,7 @@ const DEFAULT_PROPS = {
bio: null,
workInformation: null,
status: null,
+ pronouns: 'they/them',
loaded: true,
},
};
@@ -30,23 +31,18 @@ describe('User Popover Component', () => {
wrapper.destroy();
});
- const findByTestId = (testid) => wrapper.find(`[data-testid="${testid}"]`);
const findUserStatus = () => wrapper.find('.js-user-status');
const findTarget = () => document.querySelector('.js-user-link');
const findUserName = () => wrapper.find(UserNameWithStatus);
- const findSecurityBotDocsLink = () => findByTestId('user-popover-bot-docs-link');
+ const findSecurityBotDocsLink = () => wrapper.findByTestId('user-popover-bot-docs-link');
const createWrapper = (props = {}, options = {}) => {
- wrapper = shallowMount(UserPopover, {
+ wrapper = mountExtended(UserPopover, {
propsData: {
...DEFAULT_PROPS,
target: findTarget(),
...props,
},
- stubs: {
- GlSprintf,
- UserNameWithStatus,
- },
...options,
});
};
@@ -232,6 +228,12 @@ describe('User Popover Component', () => {
expect(wrapper.text()).not.toContain('(Busy)');
});
+
+ it('passes `pronouns` prop to `UserNameWithStatus` component', () => {
+ createWrapper();
+
+ expect(findUserName().props('pronouns')).toBe('they/them');
+ });
});
describe('bot user', () => {
diff --git a/spec/frontend/vue_shared/components/user_select_spec.js b/spec/frontend/vue_shared/components/user_select_spec.js
index 0fabc6525ea..b777ac0a0a4 100644
--- a/spec/frontend/vue_shared/components/user_select_spec.js
+++ b/spec/frontend/vue_shared/components/user_select_spec.js
@@ -275,48 +275,4 @@ describe('User select dropdown', () => {
expect(findEmptySearchResults().exists()).toBe(true);
});
});
-
- // TODO Remove this test after the following issue is resolved in the backend
- // https://gitlab.com/gitlab-org/gitlab/-/issues/329750
- describe('temporary error suppression', () => {
- beforeEach(() => {
- jest.spyOn(console, 'error').mockImplementation();
- });
-
- const nullError = { message: 'Cannot return null for non-nullable field GroupMember.user' };
-
- it.each`
- mockErrors
- ${[nullError]}
- ${[nullError, nullError]}
- `('does not emit errors', async ({ mockErrors }) => {
- createComponent({
- searchQueryHandler: jest.fn().mockResolvedValue({
- errors: mockErrors,
- }),
- });
- await waitForSearch();
-
- expect(wrapper.emitted()).toEqual({});
- // eslint-disable-next-line no-console
- expect(console.error).toHaveBeenCalled();
- });
-
- it.each`
- mockErrors
- ${[{ message: 'serious error' }]}
- ${[nullError, { message: 'serious error' }]}
- `('emits error when non-null related errors are included', async ({ mockErrors }) => {
- createComponent({
- searchQueryHandler: jest.fn().mockResolvedValue({
- errors: mockErrors,
- }),
- });
- await waitForSearch();
-
- expect(wrapper.emitted('error')).toEqual([[]]);
- // eslint-disable-next-line no-console
- expect(console.error).not.toHaveBeenCalled();
- });
- });
});
diff --git a/spec/frontend/vue_shared/components/web_ide_link_spec.js b/spec/frontend/vue_shared/components/web_ide_link_spec.js
index 5a6c91bda9f..0fd4d0dab87 100644
--- a/spec/frontend/vue_shared/components/web_ide_link_spec.js
+++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js
@@ -15,8 +15,8 @@ const ACTION_EDIT = {
tooltip: '',
attrs: {
'data-qa-selector': 'edit_button',
- 'data-track-event': 'click_edit',
- 'data-track-label': 'Edit',
+ 'data-track-action': 'click_consolidated_edit',
+ 'data-track-label': 'edit',
},
};
const ACTION_EDIT_CONFIRM_FORK = {
@@ -32,8 +32,8 @@ const ACTION_WEB_IDE = {
text: 'Web IDE',
attrs: {
'data-qa-selector': 'web_ide_button',
- 'data-track-event': 'click_edit_ide',
- 'data-track-label': 'Web IDE',
+ 'data-track-action': 'click_consolidated_edit_ide',
+ 'data-track-label': 'web_ide',
},
};
const ACTION_WEB_IDE_CONFIRM_FORK = {
diff --git a/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js b/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js
index 602213fca83..2d51f6dbeeb 100644
--- a/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js
+++ b/spec/frontend/vue_shared/new_namespace/components/welcome_spec.js
@@ -1,12 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { mockTracking } from 'helpers/tracking_helper';
-import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
-import { getExperimentData } from '~/experimentation/utils';
import WelcomePage from '~/vue_shared/new_namespace/components/welcome.vue';
-jest.mock('~/experimentation/utils', () => ({ getExperimentData: jest.fn() }));
-
describe('Welcome page', () => {
let wrapper;
let trackingSpy;
@@ -28,7 +24,6 @@ describe('Welcome page', () => {
beforeEach(() => {
trackingSpy = mockTracking('_category_', document, jest.spyOn);
trackingSpy.mockImplementation(() => {});
- getExperimentData.mockReturnValue(undefined);
});
afterEach(() => {
@@ -38,7 +33,7 @@ describe('Welcome page', () => {
});
it('tracks link clicks', async () => {
- createComponent({ propsData: { experiment: 'foo', panels: [{ name: 'test', href: '#' }] } });
+ createComponent({ propsData: { panels: [{ name: 'test', href: '#' }] } });
const link = wrapper.find('a');
link.trigger('click');
await nextTick();
@@ -47,25 +42,6 @@ describe('Welcome page', () => {
});
});
- it('adds experiment data if in experiment', async () => {
- const mockExperimentData = 'data';
- getExperimentData.mockReturnValue(mockExperimentData);
-
- createComponent({ propsData: { experiment: 'foo', panels: [{ name: 'test', href: '#' }] } });
- const link = wrapper.find('a');
- link.trigger('click');
- await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', {
- label: 'test',
- context: {
- data: mockExperimentData,
- schema: TRACKING_CONTEXT_SCHEMA,
- },
- });
- });
- });
-
it('renders footer slot if provided', () => {
const DUMMY = 'Test message';
createComponent({
diff --git a/spec/frontend/vue_shared/new_namespace/new_namespace_page_spec.js b/spec/frontend/vue_shared/new_namespace/new_namespace_page_spec.js
index 30937921900..6115dc6e61b 100644
--- a/spec/frontend/vue_shared/new_namespace/new_namespace_page_spec.js
+++ b/spec/frontend/vue_shared/new_namespace/new_namespace_page_spec.js
@@ -37,13 +37,6 @@ describe('Experimental new project creation app', () => {
window.location.hash = '';
});
- it('passes experiment to welcome component if provided', () => {
- const EXPERIMENT = 'foo';
- createComponent({ propsData: { experiment: EXPERIMENT } });
-
- expect(findWelcomePage().props().experiment).toBe(EXPERIMENT);
- });
-
describe('with empty hash', () => {
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/vue_shared/oncall_schedules_list_spec.js b/spec/frontend/vue_shared/oncall_schedules_list_spec.js
index 5c30809c09b..f83a5187b8b 100644
--- a/spec/frontend/vue_shared/oncall_schedules_list_spec.js
+++ b/spec/frontend/vue_shared/oncall_schedules_list_spec.js
@@ -18,7 +18,7 @@ const mockSchedules = [
},
];
-const userName = 'User 1';
+const userName = "O'User";
describe('On-call schedules list', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/plugins/global_toast_spec.js b/spec/frontend/vue_shared/plugins/global_toast_spec.js
index 89f43a5e556..322586a772c 100644
--- a/spec/frontend/vue_shared/plugins/global_toast_spec.js
+++ b/spec/frontend/vue_shared/plugins/global_toast_spec.js
@@ -1,11 +1,10 @@
-import Vue from 'vue';
-import toast from '~/vue_shared/plugins/global_toast';
+import toast, { instance } from '~/vue_shared/plugins/global_toast';
describe('Global toast', () => {
let spyFunc;
beforeEach(() => {
- spyFunc = jest.spyOn(Vue.prototype.$toast, 'show').mockImplementation(() => {});
+ spyFunc = jest.spyOn(instance.$toast, 'show').mockImplementation(() => {});
});
afterEach(() => {
@@ -18,7 +17,7 @@ describe('Global toast', () => {
toast(arg1, arg2);
- expect(Vue.prototype.$toast.show).toHaveBeenCalledTimes(1);
- expect(Vue.prototype.$toast.show).toHaveBeenCalledWith(arg1, arg2);
+ expect(instance.$toast.show).toHaveBeenCalledTimes(1);
+ expect(instance.$toast.show).toHaveBeenCalledWith(arg1, arg2);
});
});
diff --git a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
index 517eee6a729..facbd51168c 100644
--- a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
+++ b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
@@ -9,6 +9,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { humanize } from '~/lib/utils/text_utility';
import { redirectTo } from '~/lib/utils/url_utility';
import ManageViaMr from '~/vue_shared/security_configuration/components/manage_via_mr.vue';
+import { REPORT_TYPE_SAST } from '~/vue_shared/security_reports/constants';
import { buildConfigureSecurityFeatureMockFactory } from './apollo_mocks';
jest.mock('~/lib/utils/url_utility');
@@ -169,6 +170,29 @@ describe('ManageViaMr component', () => {
},
);
+ describe('canRender static method', () => {
+ it.each`
+ context | type | available | configured | canEnableByMergeRequest | expectedValue
+ ${'an unconfigured feature'} | ${REPORT_TYPE_SAST} | ${true} | ${false} | ${true} | ${true}
+ ${'a configured feature'} | ${REPORT_TYPE_SAST} | ${true} | ${true} | ${true} | ${false}
+ ${'an unavailable feature'} | ${REPORT_TYPE_SAST} | ${false} | ${false} | ${true} | ${false}
+ ${'a feature which cannot be enabled via MR'} | ${REPORT_TYPE_SAST} | ${true} | ${false} | ${false} | ${false}
+ ${'an unknown feature'} | ${'foo'} | ${true} | ${false} | ${true} | ${false}
+ `(
+ 'given $context returns $expectedValue',
+ ({ type, available, configured, canEnableByMergeRequest, expectedValue }) => {
+ expect(
+ ManageViaMr.canRender({
+ type,
+ available,
+ configured,
+ canEnableByMergeRequest,
+ }),
+ ).toBe(expectedValue);
+ },
+ );
+ });
+
describe('button props', () => {
it('passes the variant and category props to the GlButton', () => {
const variant = 'danger';
diff --git a/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js b/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
index 9138d2d3f4c..4b75da0b126 100644
--- a/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
+++ b/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
@@ -40,14 +40,13 @@ describe('SecurityReportDownloadDropdown component', () => {
expect(findDropdown().props('loading')).toBe(false);
});
- it('renders a dropdown items for each artifact', () => {
+ it('renders a dropdown item for each artifact', () => {
artifacts.forEach((artifact, i) => {
const item = findDropdownItems().at(i);
expect(item.text()).toContain(artifact.name);
- expect(item.attributes()).toMatchObject({
- href: artifact.path,
- download: expect.any(String),
- });
+
+ expect(item.element.getAttribute('href')).toBe(artifact.path);
+ expect(item.element.getAttribute('download')).toBeDefined();
});
});
});
@@ -61,4 +60,32 @@ describe('SecurityReportDownloadDropdown component', () => {
expect(findDropdown().props('loading')).toBe(true);
});
});
+
+ describe('given title props', () => {
+ beforeEach(() => {
+ createComponent({ artifacts: [], loading: true, title: 'test title' });
+ });
+
+ it('should render title', () => {
+ expect(findDropdown().attributes('title')).toBe('test title');
+ });
+
+ it('should not render text', () => {
+ expect(findDropdown().text().trim()).toBe('');
+ });
+ });
+
+ describe('given text props', () => {
+ beforeEach(() => {
+ createComponent({ artifacts: [], loading: true, text: 'test text' });
+ });
+
+ it('should not render title', () => {
+ expect(findDropdown().props().title).not.toBeDefined();
+ });
+
+ it('should render text', () => {
+ expect(findDropdown().props().text).toContain('test text');
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/security_reports/mock_data.js b/spec/frontend/vue_shared/security_reports/mock_data.js
index bd9ce3b7314..06631710509 100644
--- a/spec/frontend/vue_shared/security_reports/mock_data.js
+++ b/spec/frontend/vue_shared/security_reports/mock_data.js
@@ -581,9 +581,18 @@ export const secretDetectionArtifacts = [
},
];
-export const expectedDownloadDropdownProps = {
+export const expectedDownloadDropdownPropsWithTitle = {
loading: false,
artifacts: [...secretDetectionArtifacts, ...sastArtifacts],
+ text: '',
+ title: 'Download results',
+};
+
+export const expectedDownloadDropdownPropsWithText = {
+ loading: false,
+ artifacts: [...secretDetectionArtifacts, ...sastArtifacts],
+ title: '',
+ text: 'Download results',
};
/**
diff --git a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
index 038d7754776..bef538e1ff1 100644
--- a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
+++ b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
@@ -8,7 +8,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { trimText } from 'helpers/text_helper';
import waitForPromises from 'helpers/wait_for_promises';
import {
- expectedDownloadDropdownProps,
+ expectedDownloadDropdownPropsWithText,
securityReportMergeRequestDownloadPathsQueryNoArtifactsResponse,
securityReportMergeRequestDownloadPathsQueryResponse,
sastDiffSuccessMock,
@@ -99,7 +99,7 @@ describe('Security reports app', () => {
});
it('renders the download dropdown', () => {
- expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownPropsWithText);
});
it('renders the expected message', () => {
@@ -203,7 +203,7 @@ describe('Security reports app', () => {
});
it('renders the download dropdown', () => {
- expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownPropsWithText);
});
});
@@ -225,7 +225,7 @@ describe('Security reports app', () => {
});
it('renders the download dropdown', () => {
- expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownPropsWithText);
});
});
@@ -247,7 +247,7 @@ describe('Security reports app', () => {
});
it('renders the download dropdown', () => {
- expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownPropsWithText);
});
});