Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-17 12:09:32 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-17 12:09:32 +0300
commitafed1a4be18c74f8b95a0b8e0e359a1339ca1ad1 (patch)
tree108265d8da2c5856183f9032c16dd9ae63cf9b01 /spec/frontend
parent9e3e71602cac2593f77282b1862fbd163e78233f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/boards/board_list_helper.js6
-rw-r--r--spec/frontend/boards/board_list_spec.js6
-rw-r--r--spec/frontend/boards/board_new_issue_spec.js59
-rw-r--r--spec/frontend/boards/components/board_card_layout_spec.js6
-rw-r--r--spec/frontend/boards/components/board_card_spec.js6
-rw-r--r--spec/frontend/boards/components/board_column_spec.js5
-rw-r--r--spec/frontend/boards/components/board_content_spec.js4
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js6
-rw-r--r--spec/frontend/boards/issue_card_spec.js6
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js3
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js3
-rw-r--r--spec/frontend/ide/components/new_dropdown/upload_spec.js2
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js13
-rw-r--r--spec/frontend/ide/lib/files_spec.js4
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js2
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js2
-rw-r--r--spec/frontend/ide/utils_spec.js100
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js8
-rw-r--r--spec/frontend/integrations/edit/components/override_dropdown_spec.js6
-rw-r--r--spec/frontend/integrations/edit/store/getters_spec.js14
-rw-r--r--spec/frontend/integrations/edit/store/state_spec.js8
-rw-r--r--spec/frontend/issuable_create/components/issuable_form_spec.js1
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js185
-rw-r--r--spec/frontend/issuable_list/components/issuable_list_root_spec.js160
-rw-r--r--spec/frontend/issuable_list/components/issuable_tabs_spec.js91
-rw-r--r--spec/frontend/issuable_list/mock_data.js135
26 files changed, 720 insertions, 121 deletions
diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js
index b51a82f2a35..80d7a72151d 100644
--- a/spec/frontend/boards/board_list_helper.js
+++ b/spec/frontend/boards/board_list_helper.js
@@ -52,10 +52,12 @@ export default function createComponent({
list,
issues: list.issues,
loading: false,
- issueLinkBase: '/issues',
- rootPath: '/',
...componentProps,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
}).$mount();
Vue.nextTick(() => {
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index 3a64b004847..88883ae61d4 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -45,10 +45,12 @@ const createComponent = ({ done, listIssueProps = {}, componentProps = {}, listP
list,
issues: list.issues,
loading: false,
- issueLinkBase: '/issues',
- rootPath: '/',
...componentProps,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
}).$mount();
Vue.nextTick(() => {
diff --git a/spec/frontend/boards/board_new_issue_spec.js b/spec/frontend/boards/board_new_issue_spec.js
index 94afc8a2b45..3eebfeca965 100644
--- a/spec/frontend/boards/board_new_issue_spec.js
+++ b/spec/frontend/boards/board_new_issue_spec.js
@@ -1,6 +1,7 @@
/* global List */
import Vue from 'vue';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import boardNewIssue from '~/boards/components/board_new_issue.vue';
@@ -10,6 +11,7 @@ import '~/boards/models/list';
import { listObj, boardsMockInterceptor } from './mock_data';
describe('Issue boards new issue form', () => {
+ let wrapper;
let vm;
let list;
let mock;
@@ -24,13 +26,11 @@ describe('Issue boards new issue form', () => {
const dummySubmitEvent = {
preventDefault() {},
};
- vm.$refs.submitButton = vm.$el.querySelector('.btn-success');
- return vm.submit(dummySubmitEvent);
+ wrapper.vm.$refs.submitButton = wrapper.find({ ref: 'submitButton' });
+ return wrapper.vm.submit(dummySubmitEvent);
};
beforeEach(() => {
- setFixtures('<div class="test-container"></div>');
-
const BoardNewIssueComp = Vue.extend(boardNewIssue);
mock = new MockAdapter(axios);
@@ -43,46 +43,52 @@ describe('Issue boards new issue form', () => {
newIssueMock = Promise.resolve(promiseReturn);
jest.spyOn(list, 'newIssue').mockImplementation(() => newIssueMock);
- vm = new BoardNewIssueComp({
+ wrapper = mount(BoardNewIssueComp, {
propsData: {
+ disabled: false,
list,
},
- }).$mount(document.querySelector('.test-container'));
+ provide: {
+ groupId: null,
+ },
+ });
+
+ vm = wrapper.vm;
return Vue.nextTick();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
mock.restore();
});
it('calls submit if submit button is clicked', () => {
- jest.spyOn(vm, 'submit').mockImplementation(e => e.preventDefault());
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
vm.title = 'Testing Title';
- return Vue.nextTick().then(() => {
- vm.$el.querySelector('.btn-success').click();
-
- expect(vm.submit.mock.calls.length).toBe(1);
- });
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(wrapper.vm.submit).toHaveBeenCalled();
+ });
});
it('disables submit button if title is empty', () => {
- expect(vm.$el.querySelector('.btn-success').disabled).toBe(true);
+ expect(wrapper.find({ ref: 'submitButton' }).props().disabled).toBe(true);
});
it('enables submit button if title is not empty', () => {
- vm.title = 'Testing Title';
+ wrapper.setData({ title: 'Testing Title' });
return Vue.nextTick().then(() => {
- expect(vm.$el.querySelector('.form-control').value).toBe('Testing Title');
- expect(vm.$el.querySelector('.btn-success').disabled).not.toBe(true);
+ expect(wrapper.find({ ref: 'input' }).element.value).toBe('Testing Title');
+ expect(wrapper.find({ ref: 'submitButton' }).props().disabled).toBe(false);
});
});
it('clears title after clicking cancel', () => {
- vm.$el.querySelector('.btn-default').click();
+ wrapper.find({ ref: 'cancelButton' }).trigger('click');
return Vue.nextTick().then(() => {
expect(vm.title).toBe('');
@@ -97,7 +103,7 @@ describe('Issue boards new issue form', () => {
describe('submit success', () => {
it('creates new issue', () => {
- vm.title = 'submit title';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -107,17 +113,18 @@ describe('Issue boards new issue form', () => {
});
it('enables button after submit', () => {
- vm.title = 'submit issue';
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
.then(() => {
- expect(vm.$el.querySelector('.btn-success').disabled).toBe(false);
+ expect(wrapper.vm.$refs.submitButton.props().disabled).toBe(false);
});
});
it('clears title after submit', () => {
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -128,7 +135,7 @@ describe('Issue boards new issue form', () => {
it('sets detail issue after submit', () => {
expect(boardsStore.detail.issue.title).toBe(undefined);
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -138,7 +145,7 @@ describe('Issue boards new issue form', () => {
});
it('sets detail list after submit', () => {
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -149,7 +156,7 @@ describe('Issue boards new issue form', () => {
it('sets detail weight after submit', () => {
boardsStore.weightFeatureAvailable = true;
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -160,7 +167,7 @@ describe('Issue boards new issue form', () => {
it('does not set detail weight after submit', () => {
boardsStore.weightFeatureAvailable = false;
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
diff --git a/spec/frontend/boards/components/board_card_layout_spec.js b/spec/frontend/boards/components/board_card_layout_spec.js
index 2926f7d7e57..80f649a1a96 100644
--- a/spec/frontend/boards/components/board_card_layout_spec.js
+++ b/spec/frontend/boards/components/board_card_layout_spec.js
@@ -31,12 +31,14 @@ describe('Board card layout', () => {
propsData: {
list,
issue: list.issues[0],
- issueLinkBase: '/',
disabled: false,
index: 0,
- rootPath: '/',
...propsData,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
});
};
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index 1615a9d4df2..a3ddcdf01b7 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -38,12 +38,14 @@ describe('BoardCard', () => {
propsData: {
list,
issue: list.issues[0],
- issueLinkBase: '/',
disabled: false,
index: 0,
- rootPath: '/',
...propsData,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
});
};
diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js
index c06b7aceaad..2a4dbbb989e 100644
--- a/spec/frontend/boards/components/board_column_spec.js
+++ b/spec/frontend/boards/components/board_column_spec.js
@@ -59,10 +59,11 @@ describe('Board Column Component', () => {
propsData: {
boardId,
disabled: false,
- issueLinkBase: '/',
- rootPath: '/',
list,
},
+ provide: {
+ boardId,
+ },
});
};
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
index 2bf16b6b950..df117d06cdf 100644
--- a/spec/frontend/boards/components/board_content_spec.js
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -39,11 +39,7 @@ describe('BoardContent', () => {
propsData: {
lists: mockListsWithModel,
canAdminList: true,
- groupId: 1,
disabled: false,
- issueLinkBase: '/',
- rootPath: '/',
- boardId: '1',
},
store,
});
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 85666d47cb0..2439c347bf0 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -57,12 +57,12 @@ describe('Board List Header Component', () => {
wrapper = shallowMount(BoardListHeader, {
propsData: {
- boardId,
disabled: false,
- issueLinkBase: '/',
- rootPath: '/',
list,
},
+ provide: {
+ boardId,
+ },
});
};
diff --git a/spec/frontend/boards/issue_card_spec.js b/spec/frontend/boards/issue_card_spec.js
index dee8cb7b6e5..7e22e9647f0 100644
--- a/spec/frontend/boards/issue_card_spec.js
+++ b/spec/frontend/boards/issue_card_spec.js
@@ -47,13 +47,15 @@ describe('Issue card component', () => {
propsData: {
list,
issue,
- issueLinkBase: '/test',
- rootPath: '/',
},
store,
stubs: {
GlLabel: true,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
});
});
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index 581120344de..6c40b1ba3a7 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -119,7 +119,7 @@ describe('GfmAutoComplete', () => {
const defaultMatcher = (context, flag, subtext) =>
gfmAutoCompleteCallbacks.matcher.call(context, flag, subtext);
- const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$'];
+ const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$', '+'];
const otherFlags = ['/', ':'];
const flags = flagsUseDefaultMatcher.concat(otherFlags);
@@ -153,7 +153,6 @@ describe('GfmAutoComplete', () => {
'я',
'.',
"'",
- '+',
'-',
'_',
];
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
index fed61233e55..bb8165d1a52 100644
--- a/spec/frontend/ide/components/ide_status_list_spec.js
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -75,7 +75,8 @@ describe('ide/components/ide_status_list', () => {
describe('with binary file', () => {
beforeEach(() => {
- activeFile.binary = true;
+ activeFile.name = 'abc.dat';
+ activeFile.content = '🐱'; // non-ascii binary content
createComponent();
});
diff --git a/spec/frontend/ide/components/new_dropdown/upload_spec.js b/spec/frontend/ide/components/new_dropdown/upload_spec.js
index ad27954cd10..ae497106f73 100644
--- a/spec/frontend/ide/components/new_dropdown/upload_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/upload_spec.js
@@ -85,7 +85,6 @@ describe('new dropdown upload', () => {
name: textFile.name,
type: 'blob',
content: 'plain text',
- binary: false,
rawPath: '',
});
})
@@ -102,7 +101,6 @@ describe('new dropdown upload', () => {
name: binaryFile.name,
type: 'blob',
content: binaryTarget.result.split('base64,')[1],
- binary: true,
rawPath: binaryTarget.result,
});
});
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index f0ae2ba732b..9f4c9c1622a 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -45,7 +45,7 @@ describe('RepoEditor', () => {
const createOpenFile = path => {
const origFile = store.state.openFiles[0];
- const newFile = { ...origFile, path, key: path };
+ const newFile = { ...origFile, path, key: path, name: 'myfile.txt', content: 'hello world' };
store.state.entries[path] = newFile;
@@ -54,8 +54,9 @@ describe('RepoEditor', () => {
beforeEach(() => {
const f = {
- ...file(),
+ ...file('file.txt'),
viewMode: FILE_VIEW_MODE_EDITOR,
+ content: 'hello world',
};
const storeOptions = createStoreOptions();
@@ -142,6 +143,7 @@ describe('RepoEditor', () => {
...vm.file,
projectId: 'namespace/project',
path: 'sample.md',
+ name: 'sample.md',
content: 'testing 123',
});
@@ -200,7 +202,8 @@ describe('RepoEditor', () => {
describe('when open file is binary and not raw', () => {
beforeEach(done => {
- vm.file.binary = true;
+ vm.file.name = 'file.dat';
+ vm.file.content = '🐱'; // non-ascii binary content
vm.$nextTick(done);
});
@@ -407,6 +410,9 @@ describe('RepoEditor', () => {
beforeEach(done => {
jest.spyOn(vm.editor, 'updateDimensions').mockImplementation();
vm.file.viewMode = FILE_VIEW_MODE_PREVIEW;
+ vm.file.name = 'myfile.md';
+ vm.file.content = 'hello world';
+
vm.$nextTick(done);
});
@@ -650,7 +656,6 @@ describe('RepoEditor', () => {
path: 'foo/foo.png',
type: 'blob',
content: 'Zm9v',
- binary: true,
rawPath: 'data:image/png;base64,Zm9v',
});
});
diff --git a/spec/frontend/ide/lib/files_spec.js b/spec/frontend/ide/lib/files_spec.js
index b223cf64278..8ca6f01d9a6 100644
--- a/spec/frontend/ide/lib/files_spec.js
+++ b/spec/frontend/ide/lib/files_spec.js
@@ -1,11 +1,9 @@
-import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { decorateFiles, splitParent } from '~/ide/lib/files';
import { decorateData } from '~/ide/stores/utils';
const createEntries = paths => {
const createEntry = (acc, { path, type, children }) => {
const { name, parent } = splitParent(path);
- const previewMode = viewerInformationForPath(name);
acc[path] = {
...decorateData({
@@ -13,8 +11,6 @@ const createEntries = paths => {
name,
path,
type,
- previewMode,
- binary: (previewMode && previewMode.binary) || false,
parentPath: parent,
}),
tree: children.map(childName => expect.objectContaining({ name: childName })),
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 5166e07abcb..974c0715c06 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -241,7 +241,6 @@ describe('IDE store file actions', () => {
200,
{
raw_path: 'raw_path',
- binary: false,
},
{
'page-title': 'testing getFileData',
@@ -305,7 +304,6 @@ describe('IDE store file actions', () => {
200,
{
raw_path: 'raw_path',
- binary: false,
},
{
'page-title': 'testing old-dull-file',
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index ff904bbc9cd..b53e40be980 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -61,13 +61,11 @@ describe('IDE store file mutations', () => {
mutations.SET_FILE_DATA(localState, {
data: {
raw_path: 'raw',
- binary: true,
},
file: localFile,
});
expect(localFile.rawPath).toBe('raw');
- expect(localFile.binary).toBeTruthy();
expect(localFile.raw).toBeNull();
expect(localFile.baseRaw).toBeNull();
});
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index 4a1e1f3c45e..97dc8217ecc 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -13,60 +13,78 @@ import {
describe('WebIDE utils', () => {
describe('isTextFile', () => {
- it('returns false for known binary types', () => {
- expect(isTextFile('file content', 'image/png', 'my.png')).toBeFalsy();
- // mime types are case insensitive
- expect(isTextFile('file content', 'IMAGE/PNG', 'my.png')).toBeFalsy();
+ it.each`
+ mimeType | name | type | result
+ ${'image/png'} | ${'my.png'} | ${'binary'} | ${false}
+ ${'IMAGE/PNG'} | ${'my.png'} | ${'binary'} | ${false}
+ ${'text/plain'} | ${'my.txt'} | ${'text'} | ${true}
+ ${'TEXT/PLAIN'} | ${'my.txt'} | ${'text'} | ${true}
+ `('returns $result for known $type types', ({ mimeType, name, result }) => {
+ expect(isTextFile({ content: 'file content', mimeType, name })).toBe(result);
});
- it('returns true for known text types', () => {
- expect(isTextFile('file content', 'text/plain', 'my.txt')).toBeTruthy();
- // mime types are case insensitive
- expect(isTextFile('file content', 'TEXT/PLAIN', 'my.txt')).toBeTruthy();
- });
+ it.each`
+ content | mimeType | name
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'my.json'}
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'.tsconfig'}
+ ${'SELECT "éêė" from tablename'} | ${'application/sql'} | ${'my.sql'}
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'MY.JSON'}
+ ${'SELECT "éêė" from tablename'} | ${'application/sql'} | ${'MY.SQL'}
+ ${'var code = "something"'} | ${'application/javascript'} | ${'Gruntfile'}
+ ${'MAINTAINER Александр "a21283@me.com"'} | ${'application/octet-stream'} | ${'dockerfile'}
+ `(
+ 'returns true for file extensions that Monaco supports syntax highlighting for',
+ ({ content, mimeType, name }) => {
+ expect(isTextFile({ content, mimeType, name })).toBe(true);
+ },
+ );
- it('returns true for file extensions that Monaco supports syntax highlighting for', () => {
- // test based on both MIME and extension
- expect(isTextFile('{"éêė":"value"}', 'application/json', 'my.json')).toBeTruthy();
- expect(isTextFile('{"éêė":"value"}', 'application/json', '.tsconfig')).toBeTruthy();
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'my.sql')).toBeTruthy();
+ it('returns false if filename is same as the expected extension', () => {
+ expect(
+ isTextFile({
+ name: 'sql',
+ content: 'SELECT "éêė" from tablename',
+ mimeType: 'application/sql',
+ }),
+ ).toBeFalsy();
});
- it('returns true even irrespective of whether the mimes, extensions or file names are lowercase or upper case', () => {
- expect(isTextFile('{"éêė":"value"}', 'application/json', 'MY.JSON')).toBeTruthy();
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'MY.SQL')).toBeTruthy();
- expect(
- isTextFile('var code = "something"', 'application/javascript', 'Gruntfile'),
- ).toBeTruthy();
+ it('returns true for ASCII only content for unknown types', () => {
expect(
- isTextFile(
- 'MAINTAINER Александр "alexander11354322283@me.com"',
- 'application/octet-stream',
- 'dockerfile',
- ),
+ isTextFile({
+ name: 'hello.mytype',
+ content: 'plain text',
+ mimeType: 'application/x-new-type',
+ }),
).toBeTruthy();
});
- it('returns false if filename is same as the expected extension', () => {
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'sql')).toBeFalsy();
- });
-
- it('returns true for ASCII only content for unknown types', () => {
- expect(isTextFile('plain text', 'application/x-new-type', 'hello.mytype')).toBeTruthy();
+ it('returns false for non-ASCII content for unknown types', () => {
+ expect(
+ isTextFile({
+ name: 'my.random',
+ content: '{"éêė":"value"}',
+ mimeType: 'application/octet-stream',
+ }),
+ ).toBeFalsy();
});
- it('returns true for relevant filenames', () => {
- expect(
- isTextFile(
- 'MAINTAINER Александр "alexander11354322283@me.com"',
- 'application/octet-stream',
- 'Dockerfile',
- ),
- ).toBeTruthy();
+ it.each`
+ name | result
+ ${'myfile.txt'} | ${true}
+ ${'Dockerfile'} | ${true}
+ ${'img.png'} | ${false}
+ ${'abc.js'} | ${true}
+ ${'abc.random'} | ${false}
+ ${'image.jpeg'} | ${false}
+ `('returns $result for $filename when no content or mimeType is passed', ({ name, result }) => {
+ expect(isTextFile({ name })).toBe(result);
});
- it('returns false for non-ASCII content for unknown types', () => {
- expect(isTextFile('{"éêė":"value"}', 'application/octet-stream', 'my.random')).toBeFalsy();
+ it('returns true if content is empty string but false if content is not passed', () => {
+ expect(isTextFile({ name: 'abc.dat' })).toBe(false);
+ expect(isTextFile({ name: 'abc.dat', content: '' })).toBe(true);
+ expect(isTextFile({ name: 'abc.dat', content: ' ' })).toBe(true);
});
});
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index fccb56f4597..eeb5d21d62c 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -137,13 +137,13 @@ describe('IntegrationForm', () => {
});
});
- describe('adminState state is null', () => {
+ describe('defaultState state is null', () => {
it('does not render OverrideDropdown', () => {
createComponent(
{},
{},
{
- adminState: null,
+ defaultState: null,
},
);
@@ -151,13 +151,13 @@ describe('IntegrationForm', () => {
});
});
- describe('adminState state is an object', () => {
+ describe('defaultState state is an object', () => {
it('renders OverrideDropdown', () => {
createComponent(
{},
{},
{
- adminState: {
+ defaultState: {
...mockIntegrationProps,
},
},
diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
index 44e14cb3760..f312c456d5f 100644
--- a/spec/frontend/integrations/edit/components/override_dropdown_spec.js
+++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
@@ -13,15 +13,15 @@ describe('OverrideDropdown', () => {
override: true,
};
- const defaultAdminStateProps = {
+ const defaultDefaultStateProps = {
integrationLevel: 'group',
};
- const createComponent = (props = {}, adminStateProps = {}) => {
+ const createComponent = (props = {}, defaultStateProps = {}) => {
wrapper = shallowMount(OverrideDropdown, {
propsData: { ...defaultProps, ...props },
store: createStore({
- adminState: { ...defaultAdminStateProps, ...adminStateProps },
+ defaultState: { ...defaultDefaultStateProps, ...defaultStateProps },
}),
});
};
diff --git a/spec/frontend/integrations/edit/store/getters_spec.js b/spec/frontend/integrations/edit/store/getters_spec.js
index 700d36edaad..3353e0c84cc 100644
--- a/spec/frontend/integrations/edit/store/getters_spec.js
+++ b/spec/frontend/integrations/edit/store/getters_spec.js
@@ -5,22 +5,22 @@ import { mockIntegrationProps } from '../mock_data';
describe('Integration form store getters', () => {
let state;
const customState = { ...mockIntegrationProps, type: 'CustomState' };
- const adminState = { ...mockIntegrationProps, type: 'AdminState' };
+ const defaultState = { ...mockIntegrationProps, type: 'DefaultState' };
beforeEach(() => {
state = createState({ customState });
});
describe('isInheriting', () => {
- describe('when adminState is null', () => {
+ describe('when defaultState is null', () => {
it('returns false', () => {
expect(isInheriting(state)).toBe(false);
});
});
- describe('when adminState is an object', () => {
+ describe('when defaultState is an object', () => {
beforeEach(() => {
- state.adminState = adminState;
+ state.defaultState = defaultState;
});
describe('when override is false', () => {
@@ -47,11 +47,11 @@ describe('Integration form store getters', () => {
describe('propsSource', () => {
beforeEach(() => {
- state.adminState = adminState;
+ state.defaultState = defaultState;
});
- it('equals adminState if inheriting', () => {
- expect(propsSource(state, { isInheriting: true })).toEqual(adminState);
+ it('equals defaultState if inheriting', () => {
+ expect(propsSource(state, { isInheriting: true })).toEqual(defaultState);
});
it('equals customState if not inheriting', () => {
diff --git a/spec/frontend/integrations/edit/store/state_spec.js b/spec/frontend/integrations/edit/store/state_spec.js
index 2518e5c7b93..fc193850a94 100644
--- a/spec/frontend/integrations/edit/store/state_spec.js
+++ b/spec/frontend/integrations/edit/store/state_spec.js
@@ -3,7 +3,7 @@ import createState from '~/integrations/edit/store/state';
describe('Integration form state factory', () => {
it('states default to null', () => {
expect(createState()).toEqual({
- adminState: null,
+ defaultState: null,
customState: {},
isSaving: false,
isTesting: false,
@@ -19,9 +19,9 @@ describe('Integration form state factory', () => {
[null, { inheritFromId: null }, false],
[null, { inheritFromId: 25 }, false],
])(
- 'for adminState: %p, customState: %p: override = `%p`',
- (adminState, customState, expected) => {
- expect(createState({ adminState, customState }).override).toEqual(expected);
+ 'for defaultState: %p, customState: %p: override = `%p`',
+ (defaultState, customState, expected) => {
+ expect(createState({ defaultState, customState }).override).toEqual(expected);
},
);
});
diff --git a/spec/frontend/issuable_create/components/issuable_form_spec.js b/spec/frontend/issuable_create/components/issuable_form_spec.js
index 0d922727209..e2c6b4d9521 100644
--- a/spec/frontend/issuable_create/components/issuable_form_spec.js
+++ b/spec/frontend/issuable_create/components/issuable_form_spec.js
@@ -65,6 +65,7 @@ describe('IssuableForm', () => {
expect(titleFieldEl.find('label').text()).toBe('Title');
expect(titleFieldEl.find(GlFormInput).exists()).toBe(true);
expect(titleFieldEl.find(GlFormInput).attributes('placeholder')).toBe('Title');
+ expect(titleFieldEl.find(GlFormInput).attributes('autofocus')).toBe('true');
});
it('renders issuable description input field', () => {
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
new file mode 100644
index 00000000000..a96a4e15e6c
--- /dev/null
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -0,0 +1,185 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLink, GlLabel } from '@gitlab/ui';
+
+import IssuableItem from '~/issuable_list/components/issuable_item.vue';
+
+import { mockIssuable, mockRegularLabel, mockScopedLabel } from '../mock_data';
+
+const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable } = {}) =>
+ shallowMount(IssuableItem, {
+ propsData: {
+ issuableSymbol,
+ issuable,
+ },
+ });
+
+describe('IssuableItem', () => {
+ const mockLabels = mockIssuable.labels.nodes;
+ const mockAuthor = mockIssuable.author;
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('author', () => {
+ it('returns `issuable.author` reference', () => {
+ expect(wrapper.vm.author).toEqual(mockIssuable.author);
+ });
+ });
+
+ describe('authorId', () => {
+ it.each`
+ authorId | returnValue
+ ${1} | ${1}
+ ${'1'} | ${1}
+ ${'gid://gitlab/User/1'} | ${'1'}
+ ${'foo'} | ${''}
+ `(
+ 'returns $returnValue when value of `issuable.author.id` is $authorId',
+ async ({ authorId, returnValue }) => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ author: {
+ ...mockAuthor,
+ id: authorId,
+ },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.authorId).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('labels', () => {
+ it('returns `issuable.labels.nodes` reference when it is available', () => {
+ expect(wrapper.vm.labels).toEqual(mockLabels);
+ });
+
+ it('returns `issuable.labels` reference when it is available', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ labels: mockLabels,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labels).toEqual(mockLabels);
+ });
+
+ it('returns empty array when none of `issuable.labels.nodes` or `issuable.labels` are available', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ labels: null,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labels).toEqual([]);
+ });
+ });
+
+ describe('createdAt', () => {
+ it('returns string containing timeago string based on `issuable.createdAt`', () => {
+ expect(wrapper.vm.createdAt).toContain('created');
+ expect(wrapper.vm.createdAt).toContain('ago');
+ });
+ });
+
+ describe('updatedAt', () => {
+ it('returns string containing timeago string based on `issuable.updatedAt`', () => {
+ expect(wrapper.vm.updatedAt).toContain('updated');
+ expect(wrapper.vm.updatedAt).toContain('ago');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('scopedLabel', () => {
+ it.each`
+ label | labelType | returnValue
+ ${mockRegularLabel} | ${'regular'} | ${false}
+ ${mockScopedLabel} | ${'scoped'} | ${true}
+ `(
+ 'return $returnValue when provided label param is a $labelType label',
+ ({ label, returnValue }) => {
+ expect(wrapper.vm.scopedLabel(label)).toBe(returnValue);
+ },
+ );
+ });
+ });
+
+ describe('template', () => {
+ it('renders issuable title', () => {
+ const titleEl = wrapper.find('[data-testid="issuable-title"]');
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.find(GlLink).attributes('href')).toBe(mockIssuable.webUrl);
+ expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
+ });
+
+ it('renders issuable reference', () => {
+ const referenceEl = wrapper.find('[data-testid="issuable-reference"]');
+
+ expect(referenceEl.exists()).toBe(true);
+ expect(referenceEl.text()).toBe(`#${mockIssuable.iid}`);
+ });
+
+ it('renders issuable createdAt info', () => {
+ const createdAtEl = wrapper.find('[data-testid="issuable-created-at"]');
+
+ expect(createdAtEl.exists()).toBe(true);
+ expect(createdAtEl.attributes('title')).toBe('Jun 29, 2020 1:52pm GMT+0000');
+ expect(createdAtEl.text()).toBe(wrapper.vm.createdAt);
+ });
+
+ it('renders issuable author info', () => {
+ const authorEl = wrapper.find('[data-testid="issuable-author"]');
+
+ expect(authorEl.exists()).toBe(true);
+ expect(authorEl.attributes()).toMatchObject({
+ 'data-user-id': wrapper.vm.authorId,
+ 'data-username': mockAuthor.username,
+ 'data-name': mockAuthor.name,
+ 'data-avatar-url': mockAuthor.avatarUrl,
+ href: mockAuthor.webUrl,
+ });
+ expect(authorEl.text()).toBe(mockAuthor.name);
+ });
+
+ it('renders gl-label component for each label present within `issuable` prop', () => {
+ const labelsEl = wrapper.findAll(GlLabel);
+
+ expect(labelsEl.exists()).toBe(true);
+ expect(labelsEl).toHaveLength(mockLabels.length);
+ expect(labelsEl.at(0).props()).toMatchObject({
+ backgroundColor: mockLabels[0].color,
+ title: mockLabels[0].title,
+ description: mockLabels[0].description,
+ scoped: false,
+ size: 'sm',
+ });
+ });
+
+ it('renders issuable updatedAt info', () => {
+ const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
+
+ expect(updatedAtEl.exists()).toBe(true);
+ expect(updatedAtEl.find('span').attributes('title')).toBe('Sep 10, 2020 11:41am GMT+0000');
+ expect(updatedAtEl.text()).toBe(wrapper.vm.updatedAt);
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/components/issuable_list_root_spec.js b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
new file mode 100644
index 00000000000..34184522b55
--- /dev/null
+++ b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
@@ -0,0 +1,160 @@
+import { mount } from '@vue/test-utils';
+import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
+
+import IssuableListRoot from '~/issuable_list/components/issuable_list_root.vue';
+import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
+import IssuableItem from '~/issuable_list/components/issuable_item.vue';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+
+import { mockIssuableListProps } from '../mock_data';
+
+const createComponent = (propsData = mockIssuableListProps) =>
+ mount(IssuableListRoot, {
+ propsData,
+ slots: {
+ 'nav-actions': `
+ <button class="js-new-issuable">New issuable</button>
+ `,
+ 'empty-state': `
+ <p class="js-issuable-empty-state">Issuable empty state</p>
+ `,
+ },
+ });
+
+describe('IssuableListRoot', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ it('renders component container element with class "issuable-list-container"', () => {
+ expect(wrapper.classes()).toContain('issuable-list-container');
+ });
+
+ it('renders issuable-tabs component', () => {
+ const tabsEl = wrapper.find(IssuableTabs);
+
+ expect(tabsEl.exists()).toBe(true);
+ expect(tabsEl.props()).toMatchObject({
+ tabs: wrapper.vm.tabs,
+ tabCounts: wrapper.vm.tabCounts,
+ currentTab: wrapper.vm.currentTab,
+ });
+ });
+
+ it('renders contents for slot "nav-actions" within issuable-tab component', () => {
+ const buttonEl = wrapper.find(IssuableTabs).find('button.js-new-issuable');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('New issuable');
+ });
+
+ it('renders filtered-search-bar component', () => {
+ const searchEl = wrapper.find(FilteredSearchBar);
+ const {
+ namespace,
+ recentSearchesStorageKey,
+ searchInputPlaceholder,
+ searchTokens,
+ sortOptions,
+ initialFilterValue,
+ initialSortBy,
+ } = wrapper.vm;
+
+ expect(searchEl.exists()).toBe(true);
+ expect(searchEl.props()).toMatchObject({
+ namespace,
+ recentSearchesStorageKey,
+ searchInputPlaceholder,
+ tokens: searchTokens,
+ sortOptions,
+ initialFilterValue,
+ initialSortBy,
+ });
+ });
+
+ it('renders gl-loading-icon when `issuablesLoading` prop is true', async () => {
+ wrapper.setProps({
+ issuablesLoading: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('renders issuable-item component for each item within `issuables` array', () => {
+ const itemsEl = wrapper.findAll(IssuableItem);
+ const mockIssuable = mockIssuableListProps.issuables[0];
+
+ expect(itemsEl).toHaveLength(mockIssuableListProps.issuables.length);
+ expect(itemsEl.at(0).props()).toMatchObject({
+ issuableSymbol: wrapper.vm.issuableSymbol,
+ issuable: mockIssuable,
+ });
+ });
+
+ it('renders contents for slot "empty-state" when `issuablesLoading` is false and `issuables` is empty', async () => {
+ wrapper.setProps({
+ issuables: [],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('p.js-issuable-empty-state').exists()).toBe(true);
+ expect(wrapper.find('p.js-issuable-empty-state').text()).toBe('Issuable empty state');
+ });
+
+ it('renders gl-pagination when `showPaginationControls` prop is true', async () => {
+ wrapper.setProps({
+ showPaginationControls: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const paginationEl = wrapper.find(GlPagination);
+ expect(paginationEl.exists()).toBe(true);
+ expect(paginationEl.props()).toMatchObject({
+ perPage: 20,
+ value: 1,
+ prevPage: 0,
+ nextPage: 2,
+ align: 'center',
+ });
+ });
+ });
+
+ describe('events', () => {
+ it('issuable-tabs component emits `click-tab` event on `click-tab` event', () => {
+ wrapper.find(IssuableTabs).vm.$emit('click');
+
+ expect(wrapper.emitted('click-tab')).toBeTruthy();
+ });
+
+ it('filtered-search-bar component emits `filter` event on `onFilter` & `sort` event on `onSort` events', () => {
+ const searchEl = wrapper.find(FilteredSearchBar);
+
+ searchEl.vm.$emit('onFilter');
+ expect(wrapper.emitted('filter')).toBeTruthy();
+ searchEl.vm.$emit('onSort');
+ expect(wrapper.emitted('sort')).toBeTruthy();
+ });
+
+ it('gl-pagination component emits `page-change` event on `input` event', async () => {
+ wrapper.setProps({
+ showPaginationControls: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.find(GlPagination).vm.$emit('input');
+ expect(wrapper.emitted('page-change')).toBeTruthy();
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/components/issuable_tabs_spec.js b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
new file mode 100644
index 00000000000..12611400084
--- /dev/null
+++ b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
@@ -0,0 +1,91 @@
+import { mount } from '@vue/test-utils';
+import { GlTab, GlBadge } from '@gitlab/ui';
+
+import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
+
+import { mockIssuableListProps } from '../mock_data';
+
+const createComponent = ({
+ tabs = mockIssuableListProps.tabs,
+ tabCounts = mockIssuableListProps.tabCounts,
+ currentTab = mockIssuableListProps.currentTab,
+} = {}) =>
+ mount(IssuableTabs, {
+ propsData: {
+ tabs,
+ tabCounts,
+ currentTab,
+ },
+ slots: {
+ 'nav-actions': `
+ <button class="js-new-issuable">New issuable</button>
+ `,
+ },
+ });
+
+describe('IssuableTabs', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('methods', () => {
+ describe('isTabActive', () => {
+ it.each`
+ tabName | currentTab | returnValue
+ ${'opened'} | ${'opened'} | ${true}
+ ${'opened'} | ${'closed'} | ${false}
+ `(
+ 'returns $returnValue when tab name is "$tabName" is current tab is "$currentTab"',
+ async ({ tabName, currentTab, returnValue }) => {
+ wrapper.setProps({
+ currentTab,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isTabActive(tabName)).toBe(returnValue);
+ },
+ );
+ });
+ });
+
+ describe('template', () => {
+ it('renders gl-tab for each tab within `tabs` array', () => {
+ const tabsEl = wrapper.findAll(GlTab);
+
+ expect(tabsEl.exists()).toBe(true);
+ expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
+ });
+
+ it('renders gl-badge component within a tab', () => {
+ const badgeEl = wrapper.findAll(GlBadge).at(0);
+
+ expect(badgeEl.exists()).toBe(true);
+ expect(badgeEl.text()).toBe(`${mockIssuableListProps.tabCounts.opened}`);
+ });
+
+ it('renders contents for slot "nav-actions"', () => {
+ const buttonEl = wrapper.find('button.js-new-issuable');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('New issuable');
+ });
+ });
+
+ describe('events', () => {
+ it('gl-tab component emits `click` event on `click` event', () => {
+ const tabEl = wrapper.findAll(GlTab).at(0);
+
+ tabEl.vm.$emit('click', 'opened');
+
+ expect(wrapper.emitted('click')).toBeTruthy();
+ expect(wrapper.emitted('click')[0]).toEqual(['opened']);
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/mock_data.js b/spec/frontend/issuable_list/mock_data.js
new file mode 100644
index 00000000000..f6f914a595d
--- /dev/null
+++ b/spec/frontend/issuable_list/mock_data.js
@@ -0,0 +1,135 @@
+import {
+ mockAuthorToken,
+ mockLabelToken,
+ mockSortOptions,
+} from 'jest/vue_shared/components/filtered_search_bar/mock_data';
+
+export const mockAuthor = {
+ id: 'gid://gitlab/User/1',
+ avatarUrl: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ name: 'Administrator',
+ username: 'root',
+ webUrl: 'http://0.0.0.0:3000/root',
+};
+
+export const mockRegularLabel = {
+ id: 'gid://gitlab/GroupLabel/2048',
+ title: 'Documentation Update',
+ description: null,
+ color: '#F0AD4E',
+ textColor: '#FFFFFF',
+};
+
+export const mockScopedLabel = {
+ id: 'gid://gitlab/ProjectLabel/2049',
+ title: 'status::confirmed',
+ description: null,
+ color: '#D9534F',
+ textColor: '#FFFFFF',
+};
+
+export const mockLabels = [mockRegularLabel, mockScopedLabel];
+
+export const mockIssuable = {
+ iid: '30',
+ title: 'Dismiss Cipher with no integrity',
+ description: null,
+ createdAt: '2020-06-29T13:52:56Z',
+ updatedAt: '2020-09-10T11:41:13Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/30',
+ author: mockAuthor,
+ labels: {
+ nodes: mockLabels,
+ },
+};
+
+export const mockIssuables = [
+ mockIssuable,
+ {
+ iid: '28',
+ title: 'Dismiss Cipher with no integrity',
+ description: null,
+ createdAt: '2020-06-29T13:52:56Z',
+ updatedAt: '2020-06-29T13:52:56Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/28',
+ author: mockAuthor,
+ labels: {
+ nodes: [],
+ },
+ },
+ {
+ iid: '7',
+ title: 'Temporibus in veritatis labore explicabo velit molestiae sed.',
+ description: 'Quo consequatur rem aliquid laborum quibusdam molestiae saepe.',
+ createdAt: '2020-06-25T13:50:14Z',
+ updatedAt: '2020-08-25T06:09:27Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/7',
+ author: mockAuthor,
+ labels: {
+ nodes: mockLabels,
+ },
+ },
+ {
+ iid: '17',
+ title: 'Vel voluptatem quaerat est hic incidunt qui ut aliquid sit exercitationem.',
+ description: 'Incidunt accusamus perspiciatis aut excepturi.',
+ createdAt: '2020-06-19T13:51:36Z',
+ updatedAt: '2020-08-11T13:36:35Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/17',
+ author: mockAuthor,
+ labels: {
+ nodes: [],
+ },
+ },
+ {
+ iid: '16',
+ title: 'Vero qui quo labore libero omnis quisquam et cumque.',
+ description: 'Ipsa ipsum magni nostrum alias aut exercitationem.',
+ createdAt: '2020-06-19T13:51:36Z',
+ updatedAt: '2020-06-19T13:51:36Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/16',
+ author: mockAuthor,
+ labels: {
+ nodes: [],
+ },
+ },
+];
+
+export const mockTabs = [
+ {
+ id: 'state-opened',
+ name: 'opened',
+ title: 'Open',
+ titleTooltip: 'Filter by issuables that are currently opened.',
+ },
+ {
+ id: 'state-archived',
+ name: 'closed',
+ title: 'Closed',
+ titleTooltip: 'Filter by issuables that are currently archived.',
+ },
+ {
+ id: 'state-all',
+ name: 'all',
+ title: 'All',
+ titleTooltip: 'Show all issuables.',
+ },
+];
+
+export const mockTabCounts = {
+ opened: 5,
+ closed: 0,
+ all: 5,
+};
+
+export const mockIssuableListProps = {
+ namespace: 'gitlab-org/gitlab-test',
+ recentSearchesStorageKey: 'issues',
+ searchInputPlaceholder: 'Search issues',
+ searchTokens: [mockAuthorToken, mockLabelToken],
+ sortOptions: mockSortOptions,
+ issuables: mockIssuables,
+ tabs: mockTabs,
+ tabCounts: mockTabCounts,
+ currentTab: 'opened',
+};